mirror of
https://github.com/BanjoRecomp/BanjoRecomp
synced 2026-06-11 04:37:59 -04:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 116b58c444 | |||
| 8fa0dd559f | |||
| d331f4e5cb | |||
| 9b93be22eb | |||
| 2783e3416f | |||
| 9f39b6bf69 | |||
| 937fce9dec | |||
| 377ba80628 | |||
| 5a596e22db | |||
| 1b67b628c1 | |||
| cf486ad7d7 | |||
| b71479aeae | |||
| 7f4e38d732 | |||
| e13245c57c | |||
| a97c09db86 | |||
| cfb0e32e76 | |||
| d424ef949e | |||
| facb4d3047 | |||
| cdd25e5bf7 | |||
| d7d9a39c74 | |||
| 462471063d | |||
| dd61fa8953 | |||
| 79321e7f86 | |||
| fbe26b7a63 | |||
| c8fac11c42 | |||
| 212374cdba | |||
| 07998cb006 |
@@ -13,9 +13,6 @@
|
||||
[submodule "lib/rt64"]
|
||||
path = lib/rt64
|
||||
url = https://github.com/rt64/rt64
|
||||
[submodule "lib/slot_map"]
|
||||
path = lib/slot_map
|
||||
url = https://github.com/SergeyMakeev/slot_map
|
||||
[submodule "lib/bk-decomp"]
|
||||
path = lib/bk-decomp
|
||||
url = https://gitlab.com/banjo.decomp/banjo-kazooie
|
||||
|
||||
+1
-1
Submodule BanjoRecompSyms updated: 9d2625f2b1...6820055ca0
+3
-3
@@ -160,7 +160,7 @@ set (SOURCES
|
||||
${CMAKE_SOURCE_DIR}/src/game/config.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/game/debug.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/game/recomp_api.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/game/recomp_actor_api.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/game/recomp_extension_api.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/game/recomp_data_api.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/game/rom_decompression.cpp
|
||||
|
||||
@@ -221,7 +221,7 @@ target_include_directories(BanjoRecompiled PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/lib/rt64/src/render
|
||||
${CMAKE_SOURCE_DIR}/lib/freetype-windows-binaries/include
|
||||
${CMAKE_SOURCE_DIR}/lib/rt64/src/contrib/nativefiledialog-extended/src/include
|
||||
${CMAKE_SOURCE_DIR}/lib/slot_map/slot_map
|
||||
${CMAKE_SOURCE_DIR}/lib/SlotMap
|
||||
${CMAKE_BINARY_DIR}/shaders
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
@@ -290,7 +290,7 @@ if (WIN32)
|
||||
)
|
||||
|
||||
# target_sources(BanjoRecompiled PRIVATE ${CMAKE_SOURCE_DIR}/icons/app.rc)
|
||||
target_link_libraries(BanjoRecompiled PRIVATE SDL2)
|
||||
target_link_libraries(BanjoRecompiled PRIVATE SDL2 Winmm.lib)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
|
||||
+21
-5
@@ -4,23 +4,40 @@
|
||||
entrypoint = 0x80000400
|
||||
# Paths are relative to the location of this config file.
|
||||
output_func_path = "RecompiledFuncs"
|
||||
symbols_file_path = "BanjoRecompSyms/bk.us.rev0.syms.toml"
|
||||
rom_file_path = "banjo.us.v10.decompressed.z64"
|
||||
symbols_file_path = "BanjoRecompSyms/bk.us.rev0.syms.toml"
|
||||
# elf_path = "banjo.us.v10.elf"
|
||||
# use_mdebug = true
|
||||
# trace_mode = true
|
||||
bss_section_suffix = "_bss"
|
||||
|
||||
manual_funcs = [
|
||||
{ name = "__n_CSPVoiceHandler", section = ".core1", vram = 0x8025E438, size = 0x684 },
|
||||
{ name = "boot___osLeoAbnormalResume", section = ".boot_bk_boot", vram = 0x800037E4, size = 0xE8 },
|
||||
{ name = "boot___osLeoResume", section = ".boot_bk_boot", vram = 0x800038CC, size = 0xEC },
|
||||
]
|
||||
|
||||
mdebug_file_mappings = [
|
||||
{ filename = "src/TTC/ch/clam.c", input_section = ".text", output_section = ".TTC" },
|
||||
{ filename = "src/TTC/ch/blubber.c", input_section = ".text", output_section = ".TTC" },
|
||||
{ filename = "src/TTC/ch/lockup.c", input_section = ".text", output_section = ".TTC" },
|
||||
{ filename = "src/TTC/ch/treasure.c", input_section = ".text", output_section = ".TTC" },
|
||||
{ filename = "src/SM/ch/attacktutorial.c", input_section = ".text", output_section = ".SM" },
|
||||
{ filename = "src/SM/ch/vegetables.c", input_section = ".text", output_section = ".SM" },
|
||||
]
|
||||
|
||||
[patches]
|
||||
stubs = [
|
||||
|
||||
ignored = [
|
||||
"boot_n_aspMainTextStart",
|
||||
"boot_gSPF3DEX_fifoTextStart",
|
||||
"boot_gSPL3DEX_fifoTextStart",
|
||||
]
|
||||
|
||||
renamed = [
|
||||
"wmemcpy"
|
||||
]
|
||||
|
||||
ignored = [
|
||||
stubs = [
|
||||
# Boot segment libultra duplicates
|
||||
"boot___ll_div",
|
||||
"boot___ll_lshift",
|
||||
@@ -32,7 +49,6 @@ ignored = [
|
||||
"boot___ull_divremi",
|
||||
"boot___ull_rem",
|
||||
"boot___ull_rshift",
|
||||
"boot___osInitialize_common",
|
||||
"boot_osPiRawStartDma",
|
||||
"boot_osPiGetStatus",
|
||||
"boot___osSetSR",
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace banjo {
|
||||
|
||||
void enable_instant_present() override;
|
||||
void send_dl(const OSTask *task) override;
|
||||
void update_screen(uint32_t vi_origin) override;
|
||||
void update_screen() override;
|
||||
void shutdown() override;
|
||||
uint32_t get_display_framerate() const override;
|
||||
float get_resolution_scale() const override;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#define __RECOMP_DATA_H__
|
||||
|
||||
namespace recomputil {
|
||||
void init_extended_actor_data();
|
||||
void reset_actor_data();
|
||||
void init_extended_object_data(size_t num_types);
|
||||
void clear_all_object_data(size_t type_index);
|
||||
|
||||
void register_data_api_exports();
|
||||
}
|
||||
|
||||
+2
-1
@@ -7,7 +7,8 @@
|
||||
"project": "CMakeLists.txt",
|
||||
"projectTarget": "BanjoRecompiled.exe",
|
||||
"name": "BanjoRecompiled.exe",
|
||||
"currentDir": "${workspaceRoot}"
|
||||
"currentDir": "${workspaceRoot}",
|
||||
"args": ["--show-console"]
|
||||
}
|
||||
]
|
||||
}
|
||||
+1
-1
Submodule lib/N64ModernRuntime updated: c5e268aa0f...46b7a37a4c
@@ -0,0 +1,257 @@
|
||||
This file is originally from the repo: https://github.com/SergeyMakeev/SlotMap
|
||||
|
||||
The original license and README are as follows:
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Sergey Makeev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
# Slot Map
|
||||
|
||||
[](https://github.com/SergeyMakeev/slot_map/actions)
|
||||
[](https://ci.appveyor.com/project/SergeyMakeev/slot-map)
|
||||
[](https://codecov.io/gh/SergeyMakeev/slot_map)
|
||||

|
||||
|
||||
A Slot Map is a high-performance associative container with persistent unique keys to access stored values. Upon insertion, a key is returned that can be used to later access or remove the values. Insertion, removal, and access are all guaranteed to take `O(1)` time (best, worst, and average case)
|
||||
Great for storing collections of objects that need stable, safe references but have no clear ownership.
|
||||
|
||||
The difference between a `std::unordered_map` and a `dod::slot_map` is that the slot map generates and returns the key when inserting a value. A key is always unique and will only refer to the value that was inserted.
|
||||
|
||||
Usage example:
|
||||
```cpp
|
||||
slot_map<std::string> strings;
|
||||
auto red = strings.emplace("Red");
|
||||
auto green = strings.emplace("Green");
|
||||
auto blue = strings.emplace("Blue");
|
||||
|
||||
const std::string* val1 = strings.get(red);
|
||||
if (val1)
|
||||
{
|
||||
printf("red = '%s'\n", val1->c_str());
|
||||
}
|
||||
|
||||
strings.erase(green);
|
||||
printf("%d\n", strings.has(green));
|
||||
printf("%d\n", strings.has(blue));
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
red = 'Red'
|
||||
0
|
||||
1
|
||||
```
|
||||
|
||||
# Implementation details
|
||||
|
||||
The slot map container will allocate memory in pages (default page size = 4096 elements) to avoid memory spikes during growth and be able to deallocate pages that are no longer needed.
|
||||
Also, the page-based memory allocator is very important since it guarantees "pointers stability"; hence, we never move values in memory.
|
||||
|
||||
|
||||
Keys are always uses `uint64_t/uint32_t` (configurable) and technically typless, but we "artificially" make them typed to get a few extra compile-time checks.
|
||||
i.e., the following code will produce a compiler error
|
||||
```cpp
|
||||
slot_map<std::string> strings;
|
||||
slot_map<int> numbers;
|
||||
slot_map<int>::key numKey = numbers.emplace(3);
|
||||
const std::string* value = strings.get(numKey); // <---- can not use slot_map<int>::key to index slot_map<std::string> !
|
||||
```
|
||||
|
||||
The keys can be converted to/from their numeric types if you do not need additional type checks.
|
||||
```cpp
|
||||
slot_map<int> numbers;
|
||||
slot_map<int>::key numKey = numbers.emplace(3);
|
||||
uint64_t rawKey = numKey; // convert to numeric type (like cast pointer to void*)
|
||||
...
|
||||
slot_map<int>::key numKey2{rawKey}; // create key from numeric type
|
||||
```
|
||||
|
||||
When a slot is reused, its version is automatically incremented (to invalidate all existing keys that refers to the same slot).
|
||||
But since we only use 20-bits *(10-bits for 32 bit keys)* for version counter, there is a possibility that the version counter will wrap around,
|
||||
and a new item will get the same key as a removed item.
|
||||
|
||||
To mitigate this potential issue, once the version counter overflows, we disable that slot so that no new keys are returned for this slot
|
||||
(this gives us a guarantee that there are no key collisions)
|
||||
|
||||
To prevent version overflow from happening too often, we need to ensure that we don't reuse the same slot too often.
|
||||
So we do not reuse recently freed slot-indices as long as their number is below a certain threshold (`kMinFreeIndices = 64`).
|
||||
|
||||
Keys also can carry a few extra bits of information provided by a user that we called `tag`.
|
||||
That might be handy to add application-specific data to keys.
|
||||
|
||||
For example:
|
||||
```cpp
|
||||
slot_map<std::string> strings;
|
||||
auto red = strings.emplace("Red");
|
||||
red.set_tag(13);
|
||||
|
||||
auto tag = red.get_tag();
|
||||
assert(tag == 13);
|
||||
```
|
||||
|
||||
Here is how a key structure looks like internally
|
||||
|
||||
64-bit key type
|
||||
|
||||
| Component | Number of bits |
|
||||
| ---------------|------------------------|
|
||||
| tag | 12 |
|
||||
| version | 20 (0..1,048,575 |
|
||||
| index | 32 (0..4,294,967,295) |
|
||||
|
||||
32-bit key type
|
||||
|
||||
| Component | Number of bits |
|
||||
| ---------------|---------------------|
|
||||
| tag | 2 |
|
||||
| version | 10 (0..1023) |
|
||||
| index | 20 (0..1,048,575) |
|
||||
|
||||
Note: To use your custom memory allocator define `SLOT_MAP_ALLOC`/`SLOT_MAP_FREE` before including `"slot_map.h"`
|
||||
|
||||
```cpp
|
||||
#define SLOT_MAP_ALLOC(sizeInBytes, alignment) aligned_alloc(alignment, sizeInBytes)
|
||||
#define SLOT_MAP_FREE(ptr) free(ptr)
|
||||
#include "slot_map.h"
|
||||
```
|
||||
|
||||
|
||||
# API
|
||||
|
||||
`bool has_key(key k) const noexcept`
|
||||
Returns true if the slot map contains a specific key
|
||||
|
||||
`void reset()`
|
||||
Clears the slot map and releases any allocated memory.
|
||||
Note: By calling this function, you must guarantee that no handles are in use!
|
||||
Otherwise calling this function might be dangerous and lead to key "collisions".
|
||||
You might consider using "clear()" instead.
|
||||
|
||||
`void clear()`
|
||||
Clears the slot map but keeps the allocated memory for reuse.
|
||||
Automatically increases version for all the removed elements (the same as calling "erase()" for all existing elements)
|
||||
|
||||
`const T* get(key k) const noexcept`
|
||||
If key exists returns a const pointer to the value corresponding to the given key or returns null elsewere.
|
||||
|
||||
`T* get(key k)`
|
||||
If key exists returns a pointer to the value corresponding to the given key or returns null elsewere.
|
||||
|
||||
`key emplace(Args&&... args)`
|
||||
Constructs element in-place and returns a unique key that can be used to access this value.
|
||||
|
||||
`void erase(key k)`
|
||||
Removes element (if such key exists) from the slot map.
|
||||
|
||||
`std::optional<T> pop(key k)`
|
||||
Removes element (if such key exists) from the slot map, returning the value at the key if the key was not previously removed.
|
||||
|
||||
`bool empty() const noexcept`
|
||||
Returns true if the slot map is empty.
|
||||
|
||||
`size_type size() const noexcept`
|
||||
Returns the number of elements in the slot map.
|
||||
|
||||
`void swap(slot_map& other) noexcept`
|
||||
Exchanges the content of the slot map by the content of another slot map object of the same type.
|
||||
|
||||
`slot_map(const slot_map& other)`
|
||||
Copy constructor
|
||||
|
||||
`slot_map& operator=(const slot_map& other)`
|
||||
Copy assignment
|
||||
|
||||
`slot_map(slot_map&& other) noexcept`
|
||||
Move constructor
|
||||
|
||||
`slot_map& operator=(slot_map&& other) noexcept`
|
||||
Move asignment
|
||||
|
||||
|
||||
`const_values_iterator begin() const noexcept`
|
||||
`const_values_iterator end() const noexcept`
|
||||
Const values iterator
|
||||
|
||||
```cpp
|
||||
for (const auto& value : slotMap)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
`Items items() const noexcept`
|
||||
Const key/value iterator
|
||||
|
||||
```cpp
|
||||
for (const auto& [key, value] : slotMap.items())
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
# References
|
||||
|
||||
Sean Middleditch
|
||||
Data Structures for Game Developers: The Slot Map, 2013
|
||||
https://web.archive.org/web/20180121142549/http://seanmiddleditch.com/data-structures-for-game-developers-the-slot-map/
|
||||
|
||||
Niklas Gray
|
||||
Building a Data-Oriented Entity System (part 1), 2014
|
||||
http://bitsquid.blogspot.com/2014/08/building-data-oriented-entity-system.html
|
||||
|
||||
Noel Llopis
|
||||
Managing Data Relationships, 2010
|
||||
https://gamesfromwithin.com/managing-data-relationships
|
||||
|
||||
Stefan Reinalter
|
||||
Adventures in data-oriented design - Part 3c: External References, 2013
|
||||
https://blog.molecular-matters.com/2013/07/24/adventures-in-data-oriented-design-part-3c-external-references/
|
||||
|
||||
Niklas Gray
|
||||
Managing Decoupling Part 4 - The ID Lookup Table, 2011
|
||||
https://bitsquid.blogspot.com/2011/09/managing-decoupling-part-4-id-lookup.html
|
||||
|
||||
Sander Mertens
|
||||
Making the most of ECS identifiers, 2020
|
||||
https://ajmmertens.medium.com/doing-a-lot-with-a-little-ecs-identifiers-25a72bd2647
|
||||
|
||||
Michele Caini
|
||||
ECS back and forth. Part 9 - Sparse sets and EnTT, 2020
|
||||
https://skypjack.github.io/2020-08-02-ecs-baf-part-9/
|
||||
|
||||
Andre Weissflog
|
||||
Handles are the better pointers, 2018
|
||||
https://floooh.github.io/2018/06/17/handles-vs-pointers.html
|
||||
|
||||
Allan Deutsch
|
||||
C++Now 2017: "The Slot Map Data Structure", 2017
|
||||
https://www.youtube.com/watch?v=SHaAR7XPtNU
|
||||
|
||||
Jeff Gates
|
||||
Init, Update, Draw - Data Arrays, 2012
|
||||
https://greysphere.tumblr.com/post/31601463396/data-arrays
|
||||
|
||||
Niklas Gray
|
||||
Data Structures Part 1: Bulk Data, 2019
|
||||
https://ourmachinery.com/post/data-structures-part-1-bulk-data/
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+1
-1
Submodule lib/bk-decomp updated: fd208f77ca...351ca1580c
+1
-1
Submodule lib/rt64 updated: cf75b17fc2...50aa793ad1
-1
Submodule lib/slot_map deleted from b8ac8ebd89
+1
-1
@@ -9,7 +9,7 @@ single_file_output = true
|
||||
use_absolute_symbols = true
|
||||
# Point the recompiler at the symbol files so that it can resolve relocations during recompilation.
|
||||
func_reference_syms_file = "BanjoRecompSyms/bk.us.rev0.syms.toml"
|
||||
data_reference_syms_files = [ "BanjoRecompSyms/bk.us.rev0.datasyms.toml", "BanjoRecompSyms/bk.us.rev0.datasyms_static.toml" ]
|
||||
data_reference_syms_files = [ "BanjoRecompSyms/bk.us.rev0.datasyms.toml" ]
|
||||
# Tell the recompiler to write the output binary. Doing this instead of using objcopy allows the recompiler to patch MIPS32 relocs.
|
||||
output_binary_path = "patches/patches.bin"
|
||||
# Do not emit warnings for unpaired LO16 values, as clang produces many of them.
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ LD ?= ld.lld
|
||||
GBI_DEFINE := -DF3DEX_GBI
|
||||
CFLAGS := -target mips -mips2 -mabi=32 -O2 -G0 -mno-abicalls -mno-odd-spreg -mno-check-zero-division \
|
||||
-fomit-frame-pointer -ffast-math -fno-unsafe-math-optimizations -fno-builtin-memset \
|
||||
-Wall -Wextra -Wno-incompatible-library-redeclaration -Wno-unused-parameter -Wno-unknown-pragmas -Wno-unused-variable -Wno-missing-braces -Wno-unsupported-floating-point-opt
|
||||
-Wall -Wextra -Wno-incompatible-library-redeclaration -Wno-unused-parameter -Wno-unknown-pragmas -Wno-unused-variable -Wno-missing-braces -Wno-unsupported-floating-point-opt -Wno-cast-function-type-mismatch
|
||||
CPPFLAGS := -nostdinc -D_LANGUAGE_C -DMIPS -I ../lib/bk-decomp/include -I ../lib/bk-decomp/include/2.0L -I ../lib/bk-decomp/include/2.0L/PR -I../lib/rt64/include $(GBI_DEFINE)
|
||||
LDFLAGS := -nostdlib -T patches.ld -T syms.ld -Map patches.map --unresolved-symbols=ignore-all --emit-relocs
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#ifndef __MEM_FUNCS_H__
|
||||
#define __MEM_FUNCS_H__
|
||||
|
||||
#include "patch_helpers.h"
|
||||
|
||||
DECLARE_FUNC(u32, recomp_register_actor_extension, u32 actor_type, u32 size);
|
||||
DECLARE_FUNC(u32, recomp_register_actor_extension_generic, u32 size);
|
||||
DECLARE_FUNC(void, recomp_clear_all_actor_data);
|
||||
DECLARE_FUNC(u32, recomp_create_actor_data, u32 actor_type);
|
||||
DECLARE_FUNC(void, recomp_destroy_actor_data, u32 actor_handle);
|
||||
DECLARE_FUNC(void*, recomp_get_actor_data, u32 actor_handle, u32 extension_handle, u32 actor_type);
|
||||
DECLARE_FUNC(u32, recomp_get_actor_spawn_index, u32 actor_handle);
|
||||
|
||||
#endif
|
||||
@@ -1,379 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "prop.h"
|
||||
#include "actor.h"
|
||||
#include "functions.h"
|
||||
#include "mem_funcs.h"
|
||||
#include "bk_api.h"
|
||||
|
||||
extern ActorArray *suBaddieActorArray;
|
||||
extern Actor *suLastBaddie;
|
||||
|
||||
void func_803255FC(Actor *this);
|
||||
void func_8032B5C0(ActorMarker *arg0, ActorMarker *arg1, struct5Cs *arg2);
|
||||
s32 func_80326C18(void);
|
||||
void func_8032FFD4(ActorMarker *this, s32 arg1);
|
||||
void marker_setModelId(ActorMarker *this, enum asset_e modelIndex);
|
||||
s32 func_80306DDC(s32 *position);
|
||||
s32 func_80307258(f32 arg0[3], s32 arg1, s32 arg2);
|
||||
struct5Bs *func_8034A2C8(void);
|
||||
void func_8033F738(ActorMarker *arg0);
|
||||
void func_8034BFF8(ActorMarker *marker);
|
||||
Struct83s *func_803406B0(void);
|
||||
|
||||
// @recomp Patched to create extension data for the actor.
|
||||
RECOMP_PATCH Actor *actor_new(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags){
|
||||
ActorAnimationInfo * sp54;
|
||||
s32 i;
|
||||
f32 sp44[3];
|
||||
|
||||
if(suBaddieActorArray == NULL){
|
||||
// @recomp Reset actor data when suBaddieActorArray is initially allocated.
|
||||
recomp_clear_all_actor_data();
|
||||
suBaddieActorArray = (ActorArray *)malloc(sizeof(ActorArray) + 20*sizeof(Actor));
|
||||
suBaddieActorArray->cnt = 0;
|
||||
suBaddieActorArray->max_cnt = 20;
|
||||
}
|
||||
|
||||
if(suBaddieActorArray->cnt + 1 > suBaddieActorArray->max_cnt){
|
||||
suBaddieActorArray->max_cnt = suBaddieActorArray->cnt + 5;
|
||||
suBaddieActorArray = (ActorArray *)realloc(suBaddieActorArray, sizeof(ActorArray) + suBaddieActorArray->max_cnt*sizeof(Actor));
|
||||
}
|
||||
|
||||
++suBaddieActorArray->cnt;
|
||||
suLastBaddie = &suBaddieActorArray->data[suBaddieActorArray->cnt - 1];
|
||||
|
||||
suLastBaddie->actor_info = actorInfo;
|
||||
suLastBaddie->unk10_25 = 0;
|
||||
suLastBaddie->unk10_18 = 0;
|
||||
suLastBaddie->state = actorInfo->startAnimation;
|
||||
suLastBaddie->position_x = (f32)position[0];
|
||||
suLastBaddie->position_y = (f32)position[1];
|
||||
suLastBaddie->position_z = (f32)position[2];
|
||||
suLastBaddie->unkF4_8 = 0;
|
||||
suLastBaddie->yaw = (f32) yaw;
|
||||
suLastBaddie->yaw_ideal = (f32) yaw;
|
||||
suLastBaddie->pitch = 0.0f;
|
||||
suLastBaddie->roll = 0.0f;
|
||||
suLastBaddie->unk6C = 0.0f;
|
||||
suLastBaddie->actor_specific_1_f = 0.0f;
|
||||
suLastBaddie->unk10_12 = 0;
|
||||
suLastBaddie->unk38_0 = 0;
|
||||
suLastBaddie->unk38_31 = 0;
|
||||
suLastBaddie->unk58_0 = 1;
|
||||
suLastBaddie->unk40 = 0;
|
||||
suLastBaddie->unk44_31 = 0;
|
||||
suLastBaddie->despawn_flag = 0;
|
||||
suLastBaddie->unk44_14 = -1;
|
||||
suLastBaddie->unk48 = 0.0f;
|
||||
suLastBaddie->unk4C = 100.0f;
|
||||
suLastBaddie->unk10_1 = 1;
|
||||
suLastBaddie->unkF4_30 = 0;
|
||||
suLastBaddie->unkF4_29 = 0;
|
||||
suLastBaddie->scale = 1.0f;
|
||||
suLastBaddie->unk124_7 = 0;
|
||||
suLastBaddie->unk124_6 = 1;
|
||||
suLastBaddie->modelCacheIndex = actorInfo->actorId;
|
||||
suLastBaddie->unk44_2 = func_80326C18();
|
||||
suLastBaddie->marker = marker_init(position, actorInfo->draw_func, (asset_getFlag(actorInfo->modelId) == 1) ? 0 : 1, actorInfo->markerId, (flags & 0x400) ? 1 : 0);
|
||||
suLastBaddie->marker->unk3E_0 = 1;
|
||||
suLastBaddie->unk138_28 = 1;
|
||||
suLastBaddie->unk10_3 = -1;
|
||||
suLastBaddie->unk10_4 = 0;
|
||||
suLastBaddie->unk10_8 = 0;
|
||||
suLastBaddie->unk10_7 = 0;
|
||||
suLastBaddie->unk10_6 = 0;
|
||||
suLastBaddie->unk54 = 0.0f;
|
||||
suLastBaddie->anctrl_asset_id = 0;
|
||||
suLastBaddie->unk5C = 0.0f;
|
||||
suLastBaddie->unkF4_31 = 0;
|
||||
suLastBaddie->unk138_30 = 0;
|
||||
suLastBaddie->unk138_3 = 0;
|
||||
suLastBaddie->unk38_21 = 0;
|
||||
suLastBaddie->unk38_13 = 0;
|
||||
suLastBaddie->unk78_22 = 0;
|
||||
suLastBaddie->unk78_31 = 0;
|
||||
suLastBaddie->unk74 = 0.0f;
|
||||
suLastBaddie->unk70 = 0.0f;
|
||||
suLastBaddie->unkF4_24 = 0;
|
||||
suLastBaddie->unk140 = 0.0f;
|
||||
suLastBaddie->unk144 = 0.0f;
|
||||
suLastBaddie->unk44_1 = 0;
|
||||
suLastBaddie->unk44_0 = 0;
|
||||
suLastBaddie->initialized = FALSE;
|
||||
suLastBaddie->volatile_initialized = FALSE;
|
||||
suLastBaddie->lifetime_value = 0.0f;
|
||||
suLastBaddie->is_bundle = FALSE;
|
||||
suLastBaddie->unk104 = NULL;
|
||||
suLastBaddie->unk100 = NULL;
|
||||
suLastBaddie->unk158[0] = NULL;
|
||||
suLastBaddie->unk158[1] = NULL;
|
||||
suLastBaddie->unk78_13 = 0;
|
||||
suLastBaddie->unk124_31 = 0;
|
||||
suLastBaddie->unkF4_20 = 0;
|
||||
suLastBaddie->sound_timer = 0.0f;
|
||||
func_8032FFD4(suLastBaddie->marker, suBaddieActorArray->cnt - 1);
|
||||
marker_setModelId(suLastBaddie->marker, actorInfo->modelId);
|
||||
marker_setActorUpdateFunc(suLastBaddie->marker, actorInfo->update_func);
|
||||
marker_setActorUpdate2Func(suLastBaddie->marker, actorInfo->update2_func);
|
||||
ml_vec3f_clear(suLastBaddie->unk1C);
|
||||
ml_vec3f_clear(suLastBaddie->velocity);
|
||||
ml_vec3f_clear(suLastBaddie->spawn_position);
|
||||
suLastBaddie->stored_anctrl_index = 0;
|
||||
suLastBaddie->unk58_2 = 1;
|
||||
suLastBaddie->stored_anctrl_playbackType_ = 0;
|
||||
suLastBaddie->stored_anctrl_forwards = 0;
|
||||
suLastBaddie->stored_anctrl_smoothTransistion = 0;
|
||||
suLastBaddie->stored_anctrl_duration = 0.0f;
|
||||
suLastBaddie->stored_anctrl_timer = 0.0f;
|
||||
suLastBaddie->unk138_19 = 0;
|
||||
suLastBaddie->stored_anctrl_subrangeMin = 0.0f;
|
||||
suLastBaddie->stored_anctrl_subrangeMax = 1.0f;
|
||||
suLastBaddie->unkF4_22 = 0;
|
||||
suLastBaddie->unk58_1 = 0;
|
||||
suLastBaddie->unk138_29 = 0;
|
||||
suLastBaddie->unk18 = actorInfo->animations;
|
||||
suLastBaddie->anctrl = NULL;
|
||||
suLastBaddie->stored_anctrl_timer = 0.0f;
|
||||
suLastBaddie->unk130 = 0;
|
||||
suLastBaddie->unk124_5 = 0;
|
||||
suLastBaddie->unk124_3 = 0;
|
||||
suLastBaddie->unk138_9 = 0;
|
||||
suLastBaddie->unk138_8 = 0;
|
||||
suLastBaddie->unk138_25 = 0;
|
||||
suLastBaddie->unk16C_3 = 0;
|
||||
suLastBaddie->unk16C_2 = 0;
|
||||
suLastBaddie->unk16C_1 = 0;
|
||||
suLastBaddie->unk16C_0 = 0;
|
||||
suLastBaddie->unk17C_31 = 0;
|
||||
suLastBaddie->unk14C[0] = NULL;
|
||||
suLastBaddie->unk14C[1] = NULL;
|
||||
suLastBaddie->unk138_27 = 0;
|
||||
suLastBaddie->has_met_before = FALSE;
|
||||
suLastBaddie->unk138_23 = 0;
|
||||
suLastBaddie->unk138_22 = 0;
|
||||
suLastBaddie->unk138_21 = 0;
|
||||
suLastBaddie->unk138_20 = 0;
|
||||
suLastBaddie->unk174 = 0.0f;
|
||||
suLastBaddie->unk178 = 0.0f;
|
||||
if( actorInfo->animations){
|
||||
sp54 = &suLastBaddie->unk18[suLastBaddie->state];
|
||||
if(sp54->index != 0){
|
||||
suLastBaddie->anctrl = anctrl_new(0);
|
||||
anctrl_reset(suLastBaddie->anctrl);
|
||||
anctrl_setIndex(suLastBaddie->anctrl, sp54->index);
|
||||
anctrl_setDuration(suLastBaddie->anctrl, sp54->duration);
|
||||
anctrl_start(suLastBaddie->anctrl, "subaddie.c", 0x4A5);
|
||||
}
|
||||
}//L80327BA8
|
||||
suLastBaddie->unk124_11 = 0;
|
||||
suLastBaddie->alpha_124_19 = 0xff;
|
||||
suLastBaddie->depth_mode = MODEL_RENDER_DEPTH_FULL;
|
||||
suLastBaddie->unk124_0 = suLastBaddie->unk138_31 = 1;
|
||||
for(i = 0; i < 0x10; i++){
|
||||
((s32 *)suLastBaddie->unk7C)[i] = 0;
|
||||
}
|
||||
for(i = 0; i < 0x0C; i++){
|
||||
((s32 *)suLastBaddie->unkBC)[i] = 0;
|
||||
}
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_0){
|
||||
suLastBaddie->unk10_25 = func_80306DDC(position) + 1;
|
||||
if(suLastBaddie->unk10_25 == 0){
|
||||
suLastBaddie->unk10_25 = 0;
|
||||
}else{
|
||||
sp44[0] = (f32)position[0];
|
||||
sp44[1] = (f32)position[1];
|
||||
sp44[2] = (f32)position[2];
|
||||
suLastBaddie->unk10_18 = func_80307258(sp44, suLastBaddie->unk10_25 - 1, 0) + 1;
|
||||
}
|
||||
}//L80327D30
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_2){
|
||||
suLastBaddie->unk10_1 = 0;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_3){
|
||||
suLastBaddie->unkF4_30 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_1){
|
||||
suLastBaddie->marker->unk44 = (struct5Bs*)1;
|
||||
}
|
||||
else if(flags & ACTOR_FLAG_UNKNOWN_6){
|
||||
suLastBaddie->marker->unk44 = func_8034A2C8();
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_12){
|
||||
func_8033F738(suLastBaddie->marker);
|
||||
func_8034BFF8(suLastBaddie->marker);
|
||||
}
|
||||
|
||||
suLastBaddie->unk148 = 0;
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_11){
|
||||
suLastBaddie->unk148 = skeletalAnim_new();
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_14){
|
||||
suLastBaddie->marker->unk50 = (s32)func_803406B0();
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_4){
|
||||
suLastBaddie->unk124_31 = -1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_7){
|
||||
suLastBaddie->unkF4_22 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_19){
|
||||
suLastBaddie->unk58_1 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_8){
|
||||
suLastBaddie->unk130 = func_803255FC;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_9){
|
||||
suLastBaddie->marker->unk40_21 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_15){
|
||||
suLastBaddie->marker->unk40_20 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_17){
|
||||
suLastBaddie->marker->unk40_22 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_22){
|
||||
suLastBaddie->marker->unk40_19 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_16){
|
||||
suLastBaddie->unk138_9 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_18){
|
||||
suLastBaddie->unk138_8 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_21){
|
||||
suLastBaddie->unk138_25 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_23){
|
||||
suLastBaddie->unk16C_3 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_24){
|
||||
suLastBaddie->unk16C_2 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_25){
|
||||
suLastBaddie->unk16C_1 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_26){
|
||||
suLastBaddie->unk17C_31 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_13){
|
||||
suLastBaddie->unk138_29 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_20){
|
||||
suLastBaddie->unk58_2 = 0;
|
||||
}
|
||||
|
||||
suLastBaddie->unk154 = 0x005e0000;
|
||||
suLastBaddie->marker->unk54 = (void (*)(struct actorMarker_s *, struct actorMarker_s *, u16 *))func_8032B5C0;
|
||||
|
||||
|
||||
for(i = 0; i < 3; ++i){
|
||||
suLastBaddie->unk164[i] = 0x63;
|
||||
}
|
||||
|
||||
suLastBaddie->unk170 = -10.0f;
|
||||
suLastBaddie->unk138_7 = 0;
|
||||
suLastBaddie->unk3C = flags;
|
||||
|
||||
// @recomp Allocate extension data for this actor and place it in padding.
|
||||
suLastBaddie->pad17C_30 = recomp_create_actor_data(actorInfo->actorId) & 0x7FFFFFFFU;
|
||||
|
||||
return suLastBaddie;
|
||||
}
|
||||
|
||||
void func_8032BB88(Actor *this, s32 arg1, s32 arg2);
|
||||
void func_8033E7CC(ActorMarker *arg0);
|
||||
void func_8034A2A8(struct5Bs *this);
|
||||
void func_8034BF54(ActorMarker *marker);
|
||||
void func_8033F784(ActorMarker *arg0);
|
||||
void func_80340690(Struct83s *self);
|
||||
void func_8032ACA8(Actor *arg0);
|
||||
|
||||
// @recomp Patched to destroy the extended actor data.
|
||||
RECOMP_PATCH void func_80325FE8(Actor *this) {
|
||||
ActorMarker *marker;
|
||||
u8 temp_v0;
|
||||
|
||||
// @recomp Destroy the extended actor data.
|
||||
recomp_destroy_actor_data(this->pad17C_30);
|
||||
|
||||
marker = this->marker;
|
||||
marker->id = 0;
|
||||
if (this->anctrl != NULL) {
|
||||
anctrl_free(this->anctrl);
|
||||
}
|
||||
temp_v0 = this->unk44_31;
|
||||
if (temp_v0 != 0) {
|
||||
sfxsource_freeSfxsourceByIndex(temp_v0);
|
||||
}
|
||||
this->anctrl = NULL;
|
||||
this->unk44_31 = 0;
|
||||
|
||||
if (this->unk138_7 != 0) {
|
||||
func_8032BB88(this, -1, 8000);
|
||||
this->unk138_7 = 0;
|
||||
}
|
||||
if (marker->actorFreeFunc != NULL) {
|
||||
marker->actorFreeFunc(this);
|
||||
marker->actorFreeFunc = NULL;
|
||||
}
|
||||
if ((s32)marker->unk44 < 0) {
|
||||
func_8033E7CC(marker);
|
||||
func_8034A2A8(marker->unk44);
|
||||
marker->unk44 = 0;
|
||||
}
|
||||
if (marker->unk4C != 0) {
|
||||
func_8034BF54(this->marker);
|
||||
marker->unk4C = 0;
|
||||
}
|
||||
if (marker->unk48 != 0) {
|
||||
func_8033F784(marker);
|
||||
marker->unk48 = 0;
|
||||
}
|
||||
if (this->unk148 != NULL) {
|
||||
skeletalAnim_free(this->unk148);
|
||||
this->unk148 = NULL;
|
||||
}
|
||||
if (marker->unk50 != 0) {
|
||||
func_80340690((Struct83s *)marker->unk50);
|
||||
marker->unk50 = 0;
|
||||
}
|
||||
func_8032ACA8(this);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT ActorExtensionId bkrecomp_extend_actor(enum actor_e type, u32 size) {
|
||||
return recomp_register_actor_extension(type, size);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT ActorExtensionId bkrecomp_extend_actor_all(u32 size) {
|
||||
return recomp_register_actor_extension_generic(size);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT void* bkrecomp_get_extended_actor_data(Actor* actor, ActorExtensionId extension) {
|
||||
return recomp_get_actor_data(actor->pad17C_30, extension, actor->actor_info->actorId);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT u32 bkrecomp_get_actor_spawn_index(Actor* actor) {
|
||||
return recomp_get_actor_spawn_index(actor->pad17C_30);
|
||||
}
|
||||
+19
-5
@@ -5,12 +5,26 @@
|
||||
#include "enums.h"
|
||||
#include "prop.h"
|
||||
|
||||
typedef u32 ActorExtensionId;
|
||||
typedef enum {
|
||||
EXTENSION_TYPE_MARKER,
|
||||
EXTENSION_TYPE_PROP,
|
||||
} ExtensionType;
|
||||
|
||||
ActorExtensionId bkrecomp_extend_actor(enum actor_e type, u32 size);
|
||||
ActorExtensionId bkrecomp_extend_actor_all(u32 size);
|
||||
// ActorMarkers
|
||||
typedef u32 MarkerExtensionId;
|
||||
|
||||
void* bkrecomp_get_extended_actor_data(Actor* actor, ActorExtensionId extension);
|
||||
u32 bkrecomp_get_actor_spawn_index(Actor* actor);
|
||||
MarkerExtensionId bkrecomp_extend_marker(enum marker_e type, u32 size);
|
||||
MarkerExtensionId bkrecomp_extend_marker_all(u32 size);
|
||||
|
||||
void* bkrecomp_get_extended_marker_data(ActorMarker* marker, MarkerExtensionId extension);
|
||||
u32 bkrecomp_get_marker_spawn_index(ActorMarker* marker);
|
||||
|
||||
// Props
|
||||
typedef u32 PropExtensionId;
|
||||
|
||||
PropExtensionId bkrecomp_extend_prop_all(u32 size);
|
||||
|
||||
void *bkrecomp_get_extended_prop_data(Cube* cube, Prop* prop, PropExtensionId extension_id);
|
||||
u32 bkrecomp_get_prop_spawn_index(Cube* cube, Prop* prop);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "core1/core1.h"
|
||||
|
||||
s32 cur_perspective_projection_transform_id = 0;
|
||||
s32 backup_perspective_projection_transform_id = 0;
|
||||
|
||||
s32 cur_ortho_projection_transform_id = 0;
|
||||
s32 backup_ortho_projection_transform_id = 0;
|
||||
|
||||
void reset_projection_ids() {
|
||||
cur_perspective_projection_transform_id = 0;
|
||||
cur_ortho_projection_transform_id = 0;
|
||||
}
|
||||
|
||||
extern f32 sViewportFOVy;
|
||||
extern f32 sViewportAspect;
|
||||
extern f32 sViewportNear;
|
||||
extern f32 sViewportFar;
|
||||
extern f32 sViewportLookVector[3];
|
||||
extern f32 sViewportPosition[3];
|
||||
extern f32 sViewportRotation[3];
|
||||
extern Vp sViewportStack[];
|
||||
extern MtxF sViewportMatrix;
|
||||
extern s32 sViewportStackIndex;
|
||||
|
||||
extern f32 sViewportBackupPosition[3];
|
||||
extern f32 sViewportBackupRotation[3];
|
||||
extern f32 sViewportBackupFrustumPlanes[4][4];
|
||||
extern f32 sViewportBackupLookVector[3];
|
||||
extern MtxF sViewportBackupMatrix;
|
||||
|
||||
// @recomp Patched to specify the view matrix for better transform interpolation and set up a matrix group for the new projection.
|
||||
RECOMP_PATCH void viewport_setRenderPerspectiveMatrix(Gfx **gfx, Mtx **mtx, f32 near, f32 far) {
|
||||
u16 perspNorm;
|
||||
|
||||
near = MAX(sViewportNear, near);
|
||||
far = MIN(sViewportFar, far);
|
||||
|
||||
if(*(u32*)OS_PHYSICAL_TO_K0(0x1D8) + 0x53D4FFF0) {
|
||||
near = 750.0f;
|
||||
far = 1250.0f;
|
||||
}
|
||||
|
||||
guPerspective(*mtx, &perspNorm, sViewportFOVy, sViewportAspect, near, far, 0.5f);
|
||||
gSPPerspNormalize((*gfx)++, perspNorm);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
||||
|
||||
guRotate(*mtx, -sViewportRotation[2], 0.0f, 0.0f, -1.0f);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
||||
|
||||
guRotate(*mtx, -sViewportRotation[0], 1.0f, 0.0f, 0.0f);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
||||
|
||||
guRotate(*mtx, -sViewportRotation[1], 0.0f, 1.0f, 0.0f);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
||||
|
||||
guTranslate(*mtx, 0.0f, 0.0f, 0.0f);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Create an isolated view matrix for the viewport translation and provide it as the view matrix to counteract the camera translation.
|
||||
MtxF* view = (MtxF*)*mtx;
|
||||
(*mtx)++;
|
||||
guTranslateF(view->m, sViewportPosition[0], sViewportPosition[1], sViewportPosition[2]);
|
||||
gEXSetViewMatrixFloat((*gfx)++, view->m);
|
||||
|
||||
// @recomp If a perspective projection transform ID is set, apply it as the projection matrix group. Otherwise, use auto as the projection matrix group.
|
||||
if (all_interpolation_skipped()) {
|
||||
gEXMatrixGroupNoInterpolate((*gfx)++, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE);
|
||||
}
|
||||
else if (cur_perspective_projection_transform_id != 0) {
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, cur_perspective_projection_transform_id, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE);
|
||||
}
|
||||
else {
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, G_EX_ID_AUTO, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
float identity_matrix[4][4] = {
|
||||
{ 1.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 1.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 1.0f }
|
||||
};
|
||||
|
||||
// @recomp Patched to set up an identity view matrix to prevent bleeding the perspective projection's view matrix.
|
||||
RECOMP_PATCH void viewport_setRenderViewportAndOrthoMatrix(Gfx **gfx, Mtx **mtx) {
|
||||
gSPViewport((*gfx)++, &sViewportStack[sViewportStackIndex]);
|
||||
|
||||
guOrtho(*mtx, -(2*(f32)gFramebufferWidth), (2*(f32)gFramebufferWidth), -(2*(f32)gFramebufferHeight), (2*(f32)gFramebufferHeight), 1.0f, 20.0f, 1.0f);
|
||||
gSPMatrix((*gfx)++, OS_K0_TO_PHYSICAL((*mtx)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
||||
|
||||
guTranslate(*mtx, 0.0f, 0.0f, 0.0f);
|
||||
gSPMatrix((*gfx)++, OS_K0_TO_PHYSICAL((*mtx)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Set an identity view matrix.
|
||||
gEXSetViewMatrixFloat((*gfx)++, identity_matrix);
|
||||
|
||||
// @recomp If an ortho projection transform ID is set, apply it as the projection matrix group. Otherwise, use auto as the projection matrix group.
|
||||
if (all_interpolation_skipped()) {
|
||||
gEXMatrixGroupNoInterpolate((*gfx)++, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE);
|
||||
}
|
||||
else if (cur_ortho_projection_transform_id != 0) {
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, cur_ortho_projection_transform_id, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE);
|
||||
}
|
||||
else {
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, G_EX_ID_AUTO, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to also back up the projection matrix transform ID and reset the current one.
|
||||
RECOMP_PATCH void viewport_backupState(void) {
|
||||
s32 i, j;
|
||||
|
||||
viewport_getPosition_vec3f(sViewportBackupPosition);
|
||||
viewport_getRotation_vec3f(sViewportBackupRotation);
|
||||
viewport_getFrustumPlanes(sViewportBackupFrustumPlanes[0], sViewportBackupFrustumPlanes[1], sViewportBackupFrustumPlanes[2], sViewportBackupFrustumPlanes[3]);
|
||||
viewport_getLookVector(sViewportBackupLookVector);
|
||||
|
||||
for(i = 0; i < 4; i++){
|
||||
for(j = 0; j < 4; j++){
|
||||
sViewportBackupMatrix.m[i][j] = sViewportMatrix.m[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Back up the projection transform IDs and reset them.
|
||||
backup_perspective_projection_transform_id = cur_perspective_projection_transform_id;
|
||||
cur_perspective_projection_transform_id = 0;
|
||||
backup_ortho_projection_transform_id = cur_ortho_projection_transform_id;
|
||||
cur_ortho_projection_transform_id = 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to also restore the backed up projection matrix transform ID.
|
||||
RECOMP_PATCH void viewport_restoreState(void) {
|
||||
s32 i, j;
|
||||
|
||||
viewport_setPosition_vec3f(sViewportBackupPosition);
|
||||
viewport_setRotation_vec3f(sViewportBackupRotation);
|
||||
viewport_setFrustumPlanes(sViewportBackupFrustumPlanes[0], sViewportBackupFrustumPlanes[1], sViewportBackupFrustumPlanes[2], sViewportBackupFrustumPlanes[3]);
|
||||
ml_vec3f_copy(sViewportLookVector, sViewportBackupLookVector);
|
||||
|
||||
for(i = 0; i < 4; i++){
|
||||
for(j = 0; j < 4; j++){
|
||||
sViewportMatrix.m[i][j] = sViewportBackupMatrix.m[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Restore the backed up projection transform IDs.
|
||||
cur_perspective_projection_transform_id = backup_perspective_projection_transform_id;
|
||||
cur_ortho_projection_transform_id = backup_ortho_projection_transform_id;
|
||||
}
|
||||
@@ -1,5 +1,37 @@
|
||||
#include "patches.h"
|
||||
#include "core1/ml.h"
|
||||
#include "core1/mlmtx.h"
|
||||
|
||||
extern f32 sViewportPosition[3];
|
||||
extern f32 sViewportFrustumPlanes[4][4];
|
||||
|
||||
int frustum_checks_enabled = TRUE;
|
||||
void set_frustum_checks_enabled(int enabled) {
|
||||
frustum_checks_enabled = enabled;
|
||||
}
|
||||
|
||||
RECOMP_PATCH bool viewport_isBoundingBoxInFrustum(f32 arg0[3], f32 arg1[3]) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// @recomp Patched to allow globally disabling frustum checks.
|
||||
RECOMP_PATCH bool viewport_func_8024DB50(f32 pos[3], f32 distance) {
|
||||
// @recomp Return true if frustum checks are disabled (always pass the frustum check).
|
||||
if (!frustum_checks_enabled) {
|
||||
return TRUE;
|
||||
}
|
||||
f32 delta[3];
|
||||
s32 i;
|
||||
|
||||
delta[0] = pos[0] - sViewportPosition[0];
|
||||
delta[1] = pos[1] - sViewportPosition[1];
|
||||
delta[2] = pos[2] - sViewportPosition[2];
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
if(distance <= ml_vec3f_dot_product(delta, sViewportFrustumPlanes[i])) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -121,4 +121,7 @@ RECOMP_PATCH void game_draw(s32 arg0){
|
||||
scissorBox_setDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// Allow interpolation for the next frame.
|
||||
set_all_interpolation_skipped(FALSE);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "bk_api.h"
|
||||
#include "misc_funcs.h"
|
||||
|
||||
@@ -16,6 +17,8 @@ RECOMP_PATCH void mainThread_entry(void *arg) {
|
||||
sns_write_payload_over_heap();
|
||||
|
||||
while (1) {
|
||||
// @recomp Reset the tracked projection IDs.
|
||||
reset_projection_ids();
|
||||
mainLoop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
#include "core2/anctrl.h"
|
||||
#include "core2/modelRender.h"
|
||||
|
||||
s32 func_80320708(void);
|
||||
s32 levelSpecificFlags_validateCRC2(void);
|
||||
s32 dummy_func_80320248(void);
|
||||
enum asset_e mapModel_getOpaModelId(void);
|
||||
enum map_e map_get(void);
|
||||
s32 mapSpecificFlags_get(s32 i);
|
||||
s32 levelSpecificFlags_get(s32 i);
|
||||
u32 jiggyscore_isCollected(enum jiggy_e);
|
||||
enum bsgroup_e player_movementGroup(void);
|
||||
bool jigsawPicture_isJigsawPictureComplete(s32 world);
|
||||
bool fileProgressFlag_get(enum file_progress_e index);
|
||||
void modelRender_setAnimatedTexturesCacheId(s32 arg0);
|
||||
bool mapModel_has_xlu_bin(void);
|
||||
void func_802F7BC0(Gfx **, Mtx **, Vtx **);
|
||||
|
||||
typedef struct {
|
||||
s16 map_id; //enum map_e
|
||||
s16 opa_model_id; //enum asset_e level_model_id
|
||||
s16 xlu_model_id; //enum asset_e level2_model_id
|
||||
s16 unk6[3]; // min bounds (for cubes?)
|
||||
s16 unkC[3]; // max bounds (for cubes?)
|
||||
// u8 pad12[0x2];
|
||||
f32 scale;
|
||||
}MapModelDescription;
|
||||
|
||||
extern struct {
|
||||
s32 unk0; // Changed from void* in the decomp
|
||||
s32 unk4; // Changed from void* in the decomp
|
||||
BKCollisionList *collision_opa;
|
||||
BKCollisionList *collision_xlu;
|
||||
BKModel *model_opa;
|
||||
BKModel *model_xlu;
|
||||
BKModelBin *model_bin_opa;
|
||||
BKModelBin *model_bin_xlu;
|
||||
s32 unk20;
|
||||
struct5Bs *unk24;
|
||||
MapModelDescription *description;
|
||||
u8 env_red;
|
||||
u8 env_green;
|
||||
u8 env_blue;
|
||||
f32 scale;
|
||||
}mapModel;
|
||||
|
||||
// @recomp Patched to set the transform ID when drawing the map's opaque model.
|
||||
RECOMP_PATCH void mapModel_opa_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
s32 temp_a0;
|
||||
|
||||
if (func_80320708() && levelSpecificFlags_validateCRC2() && dummy_func_80320248()) {
|
||||
if (mapModel_getOpaModelId() == ASSET_14CF_MODEL_SM_SPIRAL_MOUNTAIN_OPA) {
|
||||
func_8033A45C(1, 0);
|
||||
func_8033A45C(2, 1);
|
||||
}
|
||||
switch (map_get()) { /* irregular */
|
||||
case MAP_88_CS_SPIRAL_MOUNTAIN_6:
|
||||
if (mapSpecificFlags_get(0) != 0) {
|
||||
func_8033A45C(1, 1);
|
||||
func_8033A45C(2, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case MAP_12_GV_GOBIS_VALLEY:
|
||||
func_8033A45C(1, levelSpecificFlags_get(LEVEL_FLAG_6_GV_UNKNOWN) ? 1 : 0);
|
||||
func_8033A45C(2, jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID) ? 0 : 1);
|
||||
func_8033A45C(5, jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID) ? 1 : 0);
|
||||
break;
|
||||
|
||||
case MAP_14_GV_SANDYBUTTS_MAZE:
|
||||
func_8033A45C(5, (player_movementGroup() == BSGROUP_4_LOOK) ? 1 : 0);
|
||||
break;
|
||||
|
||||
case MAP_E_MM_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 1);
|
||||
func_8033A45C(5, 1);
|
||||
break;
|
||||
|
||||
case MAP_47_BGS_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 2);
|
||||
func_8033A45C(5, 2);
|
||||
break;
|
||||
|
||||
case MAP_48_FP_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 3);
|
||||
func_8033A45C(5, 3);
|
||||
break;
|
||||
|
||||
case MAP_30_MMM_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 4);
|
||||
func_8033A45C(5, 4);
|
||||
break;
|
||||
|
||||
case MAP_4A_CCW_SPRING_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 5);
|
||||
func_8033A45C(5, 5);
|
||||
break;
|
||||
case MAP_4B_CCW_SUMMER_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 6);
|
||||
func_8033A45C(5, 6);
|
||||
break;
|
||||
case MAP_4C_CCW_AUTUMN_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 7);
|
||||
func_8033A45C(5, 7);
|
||||
break;
|
||||
case MAP_4D_CCW_WINTER_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 8);
|
||||
func_8033A45C(5, 8);
|
||||
break;
|
||||
case MAP_5E_CCW_SPRING_NABNUTS_HOUSE:
|
||||
case MAP_5F_CCW_SUMMER_NABNUTS_HOUSE:
|
||||
case MAP_60_CCW_AUTUMN_NABNUTS_HOUSE:
|
||||
func_8033A45C(1, 1);
|
||||
func_8033A45C(2, 0);
|
||||
break;
|
||||
case MAP_61_CCW_WINTER_NABNUTS_HOUSE:
|
||||
func_8033A45C(1, 0);
|
||||
func_8033A45C(2, 1);
|
||||
break;
|
||||
case MAP_1D_MMM_CELLAR:
|
||||
func_8033A45C(1, actorArray_findActorFromActorId(0x191) ? 0 : 1);
|
||||
break;
|
||||
case MAP_7C_CS_INTRO_BANJOS_HOUSE_1:
|
||||
case MAP_89_CS_INTRO_BANJOS_HOUSE_2:
|
||||
case MAP_8A_CS_INTRO_BANJOS_HOUSE_3:
|
||||
case MAP_8C_SM_BANJOS_HOUSE:
|
||||
case MAP_91_FILE_SELECT:
|
||||
func_8033A45C(5, 1);
|
||||
break;
|
||||
case MAP_7B_CS_INTRO_GL_DINGPOT_1:
|
||||
case MAP_81_CS_INTRO_GL_DINGPOT_2:
|
||||
func_8033A45C(4, 0);
|
||||
func_8033A45C(5, 0);
|
||||
func_8033A45C(6, 0);
|
||||
break;
|
||||
case MAP_82_CS_ENTERING_GL_MACHINE_ROOM:
|
||||
case MAP_83_CS_GAME_OVER_MACHINE_ROOM:
|
||||
case MAP_84_CS_UNUSED_MACHINE_ROOM:
|
||||
func_8033A45C(4, 1);
|
||||
func_8033A45C(5, 1);
|
||||
func_8033A45C(6, 1);
|
||||
break;
|
||||
case MAP_93_GL_DINGPOT:
|
||||
func_8033A45C(4, 1);
|
||||
func_8033A45C(5, 1);
|
||||
func_8033A45C(6, (jigsawPicture_isJigsawPictureComplete(0xA) || fileProgressFlag_get(FILEPROG_E2_DOOR_OF_GRUNTY_OPEN) || volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE)));
|
||||
break;
|
||||
}
|
||||
func_8033A450(mapModel.unk24);
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL);
|
||||
temp_a0 = mapModel.unk0;
|
||||
if (temp_a0 != 0) {
|
||||
modelRender_setAnimatedTexturesCacheId(temp_a0);
|
||||
}
|
||||
modelRender_setEnvColor(mapModel.env_red, mapModel.env_green, mapModel.env_blue, 0xFF);
|
||||
|
||||
// @recomp Set the map opaque model transform id.
|
||||
cur_drawn_model_is_map = TRUE;
|
||||
cur_drawn_model_transform_id = MAP_MODEL_OPA_TRANSFORM_ID_START;
|
||||
|
||||
modelRender_draw(gfx, mtx, NULL, NULL, mapModel.description->scale, NULL, mapModel.model_bin_opa);
|
||||
|
||||
// @recomp Clear the current model transform id after drawing.
|
||||
cur_drawn_model_is_map = FALSE;
|
||||
cur_drawn_model_transform_id = 0;
|
||||
|
||||
if (!mapModel_has_xlu_bin()) {
|
||||
func_802F7BC0(gfx, mtx, vtx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to set the transform ID when drawing the map's translucent model.
|
||||
RECOMP_PATCH void mapModel_xlu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
s32 temp_a0;
|
||||
|
||||
if (mapModel.model_bin_xlu != NULL) {
|
||||
if (map_get() == MAP_1D_MMM_CELLAR) {
|
||||
func_8033A45C(1, (actorArray_findActorFromActorId(0x191) != NULL) ? 0 : 1);
|
||||
}
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE);
|
||||
temp_a0 = mapModel.unk4;
|
||||
if (temp_a0 != 0) {
|
||||
modelRender_setAnimatedTexturesCacheId(temp_a0);
|
||||
}
|
||||
modelRender_setEnvColor(mapModel.env_red, mapModel.env_green, mapModel.env_blue, 0xFF);
|
||||
|
||||
// @recomp Set the map opaque model transform id.
|
||||
cur_drawn_model_is_map = TRUE;
|
||||
cur_drawn_model_transform_id = MAP_MODEL_XLU_TRANSFORM_ID_START;
|
||||
|
||||
modelRender_draw(gfx, mtx, NULL, NULL, mapModel.description->scale, NULL, mapModel.model_bin_xlu);
|
||||
|
||||
// @recomp Clear the current model transform id after drawing.
|
||||
cur_drawn_model_is_map = FALSE;
|
||||
cur_drawn_model_transform_id = 0;
|
||||
|
||||
func_802F7BC0(gfx, mtx, vtx);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
#include "patches.h"
|
||||
#include "prop.h"
|
||||
#include "actor.h"
|
||||
#include "functions.h"
|
||||
#include "object_extension_funcs.h"
|
||||
#include "bk_api.h"
|
||||
|
||||
// Array of handles for ActorMarker instances.
|
||||
// Normally the game only has at most 0xE0 ActorMarker instances, but this is larger to account for mods increasing
|
||||
// the ActorMarker count.
|
||||
u32 marker_handles[0x1000];
|
||||
|
||||
extern ActorMarker *D_8036E7C8;
|
||||
extern u8 D_80383428[0x1C];
|
||||
void func_8032F3D4(s32 arg0[3], ActorMarker *marker, s32 arg2);
|
||||
ActorMarker * func_80332A60(void);
|
||||
|
||||
// @recomp Patched to reset all extended marker data and skip interpolation for the next frame.
|
||||
RECOMP_PATCH void func_803329AC(void){
|
||||
s32 i;
|
||||
|
||||
D_8036E7C8 = (ActorMarker *)malloc(0xE0*sizeof(ActorMarker));
|
||||
|
||||
for( i = 0; i < 0x1C; i++){
|
||||
D_80383428[i] = 0;
|
||||
}
|
||||
|
||||
for(i =0; i<0xE0; i++){
|
||||
D_8036E7C8[i].unk5C = 0;
|
||||
}
|
||||
|
||||
// @recomp Reset all actor data and skip interpolation for the next frame.
|
||||
// Interpolation is skipped as the next frame will potentially reuse IDs from the previous frame,
|
||||
// as the marker ID tracking gets reset here.
|
||||
recomp_clear_all_object_data(EXTENSION_TYPE_MARKER);
|
||||
set_all_interpolation_skipped(TRUE);
|
||||
}
|
||||
|
||||
// @recomp Patched to create extension data for the marker.
|
||||
RECOMP_PATCH ActorMarker * marker_init(s32 *pos, MarkerDrawFunc draw_func, int arg2, int marker_id, int arg4){
|
||||
ActorMarker * marker = func_80332A60();
|
||||
marker->propPtr = NULL;
|
||||
marker->cubePtr = NULL;
|
||||
marker->drawFunc = draw_func;
|
||||
marker->id = marker_id;
|
||||
marker->unk40_23 = arg4;
|
||||
func_8032F3D4(pos, marker, arg2);
|
||||
marker->actrArrayIdx = 0;
|
||||
marker->unk14_10 = 0;
|
||||
marker->modelId = 0;
|
||||
marker->isBanjoOnTop = 0;
|
||||
marker->unk14_22 = 0;
|
||||
marker->unk14_21 = 0;
|
||||
marker->yaw = 0;
|
||||
marker->pitch = 0;
|
||||
marker->roll = 0;
|
||||
marker->unk2C_2 = 0;
|
||||
marker->unk2C_1 = 0;
|
||||
marker->collidable = TRUE;
|
||||
marker->unk3E_0 = 0;
|
||||
marker->unk40_22 = 0;
|
||||
marker->unk40_19 = 0;
|
||||
marker->unk40_21 = 0;
|
||||
marker->collisionFunc = NULL;
|
||||
marker->collision2Func = NULL;
|
||||
marker->dieFunc = NULL;
|
||||
marker->unk54 = NULL;
|
||||
marker->unk58 = 0;
|
||||
marker->unk18 = 0;
|
||||
marker->actorUpdateFunc = NULL;
|
||||
marker->actorFreeFunc = NULL;
|
||||
marker->commonParticleIndex = 0;
|
||||
marker->actorUpdate2Func = NULL;
|
||||
marker->unk38[0] = 0;
|
||||
marker->unk38[1] = 0;
|
||||
marker->unk38[2] = 0;
|
||||
marker->unk44 = 0;
|
||||
marker->unk20 = 0;
|
||||
marker->unk50 = 0;
|
||||
marker->unk48 = 0;
|
||||
marker->unk4C = 0;
|
||||
marker->unk40_20 = 0;
|
||||
marker->unk40_31 = 0;
|
||||
|
||||
// @recomp Set the marker's handle.
|
||||
u32 index = marker - D_8036E7C8;
|
||||
marker_handles[index] = recomp_create_object_data(EXTENSION_TYPE_MARKER, marker_id);
|
||||
|
||||
return marker;
|
||||
}
|
||||
|
||||
// @recomp Patched to destroy the marker's extended data.
|
||||
RECOMP_PATCH void func_80332B2C(ActorMarker * arg0){
|
||||
static s32 D_8036E804[8] = {(u8)~(1 << 7), (u8)~(1 << 6), (u8)~(1 << 5), (u8)~(1 << 4), (u8)~(1 << 3), (u8)~(1 << 2), (u8)~(1 << 1), (u8)~(1 << 0)};
|
||||
|
||||
s32 index = (arg0 - D_8036E7C8);
|
||||
arg0->unk5C = 0;
|
||||
D_80383428[index >> 3] = D_80383428[index >> 3] & D_8036E804[index & 7];
|
||||
|
||||
// @recomp Delete the handle for this marker.
|
||||
recomp_destroy_object_data(EXTENSION_TYPE_MARKER, marker_handles[index]);
|
||||
marker_handles[index] = 0;
|
||||
}
|
||||
|
||||
RECOMP_EXPORT MarkerExtensionId bkrecomp_extend_marker(enum marker_e type, u32 size) {
|
||||
return recomp_register_object_extension(EXTENSION_TYPE_MARKER, type, size);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT MarkerExtensionId bkrecomp_extend_marker_all(u32 size) {
|
||||
return recomp_register_object_extension_generic(EXTENSION_TYPE_MARKER, size);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT void* bkrecomp_get_extended_marker_data(ActorMarker* marker, MarkerExtensionId extension) {
|
||||
s32 index = (marker - D_8036E7C8);
|
||||
u32 handle = marker_handles[index];
|
||||
return recomp_get_object_data(EXTENSION_TYPE_MARKER, marker->id, handle, extension);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT u32 bkrecomp_get_marker_spawn_index(ActorMarker* marker) {
|
||||
s32 index = (marker - D_8036E7C8);
|
||||
u32 handle = marker_handles[index];
|
||||
return recomp_get_object_spawn_index(EXTENSION_TYPE_MARKER, handle);
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "patches.h"
|
||||
#include "bk_api.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
|
||||
extern u8 D_8037BFB8;
|
||||
extern s32 D_8036E7B0;
|
||||
|
||||
void eggShatter_draw(Gfx **gPtr, Mtx **mPtr, Vtx **vPtr);
|
||||
void baModel_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void func_8033A28C(bool arg0);
|
||||
void func_8033A244(f32);
|
||||
void func_8033A280(f32);
|
||||
|
||||
// @recomp Patched to set the current transform ID to banjo's when drawing the player.
|
||||
RECOMP_PATCH void player_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
if (D_8037BFB8) {
|
||||
eggShatter_draw(gfx, mtx, vtx);
|
||||
|
||||
// @recomp Set the current transform ID to banjo's.
|
||||
u32 prev_transform_id = cur_drawn_model_transform_id;
|
||||
cur_drawn_model_transform_id = BANJO_TRANSFORM_ID_START;
|
||||
|
||||
baModel_draw(gfx, mtx, vtx);
|
||||
|
||||
// @recomp Reset the current transform ID.
|
||||
cur_drawn_model_transform_id = prev_transform_id;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to set the actor being drawn before the actor's draw func is called.
|
||||
RECOMP_PATCH void __marker_draw(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
Actor *actor;
|
||||
u32 draw_dist;
|
||||
f32 draw_dist_f;
|
||||
f32 percentage;
|
||||
|
||||
// @recomp Calculate the current drawn marker's transform ID.
|
||||
s32 cur_drawn_marker_spawn_index = bkrecomp_get_marker_spawn_index(this);
|
||||
u32 prev_transform_id = cur_drawn_model_transform_id;
|
||||
u32 transform_id = MARKER_TRANSFORM_ID_START + cur_drawn_marker_spawn_index * MARKER_TRANSFORM_ID_COUNT;
|
||||
if(!this->unk3E_0){
|
||||
// @recomp Set the current drawn marker's transform ID.
|
||||
cur_drawn_model_transform_id = transform_id;
|
||||
this->drawFunc(this, gfx, mtx, vtx);
|
||||
// @recomp Clear the current transform ID after drawing.
|
||||
cur_drawn_model_transform_id = prev_transform_id;
|
||||
return;
|
||||
}
|
||||
actor = marker_getActor(this);
|
||||
func_8033A28C(actor->unk58_2);
|
||||
if( actor->unk58_2 && !this->unk40_23 && !this->unk40_21 && !D_8036E7B0){
|
||||
func_8033A244(3700.0f);
|
||||
}
|
||||
|
||||
if(actor->unk124_7 && !actor->despawn_flag && actor->unk58_0){
|
||||
draw_dist = actor->actor_info->draw_distance;
|
||||
if(draw_dist != 0){
|
||||
percentage = (f32)draw_dist*(1/(f64)0x400);
|
||||
}
|
||||
else if(this->unk40_21){
|
||||
percentage = 2.0f;
|
||||
}
|
||||
else{
|
||||
percentage = 1.0f;
|
||||
}
|
||||
func_8033A280(percentage);
|
||||
// @recomp Set the current drawn marker's transform ID.
|
||||
cur_drawn_model_transform_id = transform_id;
|
||||
this->drawFunc(this, gfx, mtx, vtx);
|
||||
// @recomp Set the current drawn marker to null after drawing.
|
||||
cur_drawn_model_transform_id = prev_transform_id;
|
||||
}//L8032D300
|
||||
func_8033A244(30000.0f);
|
||||
func_8033A280(1.0f);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#ifndef __MEM_FUNCS_H__
|
||||
#define __MEM_FUNCS_H__
|
||||
|
||||
#include "patch_helpers.h"
|
||||
|
||||
DECLARE_FUNC(u32, recomp_register_actor_extension, u32 actor_type, u32 size);
|
||||
DECLARE_FUNC(u32, recomp_register_actor_extension_generic, u32 size);
|
||||
DECLARE_FUNC(void, recomp_clear_all_actor_data);
|
||||
DECLARE_FUNC(u32, recomp_create_actor_data, u32 actor_type);
|
||||
DECLARE_FUNC(void, recomp_destroy_actor_data, u32 actor_handle);
|
||||
DECLARE_FUNC(void*, recomp_get_actor_data, u32 actor_handle, u32 extension_handle, u32 actor_type);
|
||||
DECLARE_FUNC(u32, recomp_get_actor_spawn_index, u32 actor_handle);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef __MEM_FUNCS_H__
|
||||
#define __MEM_FUNCS_H__
|
||||
|
||||
#include "patch_helpers.h"
|
||||
|
||||
DECLARE_FUNC(u32, recomp_register_object_extension, u32 type_index, u32 subtype_index, u32 size);
|
||||
DECLARE_FUNC(u32, recomp_register_object_extension_generic, u32 type_index, u32 size);
|
||||
DECLARE_FUNC(void, recomp_clear_all_object_data, u32 type_index);
|
||||
DECLARE_FUNC(u32, recomp_create_object_data, u32 type_index, u32 subtype_index);
|
||||
DECLARE_FUNC(void, recomp_destroy_object_data, u32 type_index, u32 object_handle);
|
||||
DECLARE_FUNC(void*, recomp_get_object_data, u32 type_index, u32 subtype_index, u32 object_handle, u32 extension_handle);
|
||||
DECLARE_FUNC(u32, recomp_get_object_spawn_index, u32 type_index, u32 object_handle);
|
||||
|
||||
#endif
|
||||
@@ -54,37 +54,8 @@ MAKE_OVERLAYS()
|
||||
#define OVERLAY_END(ovl) boot_##ovl##_rzip_ROM_END
|
||||
|
||||
// @recomp Patched to load overlays, prefixed with boot_ to account for the decomp build system.
|
||||
RECOMP_PATCH void boot_overlay_table_init(void) {
|
||||
gOverlayTable[ 0].start = OVERLAY_START(core2);
|
||||
gOverlayTable[ 0].end = OVERLAY_END(core2);
|
||||
gOverlayTable[ 1].start = OVERLAY_START(emptyLvl);
|
||||
gOverlayTable[ 1].end = OVERLAY_END(emptyLvl);
|
||||
gOverlayTable[ 2].start = OVERLAY_START(CC);
|
||||
gOverlayTable[ 2].end = OVERLAY_END(CC);
|
||||
gOverlayTable[ 3].start = OVERLAY_START(MMM);
|
||||
gOverlayTable[ 3].end = OVERLAY_END(MMM);
|
||||
gOverlayTable[ 4].start = OVERLAY_START(GV);
|
||||
gOverlayTable[ 4].end = OVERLAY_END(GV);
|
||||
gOverlayTable[ 5].start = OVERLAY_START(TTC);
|
||||
gOverlayTable[ 5].end = OVERLAY_END(TTC);
|
||||
gOverlayTable[ 6].start = OVERLAY_START(MM);
|
||||
gOverlayTable[ 6].end = OVERLAY_END(MM);
|
||||
gOverlayTable[ 7].start = OVERLAY_START(BGS);
|
||||
gOverlayTable[ 7].end = OVERLAY_END(BGS);
|
||||
gOverlayTable[ 8].start = OVERLAY_START(RBB);
|
||||
gOverlayTable[ 8].end = OVERLAY_END(RBB);
|
||||
gOverlayTable[ 9].start = OVERLAY_START(FP);
|
||||
gOverlayTable[ 9].end = OVERLAY_END(FP);
|
||||
gOverlayTable[10].start = OVERLAY_START(CCW);
|
||||
gOverlayTable[10].end = OVERLAY_END(CCW);
|
||||
gOverlayTable[11].start = OVERLAY_START(SM);
|
||||
gOverlayTable[11].end = OVERLAY_END(SM);
|
||||
gOverlayTable[12].start = OVERLAY_START(cutscenes);
|
||||
gOverlayTable[12].end = OVERLAY_END(cutscenes);
|
||||
gOverlayTable[13].start = OVERLAY_START(lair);
|
||||
gOverlayTable[13].end = OVERLAY_END(lair);
|
||||
gOverlayTable[14].start = OVERLAY_START(fight);
|
||||
gOverlayTable[14].end = OVERLAY_END(fight);
|
||||
RECOMP_PATCH void boot___osInitialize_common(void) {
|
||||
// Nothing of the original function needs to happen, so the body can be empty besides the overlay load.
|
||||
|
||||
// @recomp Load core1.
|
||||
recomp_load_overlays_by_rom((u32)core1_ROM_START, core1_VRAM, core1_ROM_END - core1_ROM_START);
|
||||
@@ -113,7 +84,7 @@ RECOMP_PATCH void overlay_load(
|
||||
u32 uncompressed_rom_start = rom_start;
|
||||
u32 uncompressed_rom_size = rom_end - rom_start;
|
||||
u32 overlay_vram_start = ram_start;
|
||||
void* sp34;
|
||||
u8* sp34;
|
||||
u32 sp30;
|
||||
u32 sp2C;
|
||||
u32 *tmp;
|
||||
@@ -137,10 +108,10 @@ RECOMP_PATCH void overlay_load(
|
||||
sp34 = &D_8002D500;
|
||||
}
|
||||
piMgr_read(sp34, rom_start, rom_end - rom_start);
|
||||
rarezip_uncompress(&sp34, &ram_start);
|
||||
rarezip_uncompress(&sp34, (u8**)&ram_start);
|
||||
sp2C = D_8027BF2C;
|
||||
sp30 = D_8027BF30;
|
||||
rarezip_uncompress(&sp34, &ram_start);
|
||||
rarezip_uncompress(&sp34, (u8**)&ram_start);
|
||||
|
||||
if(bss_start){
|
||||
bzero((void*)bss_start, bss_end - bss_start);
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
#include "rand.h"
|
||||
#include "core1/ml.h"
|
||||
#include "core2/anctrl.h"
|
||||
#include "core2/modelRender.h"
|
||||
#include "core2/particle.h"
|
||||
#include "core2/timedfunc.h"
|
||||
|
||||
// 2 bytes of padding between alpha and particleAccerationRange_4C. Must be at least 16-bit to fit the full range of PARTICLE_EMITTER_MAX_ID.
|
||||
#define PARTICLE_EMITTER_ID(x) (*(u16*)&((x)->pad4A))
|
||||
|
||||
// 2 bytes of padding between unk104 and unk108. Must be at least 16-bit to fit the full range of PARTICLE_EMITTER_TRANSFORM_ID_COUNT.
|
||||
#define PARTICLE_EMITTER_SPAWN_COUNT(x) (*(u16*)&((x)->pad106))
|
||||
|
||||
// 2 bytes of padding after unk5C (skipping 1 byte for alignment). Must be at least as bit as the emitter spawn count field.
|
||||
#define PARTICLE_ID(x) (*(u16*)&(&(x)->unk5C)[2])
|
||||
|
||||
u32 particle_emitter_spawn_count = 0;
|
||||
|
||||
extern ParticleEmitter **partEmitMgr;
|
||||
extern s32 partEmitMgrLength;
|
||||
|
||||
typedef struct particle{
|
||||
f32 acceleration[3];
|
||||
f32 fade;
|
||||
f32 frame; //frame
|
||||
f32 framerate; //framerate
|
||||
f32 position[3];
|
||||
f32 rotation[3];
|
||||
f32 scale; //size
|
||||
f32 initialSize_34; //initial_size
|
||||
f32 finalSizeDiff; //delta_size
|
||||
f32 angluar_velocity[3];
|
||||
f32 age_48;
|
||||
f32 lifetime_4C;
|
||||
f32 velocity_50[3];
|
||||
u8 unk5C;
|
||||
//u8 pad5D[3];
|
||||
} Particle;
|
||||
|
||||
extern Gfx D_80368978[];
|
||||
extern Gfx D_80368940[];
|
||||
|
||||
void __particleEmitter_drawOnPass(ParticleEmitter *this, Gfx **gfx, Mtx **mtx, Vtx **vtx, u32 draw_pass);
|
||||
void func_803382E4(s32);
|
||||
void func_80338338(s32, s32, s32);
|
||||
void func_803382B4(s32 arg0, s32 arg1, s32 arg2, s32 arg3);
|
||||
void func_80338370(void);
|
||||
void func_80335D30(Gfx **);
|
||||
void func_802EED1C(ParticleEmitter *this, f32 age, f32 arg2[3]);
|
||||
void func_80344C2C(bool arg0);
|
||||
void func_80344720(BKSpriteDisplayData *arg0, s32 frame, bool mirrored, f32 position[3], f32 rotation[3], f32 scale[3], Gfx **gfx, Mtx **mtx);
|
||||
void func_80344424(BKSpriteDisplayData *arg0, s32 frame, bool mirrored, f32 position[3], f32 scale[3], f32 rotation, Gfx **gfx, Mtx **mtx);
|
||||
void func_8033687C(Gfx **);
|
||||
|
||||
// @recomp Patched to tag particles as they're drawn.
|
||||
RECOMP_PATCH void __particleEmitter_drawOnPass(ParticleEmitter *this, Gfx **gfx, Mtx **mtx, Vtx **vtx, u32 draw_pass){
|
||||
f32 position[3];
|
||||
f32 flat_rotation[3];
|
||||
f32 scale[3];
|
||||
Particle *iPtr;
|
||||
|
||||
// @recomp Get the particle emitter's ID.
|
||||
u32 cur_particle_emitter_index = PARTICLE_EMITTER_ID(this);
|
||||
|
||||
if(reinterpret_cast(u32, draw_pass) != (this->draw_mode & 0x4) != 0)
|
||||
return;
|
||||
|
||||
if(this->model_20 != NULL){
|
||||
for(iPtr = this->pList_start_124; iPtr < this->pList_end_128; iPtr++){
|
||||
position[0] = iPtr->position[0] + this->unk4[0];
|
||||
position[1] = iPtr->position[1] + this->unk4[1];
|
||||
position[2] = iPtr->position[2] + this->unk4[2];
|
||||
if( 0.0f != this->fade_in || 1.0 != this->fade_out || this->alpha != 0xff ){
|
||||
modelRender_setAlpha((s32) (iPtr->fade*this->alpha));
|
||||
}//L802EEF5C
|
||||
modelRender_setDepthMode((this->draw_mode & PART_EMIT_NO_DEPTH)? MODEL_RENDER_DEPTH_NONE : MODEL_RENDER_DEPTH_FULL);
|
||||
// @recomp Get the particle's ID. Restrict it to the model particle emitter ID count to account for the smaller number of base transform IDs for
|
||||
// model particle emitters.
|
||||
u32 particle_id = PARTICLE_ID(iPtr) % PARTICLE_EMITTER_MODEL_ID_COUNT;
|
||||
// @recomp Set the current model transform ID. Divide the total per-emitter transform ID count by the per-model transform ID count to get the
|
||||
// base transform ID for the current model particle.
|
||||
cur_drawn_model_transform_id =
|
||||
PARTICLE_TRANSFORM_ID_START +
|
||||
PARTICLE_EMITTER_TRANSFORM_ID_COUNT * cur_particle_emitter_index +
|
||||
particle_id * PARTICLE_EMITTER_MODEL_ID_COUNT;
|
||||
modelRender_draw(gfx, mtx, position, iPtr->rotation, iPtr->scale, NULL, this->model_20);
|
||||
// @recomp Reset the current model transform ID.
|
||||
cur_drawn_model_transform_id = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(this->unk34){//L802EEFC4
|
||||
if( this->rgb[0] != 0xff
|
||||
|| this->rgb[1] != 0xff
|
||||
|| this->rgb[2] != 0xff
|
||||
|| this->alpha != 0xff
|
||||
){
|
||||
func_803382E4((this->draw_mode & PART_EMIT_NO_DEPTH)? 9: 0xf);
|
||||
func_80338338(this->rgb[0], this->rgb[1], this->rgb[2]);
|
||||
func_803382B4(
|
||||
(this->rgb[0] < 8)? 0 : this->rgb[0] - 8,
|
||||
(this->rgb[1] < 8)? 0 : this->rgb[1] - 8,
|
||||
(this->rgb[2] < 8)? 0 : this->rgb[2] - 8,
|
||||
(this->draw_mode & PART_EMIT_NO_OPA)? 0xff : this->alpha
|
||||
);
|
||||
func_80338370();
|
||||
func_80335D30(gfx);
|
||||
}
|
||||
else if(this->draw_mode & PART_EMIT_NO_DEPTH){//L802EF0C0
|
||||
gSPDisplayList((*gfx)++, D_80368978);
|
||||
}
|
||||
else{//L802EF0EC
|
||||
gSPDisplayList((*gfx)++, D_80368940);
|
||||
}//L802EF10C
|
||||
flat_rotation[0] = 90.0f;
|
||||
flat_rotation[1] = 0.0f;
|
||||
flat_rotation[2] = 0.0f;
|
||||
for(iPtr = this->pList_start_124; iPtr < this->pList_end_128; iPtr++){
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, this->rgb[0], this->rgb[1], this->rgb[2], iPtr->fade*this->alpha);
|
||||
position[0] = iPtr->position[0] + this->unk4[0];
|
||||
position[1] = iPtr->position[1] + this->unk4[1];
|
||||
position[2] = iPtr->position[2] + this->unk4[2];
|
||||
|
||||
scale[0] = iPtr->scale;
|
||||
scale[1] = iPtr->scale;
|
||||
scale[2] = iPtr->scale;
|
||||
if(0.0f != this->unk108){
|
||||
func_802EED1C(this, iPtr->age_48, scale);
|
||||
}
|
||||
func_80344C2C(this->unk0_16);
|
||||
// @recomp Set the matrix group for this particle.
|
||||
u32 transform_id =
|
||||
PARTICLE_TRANSFORM_ID_START +
|
||||
PARTICLE_EMITTER_TRANSFORM_ID_COUNT * cur_particle_emitter_index +
|
||||
PARTICLE_ID(iPtr);
|
||||
gEXMatrixGroupDecomposedNormal((*gfx)++, transform_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW);
|
||||
|
||||
if(this->draw_mode & PART_EMIT_ROTATABLE){
|
||||
func_80344720(this->unk34, (s32)iPtr->frame, 0, position, flat_rotation, scale, gfx, mtx);
|
||||
}//L802EF2F8
|
||||
else{
|
||||
func_80344424(this->unk34, (s32)iPtr->frame, 0, position, scale, iPtr->rotation[2], gfx, mtx);
|
||||
}//L802EF324
|
||||
|
||||
// @recomp Pop the particle's matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
}//L802EF338
|
||||
if( this->rgb[0] != 0xff || this->rgb[1] != 0xff || this->rgb[2] != 0xff || this->alpha != 0xff
|
||||
){
|
||||
func_8033687C(gfx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to set an incrementing ID for the emitter.
|
||||
RECOMP_PATCH ParticleEmitter *partEmitMgr_newEmitter(u32 cnt){
|
||||
partEmitMgr = realloc(partEmitMgr, (++partEmitMgrLength)*4);
|
||||
partEmitMgr[partEmitMgrLength - 1] = particleEmitter_new(cnt);
|
||||
partEmitMgr[partEmitMgrLength - 1]->auto_free = TRUE;
|
||||
// @recomp Set the particle emitter's ID based on the emitter spawn count and increment the spawn count.
|
||||
PARTICLE_EMITTER_ID(partEmitMgr[partEmitMgrLength - 1]) = particle_emitter_spawn_count;
|
||||
particle_emitter_spawn_count++;
|
||||
particle_emitter_spawn_count = particle_emitter_spawn_count % PARTICLE_EMITTER_MAX_ID;
|
||||
|
||||
return partEmitMgr[partEmitMgrLength - 1];
|
||||
}
|
||||
|
||||
// @recomp Patched to set an incrementing ID for the particle.
|
||||
RECOMP_PATCH void __particleEmitter_initParticle(ParticleEmitter *this, Particle *particle){
|
||||
particle->acceleration[0] = randf2(this->particleAccerationRange_4C_min_x, this->particleAccerationRange_4C_max_x);
|
||||
particle->acceleration[1] = randf2(this->particleAccerationRange_4C_min_y, this->particleAccerationRange_4C_max_y);
|
||||
particle->acceleration[2] = randf2(this->particleAccerationRange_4C_min_z, this->particleAccerationRange_4C_max_z);
|
||||
particle->unk5C = this->unk64;
|
||||
|
||||
particle->fade = (0.0f == this->fade_in) ? 1.0f : 0;
|
||||
particle->frame = randf2((f32)this->particleStartingFrameRange_84_min, (f32)this->particleStartingFrameRange_84_max);
|
||||
particle->framerate = randf2(this->particleFramerateRange_8C_min, this->particleFramerateRange_8C_max);
|
||||
|
||||
particle->position[0] = this->postion_28[0];
|
||||
particle->position[1] = this->postion_28[1];
|
||||
particle->position[2] = this->postion_28[2];
|
||||
|
||||
particle->position[0] = particle->position[0] + randf2(this->particleSpawnPositionRange_94_min_x, this->particleSpawnPositionRange_94_max_x);
|
||||
particle->position[1] = particle->position[1] + randf2(this->particleSpawnPositionRange_94_min_y, this->particleSpawnPositionRange_94_max_y);
|
||||
particle->position[2] = particle->position[2] + randf2(this->particleSpawnPositionRange_94_min_z, this->particleSpawnPositionRange_94_max_z);
|
||||
|
||||
particle->initialSize_34 = particle->scale = randf2(this->particleStartingScaleRange_AC_min, this->particleStartingScaleRange_AC_max);
|
||||
if(0.0f == this->particleFinalScaleRange_B4_min && 0.0f == this->particleFinalScaleRange_B4_max)
|
||||
particle->finalSizeDiff = 0.0f;
|
||||
else
|
||||
particle->finalSizeDiff = randf2(this->particleFinalScaleRange_B4_min, this->particleFinalScaleRange_B4_max)- particle->initialSize_34;
|
||||
|
||||
particle->rotation[2] = 0.0f;
|
||||
particle->rotation[1] = 0.0f;
|
||||
particle->rotation[0] = 0.0f;
|
||||
|
||||
particle->angluar_velocity[0] = randf2(this->unkBC[0], this->unkC8[0]);
|
||||
particle->angluar_velocity[1] = randf2(this->unkBC[1], this->unkC8[1]);
|
||||
particle->angluar_velocity[2] = randf2(this->unkBC[2], this->unkC8[2]);
|
||||
|
||||
particle->age_48 = 0.0f;
|
||||
particle->lifetime_4C = randf2(this->particleLifeTimeRange[0], this->particleLifeTimeRange[1]) + 0.001;
|
||||
if(!this->sphericalParticleVelocity_48){
|
||||
particle->velocity_50[0] = randf2(this->particleVelocityRange_E4.cartisian_min_x, this->particleVelocityRange_E4.cartisian_max_x);
|
||||
particle->velocity_50[1] = randf2(this->particleVelocityRange_E4.cartisian_min_y, this->particleVelocityRange_E4.cartisian_max_y);
|
||||
particle->velocity_50[2] = randf2(this->particleVelocityRange_E4.cartisian_min_z, this->particleVelocityRange_E4.cartisian_max_z);
|
||||
}
|
||||
else{
|
||||
func_80256E24(particle->velocity_50,
|
||||
mlNormalizeAngle(randf2(this->particleVelocityRange_E4.spherical.pitch_min, this->particleVelocityRange_E4.spherical.pitch_max)),
|
||||
mlNormalizeAngle(randf2(this->particleVelocityRange_E4.spherical.yaw_min, this->particleVelocityRange_E4.spherical.yaw_max)),
|
||||
0.0f,
|
||||
0.0f,
|
||||
randf2(this->particleVelocityRange_E4.spherical.radius_min, this->particleVelocityRange_E4.spherical.radius_max)
|
||||
);
|
||||
}
|
||||
|
||||
// @recomp Set the particle's ID based on the particle emitters's spawn count.
|
||||
PARTICLE_ID(particle) = PARTICLE_EMITTER_SPAWN_COUNT(this);
|
||||
// @recomp Increment the particle emitter's spawn count.
|
||||
PARTICLE_EMITTER_SPAWN_COUNT(this)++;
|
||||
}
|
||||
|
||||
extern void mlMtxRotatePYR(f32, f32, f32);
|
||||
|
||||
typedef struct {
|
||||
BKSprite *sprite_0;
|
||||
f32 position[3];
|
||||
f32 rotation[3];
|
||||
f32 unk1C;
|
||||
s16 unk20[2];
|
||||
u8 color[3];
|
||||
u8 unk27;
|
||||
u32 frame_28_31:8;
|
||||
u32 unk28_23:2;
|
||||
u32 unk28_21:8;
|
||||
u32 unk28_13:1;
|
||||
u32 unk28_12:1;
|
||||
u32 pad28_11:12;
|
||||
} Struct_B8860_0s;
|
||||
|
||||
void projectile_setRoll(u8 indx, f32 angle);
|
||||
f32 projectile_getRoll(u8 indx);
|
||||
void projectile_freeByIndex(u8 arg0);
|
||||
void func_803382FC(s32);
|
||||
void func_80338308(s32 arg0, s32 arg1);
|
||||
void func_8033837C(s32 arg0);
|
||||
void spriteRender_draw(Gfx **gfx, Vtx **vtx, BKSprite *sp, u32 frame);
|
||||
|
||||
extern Struct_B8860_0s D_80385000[0x32];
|
||||
|
||||
// @recomp Patched to tag projectiles.
|
||||
RECOMP_PATCH void func_8033F7F0(u8 indx, Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
Struct_B8860_0s *sp54;
|
||||
f32 sp48[3];
|
||||
f32 sp3C[3];
|
||||
f32 sp30[3];
|
||||
|
||||
sp54 = &D_80385000[indx];
|
||||
if(sp54->unk28_23 != 1){
|
||||
ml_vec3f_copy(sp48, sp54->position);
|
||||
sp48[1] += (sp54->unk1C*sp54->unk20[1])/100.0;
|
||||
viewport_getPosition_vec3f(sp3C);
|
||||
ml_vec3f_diff_copy(sp30, sp48, sp3C);
|
||||
if(sp54->unk28_12){
|
||||
mlMtxSet(viewport_getMatrix());
|
||||
}
|
||||
else{
|
||||
mlMtxIdent();
|
||||
}
|
||||
mlMtxRotatePYR(sp54->rotation[0], sp54->rotation[1], sp54->rotation[2]);
|
||||
func_80252330(sp30[0], sp30[1], sp30[2]);
|
||||
mlMtxApply(*mtx);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
func_803382E4(sp54->unk28_21);
|
||||
func_80338338(sp54->color[0], sp54->color[1],sp54->color[2]);
|
||||
func_803382FC(sp54->unk27);
|
||||
func_80338308(sp54->unk20[0], sp54->unk20[1]);
|
||||
func_8033837C(1);
|
||||
func_80338370();
|
||||
|
||||
// @recomp Set a matrix group before drawing the sprite.
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, PROJECTILE_TRANSFORM_ID_START + indx, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
|
||||
spriteRender_draw(gfx, vtx, sp54->sprite_0, sp54->frame_28_31);
|
||||
gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
}
|
||||
}
|
||||
+16
-13
@@ -28,6 +28,7 @@ void osWriteBackDCacheAll(void);
|
||||
#define strchr strchr_recomp
|
||||
#define strlen strlen_recomp
|
||||
#define osVirtualToPhysical osVirtualToPhysical_recomp
|
||||
#define osPiStartDma osPiStartDma_recomp
|
||||
|
||||
#include "ultra64.h"
|
||||
#pragma GCC diagnostic push
|
||||
@@ -47,29 +48,26 @@ void osWriteBackDCacheAll(void);
|
||||
)
|
||||
#endif
|
||||
|
||||
#define gEXMatrixGroupNoInterpolation(cmd, push, proj, edit) \
|
||||
gEXMatrixGroup(cmd, G_EX_ID_IGNORE, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_ORDER_LINEAR, edit)
|
||||
|
||||
#define gEXMatrixGroupInterpolateOnlyTiles(cmd, push, proj, edit) \
|
||||
gEXMatrixGroup(cmd, G_EX_ID_IGNORE, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
#define gEXMatrixGroupSimpleNormal(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroup(cmd, id, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_ASPECT_AUTO, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_AUTO)
|
||||
|
||||
#define gEXMatrixGroupSimpleVerts(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroup(cmd, id, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_ASPECT_AUTO, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_AUTO)
|
||||
|
||||
#define gEXMatrixGroupDecomposedNormal(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_AUTO)
|
||||
|
||||
#define gEXMatrixGroupDecomposedSkipRot(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_AUTO)
|
||||
|
||||
#define gEXMatrixGroupDecomposedSkipPosRot(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
|
||||
#define gEXMatrixGroupDecomposedSkipAll(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_AUTO)
|
||||
|
||||
#define gEXMatrixGroupDecomposedVerts(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_AUTO)
|
||||
|
||||
#define gEXMatrixGroupDecomposedVertsOrderAuto(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_AUTO, edit)
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_AUTO, edit, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_AUTO)
|
||||
|
||||
typedef int bool;
|
||||
|
||||
@@ -78,4 +76,9 @@ void memcpy(void * dst, void *src, int size);
|
||||
char* strchr(const char* s, int c);
|
||||
int recomp_printf(const char* fmt, ...);
|
||||
|
||||
void set_additional_model_scale(f32 x, f32 y, f32 z);
|
||||
void set_frustum_checks_enabled(int enabled);
|
||||
void set_all_interpolation_skipped(bool skipped);
|
||||
bool all_interpolation_skipped();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,3 +17,12 @@ RECOMP_EXPORT int recomp_printf(const char* fmt, ...) {
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rmonPrintf_recomp(const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
int ret = _Printf(&proutPrintf, NULL, fmt, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "core1/core1.h"
|
||||
#include "functions.h"
|
||||
#include "../src/core2/gc/zoombox.h"
|
||||
|
||||
extern u32 D_803835E0;
|
||||
void func_802BBD2C(f32 *arg0, f32 *arg1);
|
||||
s32 func_80320708(void);
|
||||
void spawnQueue_unlock(void);
|
||||
void sky_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
bool mapModel_has_xlu_bin(void);
|
||||
void mapModel_opa_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
int game_is_frozen(void);
|
||||
void func_80322E64(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void player_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void func_80302C94(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void jiggylist_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void func_803500D8(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void func_802F2ED0(Struct64s *arg0, Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
Struct64s* func_8032994C(void);
|
||||
void partEmitMgr_drawPass0(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
void mapModel_xlu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void func_8032D3D8(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
void partEmitMgr_drawPass1(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
void func_8034F6F0(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
void func_802D520C(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void partEmitMgr_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
void func_80350818(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void func_802BBD0C(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
void spawnQueue_lock(void);
|
||||
s32 getGameMode(void);
|
||||
void sfx_rand_sync_to_rand(void);
|
||||
void func_803162B4(GcZoombox *this);
|
||||
void rand_sync_to_sfx_rand(void);
|
||||
void func_80338338(s32, s32, s32);
|
||||
void func_803382FC(s32);
|
||||
void func_803382E4(s32);
|
||||
void func_8033687C(Gfx **);
|
||||
void func_80335D30(Gfx **);
|
||||
void func_80344090(BKSpriteDisplayData *self, s32 frame, Gfx **gfx);
|
||||
|
||||
// @recomp Patched to set the projection transform ID for the main projection.
|
||||
RECOMP_PATCH void func_80334540(Gfx** gdl, Mtx **mptr, Vtx **vptr) {
|
||||
f32 sp44;
|
||||
f32 sp40;
|
||||
|
||||
if (D_803835E0 == 0) {
|
||||
drawRectangle2D(gdl, 0, 0, gFramebufferWidth, gFramebufferHeight, 0, 0, 0);
|
||||
func_802BBD2C(&sp44, &sp40);
|
||||
viewport_setNearAndFar(sp44, sp40);
|
||||
|
||||
// @recomp Set the perpsective projection transform ID.
|
||||
cur_perspective_projection_transform_id = PROJECTION_GAMEPLAY_TRANSFORM_ID;
|
||||
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr);
|
||||
return;
|
||||
}
|
||||
if (func_80320708() == 0) {
|
||||
eeprom_writeBlocks(0, 0, (void*)0x80BC7230, EEPROM_MAXBLOCKS);
|
||||
}
|
||||
spawnQueue_unlock();
|
||||
sky_draw(gdl, mptr, vptr);
|
||||
func_802BBD2C(&sp44, &sp40);
|
||||
viewport_setNearAndFar(sp44, sp40);
|
||||
|
||||
// @recomp Set the perpsective projection transform ID.
|
||||
cur_perspective_projection_transform_id = PROJECTION_GAMEPLAY_TRANSFORM_ID;
|
||||
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr);
|
||||
if (mapModel_has_xlu_bin() != 0) {
|
||||
mapModel_opa_draw(gdl, mptr, vptr);
|
||||
if (game_is_frozen() == 0) {
|
||||
func_80322E64(gdl, mptr, vptr);
|
||||
}
|
||||
if (game_is_frozen() == 0) {
|
||||
player_draw(gdl, mptr, vptr);
|
||||
}
|
||||
if (game_is_frozen() == 0) {
|
||||
func_80302C94(gdl, mptr, vptr);
|
||||
}
|
||||
if (game_is_frozen() == 0) {
|
||||
jiggylist_draw(gdl, mptr, vptr);
|
||||
}
|
||||
if (game_is_frozen() == 0) {
|
||||
func_803500D8(gdl, mptr, vptr);
|
||||
}
|
||||
if (game_is_frozen() == 0) {
|
||||
func_802F2ED0(func_8032994C(), gdl, mptr, vptr);
|
||||
}
|
||||
if (game_is_frozen() == 0) {
|
||||
partEmitMgr_drawPass0(gdl, mptr, vptr);
|
||||
}
|
||||
if (game_is_frozen() == 0) {
|
||||
mapModel_xlu_draw(gdl, mptr, vptr);
|
||||
}
|
||||
if (game_is_frozen() == 0) {
|
||||
func_8032D3D8(gdl, mptr, vptr);
|
||||
}
|
||||
if (game_is_frozen() == 0) {
|
||||
partEmitMgr_drawPass1(gdl, mptr, vptr);
|
||||
}
|
||||
if (game_is_frozen() == 0) {
|
||||
func_8034F6F0(gdl, mptr, vptr);
|
||||
}
|
||||
func_802D520C(gdl, mptr, vptr);
|
||||
} else {
|
||||
mapModel_opa_draw(gdl, mptr, vptr);
|
||||
func_80322E64(gdl, mptr, vptr);
|
||||
func_8034F6F0(gdl, mptr, vptr);
|
||||
player_draw(gdl, mptr, vptr);
|
||||
func_80302C94(gdl, mptr, vptr);
|
||||
func_8032D3D8(gdl, mptr, vptr);
|
||||
jiggylist_draw(gdl, mptr, vptr);
|
||||
func_803500D8(gdl, mptr, vptr);
|
||||
func_802F2ED0(func_8032994C(), gdl, mptr, vptr);
|
||||
func_802D520C(gdl, mptr, vptr);
|
||||
partEmitMgr_draw(gdl, mptr, vptr);
|
||||
}
|
||||
if (game_is_frozen() == 0) {
|
||||
func_80350818(gdl, mptr, vptr);
|
||||
}
|
||||
if (game_is_frozen() == 0) {
|
||||
func_802BBD0C(gdl, mptr, vptr);
|
||||
}
|
||||
spawnQueue_lock();
|
||||
|
||||
// @recomp Clear the perpsective projection transform ID.
|
||||
cur_perspective_projection_transform_id = 0;
|
||||
}
|
||||
|
||||
void actor_predrawMethod(Actor *);
|
||||
void actor_postdrawMethod(ActorMarker *);
|
||||
extern bool D_8037DE84;
|
||||
|
||||
// @recomp Patched to set the transform ID for the press start projection.
|
||||
RECOMP_PATCH Actor *chOverlayPressStart_draw(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **vptr){
|
||||
Actor * actor;
|
||||
f32 sp58[3];
|
||||
f32 sp4C[3];
|
||||
f32 sp40[3];
|
||||
f32 sp34[3];
|
||||
|
||||
|
||||
actor = marker_getActor(marker);
|
||||
if(D_8037DE84)
|
||||
return actor;
|
||||
|
||||
modelRender_preDraw((GenFunction_1)actor_predrawMethod, (s32)actor);
|
||||
modelRender_postDraw((GenFunction_1)actor_postdrawMethod, (s32)marker);
|
||||
viewport_backupState();
|
||||
{sp58[0] = 0.0f; sp58[1] = 0.0f; sp58[2] = 1312.5f;};
|
||||
{sp4C[0] = 0.0f; sp4C[1] = 0.0f; sp4C[2] = 0.0f;};
|
||||
viewport_setPosition_vec3f(sp58);
|
||||
viewport_setRotation_vec3f(sp4C);
|
||||
viewport_update();
|
||||
|
||||
// @recomp Record the current projection transform, then set the projection transform ID for the press start projection.
|
||||
s32 prev_perspective_projection_transform = cur_perspective_projection_transform_id;
|
||||
cur_perspective_projection_transform_id = PROJECTION_PRESS_START_TRANSFORM_ID;
|
||||
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr);
|
||||
{sp40[0] = 0.0f; sp40[1] = 0.0f; sp40[2] = 0.0f;};
|
||||
{sp34[0] = 0.0f; sp34[1] = 400.0f; sp34[2] = 0.0f;};
|
||||
modelRender_draw(gdl, mptr, sp40, 0, 1.0f, sp34, marker_loadModelBin(marker));
|
||||
|
||||
// @recomp Restore the previous perpsective projection transform ID.
|
||||
cur_perspective_projection_transform_id = prev_perspective_projection_transform;
|
||||
|
||||
viewport_restoreState();
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr);
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
#define ASSET_54D_MODEL_BK_TITLE_LOGO 0x54D
|
||||
#define ASSET_56C_MODEL_THE_END 0x56C
|
||||
|
||||
// @recomp Patched to set the transform ID for the title logo and copyright text projections.
|
||||
RECOMP_PATCH Actor *func_802DC7E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
Actor *this;
|
||||
f32 sp58[3];
|
||||
f32 sp4C[3];
|
||||
f32 sp40[3];
|
||||
f32 sp34[3];
|
||||
|
||||
this = marker_getActor(marker);
|
||||
modelRender_preDraw( (GenFunction_1)actor_predrawMethod, (s32)this);
|
||||
modelRender_postDraw((GenFunction_1)actor_postdrawMethod, (s32)marker);
|
||||
viewport_backupState();
|
||||
sp58[0] = 0.0f;
|
||||
sp58[1] = 0.0f;
|
||||
sp58[2] = 860.0f;
|
||||
sp4C[0] = 0.0f;
|
||||
sp4C[1] = 0.0f;
|
||||
sp4C[2] = 0.0f;
|
||||
viewport_setPosition_vec3f(sp58);
|
||||
viewport_setRotation_vec3f(sp4C);
|
||||
viewport_update();
|
||||
|
||||
// @recomp Record the current projection transform, then set the projection transform ID for the projection determined by the model ID.
|
||||
s32 prev_perspective_projection_transform = cur_perspective_projection_transform_id;
|
||||
if (marker->modelId == ASSET_54D_MODEL_BK_TITLE_LOGO) {
|
||||
cur_perspective_projection_transform_id = PROJECTION_BK_LOGO_TRANSFORM_ID;
|
||||
}
|
||||
else if (marker->modelId == ASSET_54E_MODEL_COPYRIGHT_OVERLAY) {
|
||||
cur_perspective_projection_transform_id = PROJECTION_COPYRIGHT_TRANSFORM_ID;
|
||||
}
|
||||
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
sp40[0] = 0.0f;
|
||||
sp40[1] = 0.0f;
|
||||
sp40[2] = 0.0f;
|
||||
sp34[0] = 0.0f;
|
||||
sp34[1] = -87.0f;
|
||||
sp34[2] = 0.0f;
|
||||
modelRender_draw(gfx, mtx, sp40, NULL, 1.0f, sp34, marker_loadModelBin(marker));
|
||||
|
||||
// @recomp Restore the previous perpsective projection transform ID.
|
||||
cur_perspective_projection_transform_id = prev_perspective_projection_transform;
|
||||
viewport_restoreState();
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
return this;
|
||||
}
|
||||
|
||||
// @recomp Patched to set the transform ID for the game over and THE END projections.
|
||||
RECOMP_PATCH Actor *func_802DC320(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
Actor *this;
|
||||
f32 vp_position[3];
|
||||
f32 vp_rotation[3];
|
||||
f32 model_position[3];
|
||||
f32 sp34[3];
|
||||
|
||||
this = marker_getActor(marker);
|
||||
modelRender_preDraw( (GenFunction_1)actor_predrawMethod, (s32)this);
|
||||
modelRender_postDraw((GenFunction_1)actor_postdrawMethod, (s32)marker);
|
||||
viewport_backupState();
|
||||
vp_position[0] = 0.0f;
|
||||
vp_position[1] = 0.0f;
|
||||
vp_position[2] = 937.5f;
|
||||
vp_rotation[0] = 0.0f;
|
||||
vp_rotation[1] = 0.0f;
|
||||
vp_rotation[2] = 0.0f;
|
||||
viewport_setPosition_vec3f(vp_position);
|
||||
viewport_setRotation_vec3f(vp_rotation);
|
||||
viewport_update();
|
||||
|
||||
// @recomp Record the current projection transform, then set the projection transform ID for the projection determined by the model ID.
|
||||
s32 prev_perspective_projection_transform = cur_perspective_projection_transform_id;
|
||||
if (marker->modelId == ASSET_54C_MODEL_GAME_OVER) {
|
||||
cur_perspective_projection_transform_id = PROJECTION_GAME_OVER_TRANSFORM_ID;
|
||||
}
|
||||
else if (marker->modelId == ASSET_56C_MODEL_THE_END) {
|
||||
cur_perspective_projection_transform_id = PROJECTION_THE_END_TRANSFORM_ID;
|
||||
}
|
||||
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
model_position[0] = 0.0f;
|
||||
model_position[1] = 0.0f;
|
||||
model_position[2] = 0.0f;
|
||||
sp34[0] = 0.0f;
|
||||
sp34[1] = 137.5f;
|
||||
sp34[2] = 0.0f;
|
||||
modelRender_draw(gfx, mtx, model_position, NULL, 1.0f, sp34, marker_loadModelBin(marker));
|
||||
|
||||
// @recomp Restore the previous perpsective projection transform ID.
|
||||
cur_perspective_projection_transform_id = prev_perspective_projection_transform;
|
||||
viewport_restoreState();
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
return this;
|
||||
}
|
||||
|
||||
// @recomp Patched to set the zoombox's model transform ID.
|
||||
RECOMP_PATCH void func_803163A8(GcZoombox *this, Gfx **gfx, Mtx **mtx) {
|
||||
f32 sp5C[3];
|
||||
f32 sp50[3];
|
||||
f32 sp44[3];
|
||||
f32 sp38[3];
|
||||
f32 sp34;
|
||||
|
||||
sp34 = viewport_transformCoordinate(this->unk170, this->unk172, sp50, sp5C);
|
||||
if (this->unk1A4_24) {
|
||||
sp5C[1] += 180.0f;
|
||||
sp5C[0] -= 2*sp5C[0];
|
||||
}
|
||||
sp38[0] = 0.0f; sp38[1] = 0.0f; sp38[2] = 0.0f;
|
||||
sp44[0] = 0.0f; sp44[1] = 0.0f; sp44[2] = 0.0f;
|
||||
func_8033A308(sp44);
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_NONE);
|
||||
if (this->anim_ctrl != NULL) {
|
||||
anctrl_drawSetup(this->anim_ctrl, sp50, 1);
|
||||
}
|
||||
|
||||
// @recomp Set the model transform ID.
|
||||
u32 prev_transform_id = cur_drawn_model_transform_id;
|
||||
cur_drawn_model_transform_id = ZOOMBOX_TRANSFORM_ID_START + this->portrait_id;
|
||||
|
||||
modelRender_draw(gfx, mtx, sp50, sp5C, this->unk198 * sp34, sp38, this->model);
|
||||
|
||||
// @recomp Reset the model transform ID.
|
||||
cur_drawn_model_transform_id = prev_transform_id;
|
||||
}
|
||||
|
||||
// @recomp Patched to set the zoombox portrait's model and ortho projection transform IDs.
|
||||
RECOMP_PATCH void func_803164B0(GcZoombox *this, Gfx **gfx, Mtx **mtx, s32 arg3, s32 arg4, BKSpriteDisplayData *arg5, f32 arg6) {
|
||||
f32 sp2C[3];
|
||||
f32 temp_f12;
|
||||
|
||||
if (this->portrait_id == ZOOMBOX_SPRITE_46_TUMBLAR) {
|
||||
arg6 = 0.75f;
|
||||
}
|
||||
func_80338338(0xFF, 0xFF, 0xFF);
|
||||
func_803382FC(this->unk168 * arg6);
|
||||
func_803382E4(5);
|
||||
func_80335D30(gfx);
|
||||
|
||||
// @recomp Set the ortho projection transform ID for the portrait.
|
||||
cur_ortho_projection_transform_id = PROJECTION_PORTRAIT_TRANSFORM_ID_START + this->portrait_id;
|
||||
|
||||
viewport_setRenderViewportAndOrthoMatrix(gfx, mtx);
|
||||
|
||||
// @recomp Clear the current ortho projection transform ID.
|
||||
cur_ortho_projection_transform_id = 0;
|
||||
|
||||
mlMtxIdent();
|
||||
if (this->unk1A4_24) {
|
||||
mlMtxRotYaw(180.0f);
|
||||
sp2C[0] = (f32) this->unk170 - ((f32) arg3 * this->unk198);
|
||||
} else {
|
||||
sp2C[0] = (f32) this->unk170 + ((f32) arg3 * this->unk198);
|
||||
}
|
||||
sp2C[1] = this->unk172 + ((f32) arg4 * this->unk198);
|
||||
sp2C[2] = -10.0f;
|
||||
func_80252330((sp2C[0] * 4.0f) - ((f32)gFramebufferWidth * 2), ((f32)gFramebufferHeight * 2) - (sp2C[1] * 4.0f), sp2C[2]);
|
||||
temp_f12 = (f32) ((f64) this->unk198 * 0.8);
|
||||
mlMtxScale_xyz(temp_f12, temp_f12, 1.0f);
|
||||
mlMtxApply(*mtx);
|
||||
gSPMatrix((*gfx)++, (*mtx)++, G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Create a matrix group for the portrait's model matrix.
|
||||
gEXMatrixGroupDecomposedVerts((*gfx)++, ZOOMBOX_PORTRAIT_TRANSFORM_ID_START + this->portrait_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_NONE);
|
||||
func_80344090(arg5, this->unk186, gfx);
|
||||
func_8033687C(gfx);
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
|
||||
// @recomp Pop the model matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
}
|
||||
@@ -0,0 +1,406 @@
|
||||
#include "patches.h"
|
||||
#include "prop.h"
|
||||
#include "actor.h"
|
||||
#include "functions.h"
|
||||
#include "object_extension_funcs.h"
|
||||
#include "bk_api.h"
|
||||
#include "core2/coords.h"
|
||||
#include "core2/file.h"
|
||||
|
||||
// Max props per cube, limited by cube->prop2Cnt which is only 6 bits.
|
||||
#define CUBE_MAX_PROPS 63
|
||||
// Hardcoded cube limit, TODO implement a better solution that doesn't involve dedicating this much memory and allows for larger cube counts.
|
||||
#define MAX_CUBES 4000
|
||||
|
||||
typedef struct {
|
||||
u32 prop_handles[CUBE_MAX_PROPS];
|
||||
} CubeHandle;
|
||||
|
||||
CubeHandle all_cube_handles[MAX_CUBES];
|
||||
CubeHandle cube_3C_handle;
|
||||
CubeHandle cube_40_handle;
|
||||
|
||||
extern s32 *D_8036A9E0;
|
||||
extern s32 D_80383450[0x40];
|
||||
|
||||
void vtxList_getBounds_s32(BKVertexList *, s32[3], s32[3]);
|
||||
enum map_e map_get(void);
|
||||
void code7AF80_initCubeFromFile(File *file_ptr, Cube *cube);
|
||||
bool func_80305D14(void);
|
||||
void func_80305CD8(s32 idx, s32 count);
|
||||
s32 func_803058C0(f32 arg0);
|
||||
void code_A5BC0_initCubePropActorProp(Cube*);
|
||||
void func_80332B2C(ActorMarker * arg0);
|
||||
void bitfield_free(s32 *arg0);
|
||||
|
||||
extern struct {
|
||||
Cube *cubes;
|
||||
f32 margin;
|
||||
s32 min[3];
|
||||
s32 max[3];
|
||||
s32 stride[2];
|
||||
s32 cubeCnt;
|
||||
s32 unk2C;
|
||||
s32 width[3];
|
||||
Cube *unk3C; // fallback cube?
|
||||
Cube *unk40; // some other fallback cube?
|
||||
s32 unk44; // index of some sort
|
||||
} sCubeList;
|
||||
|
||||
typedef struct {
|
||||
s16 map_id; //enum map_e
|
||||
s16 opa_model_id; //enum asset_e level_model_id
|
||||
s16 xlu_model_id; //enum asset_e level2_model_id
|
||||
s16 unk6[3]; // min bounds (for cubes?)
|
||||
s16 unkC[3]; // max bounds (for cubes?)
|
||||
// u8 pad12[0x2];
|
||||
f32 scale;
|
||||
}MapModelDescription;
|
||||
|
||||
extern struct {
|
||||
void *unk0;
|
||||
void *unk4;
|
||||
BKCollisionList *collision_opa;
|
||||
BKCollisionList *collision_xlu;
|
||||
BKModel *model_opa;
|
||||
BKModel *model_xlu;
|
||||
BKModelBin *model_bin_opa;
|
||||
BKModelBin *model_bin_xlu;
|
||||
s32 unk20;
|
||||
struct5Bs *unk24;
|
||||
MapModelDescription *description;
|
||||
u8 env_red;
|
||||
u8 env_green;
|
||||
u8 env_blue;
|
||||
f32 scale;
|
||||
}mapModel;
|
||||
|
||||
void recomp_abort(const char* msg);
|
||||
|
||||
// @recomp Patched to verify the cube count is less than the fixed amount.
|
||||
RECOMP_PATCH void mapModel_getCubeBounds(s32 min[3], s32 max[3]) {
|
||||
vtxList_getBounds_s32(model_getVtxList(mapModel.model_bin_opa), min, max);
|
||||
coords_scale(min, max, 1000);
|
||||
min[0] = min[0] + mapModel.description->unk6[0];
|
||||
min[1] = min[1] + mapModel.description->unk6[1];
|
||||
min[2] = min[2] + mapModel.description->unk6[2];
|
||||
max[0] = max[0] + mapModel.description->unkC[0];
|
||||
max[1] = max[1] + mapModel.description->unkC[1];
|
||||
max[2] = max[2] + mapModel.description->unkC[2];
|
||||
|
||||
// @recomp Calculate and validate the cube count.
|
||||
u32 width0 = max[0] - min[0] + 1;
|
||||
u32 width1 = max[1] - min[1] + 1;
|
||||
u32 width2 = max[2] - min[2] + 1;
|
||||
u32 stride0 = width0;
|
||||
u32 stride1 = stride0 * width1;
|
||||
u32 cubeCnt = stride1 * width2;
|
||||
|
||||
if (cubeCnt > MAX_CUBES) {
|
||||
recomp_abort("Cube count too high\n");
|
||||
}
|
||||
}
|
||||
|
||||
CubeHandle* get_cube_handle(Cube *cube) {
|
||||
if (cube == sCubeList.unk3C) {
|
||||
return &cube_3C_handle;
|
||||
}
|
||||
else if (cube == sCubeList.unk40) {
|
||||
return &cube_40_handle;
|
||||
}
|
||||
else {
|
||||
s32 cube_index = cube - sCubeList.cubes;
|
||||
if (cube_index < 0 || cube_index >= sCubeList.cubeCnt) {
|
||||
recomp_printf("Invalid cube index %d\n", cube_index);
|
||||
recomp_abort("Got invalid cube\n");
|
||||
}
|
||||
return &all_cube_handles[cube_index];
|
||||
}
|
||||
}
|
||||
|
||||
// Alloc prop handles:
|
||||
// __codeA5BC0_initProp2Ptr
|
||||
// code7AF80_initCubeFromFile (covered by __code7AF80_initCubeFromFile)
|
||||
|
||||
// Delete prop handles:
|
||||
// func_8032D9C0
|
||||
// cube_free
|
||||
|
||||
// Swap prop handles:
|
||||
// __cube_sort
|
||||
|
||||
// Reset all prop handles candidates:
|
||||
// cubeList_free
|
||||
|
||||
// @recomp Patched to create a handle for the new prop.
|
||||
RECOMP_PATCH Prop *__codeA5BC0_initProp2Ptr(Cube *cube) {
|
||||
Prop *sp1C;
|
||||
|
||||
if (cube->prop2Ptr != NULL) {
|
||||
cube->prop2Cnt++;
|
||||
cube->prop2Ptr = realloc(cube->prop2Ptr, cube->prop2Cnt * sizeof(Prop));
|
||||
} else {
|
||||
cube->prop2Cnt = 1;
|
||||
cube->prop2Ptr = malloc(sizeof(Prop));
|
||||
}
|
||||
sp1C = &cube->prop2Ptr[cube->prop2Cnt-1];
|
||||
sp1C->is_actor = FALSE;
|
||||
code_A5BC0_initCubePropActorProp(cube);
|
||||
|
||||
// @recomp Get the cube's prop handle list.
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
u32 prop_index = cube->prop2Cnt - 1;
|
||||
// TODO prop subtypes.
|
||||
cube_handle->prop_handles[prop_index] = recomp_create_object_data(EXTENSION_TYPE_PROP, 0);
|
||||
|
||||
return sp1C;
|
||||
}
|
||||
|
||||
// @recomp Patched to initialize prop handles after a cube has been loaded.
|
||||
RECOMP_PATCH void __code7AF80_initCubeFromFile(Cube *cube, File* file_ptr) {
|
||||
s32 pad[3];
|
||||
|
||||
// @recomp Get the cube's prop handle list.
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
|
||||
// @recomp Free any prop handles that the cube may already have, as this initialization resets the cube's prop list.
|
||||
for (u32 i = 0; i < cube->prop2Cnt; i++) {
|
||||
recomp_destroy_object_data(EXTENSION_TYPE_PROP, cube_handle->prop_handles[i]);
|
||||
cube_handle->prop_handles[i] = 0;
|
||||
}
|
||||
|
||||
while(!file_isNextByteExpected(file_ptr, 1)) {
|
||||
if (file_getNWords_ifExpected(file_ptr, 0, pad, 3)) {
|
||||
file_getNWords(file_ptr, pad, 3);
|
||||
} else if (!file_getNWords_ifExpected(file_ptr, 2, pad, 3) && file_isNextByteExpected(file_ptr, 3)
|
||||
) {
|
||||
code7AF80_initCubeFromFile(file_ptr, cube);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Initialize prop handles after loading the cube.
|
||||
for (u32 i = 0; i < cube->prop2Cnt; i++) {
|
||||
// TODO prop subtypes.
|
||||
cube_handle->prop_handles[i] = recomp_create_object_data(EXTENSION_TYPE_PROP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to delete the handle for the deleted prop and shift the remaining prop handles.
|
||||
RECOMP_PATCH s32 func_8032D9C0(Cube *cube, Prop* prop){
|
||||
s32 sp24;
|
||||
s32 tmp;
|
||||
|
||||
// @recomp Get the cube's prop handle list.
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
|
||||
sp24 = 0;
|
||||
if(cube->prop2Cnt != 0){
|
||||
// @recomp Delete the handle for the deleted prop.
|
||||
u32 prop_index = prop - cube->prop2Ptr;
|
||||
|
||||
sp24 = prop->is_3d;
|
||||
if(func_80305D14()){
|
||||
func_80305CD8(func_803058C0(prop->unk4[1]), -1);
|
||||
}
|
||||
|
||||
// @recomp Destroy the prop's extension data.
|
||||
recomp_destroy_object_data(EXTENSION_TYPE_PROP, cube_handle->prop_handles[prop_index]);
|
||||
|
||||
if((prop - cube->prop2Ptr) < (cube->prop2Cnt - 1)){
|
||||
memcpy(prop, prop + 1, (s32)(&cube->prop2Ptr[cube->prop2Cnt-1]) - (s32)(prop));
|
||||
// @recomp Shift the prop handles back by 1 to remove the gap.
|
||||
for (u32 cur_prop_index = prop_index; cur_prop_index < cube->prop2Cnt - 1; cur_prop_index++) {
|
||||
cube_handle->prop_handles[cur_prop_index] = cube_handle->prop_handles[cur_prop_index + 1];
|
||||
}
|
||||
// @recomp Clear the handle at the end of the list to account for the list decreasing in size.
|
||||
cube_handle->prop_handles[cube->prop2Cnt - 1] = 0;
|
||||
}
|
||||
cube->prop2Cnt--;
|
||||
if(cube->prop2Cnt){
|
||||
cube->prop2Ptr = realloc(cube->prop2Ptr, cube->prop2Cnt*sizeof(Prop));
|
||||
code_A5BC0_initCubePropActorProp(cube);
|
||||
}else{
|
||||
free(cube->prop2Ptr);
|
||||
cube->prop2Ptr = NULL;
|
||||
}
|
||||
return sp24;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to clear all prop handles for a cube when freeing a cube.
|
||||
RECOMP_PATCH void cube_free(Cube *cube){
|
||||
Prop *iProp;
|
||||
|
||||
// @recomp Get the cube's prop handle list.
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
|
||||
// @recomp Delete and clear the cube's prop handles.
|
||||
for (u32 prop_index = 0; prop_index < cube->prop2Cnt; prop_index++) {
|
||||
recomp_destroy_object_data(EXTENSION_TYPE_PROP, cube_handle->prop_handles[prop_index]);
|
||||
cube_handle->prop_handles[prop_index] = 0;
|
||||
}
|
||||
|
||||
if(cube->prop2Ptr){
|
||||
for(iProp = cube->prop2Ptr; iProp < cube->prop2Ptr +cube->prop2Cnt; iProp++){
|
||||
if(iProp->is_actor){
|
||||
func_80332B2C(iProp->actorProp.marker);
|
||||
}
|
||||
}
|
||||
free(cube->prop2Ptr);
|
||||
cube->prop2Ptr = NULL;
|
||||
}
|
||||
if(cube->prop1Ptr){
|
||||
free(cube->prop1Ptr);
|
||||
cube->prop1Ptr = NULL;
|
||||
}
|
||||
cube->prop2Cnt = 0;
|
||||
cube->prop1Cnt = 0;
|
||||
cube->unk0_4 = 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to swap prop handles when sorting a cube's props.
|
||||
RECOMP_PATCH void __cube_sort(Cube *cube, bool global) {
|
||||
s32 ref_position[3];
|
||||
Prop *var_v1;
|
||||
Prop *start_prop;
|
||||
s32 temp_a2;
|
||||
Prop *var_t1;
|
||||
Prop * var_a3;
|
||||
Prop * var_t0;
|
||||
s32 i;
|
||||
Prop *new_var;
|
||||
|
||||
// @recomp Get the cube's prop handle list.
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
|
||||
if (cube->prop2Cnt >= 2) {
|
||||
if (global == 0) {
|
||||
viewport_getPosition_vec3w(ref_position); //distance from viewport
|
||||
} else {
|
||||
ref_position[0] = 0;
|
||||
ref_position[1] = 0;
|
||||
ref_position[2] = 0;
|
||||
}
|
||||
|
||||
//calculate prop distances
|
||||
new_var = var_v1 = cube->prop2Ptr;
|
||||
for(i = 0; i < cube->prop2Cnt; var_v1++, i++){
|
||||
D_80383450[i] = (var_v1->actorProp.x - ref_position[0])*(var_v1->actorProp.x - ref_position[0])
|
||||
+ (var_v1->actorProp.y - ref_position[1])* (var_v1->actorProp.y - ref_position[1])
|
||||
+ (var_v1->actorProp.z - ref_position[2])* (var_v1->actorProp.z - ref_position[2]);
|
||||
}
|
||||
|
||||
//sort prop list
|
||||
start_prop = cube->prop2Ptr;
|
||||
var_t0 = cube->prop2Ptr + (cube->prop2Cnt - 1);
|
||||
do {
|
||||
new_var = start_prop;
|
||||
var_t1 = var_t0;
|
||||
start_prop = NULL;
|
||||
var_v1 = new_var;
|
||||
i = (new_var - cube->prop2Ptr);
|
||||
while(var_v1 < var_t1){
|
||||
if(D_80383450[i] < D_80383450[i + 1]){
|
||||
var_t0 = var_v1 + 1;
|
||||
if (start_prop != 0) {
|
||||
var_t0 = var_v1;
|
||||
} else {
|
||||
start_prop = (var_v1 == cube->prop2Ptr) ? var_v1 : var_v1 - 1;
|
||||
}
|
||||
|
||||
//swap_distances
|
||||
temp_a2 = D_80383450[i];
|
||||
D_80383450[i] = D_80383450[i + 1];
|
||||
D_80383450[i + 1] = temp_a2;
|
||||
|
||||
//swap_props
|
||||
temp_a2 = ((s32*)(&var_v1[0]))[0];
|
||||
((s32*)(&var_v1[0]))[0] = ((s32*)(&var_v1[1]))[0];
|
||||
((s32*)(&var_v1[1]))[0] = temp_a2;
|
||||
|
||||
temp_a2 = ((s32*)(&var_v1[0]))[1];
|
||||
((s32*)(&var_v1[0]))[1] = ((s32*)(&var_v1[1]))[1];
|
||||
((s32*)(&var_v1[1]))[1] = temp_a2;
|
||||
|
||||
temp_a2 = ((s32*)(&var_v1[0]))[2];
|
||||
((s32*)(&var_v1[0]))[2] = ((s32*)(&var_v1[1]))[2];
|
||||
((s32*)(&var_v1[1]))[2] = temp_a2;
|
||||
|
||||
// @recomp Swap prop extension data handles.
|
||||
u32 temp_handle = cube_handle->prop_handles[i];
|
||||
cube_handle->prop_handles[i] = cube_handle->prop_handles[i + 1];
|
||||
cube_handle->prop_handles[i + 1] = temp_handle;
|
||||
}
|
||||
|
||||
var_v1++;
|
||||
i++;
|
||||
}
|
||||
} while (start_prop != NULL);
|
||||
code_A5BC0_initCubePropActorProp(cube);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to reset the prop handle list.
|
||||
RECOMP_PATCH void cubeList_free(){
|
||||
Cube *iCube;
|
||||
|
||||
for(iCube = sCubeList.cubes; iCube < sCubeList.cubes + sCubeList.cubeCnt; iCube++){
|
||||
cube_free(iCube);
|
||||
}
|
||||
free(sCubeList.cubes);
|
||||
|
||||
if(sCubeList.unk3C){
|
||||
cube_free(sCubeList.unk3C);
|
||||
free(sCubeList.unk3C);
|
||||
}
|
||||
|
||||
if(sCubeList.unk40){
|
||||
cube_free(sCubeList.unk40);
|
||||
free(sCubeList.unk40);
|
||||
}
|
||||
bitfield_free(D_8036A9E0);
|
||||
D_8036A9E0 = NULL;
|
||||
|
||||
// @recomp Reset the prop handle list.
|
||||
recomp_clear_all_object_data(EXTENSION_TYPE_PROP);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT PropExtensionId bkrecomp_extend_prop_all(u32 size) {
|
||||
return recomp_register_object_extension_generic(EXTENSION_TYPE_PROP, size);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT void *bkrecomp_get_extended_prop_data(Cube* cube, Prop* prop, PropExtensionId extension_id) {
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
s32 prop_index = prop - cube->prop2Ptr;
|
||||
if (prop_index < 0 || prop_index >= cube->prop2Cnt) {
|
||||
recomp_printf("bkrecomp_get_extended_prop_data: Invalid Cube/Prop pair\n");
|
||||
recomp_abort("Fatal error in mod - Invalid call to bkrecomp_get_extended_prop_data");
|
||||
}
|
||||
|
||||
// TODO prop subtypes.
|
||||
void* data = recomp_get_object_data(EXTENSION_TYPE_PROP, 0, cube_handle->prop_handles[prop_index], extension_id);
|
||||
if (data == NULL) {
|
||||
recomp_printf("bkrecomp_get_extended_prop_data: Invalid extension id 0x%08X\n", extension_id);
|
||||
recomp_abort("Fatal error in mod - Invalid call to bkrecomp_get_extended_prop_data");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
RECOMP_EXPORT u32 bkrecomp_get_prop_spawn_index(Cube* cube, Prop* prop) {
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
s32 prop_index = prop - cube->prop2Ptr;
|
||||
if (prop_index < 0 || prop_index >= cube->prop2Cnt) {
|
||||
recomp_printf("bkrecomp_get_prop_spawn_index: Invalid Cube/Prop pair\n");
|
||||
recomp_abort("Fatal error in mod - Invalid call to bkrecomp_get_prop_spawn_index");
|
||||
}
|
||||
|
||||
u32 spawn_index = recomp_get_object_spawn_index(EXTENSION_TYPE_PROP, cube_handle->prop_handles[prop_index]);
|
||||
if (spawn_index == 0xFFFFFFFF) {
|
||||
recomp_printf("bkrecomp_get_prop_spawn_index: Internal error\n");
|
||||
recomp_abort("Fatal error - Internal error in bkrecomp_get_prop_spawn_index");
|
||||
}
|
||||
|
||||
return spawn_index;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
#include "patches.h"
|
||||
#include "bk_api.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
#include "core2/vla.h"
|
||||
|
||||
typedef union{
|
||||
struct{
|
||||
u32 pad31: 27;
|
||||
u32 unk4: 1;
|
||||
u32 pad3: 1;
|
||||
u32 unk2: 1;
|
||||
u32 unk1: 1;
|
||||
u32 unk0: 1;
|
||||
};
|
||||
u32 word;
|
||||
} tmp_bitfield;
|
||||
|
||||
extern vector(ActorMarker *) *D_80383550;
|
||||
extern vector(ActorMarker *) *D_80383554;
|
||||
|
||||
void propModelList_drawSprite(Gfx **, Mtx **, Vtx **, f32[3], f32, s32, Cube*,s32 ,s32, s32, s32, s32);
|
||||
void propModelList_drawModel(Gfx **, Mtx **, Vtx **, f32[3], f32[3], f32, s32, Cube*);
|
||||
void __marker_draw(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void __cube_sort(Cube *cube, bool global);
|
||||
void func_8032CD60(Prop *);
|
||||
|
||||
// @recomp Patched to add transform tagging when drawing sprite and model props.
|
||||
RECOMP_PATCH void func_8032D510(Cube *cube, Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
Prop *iProp;
|
||||
int i;
|
||||
f32 position[3];
|
||||
f32 rotation[3];
|
||||
tmp_bitfield tmp_v0;
|
||||
int iOffset;
|
||||
ActorMarker **markerPtr;
|
||||
|
||||
if(cube->prop2Cnt == 0 ) return;
|
||||
|
||||
__cube_sort(cube, 0);
|
||||
iOffset = 0;
|
||||
for(i = 0; i < cube->prop2Cnt; i++){//L8032D5A0
|
||||
iOffset = i * 0xC;
|
||||
iProp = (Prop *)((s32)cube->prop2Ptr + iOffset);
|
||||
tmp_v0.word = *(u32 *)((s32)iProp + 0x8);
|
||||
if(!tmp_v0.unk4){
|
||||
|
||||
}else{
|
||||
if(!tmp_v0.unk1){
|
||||
func_8032CD60(iProp);
|
||||
}
|
||||
tmp_v0.word = *(u32 *)((s32)iProp + 0x8);
|
||||
if(tmp_v0.unk0){//actorProp;
|
||||
if(iProp->actorProp.marker->unk40_22){
|
||||
markerPtr = (ActorMarker **)vector_pushBackNew(&D_80383550);
|
||||
*markerPtr = iProp->actorProp.marker;
|
||||
}
|
||||
else if(iProp->actorProp.marker->unk40_19){
|
||||
markerPtr = (ActorMarker **)vector_pushBackNew(&D_80383554);
|
||||
*markerPtr = iProp->actorProp.marker;
|
||||
}
|
||||
else{
|
||||
__marker_draw(iProp->actorProp.marker, gfx, mtx, vtx);
|
||||
}//L8032D62C
|
||||
}
|
||||
else{//L8032D640
|
||||
// @recomp Calculate the base transform ID for the prop.
|
||||
u32 spawn_index = bkrecomp_get_prop_spawn_index(cube, iProp);
|
||||
u32 base_transform_id = spawn_index * PROP_TRANSFORM_ID_COUNT + PROP_TRANSFORM_ID_START;
|
||||
|
||||
position[0] = (f32)iProp->modelProp.position[0];
|
||||
position[1] = (f32)iProp->modelProp.position[1];
|
||||
position[2] = (f32)iProp->modelProp.position[2];
|
||||
if(iProp->is_3d){
|
||||
rotation[0] = 0.0f;
|
||||
rotation[1] = (f32)((s32)iProp->modelProp.yaw*2);
|
||||
rotation[2] = (f32)((s32)iProp->modelProp.roll*2);
|
||||
|
||||
// @recomp Set the model render transform ID before drawing the model.
|
||||
cur_drawn_model_transform_id = base_transform_id;
|
||||
|
||||
propModelList_drawModel(gfx, mtx, vtx,
|
||||
position, rotation, (f32)iProp->modelProp.scale/100.0,
|
||||
iProp->modelProp.model_index, cube
|
||||
);
|
||||
|
||||
|
||||
// @recomp Clear the model render transform ID after drawing the model.
|
||||
cur_drawn_model_transform_id = 0;
|
||||
}
|
||||
else{//L8032D72C
|
||||
// @recomp Set the matrix group before drawing the sprite.
|
||||
// Skip interpolation on vertices to account for vertex lists changing between frames of the sprite.
|
||||
// Also skip interpolation on scale to account for the scale inverting when sprites are mirrored.
|
||||
// TODO track this matrix for skipping interpolation when camera interpolation is skipped.
|
||||
gEXMatrixGroupDecomposed((*gfx)++, base_transform_id, G_EX_PUSH, G_MTX_MODELVIEW,
|
||||
G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE,
|
||||
G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE,
|
||||
G_EX_ORDER_LINEAR, G_EX_EDIT_ALLOW, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_AUTO);
|
||||
|
||||
// @recomp Also set the model render transform ID before drawing the sprite. This won't have any effect
|
||||
// in the unmodified game, but will allow transform tagging for mods that draw models in place of sprites.
|
||||
cur_drawn_model_transform_id = base_transform_id;
|
||||
|
||||
propModelList_drawSprite(gfx, mtx, vtx,
|
||||
position, (f32)iProp->spriteProp.scale/100.0, iProp->spriteProp.sprite_index, cube,
|
||||
iProp->spriteProp.r, iProp->spriteProp.b, iProp->spriteProp.g,
|
||||
iProp->spriteProp.mirrored, iProp->spriteProp.frame
|
||||
);
|
||||
|
||||
// @recomp Pop the sprite's matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Clear the model render transform ID after drawing the sprite.
|
||||
cur_drawn_model_transform_id = 0;
|
||||
}
|
||||
}//L8032D7C4
|
||||
}
|
||||
iOffset+=0xC;
|
||||
}//L8032D7D4
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "patches.h"
|
||||
#include "functions.h"
|
||||
|
||||
extern vector(struct21s) *D_80383CE0[2];
|
||||
|
||||
#define PRINT_DEFRAG_CHANGES 0
|
||||
|
||||
// @recomp Patched to just use a normal DMA.
|
||||
RECOMP_PATCH s32 boot_osPiRawStartDma(s32 direction, u32 devAddr, void *dramAddr, u32 size) {
|
||||
OSMesgQueue mq;
|
||||
OSMesg buffer;
|
||||
OSIoMesg io;
|
||||
osCreateMesgQueue(&mq, &buffer, 1);
|
||||
|
||||
// Complete the DMA synchronously (the game immediately waits until it's done anyways)
|
||||
osPiStartDma(&io, OS_MESG_PRI_HIGH, direction, devAddr, dramAddr, size, &mq);
|
||||
osRecvMesg(&mq, NULL, OS_MESG_BLOCK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to not read hardware registers.
|
||||
RECOMP_PATCH s32 boot_osPiGetStatus() {
|
||||
// PI not busy
|
||||
return 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to fix a bug where defrag was used instead of vector_defrag, which would break these vectors
|
||||
// if the defrag call moved the vector's memory.
|
||||
RECOMP_PATCH void func_8033B268(void) {
|
||||
#if PRINT_DEFRAG_CHANGES
|
||||
vector(struct21s) *old_0 = D_80383CE0[0];
|
||||
vector(struct21s) *old_1 = D_80383CE0[1];
|
||||
#endif
|
||||
|
||||
D_80383CE0[0] = (vector(struct21s) *)vector_defrag(D_80383CE0[0]);
|
||||
D_80383CE0[1] = (vector(struct21s) *)vector_defrag(D_80383CE0[1]);
|
||||
|
||||
#if PRINT_DEFRAG_CHANGES
|
||||
if (D_80383CE0[0] != old_0) {
|
||||
recomp_printf("vector_defrag() moved D_80383CE0[0] from 0x%08X to 0x%08X.\n", old_0, D_80383CE0[0]);
|
||||
}
|
||||
|
||||
if (D_80383CE0[1] != old_1) {
|
||||
recomp_printf("vector_defrag() moved D_80383CE0[1] from 0x%08X to 0x%08X.\n", old_1, D_80383CE0[1]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "core1/core1.h"
|
||||
|
||||
typedef struct {
|
||||
s16 model_id;
|
||||
// u8 pad2[0x2];
|
||||
f32 scale;
|
||||
f32 rotation_speed;
|
||||
}SkyInfo;
|
||||
|
||||
typedef struct {
|
||||
s16 map;
|
||||
// u8 pad2[2];
|
||||
SkyInfo sky_list[3];
|
||||
}MapSkyInfo;
|
||||
|
||||
extern struct
|
||||
{
|
||||
MapSkyInfo *sky_info;
|
||||
BKModel *model[3];
|
||||
BKModelBin *model_bins[3];
|
||||
f32 timer;
|
||||
} gcSky;
|
||||
|
||||
// @recomp Patched to tag the skybox projection and skybox models.
|
||||
RECOMP_PATCH void sky_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
int i;
|
||||
f32 position[3];
|
||||
f32 rotation[3];
|
||||
BKModelBin *iAsset;
|
||||
|
||||
viewport_setNearAndFar(5.0f, 15000.0f);
|
||||
if(gcSky.model_bins[0]){
|
||||
drawRectangle2D(gfx, 0, 0, (s32)(f32) gFramebufferWidth, (s32)(f32)gFramebufferHeight,0, 0, 0); //fill screen with black
|
||||
// @recomp Set the skybox projection matrix group.
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, PROJECTION_SKYBOX_TRANSFORM_ID, G_EX_PUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE);
|
||||
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
viewport_getPosition_vec3f(position);
|
||||
for(i = 0; i < 3; i++){
|
||||
iAsset = gcSky.model_bins[i];
|
||||
if(iAsset){
|
||||
rotation[0] = 0.0f;
|
||||
rotation[1] = gcSky.sky_info->sky_list[i].rotation_speed * gcSky.timer;
|
||||
rotation[2] = 0.0f;
|
||||
|
||||
// @recomp Set the model transform ID before drawing the skybox.
|
||||
cur_drawn_model_transform_id = SKYBOX_TRANSFORM_ID_START + SKYBOX_MODEL_TRANSFORM_ID_COUNT * i;
|
||||
|
||||
modelRender_draw(gfx, mtx, position, rotation, gcSky.sky_info->sky_list[i].scale, NULL, iAsset);
|
||||
|
||||
// @recomp Clear the model transform ID after drawing the skybox.
|
||||
cur_drawn_model_transform_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Pop the skybox projection matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_PROJECTION);
|
||||
}
|
||||
else{//L8030B200
|
||||
drawRectangle2D(gfx, 0, 0, (s32)(f32) gFramebufferWidth, (s32)(f32)gFramebufferHeight, 0, 0, 0);
|
||||
}//L8030B254
|
||||
}
|
||||
+10
-7
@@ -18,13 +18,13 @@ osDpSetStatus_recomp = 0x8F000034;
|
||||
malloc_recomp = 0x8F000038;
|
||||
free_recomp = 0x8F00003C;
|
||||
realloc_recomp = 0x8F000040;
|
||||
recomp_register_actor_extension = 0x8F000044;
|
||||
recomp_register_actor_extension_generic = 0x8F000048;
|
||||
recomp_clear_all_actor_data = 0x8F00004C;
|
||||
recomp_create_actor_data = 0x8F000050;
|
||||
recomp_destroy_actor_data = 0x8F000054;
|
||||
recomp_get_actor_data = 0x8F000058;
|
||||
recomp_get_actor_spawn_index = 0x8F00005C;
|
||||
recomp_register_object_extension = 0x8F000044;
|
||||
recomp_register_object_extension_generic = 0x8F000048;
|
||||
recomp_clear_all_object_data = 0x8F00004C;
|
||||
recomp_create_object_data = 0x8F000050;
|
||||
recomp_destroy_object_data = 0x8F000054;
|
||||
recomp_get_object_data = 0x8F000058;
|
||||
recomp_get_object_spawn_index = 0x8F00005C;
|
||||
recomp_error = 0x8F000060;
|
||||
memcpy_recomp = 0x8F000064;
|
||||
__divdi3_recomp = 0x8F000068;
|
||||
@@ -32,3 +32,6 @@ __udivdi3_recomp = 0x8F00006C;
|
||||
__umoddi3_recomp = 0x8F000070;
|
||||
strlen_recomp = 0x8F000074;
|
||||
osVirtualToPhysical_recomp = 0x8F000078;
|
||||
osPiStartDma_recomp = 0x8F00007C;
|
||||
recomp_abort = 0x8F000080;
|
||||
recomp_get_target_aspect_ratio = 0x8F000084;
|
||||
|
||||
@@ -0,0 +1,525 @@
|
||||
#include "patches.h"
|
||||
#include "core1/core1.h"
|
||||
#include "functions.h"
|
||||
#include "misc_funcs.h"
|
||||
|
||||
BKSpriteTextureBlock font_base_texture;
|
||||
u8 font_base_texture_data[0x800];
|
||||
|
||||
typedef struct{
|
||||
s16 x;
|
||||
s16 y;
|
||||
s16 unk4;
|
||||
s16 unk6;
|
||||
u8 fmtString[8];
|
||||
f32 unk10;
|
||||
u8 *string;
|
||||
u8 rgba[4];
|
||||
} PrintBuffer;
|
||||
|
||||
typedef struct font_letter{
|
||||
BKSpriteTextureBlock *unk0;//chunkPtr
|
||||
void *unk4;//palPtr
|
||||
} FontLetter;
|
||||
|
||||
typedef struct map_font_texture_map{
|
||||
s16 mapID;
|
||||
s16 assetId;
|
||||
} MapFontTextureMap;
|
||||
|
||||
typedef struct{
|
||||
u8 unk0;
|
||||
u8 unk1;
|
||||
s8 unk2;
|
||||
s8 unk3;
|
||||
}Struct_6DA30_0_s;
|
||||
|
||||
extern Struct_6DA30_0_s D_80369000[];
|
||||
extern s32 D_80369068[];
|
||||
extern struct {
|
||||
u8 unk0;
|
||||
u8 unk1;
|
||||
u8 unk2;
|
||||
u8 unk3;
|
||||
} D_80369078;
|
||||
|
||||
extern MapFontTextureMap D_8036907C[];
|
||||
extern char D_80369200[];
|
||||
extern Gfx D_80369238[];
|
||||
|
||||
extern char D_80380AB0;
|
||||
extern BKSprite *D_80380AB8[0x5];
|
||||
|
||||
extern FontLetter *print_sFonts[4];
|
||||
extern PrintBuffer *print_sPrintBuffer;
|
||||
extern PrintBuffer *print_sCurrentPtr;
|
||||
extern s32 D_80380AE8;
|
||||
extern s32 D_80380AEC;
|
||||
extern s32 D_80380AF0; //print_sMonospaced
|
||||
extern s32 D_80380AF4;
|
||||
extern s32 D_80380AF8;
|
||||
extern s32 D_80380AFC;
|
||||
extern s32 D_80380B00;
|
||||
extern s32 D_80380B04;
|
||||
extern bool print_sInFontFormatMode;
|
||||
extern s32 D_80380B0C;
|
||||
extern s32 D_80380B10;
|
||||
extern s32 D_80380B14;
|
||||
extern s32 D_80380B18;
|
||||
extern s32 D_80380B1C;
|
||||
extern s8 D_80380B20[0x400];
|
||||
extern s8 D_80380F20[0x80];
|
||||
|
||||
BKSpriteTextureBlock *func_802F5494(s32 letterId, s32 *fontType);
|
||||
void *func_802F55A8(u8 arg0);
|
||||
|
||||
#define SPRITE_TYPE_IA16_MASK (1 << 12)
|
||||
|
||||
// Creates an IA16 texture that mimics the behavior of the operation done in func_802F4A24.
|
||||
// The masking operation is moved to the color combiner, allowing texture packs to replace the individual mask textures
|
||||
// instead of having to replace every single combination of mask and base texture.
|
||||
void unpack_rgba32_to_ia16(BKSpriteTextureBlock *alphaMask) {
|
||||
u32 *pxl_in;
|
||||
u16 *pxl_out;
|
||||
s32 x;
|
||||
s32 y;
|
||||
|
||||
pxl_in = (u32*)(alphaMask + 1);
|
||||
pxl_out = (u16*)(pxl_in);
|
||||
|
||||
int width_padding = (-alphaMask->w) & 0x3;
|
||||
|
||||
recomp_printf("Size: %-3d %-3d %-3d %-3d (%d)\n", alphaMask->w, alphaMask->h, alphaMask->x, alphaMask->y, width_padding);
|
||||
|
||||
for (y = 0; y < alphaMask->h; y++) {
|
||||
for (x = 0; x < alphaMask->w; x++) {
|
||||
s32 b = (*pxl_in >> 8) & 0xFF;
|
||||
s32 a = (*pxl_in >> 0) & 0xFF;
|
||||
// The original function divides the intensity by 0x1F, so repeat that here and then undo the division to scale back to 8-bit color depth.
|
||||
b /= 0x1F;
|
||||
b *= 0x1F;
|
||||
*pxl_out = (b << 8) | (a << 0);
|
||||
pxl_in++;
|
||||
pxl_out++;
|
||||
}
|
||||
for (int i = 0; i < width_padding; i++) {
|
||||
*pxl_out = 0;
|
||||
pxl_out++;
|
||||
}
|
||||
}
|
||||
|
||||
alphaMask->w += width_padding;
|
||||
}
|
||||
|
||||
void darken_blue_channel(BKSpriteTextureBlock *alphaMask) {
|
||||
u32 *pxl;
|
||||
s32 x;
|
||||
s32 y;
|
||||
|
||||
pxl = (u32*)(alphaMask + 1);
|
||||
|
||||
for (y = 0; y < alphaMask->h; y++) {
|
||||
for (x = 0; x < alphaMask->w; x++) {
|
||||
s32 masked_data = *pxl & 0xFFFF00FF;
|
||||
s32 b = (*pxl >> 8) & 0xFF;
|
||||
// The original function divides the intensity by 0x1F, so repeat that here and then undo the division to scale back to 8-bit color depth.
|
||||
b /= 0x1F;
|
||||
b *= 0x1F;
|
||||
|
||||
*pxl = masked_data | (b << 8);
|
||||
pxl++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to turn RGBA32 alpha masks into IA16 ones instead of mixing the texture sprite into the mask.
|
||||
// This works because the game only uses the blue and alpha channels (as intensity and alpha respectively).
|
||||
// The texture sprite will be incorporated during rendering by using the color combiner, allowing fewer texture replacements
|
||||
// for a texture pack while maintaining an identical appearance.
|
||||
RECOMP_PATCH FontLetter *func_802F4C3C(BKSprite *alphaMask, BKSprite *textureSprite){
|
||||
BKSpriteFrame * font = sprite_getFramePtr(alphaMask, 0);
|
||||
BKSpriteTextureBlock *chunkPtr;
|
||||
FontLetter * sp2C = malloc((font->chunkCnt + 1)*sizeof(FontLetter));
|
||||
u8* palDataPtr;
|
||||
u8* chunkDataPtr;
|
||||
s32 chunkSize;
|
||||
s32 i;
|
||||
|
||||
|
||||
switch(alphaMask->type){
|
||||
case SPRITE_TYPE_CI8:
|
||||
{//L802F4CA8
|
||||
chunkPtr = (BKSpriteTextureBlock *) (font + 1);
|
||||
chunkDataPtr = (u8 *)chunkPtr;
|
||||
while((s32)chunkDataPtr % 8)
|
||||
chunkDataPtr++;
|
||||
|
||||
palDataPtr = chunkDataPtr;
|
||||
chunkPtr = (BKSpriteTextureBlock *) (palDataPtr + 2*0x100);
|
||||
|
||||
for(i= 0; i < font->chunkCnt; i++){
|
||||
|
||||
chunkDataPtr = (u8*)(chunkPtr + 1);
|
||||
while((s32)chunkDataPtr % 8)
|
||||
chunkDataPtr++;
|
||||
|
||||
sp2C[i].unk0 = chunkPtr;
|
||||
sp2C[i].unk4 = palDataPtr;
|
||||
chunkSize = chunkPtr->w*chunkPtr->h;
|
||||
chunkPtr = (BKSpriteTextureBlock *)(chunkDataPtr + chunkSize);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPRITE_TYPE_RGBA32://L802F4D80
|
||||
{
|
||||
// @recomp Replace the alpha mask's format with IA16 to match what it will be unpacked as.
|
||||
alphaMask->type = SPRITE_TYPE_IA16_MASK;
|
||||
|
||||
// @recomp Copy the texture sprite's data into the font texture data buffer.
|
||||
BKSpriteTextureBlock* base_texture = (BKSpriteTextureBlock *)(sprite_getFramePtr(textureSprite, 0) + 1);
|
||||
font_base_texture = *base_texture;
|
||||
u16* pixels_in = ((u16*)(base_texture + 1));
|
||||
memcpy(font_base_texture_data, pixels_in, base_texture->w * base_texture->h * sizeof(u16));
|
||||
|
||||
chunkPtr = (BKSpriteTextureBlock *)(font + 1);
|
||||
for( i = 0; i < font->chunkCnt; i++){
|
||||
// @recomp Remove the texture mixing and darken the blue channel of each pixel to mimic the division done in the original pixel math.
|
||||
darken_blue_channel(chunkPtr);
|
||||
// unpack_rgba32_to_ia16(chunkPtr);
|
||||
|
||||
sp2C[i].unk0 = chunkPtr;
|
||||
chunkSize = chunkPtr->w*chunkPtr->h;
|
||||
chunkDataPtr = (u8*)(chunkPtr + 1);
|
||||
while((s32)chunkDataPtr % 8)
|
||||
chunkDataPtr++;
|
||||
chunkPtr = (BKSpriteTextureBlock *) (chunkDataPtr + chunkSize*4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPRITE_TYPE_I4://L802F4E24
|
||||
{
|
||||
chunkPtr = (BKSpriteTextureBlock *) (font + 1);
|
||||
for( i = 0; i < font->chunkCnt; i++){
|
||||
sp2C[i].unk0 = chunkPtr;
|
||||
chunkDataPtr = (u8*)(chunkPtr + 1);
|
||||
chunkSize = chunkPtr->w*chunkPtr->h;
|
||||
while((s32)chunkDataPtr % 8)
|
||||
chunkDataPtr++;
|
||||
chunkPtr = (BKSpriteTextureBlock *) (chunkDataPtr + chunkSize/2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default://L802F4EC0
|
||||
{
|
||||
chunkPtr = (BKSpriteTextureBlock *)(font + 1);
|
||||
for( i = 0; i < font->chunkCnt; i++){
|
||||
chunkDataPtr = (u8*)(chunkPtr + 1);
|
||||
sp2C[i].unk0 = chunkPtr;
|
||||
chunkSize = chunkPtr->w*chunkPtr->h;
|
||||
while((s32)chunkDataPtr % 8)
|
||||
chunkDataPtr++;
|
||||
chunkPtr = (BKSpriteTextureBlock *)(chunkDataPtr + chunkSize);
|
||||
}
|
||||
}
|
||||
break;
|
||||
};
|
||||
return sp2C;
|
||||
}
|
||||
|
||||
// @recomp Patched to add the ability to load IA16 masks.
|
||||
RECOMP_PATCH void _printbuffer_draw_letter(char letter, f32* xPtr, f32* yPtr, f32 arg3, Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
static f32 D_80380FA0;
|
||||
|
||||
// u8 letter = arg0;
|
||||
BKSpriteTextureBlock *sp214;
|
||||
s32 sp210;
|
||||
s32 sp20C;
|
||||
s32 t0;
|
||||
s8 t1;
|
||||
f32 sp200;
|
||||
f32 f28;
|
||||
f32 sp1F8;
|
||||
s32 sp1F4; //font_type;
|
||||
|
||||
int i;
|
||||
|
||||
|
||||
|
||||
t0 = 0;
|
||||
sp200 = *xPtr;
|
||||
f28 = *yPtr;
|
||||
t1 = 0;
|
||||
|
||||
if(!D_80380B04 && !letter){
|
||||
D_80380FA0 = 0.0f;
|
||||
}//L802F563C
|
||||
|
||||
switch(D_80380AE8){
|
||||
case 0: //L802F5678
|
||||
if(letter >= '\x21' && letter < '\x5f'){
|
||||
sp20C = letter - '\x21';
|
||||
t0 = 1;
|
||||
}
|
||||
break;
|
||||
case 1: //L802F56A0
|
||||
if(letter < '\x80' && D_80380F20[(unsigned char)letter] >= 0){
|
||||
for(i = 0; D_80369000[i].unk0 != 0; i++){
|
||||
if(letter == D_80369000[i].unk1 && D_80380AB0 == D_80369000[i].unk0){
|
||||
t1 = D_80369000[i].unk3;
|
||||
break;
|
||||
}
|
||||
}//L802F5710
|
||||
sp20C = D_80380F20[(unsigned char)letter];
|
||||
t0 = 1;
|
||||
D_80380AB0 = letter;
|
||||
f28 += (f32)t1*arg3;
|
||||
}//L802F5738
|
||||
break;
|
||||
case 2: //L802F5740
|
||||
sp20C = letter;
|
||||
if(D_80380B04){
|
||||
t0 = 1;
|
||||
sp20C += (D_80380B04 << 8) - 0x100;
|
||||
D_80380B04 = 0;
|
||||
}
|
||||
else{//L802F5764
|
||||
if(sp20C > 0 && sp20C < 0xfD)
|
||||
t0 = 1;
|
||||
}
|
||||
break;
|
||||
}//L802F5778
|
||||
|
||||
if(!t0 || print_sInFontFormatMode){
|
||||
print_sInFontFormatMode = FALSE;
|
||||
switch(letter){
|
||||
case ' '://802F5818
|
||||
*xPtr += ((D_80380AF0) ? D_80369068[D_80380AE8]: D_80369068[D_80380AE8]*0.8) * arg3;
|
||||
break;
|
||||
|
||||
case 'b': //L802F5890
|
||||
//toggle background
|
||||
D_80380B00 = D_80380B00 ^ 1;
|
||||
break;
|
||||
|
||||
case 'f': //L802F58A8
|
||||
D_80380AEC = D_80380AE8 = D_80380AE8 ^ 1;
|
||||
break;
|
||||
|
||||
case 'l': //L802F58BC
|
||||
D_80380B10 = 0;
|
||||
break;
|
||||
|
||||
case 'h': //L802F58C8
|
||||
D_80380B10 = 1;
|
||||
break;
|
||||
|
||||
case 'j': //L802F58D4
|
||||
if(D_80380AFC == 0){
|
||||
D_80380AFC = 1;
|
||||
D_80380AEC = D_80380AE8;
|
||||
D_80380AE8 = 2;
|
||||
// D_80380AE8 = 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'e': //L802F58FC
|
||||
if(D_80380AFC){
|
||||
D_80380AFC = 0;
|
||||
D_80380AE8 = D_80380AEC;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p': //L802F5924
|
||||
D_80380AF0 = D_80380AF0 ^1;
|
||||
break;
|
||||
|
||||
case 'q': //L802F593C
|
||||
D_80380B14 = D_80380B14^1;
|
||||
if(D_80380B14){
|
||||
gDPSetTextureFilter((*gfx)++, G_TF_POINT);
|
||||
}
|
||||
else{//L802F5978
|
||||
gDPSetTextureFilter((*gfx)++, G_TF_BILERP);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v': //L802F59A0
|
||||
//toggle letter gradient
|
||||
D_80380AF4 ^= 1;
|
||||
if(D_80380AF4){
|
||||
viewport_setRenderViewportAndOrthoMatrix(gfx, mtx);
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetTexturePersp((*gfx)++, G_TP_PERSP);
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, 0x00, 0x00, 0x00, 0xFF);
|
||||
gDPSetCombineLERP((*gfx)++, 0, 0, 0, TEXEL0, TEXEL0, 0, SHADE, 0, 0, 0, 0, TEXEL0, TEXEL0, 0, SHADE, 0);
|
||||
}
|
||||
else{//L802F5A44
|
||||
gDPSetCombineMode((*gfx)++, G_CC_DECALRGBA, G_CC_DECALRGBA);
|
||||
gDPSetTexturePersp((*gfx)++, G_TP_NONE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd': //L802F5A8C
|
||||
D_80380AF8 ^= 1;
|
||||
if(D_80380AF8){
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetCycleType((*gfx)++, G_CYC_2CYCLE);
|
||||
gDPSetRenderMode((*gfx)++, G_RM_PASS, G_RM_XLU_SURF2);
|
||||
gDPSetTextureLOD((*gfx)++, G_TL_TILE);
|
||||
gDPSetCombineLERP((*gfx)++, 0, 0, 0, TEXEL0, TEXEL0, 0, TEXEL1, 0, 0, 0, 0, COMBINED, 0, 0, 0, COMBINED);
|
||||
}
|
||||
else{//L802F5B48
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetCombineMode((*gfx)++, G_CC_DECALRGBA, G_CC_DECALRGBA);
|
||||
gDPSetCycleType((*gfx)++, G_CYC_1CYCLE);
|
||||
gDPSetTextureLOD((*gfx)++, G_TL_LOD);
|
||||
gDPSetRenderMode((*gfx)++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xfd: //L802F5BEC
|
||||
print_sInFontFormatMode = TRUE;
|
||||
break;
|
||||
|
||||
case 0xfe://L802F5BF4
|
||||
D_80380B04 = 1;
|
||||
break;
|
||||
|
||||
case 0xff://L802F5BFC
|
||||
D_80380B04 = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{//L802F5C08
|
||||
sp214 = func_802F5494(sp20C, &sp1F4);
|
||||
if (D_80380B10 != 0) {
|
||||
sp200 += randf2(-2.0f, 2.0f);
|
||||
f28 += randf2(-2.0f, 2.0f);
|
||||
}
|
||||
sp1F8 = (D_80380AF0 != 0) ? D_80369068[D_80380AE8] : sp214->x;
|
||||
|
||||
// temp_f2 = D_80380FA0;
|
||||
// phi_f2 = temp_f2;
|
||||
if (D_80380FA0 == 0.0f) {
|
||||
D_80380FA0 = -sp1F8 * 0.5;
|
||||
}
|
||||
|
||||
// @recomp Track the texture scroll offset. Only nonzero if the font is an IA16 mask.
|
||||
s32 scroll_x = 0;
|
||||
s32 scroll_y = 0;
|
||||
|
||||
sp200 += (D_80380FA0 + (sp1F8 - sp214->x) * 0.5);
|
||||
f28 -= sp214->h*0.5;
|
||||
sp210 = (s32)(sp214 + 1);
|
||||
while(sp210 % 8){
|
||||
sp210++;
|
||||
}
|
||||
if (sp1F4 == SPRITE_TYPE_RGBA32) {
|
||||
gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_RGBA, G_IM_SIZ_32b, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y - 1, NULL, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
} else if (sp1F4 == SPRITE_TYPE_IA8) {
|
||||
gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_IA, G_IM_SIZ_8b, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y - 1, NULL, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
} else if (sp1F4 == SPRITE_TYPE_I8) {
|
||||
gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_I, G_IM_SIZ_8b, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y - 1, NULL, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
} else if (sp1F4 == SPRITE_TYPE_I4) {
|
||||
gDPLoadTextureTile_4b((*gfx)++, sp210, G_IM_FMT_I, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y-1, NULL, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
} else if (sp1F4 == SPRITE_TYPE_CI8) {
|
||||
void * pal = func_802F55A8(sp20C);
|
||||
gDPLoadTLUT_pal256((*gfx)++, pal);
|
||||
gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_CI, G_IM_SIZ_8b, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y-1, NULL, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
gDPSetTextureLUT((*gfx)++, G_TT_RGBA16);
|
||||
}//L802F6570
|
||||
// @recomp Add a case for handling the new IA16 mask sprite type.
|
||||
else if (sp1F4 == SPRITE_TYPE_IA16_MASK) {
|
||||
if (D_80380AF8) {
|
||||
recomp_error("Tried to use IA16 mask font and two texture font at the same time");
|
||||
}
|
||||
|
||||
scroll_x = ((font_base_texture.w - sp214->w) >> 1);
|
||||
scroll_y = ((font_base_texture.h - sp214->h) >> 1);
|
||||
|
||||
gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_RGBA, G_IM_SIZ_32b, sp214->w, sp214->h, 0, 0, sp214->x-1, sp214->y - 1, NULL, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
gDPSetTile((*gfx)++, G_IM_FMT_IA, G_IM_SIZ_16b, (((((sp214->x - 1)-(0)+1) * G_IM_SIZ_16b_TILE_BYTES)+7)>>3), 0x100, 0, 0, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD);
|
||||
gDPLoadMultiTile((*gfx)++, font_base_texture_data, 0x00, 1, G_IM_FMT_RGBA, G_IM_SIZ_16b,
|
||||
font_base_texture.w, font_base_texture.h,
|
||||
0, 0,
|
||||
font_base_texture.w - 1, font_base_texture.h - 1,
|
||||
0,
|
||||
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP,
|
||||
G_TX_NOMASK, G_TX_NOMASK,
|
||||
G_TX_NOLOD, G_TX_NOLOD);
|
||||
gEXPushOtherMode((*gfx)++);
|
||||
gEXPushCombineMode((*gfx)++);
|
||||
gDPSetCycleType((*gfx)++, G_CYC_2CYCLE);
|
||||
gDPSetRenderMode((*gfx)++, G_RM_PASS, G_RM_XLU_SURF2);
|
||||
gDPSetTextureLOD((*gfx)++, G_TL_TILE);
|
||||
gDPSetCombineLERP((*gfx)++, TEXEL0, 0, TEXEL1, 0, 0, 0, 0, TEXEL0, 0, 0, 0, COMBINED, 0, 0, 0, COMBINED);
|
||||
|
||||
gDPSetTileSize((*gfx)++, 0, scroll_x * 4, scroll_y * 4, (scroll_x + sp214->x - 1) * 4, (scroll_y + sp214->y - 1) * 4);
|
||||
}
|
||||
if (D_80380AF8 != 0) {
|
||||
s32 temp_t1;
|
||||
s32 phi_a0;
|
||||
temp_t1 = ((print_sCurrentPtr->unk4 - print_sCurrentPtr->y) - D_80380B0C) + 1;
|
||||
phi_a0 = - MAX(1 - D_80380B0C, MIN(0, temp_t1));
|
||||
|
||||
gDPSetTextureImage((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, 32, &D_80380B20);
|
||||
gDPSetTile((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, (sp214->x + 8) >> 3, 0x0100, G_TX_LOADTILE, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD);
|
||||
gDPLoadSync((*gfx)++);
|
||||
gDPLoadTile((*gfx)++, G_TX_LOADTILE, 0 << G_TEXTURE_IMAGE_FRAC, (phi_a0) << G_TEXTURE_IMAGE_FRAC, (sp214->x) << G_TEXTURE_IMAGE_FRAC, (D_80380B0C - 1) << G_TEXTURE_IMAGE_FRAC);
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetTile((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, ((sp214->x - 0 + 1)*G_IM_SIZ_8b_LINE_BYTES + 7) >> 3, 0x0100, 1, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD);
|
||||
gDPSetTileSize((*gfx)++, 1, 0 << G_TEXTURE_IMAGE_FRAC, (MAX(0, temp_t1) + phi_a0) << G_TEXTURE_IMAGE_FRAC, (sp214->x) << G_TEXTURE_IMAGE_FRAC, (MAX(0, temp_t1) - (1 - D_80380B0C))<<G_TEXTURE_IMAGE_FRAC);
|
||||
|
||||
// gDPLoadMultiTile((*gfx)++, &D_80380B20,)
|
||||
|
||||
}//L802F677C
|
||||
if (D_80380AF4 != 0) {
|
||||
f32 temp_f24;
|
||||
f32 spD0;
|
||||
f32 ix;
|
||||
f32 iy;
|
||||
f32 temp_f26;
|
||||
f32 spC0;
|
||||
|
||||
temp_f24 = (sp214->x - 1.0);
|
||||
spD0 = sp214->y - 1.0;
|
||||
temp_f26 = (f64) sp200 - (f32) gFramebufferWidth * 0.5;
|
||||
spC0 = (f64)f28 - (f32)gFramebufferHeight*0.5 -0.5f;
|
||||
gSPVertex((*gfx)++, *vtx, 4, 0);
|
||||
for(iy = 0.0f; iy < 2.0; iy+= 1.0){
|
||||
for(ix = 0.0f; ix < 2.0; ix += 1.0){
|
||||
s32 s = (ix * temp_f24 * 64.0f);
|
||||
// @recomp Add the texture scroll.
|
||||
s += scroll_x * 64;
|
||||
(*vtx)->v.ob[0] = (s16)(s32)((f64) (temp_f26 + (temp_f24 * arg3 * ix)) * 4.0);
|
||||
{
|
||||
s32 t = (iy * spD0 * 64.0f);
|
||||
// @recomp Add the texture scroll.
|
||||
t += scroll_y * 64;
|
||||
(*vtx)->v.ob[1] = (s16) (s32) ((f64) (spC0 + (spD0 * arg3 * iy)) * -4.0);
|
||||
(*vtx)->v.ob[2] = -0x14;
|
||||
(*vtx)->v.tc[0] = s;
|
||||
(*vtx)->v.tc[1] = t;
|
||||
}
|
||||
(*vtx)->v.cn[3] =(iy != 0.0f) ? print_sCurrentPtr->unk6 : print_sCurrentPtr->unk4;
|
||||
|
||||
(*vtx)++;
|
||||
}
|
||||
}
|
||||
|
||||
gSP1Quadrangle((*gfx)++, 0, 1, 3, 2, 0);
|
||||
}
|
||||
else{
|
||||
gSPScisTextureRectangle((*gfx)++, (s32)(sp200*4.0f), (s32)(f28*4.0f), (s32)((sp200 + sp214->x*arg3)*4.0f), (s32)((f28 + sp214->y*arg3)*4.0f), 0, scroll_x * 32, scroll_y * 32, (s32)(1024.0f / arg3), (s32)(1024.0f / arg3));
|
||||
}
|
||||
// @recomp Reset the othermode after drawing the character.
|
||||
if (sp1F4 == SPRITE_TYPE_IA16_MASK) {
|
||||
gEXPopOtherMode((*gfx)++);
|
||||
gEXPopCombineMode((*gfx)++);
|
||||
}
|
||||
*xPtr += sp1F8 * arg3;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ extern Struct_core2_9B180_0 D_8036DE00[];
|
||||
void func_80322318(Struct_core2_9B180_0*);
|
||||
int map_get(void);
|
||||
|
||||
// @recomp Patched to always allow skipping the intro sequence.
|
||||
RECOMP_PATCH void func_80322490(void) {
|
||||
Struct_core2_9B180_0 *i_ptr;
|
||||
|
||||
|
||||
+46
-2
@@ -1,8 +1,52 @@
|
||||
#ifndef __TRANSFORM_IDS_H__
|
||||
#define __TRANSFORM_IDS_H__
|
||||
|
||||
#define ACTOR_TRANSFORM_ID_COUNT 256 // Number of transform IDs for each actor.
|
||||
#include "PR/ultratypes.h"
|
||||
#include "rt64_extended_gbi.h"
|
||||
|
||||
#define PROJECTION_GAMEPLAY_TRANSFORM_ID 0x00001000
|
||||
#define PROJECTION_SKYBOX_TRANSFORM_ID 0x00001001
|
||||
#define PROJECTION_TRANSITION_TRANSFORM_ID 0x00001002
|
||||
#define PROJECTION_PRESS_START_TRANSFORM_ID 0x00001003
|
||||
#define PROJECTION_BOTTLES_BONUS_TRANSFORM_ID 0x00001004
|
||||
#define PROJECTION_BK_LOGO_TRANSFORM_ID 0x00001005
|
||||
#define PROJECTION_COPYRIGHT_TRANSFORM_ID 0x00001006
|
||||
#define PROJECTION_GAME_OVER_TRANSFORM_ID 0x00001007
|
||||
#define PROJECTION_THE_END_TRANSFORM_ID 0x00001008
|
||||
#define PROJECTION_PORTRAIT_TRANSFORM_ID_START 0x00001100 // 1 for each portrait ID
|
||||
|
||||
#define MAP_MODEL_OPA_TRANSFORM_ID_START 0x00400000
|
||||
#define MAP_MODEL_XLU_TRANSFORM_ID_START 0x00800000
|
||||
|
||||
#define TRANSITION_MODEL_TRANSFORM_ID_START 0x00F00000
|
||||
|
||||
#define SKYBOX_MODEL_TRANSFORM_ID_COUNT 256
|
||||
#define SKYBOX_TRANSFORM_ID_START 0x00F20000
|
||||
|
||||
#define ZOOMBOX_TRANSFORM_ID_START 0x00F30000
|
||||
#define ZOOMBOX_PORTRAIT_TRANSFORM_ID_START 0x00F31000
|
||||
|
||||
#define PROJECTILE_TRANSFORM_ID_START 0x00F32000
|
||||
|
||||
#define MARKER_TRANSFORM_ID_COUNT 256 // Number of transform IDs for each ActorMarker.
|
||||
#define BANJO_TRANSFORM_ID_START 0x01000000
|
||||
#define ACTOR_TRANSFORM_ID_START (BANJO_TRANSFORM_ID_START + ACTOR_TRANSFORM_ID_COUNT)
|
||||
#define MARKER_TRANSFORM_ID_START (BANJO_TRANSFORM_ID_START + MARKER_TRANSFORM_ID_COUNT)
|
||||
|
||||
#define PROP_TRANSFORM_ID_COUNT 256
|
||||
#define PROP_TRANSFORM_ID_START 0x02000000
|
||||
|
||||
#define PARTICLE_EMITTER_TRANSFORM_ID_COUNT (256 * 256) // Number of transform IDs for each particle manager.
|
||||
#define PARTICLE_MODEL_TRANSFORM_ID_COUNT 256 // Number of transform IDs for each model particle.
|
||||
#define PARTICLE_EMITTER_MODEL_ID_COUNT (PARTICLE_EMITTER_TRANSFORM_ID_COUNT / PARTICLE_MODEL_TRANSFORM_ID_COUNT) // Number of model transform IDs for a model particle emitter.
|
||||
#define PARTICLE_TRANSFORM_ID_START 0x03000000
|
||||
#define PARTICLE_EMITTER_TRANSFORM_ID_TOTAL 0x02000000
|
||||
#define PARTICLE_EMITTER_MAX_ID (PARTICLE_EMITTER_TRANSFORM_ID_TOTAL / PARTICLE_EMITTER_TRANSFORM_ID_COUNT)
|
||||
|
||||
void reset_projection_ids();
|
||||
|
||||
extern s32 cur_drawn_model_is_map;
|
||||
extern s32 cur_drawn_model_transform_id;
|
||||
extern s32 cur_perspective_projection_transform_id;
|
||||
extern s32 cur_ortho_projection_transform_id;
|
||||
|
||||
#endif
|
||||
|
||||
+236
-186
@@ -6,107 +6,57 @@
|
||||
#include "core1/mlmtx.h"
|
||||
#include "functions.h"
|
||||
|
||||
extern struct{
|
||||
s32 unk0;
|
||||
s32 game_mode; //game_mode
|
||||
f32 unk8;
|
||||
s32 unkC; //freeze_scene_flag (used for pause menu)
|
||||
f32 unk10;
|
||||
u8 transition;
|
||||
u8 map;
|
||||
u8 exit;
|
||||
u8 unk17; //reset_on_map_load
|
||||
u8 unk18;
|
||||
u8 unk19;
|
||||
u8 unk1A;
|
||||
u8 unk1B;
|
||||
u8 unk1C;
|
||||
} D_8037E8E0;
|
||||
bool skip_all_interpolation = FALSE;
|
||||
bool has_additional_model_scale = FALSE;
|
||||
f32 additional_model_scale_x;
|
||||
f32 additional_model_scale_y;
|
||||
f32 additional_model_scale_z;
|
||||
|
||||
void func_802E39D0(Gfx **gdl, Mtx **mptr, Vtx **vptr, s32 framebuffer_idx, s32 arg4);
|
||||
|
||||
#define PRINT_FUNC() \
|
||||
recomp_printf("%s\n", __func__)
|
||||
|
||||
#define PRINT_FUNC_INDENT() \
|
||||
recomp_printf(" %s\n", __func__)
|
||||
|
||||
extern f32 sViewportFOVy;
|
||||
extern f32 sViewportAspect;
|
||||
extern f32 sViewportNear;
|
||||
extern f32 sViewportFar;
|
||||
extern f32 sViewportPosition[3];
|
||||
extern f32 sViewportRotation[3];
|
||||
|
||||
void func_80256E24(f32 dst[3], f32 theta, f32 phi, f32 x, f32 y, f32 z);
|
||||
void ml_vec3f_copy(f32 dst[3], f32 src[3]);
|
||||
|
||||
// RECOMP_PATCH void viewport_moveAlongZAxis(f32 offset) {
|
||||
// PRINT_FUNC_INDENT();
|
||||
// f32 delta_position[3];
|
||||
|
||||
// func_80256E24(delta_position, sViewportRotation[0], sViewportRotation[1], 0.0f, 0.0f, offset);
|
||||
|
||||
// sViewportPosition[0] += delta_position[0];
|
||||
// sViewportPosition[1] += delta_position[1];
|
||||
// sViewportPosition[2] += delta_position[2];
|
||||
// }
|
||||
|
||||
// RECOMP_PATCH void viewport_setPosition_vec3f(f32 src[3]) {
|
||||
// PRINT_FUNC_INDENT();
|
||||
// ml_vec3f_copy(sViewportPosition, src);
|
||||
// }
|
||||
|
||||
// RECOMP_PATCH void viewport_setPosition_vec3w(s32 src[3]) {
|
||||
// PRINT_FUNC_INDENT();
|
||||
// sViewportPosition[0] = (f32)src[0];
|
||||
// sViewportPosition[1] = (f32)src[1];
|
||||
// sViewportPosition[2] = (f32)src[2];
|
||||
// }
|
||||
|
||||
// RECOMP_PATCH void viewport_setPosition_f3(f32 x, f32 y, f32 z) {
|
||||
// PRINT_FUNC_INDENT();
|
||||
// sViewportPosition[0] = x;
|
||||
// sViewportPosition[1] = y;
|
||||
// sViewportPosition[2] = z;
|
||||
// }
|
||||
|
||||
RECOMP_PATCH void viewport_setRenderPerspectiveMatrix(Gfx **gfx, Mtx **mtx, f32 near, f32 far) {
|
||||
u16 perspNorm;
|
||||
|
||||
near = MAX(sViewportNear, near);
|
||||
far = MIN(sViewportFar, far);
|
||||
|
||||
if(*(u32*)OS_PHYSICAL_TO_K0(0x1D8) + 0x53D4FFF0) {
|
||||
near = 750.0f;
|
||||
far = 1250.0f;
|
||||
}
|
||||
|
||||
guPerspective(*mtx, &perspNorm, sViewportFOVy, sViewportAspect, near, far, 0.5f);
|
||||
gSPPerspNormalize((*gfx)++, perspNorm);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
||||
|
||||
guRotate(*mtx, -sViewportRotation[2], 0.0f, 0.0f, -1.0f);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
||||
|
||||
guRotate(*mtx, -sViewportRotation[0], 1.0f, 0.0f, 0.0f);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
||||
|
||||
guRotate(*mtx, -sViewportRotation[1], 0.0f, 1.0f, 0.0f);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
||||
|
||||
guTranslate(*mtx, 0.0f, 0.0f, 0.0f);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Create an inverse matrix for the viewport translation and provide it as the inverse view matrix to counteract the camera translation.
|
||||
MtxF* invView = (MtxF*)*mtx;
|
||||
(*mtx)++;
|
||||
guTranslateF(invView->m, -sViewportPosition[0], -sViewportPosition[1], -sViewportPosition[2]);
|
||||
gEXSetInvViewMatrixFloat((*gfx)++, invView->m);
|
||||
void set_all_interpolation_skipped(bool skipped) {
|
||||
skip_all_interpolation = skipped;
|
||||
}
|
||||
|
||||
bool all_interpolation_skipped() {
|
||||
return skip_all_interpolation;
|
||||
}
|
||||
|
||||
void set_additional_model_scale(f32 x, f32 y, f32 z) {
|
||||
has_additional_model_scale = TRUE;
|
||||
additional_model_scale_x = x;
|
||||
additional_model_scale_y = y;
|
||||
additional_model_scale_z = z;
|
||||
}
|
||||
|
||||
s32 cur_drawn_model_is_map = FALSE;
|
||||
s32 cur_drawn_model_transform_id = 0;
|
||||
|
||||
Mtx identity_fixed_mtx = {{
|
||||
{
|
||||
0x00010000, 0x00000000,
|
||||
0x00000001, 0x00000000, }, {
|
||||
0x00000000, 0x00010000,
|
||||
0x00000000, 0x00000001,
|
||||
},
|
||||
{
|
||||
0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, }, {
|
||||
0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000,
|
||||
}
|
||||
}};
|
||||
|
||||
typedef void (*GeoListFunc)(Gfx **, Mtx **, void *);
|
||||
|
||||
typedef struct {
|
||||
s32 cmd_0;
|
||||
s32 size_4;
|
||||
f32 unk8[3];
|
||||
f32 unk14[3];
|
||||
s16 unk20;
|
||||
s16 unk22;
|
||||
s32 unk24;
|
||||
}GeoCmd1;
|
||||
|
||||
typedef struct {
|
||||
s32 cmd_0;
|
||||
s32 size_4;
|
||||
@@ -114,19 +64,23 @@ typedef struct {
|
||||
s8 unk9;
|
||||
}GeoCmd2;
|
||||
|
||||
extern u8 D_8037BFB8;
|
||||
extern s32 D_8036E7B0;
|
||||
typedef struct {
|
||||
s32 cmd_0;
|
||||
s32 size_4;
|
||||
s16 unk8;
|
||||
}GeoCmd3;
|
||||
|
||||
extern BKModelBin *modelRenderModelBin;
|
||||
extern BKGfxList *modelRenderDisplayList;
|
||||
extern AnimMtxList *D_8038371C;
|
||||
extern MtxF D_80383BF8;
|
||||
extern s32 D_80370990;
|
||||
extern GeoListFunc D_80370994[];
|
||||
extern f32 D_80383C64;
|
||||
extern f32 D_80383C68[3];
|
||||
extern f32 D_80383C78[3];
|
||||
extern f32 D_80383C88[3];
|
||||
|
||||
void eggShatter_draw(Gfx **gPtr, Mtx **mPtr, Vtx **vPtr);
|
||||
void baModel_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
Actor *marker_getActor(ActorMarker *);
|
||||
void func_8033A28C(bool arg0);
|
||||
void func_8033A244(f32);
|
||||
void func_8033A280(f32);
|
||||
void func_80339124(Gfx **, Mtx **, BKGeoList *);
|
||||
MtxF *animMtxList_get(AnimMtxList *this, s32 arg1);
|
||||
bool AnimTextureListCache_tryGetTextureOffset(s32 list_index, s32 texture_index, s32 *current_frame);
|
||||
@@ -137,81 +91,56 @@ void func_802ED52C(BKModelUnk20List *arg0, f32 arg1[3], f32 arg2);
|
||||
void func_802E6BD0(BKModelUnk28List *arg0, BKVertexList *arg1, AnimMtxList *mtx_list);
|
||||
void assetCache_free(void *arg0);
|
||||
|
||||
Actor* cur_drawn_actor = NULL;
|
||||
u32 cur_drawn_actor_spawn_index = 0;
|
||||
u32 cur_drawn_actor_transform_id = 0;
|
||||
|
||||
// @recomp Patched to set the current transform ID to banjo's when drawing the player.
|
||||
RECOMP_PATCH void player_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
if (D_8037BFB8) {
|
||||
eggShatter_draw(gfx, mtx, vtx);
|
||||
|
||||
// @recomp Set the current transform ID to banjo's.
|
||||
cur_drawn_actor_transform_id = BANJO_TRANSFORM_ID_START;
|
||||
|
||||
baModel_draw(gfx, mtx, vtx);
|
||||
|
||||
// @recomp Clear the current transform ID.
|
||||
cur_drawn_actor_transform_id = 0;
|
||||
void set_model_matrix_group(Gfx **gfx, void *geo_list, u32 bone_index) {
|
||||
if (skip_all_interpolation || cur_drawn_model_transform_id == -1) {
|
||||
// @recomp Skip interpolation if all interpolation is currently skipped or the transform id is -1.
|
||||
gEXMatrixGroupNoInterpolate((*gfx)++, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW);
|
||||
}
|
||||
else if (cur_drawn_model_transform_id != 0) {
|
||||
u32 group_id;
|
||||
// Pick a group ID based on whether this is a map or not.
|
||||
if (cur_drawn_model_is_map) {
|
||||
// Map models use a group ID determined by the offset of the geo command to guarantee they're unique and consistent between frames.
|
||||
group_id = cur_drawn_model_transform_id + (u32)geo_list - (u32)modelRenderModelBin - modelRenderModelBin->geo_list_offset_4;
|
||||
}
|
||||
else {
|
||||
// Other models use a group ID determined by the bone index.
|
||||
group_id = cur_drawn_model_transform_id + bone_index;
|
||||
}
|
||||
// @recomp Tag the matrix.
|
||||
// gEXMatrixGroupSimpleNormal((*gfx)++, group_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW);
|
||||
gEXMatrixGroupSimpleVerts((*gfx)++, group_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW);
|
||||
// gEXMatrixGroupDecomposedNormal((*gfx)++, group_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW);
|
||||
// gEXMatrixGroupDecomposedVerts((*gfx)++, group_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to set the actor being drawn before the actor's draw func is called.
|
||||
RECOMP_PATCH void __marker_draw(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
Actor *actor;
|
||||
u32 draw_dist;
|
||||
f32 draw_dist_f;
|
||||
f32 percentage;
|
||||
if(!this->unk3E_0){
|
||||
// @recomp Set the current drawn actor to null, as this marker has no actor.
|
||||
cur_drawn_actor = NULL;
|
||||
cur_drawn_actor_spawn_index = 0;
|
||||
cur_drawn_actor_transform_id = 0;
|
||||
|
||||
this->drawFunc(this, gfx, mtx, vtx);
|
||||
return;
|
||||
}
|
||||
actor = marker_getActor(this);
|
||||
func_8033A28C(actor->unk58_2);
|
||||
if( actor->unk58_2 && !this->unk40_23 && !this->unk40_21 && !D_8036E7B0){
|
||||
func_8033A244(3700.0f);
|
||||
}
|
||||
|
||||
if(actor->unk124_7 && !actor->despawn_flag && actor->unk58_0){
|
||||
draw_dist = actor->actor_info->draw_distance;
|
||||
if(draw_dist != 0){
|
||||
percentage = (f32)draw_dist*(1/(f64)0x400);
|
||||
}
|
||||
else if(this->unk40_21){
|
||||
percentage = 2.0f;
|
||||
}
|
||||
else{
|
||||
percentage = 1.0f;
|
||||
}
|
||||
func_8033A280(percentage);
|
||||
|
||||
// @recomp Set the current drawn actor.
|
||||
cur_drawn_actor = actor;
|
||||
cur_drawn_actor_spawn_index = bkrecomp_get_actor_spawn_index(actor);
|
||||
cur_drawn_actor_transform_id = ACTOR_TRANSFORM_ID_START + cur_drawn_actor_spawn_index * ACTOR_TRANSFORM_ID_COUNT;
|
||||
// printf("Drawing actor %02X\n", actor->actor_info->actorId);
|
||||
|
||||
this->drawFunc(this, gfx, mtx, vtx);
|
||||
|
||||
// @recomp Clear the current drawn actor after drawing.
|
||||
cur_drawn_actor = NULL;
|
||||
cur_drawn_actor_spawn_index = 0;
|
||||
cur_drawn_actor_transform_id = 0;
|
||||
}//L8032D300
|
||||
func_8033A244(30000.0f);
|
||||
func_8033A280(1.0f);
|
||||
void pop_model_matrix_group(Gfx **gfx) {
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
#define gEXMatrixGroupSimpleNormal(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroup(cmd, id, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
|
||||
#define gEXMatrixGroupSimpleVerts(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroup(cmd, id, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
// @recomp Patched to multiply the identity matrix to create a new matrix group and count up if drawing a map model.
|
||||
RECOMP_PATCH void func_80338904(Gfx **gfx, Mtx **mtx, void *arg2){
|
||||
GeoCmd3 *cmd = (GeoCmd3 *)arg2;
|
||||
Gfx *vptr;
|
||||
|
||||
if(D_80370990){
|
||||
// @recomp Create a new matrix by multiplying in the identity matrix.
|
||||
if (cur_drawn_model_is_map) {
|
||||
gSPMatrix((*gfx)++, &identity_fixed_mtx, G_MTX_PUSH | G_MTX_MUL | G_MTX_MODELVIEW);
|
||||
set_model_matrix_group(gfx, arg2, 0);
|
||||
}
|
||||
|
||||
vptr = &modelRenderDisplayList->list[cmd->unk8];
|
||||
gSPDisplayList((*gfx)++, osVirtualToPhysical(vptr));
|
||||
|
||||
// @recomp Pop the matrix if one was created.
|
||||
if (cur_drawn_model_is_map) {
|
||||
gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW);
|
||||
pop_model_matrix_group(gfx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to set matrix groups when processing geo bones.
|
||||
RECOMP_PATCH void func_803387F8(Gfx **gfx, Mtx **mtx, void *arg2){
|
||||
@@ -223,12 +152,8 @@ RECOMP_PATCH void func_803387F8(Gfx **gfx, Mtx **mtx, void *arg2){
|
||||
mlMtxApply(*mtx);
|
||||
gSPMatrix((*gfx)++, (*mtx)++, G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
if (cur_drawn_actor_transform_id != 0) {
|
||||
// @recomp Tag the matrix.
|
||||
// gEXMatrixGroupSimpleNormal((*gfx)++, cur_drawn_actor_transform_id + cmd->unk9, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW);
|
||||
gEXMatrixGroupSimpleVerts((*gfx)++, cur_drawn_actor_transform_id + cmd->unk9, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW);
|
||||
// gEXMatrixGroupDecomposedNormal((*gfx)++, cur_drawn_actor_transform_id + cmd->unk9 + 1, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW);
|
||||
}
|
||||
// Create a matrix group for this bone.
|
||||
set_model_matrix_group(gfx, arg2, cmd->unk9);
|
||||
}
|
||||
}
|
||||
if(cmd->unk8){
|
||||
@@ -239,14 +164,107 @@ RECOMP_PATCH void func_803387F8(Gfx **gfx, Mtx **mtx, void *arg2){
|
||||
if(D_80370990){
|
||||
gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW);
|
||||
|
||||
if (cur_drawn_actor_transform_id != 0) {
|
||||
if (cur_drawn_model_transform_id != 0) {
|
||||
// @recomp Pop the matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
pop_model_matrix_group(gfx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to set process sorted geo commands in a consistent order while still drawing them in the original order.
|
||||
// This allows a consistent ID scheme even when sorting changes.
|
||||
RECOMP_PATCH void func_803385BC(Gfx **gfx, Mtx **mtx, void *arg2){
|
||||
GeoCmd1 *cmd = (GeoCmd1 *)arg2;
|
||||
f32 f14;
|
||||
s32 tmp_v0;
|
||||
|
||||
mlMtx_apply_vec3f(D_80383C78, cmd->unk8);
|
||||
mlMtx_apply_vec3f(D_80383C88, cmd->unk14);
|
||||
|
||||
D_80383C68[0] = D_80383C88[0] - D_80383C78[0];
|
||||
D_80383C68[1] = D_80383C88[1] - D_80383C78[1];
|
||||
D_80383C68[2] = D_80383C88[2] - D_80383C78[2];
|
||||
|
||||
f14 = D_80383C68[0]*D_80383C78[0] + D_80383C68[1]*D_80383C78[1] + D_80383C68[2]*D_80383C78[2];
|
||||
f14 = -f14;
|
||||
if(cmd->unk20 & 1){
|
||||
// recomp_printf("stuff 1 %08X\n", cur_drawn_model_transform_id);
|
||||
if(0.0f <= f14 && (tmp_v0 = cmd->unk24)){
|
||||
D_80383C64 = f14;
|
||||
func_80339124(gfx, mtx, (BKGeoList*)((s32)cmd + tmp_v0));
|
||||
}
|
||||
else{
|
||||
D_80383C64 = f14;
|
||||
if(f14 < 0.0f){
|
||||
if(cmd->unk22)
|
||||
func_80339124(gfx, mtx, (BKGeoList*)((s32)cmd + cmd->unk22));
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
D_80383C64 = f14;
|
||||
if(0.0f <= f14){
|
||||
// recomp_printf("stuff 2 %08X\n", cur_drawn_model_transform_id);
|
||||
if(cmd->unk22)
|
||||
func_80339124(gfx, mtx, (BKGeoList*)((s32)cmd + cmd->unk22));
|
||||
|
||||
if(cmd->unk24)
|
||||
func_80339124(gfx, mtx, (BKGeoList*)((s32)cmd + cmd->unk24));
|
||||
}
|
||||
else{
|
||||
// recomp_printf("stuff 3 %08X\n", cur_drawn_model_transform_id);
|
||||
// @recomp Nodes have been sorted into the reverse order. This code has been modified
|
||||
// to process the nodes in the forward order, but uses DL branch list commands to run the
|
||||
// DL commands of the nodes in the reverse order.
|
||||
// This makes matrix group IDs consistent between frames while still running the actual DL commands
|
||||
// in the sorted order.
|
||||
// The resulting DL will look like this:
|
||||
// before_cmds:
|
||||
// BranchList(before_unk24)──────╖
|
||||
// before_unk22: <─────────────────╫────╖
|
||||
// Commands for node 22 ║ ║
|
||||
// between_cmds: ║ ║
|
||||
// BranchList(after_commands) ───╫────╫───╖
|
||||
// before_unk24: <─────────────────╜ ║ ║
|
||||
// Commands for node 24 ║ ║
|
||||
// after_unk24: ║ ║
|
||||
// BranchList(before_unk22)───────────╜ ║
|
||||
// after_commands: <────────────────────────╜
|
||||
|
||||
// Reserve one command worth of space for the branch list to the unk22 node.
|
||||
Gfx* before_cmds = (*gfx);
|
||||
(*gfx)++;
|
||||
Gfx* before_unk22 = (*gfx);
|
||||
|
||||
// Run the unk22 node's processing first.
|
||||
// Branch list commands will be used to run these commands after the unk24 node's commands.
|
||||
if(cmd->unk22)
|
||||
func_80339124(gfx, mtx, (BKGeoList*)((s32)cmd + cmd->unk22));
|
||||
|
||||
// Reserve another command for the branch list that takes the command cursor past the unk24 node's DL commands
|
||||
// after running the unk22 node's DL commands.
|
||||
Gfx* between_cmds = (*gfx);
|
||||
(*gfx)++;
|
||||
Gfx* before_unk24 = (*gfx);
|
||||
|
||||
// Run the unk24 node's processing second.
|
||||
if(cmd->unk24)
|
||||
func_80339124(gfx, mtx, (BKGeoList*)((s32)cmd + cmd->unk24));
|
||||
|
||||
// Reserve the command for the third branch list.
|
||||
Gfx* after_unk24 = (*gfx);
|
||||
(*gfx)++;
|
||||
Gfx* after_commands = (*gfx);
|
||||
|
||||
// Populate the branch list commands.
|
||||
gSPBranchList(before_cmds, before_unk24);
|
||||
gSPBranchList(between_cmds, after_commands);
|
||||
gSPBranchList(after_unk24, before_unk22);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern Gfx setup2CycleDL[];
|
||||
extern Gfx setup2CycleBlackPrimDL[];
|
||||
extern Gfx setup2CycleWhiteEnvDL[];
|
||||
@@ -302,7 +320,6 @@ extern struct {
|
||||
extern MtxF D_80383BF8;
|
||||
extern f32 modelRenderCameraPosition[3];
|
||||
extern f32 modelRenderCameraRotation[3];
|
||||
extern BKModelBin *modelRenderModelBin;
|
||||
extern f32 modelRenderRotation[3];
|
||||
extern f32 D_80383C64;
|
||||
extern f32 D_80383C68[3];
|
||||
@@ -339,6 +356,15 @@ extern struct{
|
||||
s32 prim[4];
|
||||
} modelRenderDynColors;
|
||||
|
||||
RECOMP_PATCH void func_80339124(Gfx ** gfx, Mtx ** mtx, BKGeoList *geo_list){
|
||||
do{
|
||||
D_80370994[geo_list->cmd_0](gfx, mtx, geo_list);
|
||||
if(geo_list->size_4 == 0)
|
||||
return;
|
||||
geo_list = (BKGeoList*)((s32)geo_list + geo_list->size_4);
|
||||
}while(1);
|
||||
}
|
||||
|
||||
// @recomp Patched to set an initial matrix group for the draw.
|
||||
RECOMP_PATCH BKModelBin *modelRender_draw(Gfx **gfx, Mtx **mtx, f32 position[3], f32 rotation[3], f32 scale, f32*arg5, BKModelBin* model_bin){
|
||||
f32 camera_focus[3];
|
||||
@@ -430,7 +456,14 @@ RECOMP_PATCH BKModelBin *modelRender_draw(Gfx **gfx, Mtx **mtx, f32 position[3],
|
||||
return 0;
|
||||
}
|
||||
|
||||
// @recomp Disable frustum checks.
|
||||
set_frustum_checks_enabled(FALSE);
|
||||
|
||||
D_80370990 = (D_80383704) ? viewport_func_8024DB50(object_position, spD0*scale) : 1;
|
||||
|
||||
// @recomp Re-enable frustum checks.
|
||||
set_frustum_checks_enabled(TRUE);
|
||||
|
||||
if(D_80370990 == 0){
|
||||
modelRender_reset();
|
||||
return 0;
|
||||
@@ -591,6 +624,12 @@ RECOMP_PATCH BKModelBin *modelRender_draw(Gfx **gfx, Mtx **mtx, f32 position[3],
|
||||
func_80252AF0(modelRenderCameraPosition, object_position, rotation, scale, arg5);
|
||||
}
|
||||
|
||||
// @recomp Patched to provide a spot to apply a non-uniform scale.
|
||||
if (has_additional_model_scale) {
|
||||
mlMtxScale_xyz(additional_model_scale_x, additional_model_scale_y, additional_model_scale_z);
|
||||
has_additional_model_scale = FALSE;
|
||||
}
|
||||
|
||||
if(D_803837B0.unk0){
|
||||
mlMtxRotatePYR(D_803837B0.unk4[0], D_803837B0.unk4[1], D_803837B0.unk4[2]);
|
||||
}
|
||||
@@ -600,8 +639,12 @@ RECOMP_PATCH BKModelBin *modelRender_draw(Gfx **gfx, Mtx **mtx, f32 position[3],
|
||||
gSPMatrix((*gfx)++, (*mtx)++, G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Create a matrix group if a transform id is set.
|
||||
if (cur_drawn_actor_transform_id != 0) {
|
||||
gEXMatrixGroupDecomposedVerts((*gfx)++, cur_drawn_actor_transform_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW);
|
||||
if (skip_all_interpolation || cur_drawn_model_transform_id == -1) {
|
||||
// @recomp Skip interpolation if all interpolation is currently skipped or the transform id is -1.
|
||||
gEXMatrixGroupNoInterpolate((*gfx)++, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW);
|
||||
}
|
||||
else if (cur_drawn_model_transform_id != 0) {
|
||||
gEXMatrixGroupDecomposedVerts((*gfx)++, cur_drawn_model_transform_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW);
|
||||
}
|
||||
|
||||
modelRenderScale = scale;
|
||||
@@ -614,11 +657,18 @@ RECOMP_PATCH BKModelBin *modelRender_draw(Gfx **gfx, Mtx **mtx, f32 position[3],
|
||||
modelRenderRotation[0] = modelRenderRotation[1] = modelRenderRotation[2] = 0.0f;
|
||||
}
|
||||
|
||||
// @recomp Disable frustum checks before processing bones.
|
||||
set_frustum_checks_enabled(FALSE);
|
||||
|
||||
func_80339124(gfx, mtx, (BKGeoList *)((u8 *)model_bin + model_bin->geo_list_offset_4));
|
||||
|
||||
// @recomp Re-enable frustum checks after processing bones.
|
||||
set_frustum_checks_enabled(TRUE);
|
||||
|
||||
gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Pop the matrix group if a transform id is set.
|
||||
if (cur_drawn_actor_transform_id != 0) {
|
||||
if (cur_drawn_model_transform_id != 0) {
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,452 @@
|
||||
#include "patches.h"
|
||||
#include "graphics.h"
|
||||
#include "transform_ids.h"
|
||||
#include "core1/core1.h"
|
||||
#include "gc/gctransition.h"
|
||||
#include "gc/gcbound.h"
|
||||
|
||||
float gu_sqrtf(float val);
|
||||
BKGfxList *model_getDisplayList(BKModelBin *arg0);
|
||||
s32 getGameMode(void);
|
||||
void scissorBox_setSmall(void);
|
||||
s16 *func_8030C704(void);
|
||||
|
||||
typedef enum {
|
||||
TRANSITION_ID_1_BLACK_IN = 1,
|
||||
TRANSITION_ID_2_BLACK_OUT,
|
||||
TRANSITION_ID_3_CIRCLE_IN,
|
||||
TRANSITION_ID_4_CIRCLE_OUT,
|
||||
TRANSITION_ID_5_JIGGY_IN,
|
||||
TRANSITION_ID_6_JIGGY_OUT,
|
||||
TRANSITION_ID_7,
|
||||
TRANSITION_ID_8_WHITE_IN,
|
||||
TRANSITION_ID_9_WHITE_OUT,
|
||||
TRANSITION_ID_A_WITCH_HEAD_OUT,
|
||||
TRANSITION_ID_B_CIRCLE_IN_FAST,
|
||||
TRANSITION_ID_C_CIRCLE_OUT_FAST,
|
||||
TRANSITION_ID_D,
|
||||
TRANSITION_ID_E_CIRCLE_IN_SLOW,
|
||||
TRANSITION_ID_F_CIRCLE_OUT_SLOW,
|
||||
TRANSITION_ID_10_FALLING_PIECES_IN,
|
||||
TRANSITION_ID_11_FALLING_PIECES_OUT,
|
||||
TRANSITION_ID_12_CIRCLE_IN_EXTRA_SLOW,
|
||||
TRANSITION_ID_13_CIRCLE_OUT_EXTRA_SLOW,
|
||||
TRANSITION_ID_14_CIRCLE_IN_SUPER_SLOW,
|
||||
TRANSITION_ID_15_CIRCLE_OUT_SUPER_SLOW
|
||||
} TransitionId;
|
||||
|
||||
typedef enum {
|
||||
TRANSITION_STATE_0_NONE,
|
||||
TRANSITION_STATE_1_LOADING,
|
||||
TRANSITION_STATE_2_BLACK_IN,
|
||||
TRANSITION_STATE_3_BLACK_OUT,
|
||||
TRANSITION_STATE_4_FADE_IN,
|
||||
TRANSITION_STATE_5_FADE_OUT,
|
||||
TRANSITION_STATE_6_LOADING_WHITE,
|
||||
TRANSITION_STATE_7_WHITE_IN,
|
||||
TRANSITION_STATE_8_WHITE_OUT
|
||||
} TransitionState;
|
||||
|
||||
typedef struct {
|
||||
u8 uid;
|
||||
u8 state;
|
||||
u8 next_state;
|
||||
// u8 pad3[1];
|
||||
f32 duration;
|
||||
s32 model_index;
|
||||
s32 anim_index;
|
||||
f32 scale;
|
||||
}TransitionInfo;
|
||||
|
||||
extern struct{
|
||||
s32 unk0; //times drawn?
|
||||
TransitionInfo *transistion_info;
|
||||
u8 state;
|
||||
//u8 pad9[3]; //not needed
|
||||
void * model_ptr; //asset_ptr
|
||||
f32 rotation;
|
||||
f32 timer;
|
||||
AnimCtrl *anctrl;
|
||||
s32 substate; //times update called?
|
||||
} s_current_transition;
|
||||
|
||||
extern f32 D_8036C440;
|
||||
extern f32 D_8036C444;
|
||||
|
||||
// Dedicated framebuffer to hold the frame that was rendered as the jiggy transition texture.
|
||||
u16 jiggy_transition_framebuffer[DEFAULT_FRAMEBUFFER_WIDTH * DEFAULT_FRAMEBUFFER_HEIGHT];
|
||||
|
||||
Gfx load_jiggy_transition_texture[] = {
|
||||
// Load the entire framebuffer as a texture, as tmem limits can be bypassed in RT64 for framebuffer textures.
|
||||
gsDPLoadTextureTile(jiggy_transition_framebuffer, G_IM_FMT_RGBA, G_IM_SIZ_16b,
|
||||
DEFAULT_FRAMEBUFFER_WIDTH, DEFAULT_FRAMEBUFFER_HEIGHT,
|
||||
0, 0,
|
||||
DEFAULT_FRAMEBUFFER_WIDTH - 1, DEFAULT_FRAMEBUFFER_HEIGHT - 1,
|
||||
0,
|
||||
G_TX_CLAMP | G_TX_NOMIRROR, G_TX_CLAMP | G_TX_NOMIRROR,
|
||||
G_TX_NOMASK, G_TX_NOMASK,
|
||||
G_TX_NOLOD, G_TX_NOLOD
|
||||
),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
||||
const s32 fb_tiles_per_row = 10;
|
||||
const s32 fb_tiles_per_column = 8;
|
||||
const s32 fb_tile_size = 32;
|
||||
const s32 fb_grid_width = fb_tile_size * fb_tiles_per_row;
|
||||
const s32 fb_grid_height = fb_tile_size * fb_tiles_per_column;
|
||||
|
||||
// Input vertex coordinates for the corners of the jiggy transition effect.
|
||||
const float left_x_input = -701.0f;
|
||||
const float top_y_input = 701.0f;
|
||||
const float right_x_input = 701.0f;
|
||||
const float bottom_y_input = -701.0f;
|
||||
|
||||
// NDC output vertex coordinates for the corners of the jiggy transition effect, measured via renderdoc.
|
||||
const float left_x_output = -1.0941545714285714285714285714286f;
|
||||
const float top_y_output = 1.4791303428571428571428571428571f;
|
||||
const float right_x_output = 1.101004f;
|
||||
const float bottom_y_output = -1.4883895428571428571428571428571;
|
||||
|
||||
const float output_per_input_x = (right_x_output - left_x_output) / (right_x_input - left_x_input);
|
||||
const float output_per_input_y = (bottom_y_output - top_y_output) / (bottom_y_input - top_y_input);
|
||||
|
||||
void set_vertex_texcoord(Vtx* v) {
|
||||
// Calculate vertex texture coordinates based on the input coordinate. The untransformed positions of the jiggy piece vertices
|
||||
// reflect where they end up in the combined picture already, so they can be used to calculate the correct texcoord without
|
||||
// taking into account the animation.
|
||||
|
||||
float output_x = output_per_input_x * v->v.ob[0];
|
||||
float output_y = output_per_input_y * v->v.ob[1];
|
||||
|
||||
// Convert from -1,1 to 0,1. Also flip the Y-axis.
|
||||
float output_x_adjusted = output_x * 0.5f + 0.5f;
|
||||
float output_y_adjusted = output_y * -0.5f + 0.5f;
|
||||
|
||||
// Calculate texcoords based on the input texture size, accounting for a texcoord scale of 0.5.
|
||||
float texcoord_s = output_x_adjusted * DEFAULT_FRAMEBUFFER_WIDTH * 2.0f;
|
||||
float texcoord_t = output_y_adjusted * DEFAULT_FRAMEBUFFER_HEIGHT * 2.0f;
|
||||
|
||||
// Convert the texcoords to fixed point with 5 bits of fractional precision.
|
||||
v->v.tc[0] = (s32)(texcoord_s * 32.0f);
|
||||
v->v.tc[1] = (s32)(texcoord_t * 32.0f);
|
||||
}
|
||||
|
||||
void patch_falling_jiggies_model(BKModelBin* model) {
|
||||
// Validate that this is the unmodified falling jiggy transition model.
|
||||
if (model->texture_list_offset_8 != 0x38) {
|
||||
return;
|
||||
}
|
||||
if (model->gfx_list_offset_C != 0x28770) {
|
||||
return;
|
||||
}
|
||||
if (model->vtx_list_offset_10 != 0x2EC40) {
|
||||
return;
|
||||
}
|
||||
// Start and end segmented addresses of the framebuffer tile range.
|
||||
const u32 fb_tiles_start = 0x02000000;
|
||||
const u32 fb_tiles_end = 0x02028000;
|
||||
const u32 fb_tile_bytes = 32 * 32 * sizeof(u16);
|
||||
// // Texcoord offsets, multiplied by 2 to account for 0.5 texcoord scaling and converted to fixed point.
|
||||
// const u32 fb_s_offset = (((fb_grid_width - DEFAULT_FRAMEBUFFER_WIDTH /*- 1*/) * 2 / 2)) << 5;
|
||||
// const u32 fb_t_offset = (((fb_grid_height - DEFAULT_FRAMEBUFFER_HEIGHT /*- 1*/) * 2 / 2)) << 5;
|
||||
|
||||
BKGfxList* gfx_list = model_getDisplayList(model);
|
||||
|
||||
// Iterate until the end of the displaylist data, which lines up with the start of the vertex data.
|
||||
Gfx* cur_gfx = &gfx_list->list[0];
|
||||
Gfx* end_gfx = (Gfx*)((char*)model + model->vtx_list_offset_10);
|
||||
Vtx* model_verts = model_getVtxList(model)->vtx_18;
|
||||
s32 prev_tile_col = -1;
|
||||
s32 prev_tile_row = -1;
|
||||
while (cur_gfx < end_gfx) {
|
||||
// Check if this is a set texture image command.
|
||||
if (cur_gfx->words.w0 >> 24 == G_SETTIMG) {
|
||||
// Check if the texture pointer is a framebuffer tile.
|
||||
if (cur_gfx->words.w1 >= fb_tiles_start && cur_gfx->words.w1 < fb_tiles_end) {
|
||||
// Determine the row and column of the tile.
|
||||
u32 tile_offset = cur_gfx->words.w1 - fb_tiles_start;
|
||||
u32 tile_index = tile_offset / fb_tile_bytes;
|
||||
prev_tile_row = tile_index / fb_tiles_per_row;
|
||||
prev_tile_col = tile_index % fb_tiles_per_row;
|
||||
|
||||
// Overwrite this command with a displaylist call to the new texture load.
|
||||
gSPDisplayList(cur_gfx++, load_jiggy_transition_texture);
|
||||
|
||||
// Overwrite the next 6 commands with noops.
|
||||
gSPNoOp(cur_gfx++);
|
||||
gSPNoOp(cur_gfx++);
|
||||
gSPNoOp(cur_gfx++);
|
||||
gSPNoOp(cur_gfx++);
|
||||
gSPNoOp(cur_gfx++);
|
||||
gSPNoOp(cur_gfx++);
|
||||
|
||||
// Rewind the graphics pointer by 1 to account for the increment that happens at the end of the loop.
|
||||
cur_gfx--;
|
||||
}
|
||||
}
|
||||
// Patch vertices.
|
||||
else if (cur_gfx->words.w0 >> 24 == G_VTX) {
|
||||
// Get the loaded vertex count for this command.
|
||||
u32 cur_vtx_count = (cur_gfx->words.w0 >> 10) & 0b111111;
|
||||
|
||||
// Get the vertex address, converting from a segmented address if necessary.
|
||||
Vtx* cur_vtx;
|
||||
if (cur_gfx->words.w1 >> 24 == 0x01) {
|
||||
cur_vtx = (Vtx*)(SEGMENT_OFFSET(cur_gfx->words.w1) + (char*)model_verts);
|
||||
}
|
||||
else {
|
||||
// Not a segmented address (should never happen, but may help with compatibility for future mods).
|
||||
cur_vtx = (Vtx*)cur_gfx->words.w1;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < cur_vtx_count; i++) {
|
||||
// Recalculate texture coordinates based on the vertex coordinate. The untransformed vertices of the jiggy pieces
|
||||
// have their final position already, so they can be used to calculate the correct texcoord.
|
||||
|
||||
// All texcoords in the model can be written to without an issue, as any vertices that aren't used to display
|
||||
// the framebuffer have texcoord generation enabled, so these edits will be ignored.
|
||||
set_vertex_texcoord(&cur_vtx[i]);
|
||||
}
|
||||
}
|
||||
cur_gfx++;
|
||||
}
|
||||
};
|
||||
|
||||
bool should_draw_to_transition_framebuffer() {
|
||||
if (s_current_transition.transistion_info == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (s_current_transition.transistion_info->uid == TRANSITION_ID_10_FALLING_PIECES_IN) {
|
||||
return s_current_transition.substate <= 2;
|
||||
}
|
||||
else {
|
||||
return s_current_transition.substate == 2;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to use the dedicated transition framebuffer if this is drawing a transition frame.
|
||||
RECOMP_PATCH void scissorBox_SetForGameMode(Gfx **gdl, s32 framebuffer_idx) {
|
||||
if(getGameMode() == GAME_MODE_8_BOTTLES_BONUS || getGameMode() == GAME_MODE_A_SNS_PICTURE)
|
||||
{
|
||||
scissorBox_setSmall();
|
||||
func_80253640(gdl, func_8030C704());
|
||||
}
|
||||
else{
|
||||
scissorBox_setDefault();
|
||||
func_80253640(gdl, gFramebuffers[framebuffer_idx]);
|
||||
// @recomp After clearing the main framebuffer, switch to and clear the dedicated transition framebuffer.
|
||||
if (should_draw_to_transition_framebuffer()) {
|
||||
func_80253640(gdl, jiggy_transition_framebuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// s_current_transition.transistion_info != NULL
|
||||
// s_current_transition.transistion_info->model_index == ASSET_467_MODEL_TRANSITION_FALLING_JIGGIES
|
||||
// s_current_transition.substate == 1 (or maybe < 2)
|
||||
|
||||
// @recomp Patched to set a transform ID for transition models and the transition projection transform ID.
|
||||
RECOMP_PATCH void gctransition_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr){
|
||||
f32 vp_position[3];
|
||||
f32 vp_rotation[3];
|
||||
f32 percentage;
|
||||
f32 sp58[3];
|
||||
f32 scale;
|
||||
|
||||
s_current_transition.unk0++;
|
||||
if(s_current_transition.state == 0)
|
||||
return;
|
||||
|
||||
viewport_backupState();
|
||||
if(s_current_transition.anctrl != NULL){
|
||||
vp_position[0] = 0.0f;
|
||||
vp_position[1] = 0.0f;
|
||||
vp_position[2] = 350.0f;
|
||||
}else{
|
||||
vp_position[0] = 0.0f;
|
||||
vp_position[1] = 0.0f;
|
||||
vp_position[2] = 300.0f;
|
||||
}
|
||||
|
||||
vp_rotation[0] = 0.0f;
|
||||
vp_rotation[1] = 0.0f;
|
||||
vp_rotation[2] = 0.0f;
|
||||
viewport_setNearAndFar(D_8036C440, D_8036C444);
|
||||
viewport_setPosition_vec3f(vp_position); //viewport_getPosition_vec3f
|
||||
viewport_setRotation_vec3f(vp_rotation); //viewport_getRotation_vec3f
|
||||
viewport_update(); //camera_updateNormal
|
||||
|
||||
// @recomp Set the perspective projection transform ID for the transition projection.
|
||||
cur_perspective_projection_transform_id = PROJECTION_TRANSITION_TRANSFORM_ID;
|
||||
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr);
|
||||
|
||||
sp58[0] = 0.0f;
|
||||
sp58[1] = 0.0f;
|
||||
sp58[2] = 0.0f;
|
||||
if(s_current_transition.anctrl != NULL){
|
||||
gDPSetTextureFilter((*gdl)++, G_TF_POINT);
|
||||
gDPSetColorDither((*gdl)++, G_CD_DISABLE);
|
||||
anctrl_drawSetup(s_current_transition.anctrl, sp58, 1);
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL);
|
||||
}
|
||||
|
||||
// @recomp Calculate the ratio between the original aspect ratio and the current aspect ratio.
|
||||
float original_aspect = (float)DEFAULT_FRAMEBUFFER_WIDTH / DEFAULT_FRAMEBUFFER_HEIGHT;
|
||||
float cur_aspect = recomp_get_target_aspect_ratio(original_aspect);
|
||||
float aspect_ratio_ratio = cur_aspect / original_aspect;
|
||||
|
||||
// @recomp Determine what scaling to use based on the transition type.
|
||||
float transition_scale = 1.0f;
|
||||
float transition_x_scale = 1.0f;
|
||||
if (s_current_transition.transistion_info != NULL) {
|
||||
// recomp_printf(" Transition uid: %d\n", s_current_transition.transistion_info->uid);
|
||||
// recomp_printf(" Transition model index: %04X\n", s_current_transition.transistion_info->model_index);
|
||||
switch (s_current_transition.transistion_info->uid) {
|
||||
// Scale the jiggy framebuffer transition by the aspect ratio ratio as it just needs to cover the additional horizontal space.
|
||||
// Only scale along the X axis.
|
||||
case TRANSITION_ID_10_FALLING_PIECES_IN:
|
||||
case TRANSITION_ID_11_FALLING_PIECES_OUT:
|
||||
transition_x_scale = aspect_ratio_ratio;
|
||||
break;
|
||||
// Scale other transitions by slightly more to account for overscan removal.
|
||||
default:
|
||||
transition_scale = aspect_ratio_ratio + 0.1f;
|
||||
}
|
||||
|
||||
// Check if the transition model is the falling jiggies transition model, and patch it if it hasn't been patched yet.
|
||||
if (s_current_transition.transistion_info->model_index == ASSET_467_MODEL_TRANSITION_FALLING_JIGGIES && s_current_transition.model_ptr != NULL) {
|
||||
// Use pad0 to tell if the model has been patched.
|
||||
BKModelBin* transition_model = s_current_transition.model_ptr;
|
||||
if (transition_model->pad0[0] != 0xBA) {
|
||||
patch_falling_jiggies_model(transition_model);
|
||||
transition_model->pad0[0] = 0xBA;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// recomp_printf(" No transition_info\n");
|
||||
transition_scale = aspect_ratio_ratio + 0.1f;
|
||||
}
|
||||
|
||||
//complex animation (from animation bin file)
|
||||
if(s_current_transition.state == 1 || s_current_transition.state == 6){
|
||||
// @recomp Set the current transform ID to the transition model's.
|
||||
cur_drawn_model_transform_id = TRANSITION_MODEL_TRANSFORM_ID_START;
|
||||
|
||||
// recomp_printf(" A\n");
|
||||
|
||||
// @recomp Scale the transition.
|
||||
set_additional_model_scale(transition_x_scale, 1.0f, 1.0f);
|
||||
modelRender_draw(gdl, mptr, sp58, vp_rotation, transition_scale, 0, s_current_transition.model_ptr);
|
||||
|
||||
// @recomp Clear the current transform ID.
|
||||
cur_drawn_model_transform_id = 0;
|
||||
if(s_current_transition.anctrl != NULL){
|
||||
gDPSetTextureFilter((*gdl)++, G_TF_BILERP);
|
||||
gDPSetColorDither((*gdl)++, G_CD_MAGICSQ);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
percentage = s_current_transition.timer/(s_current_transition.transistion_info->duration);
|
||||
if(s_current_transition.state == TRANSITION_STATE_4_FADE_IN){
|
||||
//rotate and zoom in
|
||||
if(s_current_transition.transistion_info->uid == 0x10){
|
||||
scale = s_current_transition.transistion_info->scale;
|
||||
|
||||
}
|
||||
else{
|
||||
vp_rotation[2] = s_current_transition.rotation - 90.0f*percentage;
|
||||
scale = percentage*s_current_transition.transistion_info->scale + 0.1;
|
||||
}
|
||||
// @recomp Set the current transform ID to the transition model's.
|
||||
cur_drawn_model_transform_id = TRANSITION_MODEL_TRANSFORM_ID_START;
|
||||
|
||||
// recomp_printf(" B\n");
|
||||
|
||||
// @recomp Scale the transition.
|
||||
set_additional_model_scale(transition_x_scale, 1.0f, 1.0f);
|
||||
modelRender_draw(gdl, mptr, sp58, vp_rotation, scale * transition_scale, 0, s_current_transition.model_ptr);
|
||||
|
||||
// @recomp Clear the current transform ID.
|
||||
cur_drawn_model_transform_id = 0;
|
||||
}
|
||||
else if(s_current_transition.state == TRANSITION_STATE_5_FADE_OUT){//L8030B9EC
|
||||
switch (s_current_transition.transistion_info->uid)
|
||||
{
|
||||
default:
|
||||
//rotate and zoom out
|
||||
vp_rotation[2] = s_current_transition.rotation - 90.0f*percentage;
|
||||
scale = (1.0f - percentage)*s_current_transition.transistion_info->scale + 0.1;
|
||||
break;
|
||||
case 0x11:
|
||||
//static
|
||||
scale = s_current_transition.transistion_info->scale;
|
||||
break;
|
||||
case 0xA:
|
||||
//zoom out only
|
||||
vp_rotation[2] = 0.0f;
|
||||
scale = (1.0f - func_80257618(percentage))*s_current_transition.transistion_info->scale + 0.1;
|
||||
break;
|
||||
}
|
||||
if(!(s_current_transition.substate < 3) || s_current_transition.transistion_info->uid != 0x11){
|
||||
// @recomp Set the current transform ID to the transition model's.
|
||||
cur_drawn_model_transform_id = TRANSITION_MODEL_TRANSFORM_ID_START;
|
||||
|
||||
// recomp_printf(" C\n");
|
||||
|
||||
// @recomp Scale the transition.
|
||||
set_additional_model_scale(transition_x_scale, 1.0f, 1.0f);
|
||||
modelRender_draw(gdl, mptr, sp58, vp_rotation, scale * transition_scale, 0, s_current_transition.model_ptr);
|
||||
|
||||
// @recomp Clear the current transform ID.
|
||||
cur_drawn_model_transform_id = 0;
|
||||
}
|
||||
else{
|
||||
modelRender_reset();
|
||||
}
|
||||
|
||||
}
|
||||
else if(s_current_transition.state == TRANSITION_STATE_2_BLACK_IN){//L8030BAF4
|
||||
//fade in black (i.e. get less black)
|
||||
gcbound_reset();
|
||||
gcbound_alpha((1.0f - percentage)*255.0f + 0.5);
|
||||
gcbound_color(0,0,0);
|
||||
gcbound_draw(gdl);
|
||||
}
|
||||
else if(s_current_transition.state == TRANSITION_STATE_3_BLACK_OUT){//L8030BB6C
|
||||
//fade out black (i.e. get more black)
|
||||
gcbound_reset();
|
||||
gcbound_alpha(percentage*255.0f + 0.5);
|
||||
gcbound_color(0,0,0);
|
||||
gcbound_draw(gdl);
|
||||
}
|
||||
else if(s_current_transition.state == TRANSITION_STATE_7_WHITE_IN){//L8030BBD8
|
||||
//fade in white (i.e. get less white)
|
||||
percentage = (percentage <= 0.5)? 1.0 : 1.0 - (percentage-0.5)/0.5;
|
||||
gcbound_reset();
|
||||
gcbound_alpha(percentage*255.0f + 0.5);
|
||||
gcbound_color(0xff,0xff,0xff);
|
||||
gcbound_draw(gdl);
|
||||
}
|
||||
else if(s_current_transition.state == TRANSITION_STATE_8_WHITE_OUT){//L8030BC8C
|
||||
//fade out white (i.e. get more white)
|
||||
gcbound_reset();
|
||||
gcbound_alpha(percentage*255.0f + 0.5);
|
||||
gcbound_color(0xff,0xff,0xff);
|
||||
gcbound_draw(gdl);
|
||||
}//L8030BD00
|
||||
else{
|
||||
|
||||
}
|
||||
if(s_current_transition.anctrl != NULL){
|
||||
gDPSetTextureFilter((*gdl)++, G_TF_BILERP);
|
||||
}
|
||||
viewport_restoreState();
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr);
|
||||
|
||||
}
|
||||
+4
-1
@@ -1,3 +1,6 @@
|
||||
#pragma GCC diagnostic ignored "-Wpointer-sign"
|
||||
#pragma GCC diagnostic ignored "-Wlogical-op-parentheses"
|
||||
|
||||
#include "patches.h"
|
||||
#include "string.h"
|
||||
#include "xstdio.h"
|
||||
@@ -55,7 +58,7 @@ static const ldouble pows[] = {10e0L, 10e1L, 10e3L, 10e7L, 10e15L, 10e31L, 10e63
|
||||
#define _D2 2
|
||||
#define _D3 3
|
||||
|
||||
#define ALIGN(s, align) (((unsigned int)(s) + ((align)-1)) & ~((align)-1))
|
||||
// #define ALIGN(s, align) (((unsigned int)(s) + ((align)-1)) & ~((align)-1))
|
||||
|
||||
void _Ldtob(_Pft* px, char code) {
|
||||
char buff[BUFF_LEN];
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma GCC diagnostic ignored "-Wpointer-sign"
|
||||
#pragma GCC diagnostic ignored "-Wunused-value"
|
||||
|
||||
#include "patches.h"
|
||||
#include "string.h"
|
||||
#include "stdarg.h"
|
||||
|
||||
@@ -1,237 +0,0 @@
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
||||
#include "slot_map.h"
|
||||
|
||||
#include "librecomp/helpers.hpp"
|
||||
#include "librecomp/addresses.hpp"
|
||||
#include "ultramodern/error_handling.hpp"
|
||||
#include "recomp_ui.h"
|
||||
#include "recomp_data.h"
|
||||
#include "../patches/actor_funcs.h"
|
||||
|
||||
struct ExtensionInfo {
|
||||
// Either the actor's type ID, or 0xFFFFFFFF if this is for generic data.
|
||||
uint32_t actor_type;
|
||||
// The offset from either the start of the actor's data or the start of the actor's specific extension data depending on the value of actor_type.
|
||||
uint32_t data_offset;
|
||||
};
|
||||
|
||||
struct ExtensionData {
|
||||
uint32_t actor_spawn_index;
|
||||
PTR(void) data_addr;
|
||||
};
|
||||
|
||||
std::mutex actor_data_mutex{};
|
||||
// The total size of actor-specific extension data for each actor type.
|
||||
std::vector<uint32_t> actor_data_sizes{};
|
||||
// The total size of all generic actor extension data.
|
||||
uint32_t generic_data_size;
|
||||
// The registered actor extensions.
|
||||
std::vector<ExtensionInfo> actor_extensions{};
|
||||
// The extension data for every actor.
|
||||
using actor_data_map_t = dod::slot_map32<ExtensionData>;
|
||||
actor_data_map_t actor_data{};
|
||||
// The number of actors spawned since the last reset.
|
||||
uint32_t actor_spawn_count = 0;
|
||||
// Whether or not extensions can be registered at this time.
|
||||
bool can_register = false;
|
||||
|
||||
// Debug counters.
|
||||
size_t alloc_count = 0;
|
||||
size_t free_count = 0;
|
||||
|
||||
void recomputil::init_extended_actor_data() {
|
||||
std::lock_guard lock{ actor_data_mutex };
|
||||
|
||||
actor_data_sizes.clear();
|
||||
generic_data_size = 0;
|
||||
actor_extensions.clear();
|
||||
actor_data.reset();
|
||||
actor_spawn_count = 0;
|
||||
can_register = true;
|
||||
// Create a dummy extension so the first extension handle is nonzero, should help catch bugs.
|
||||
actor_extensions.push_back({});
|
||||
}
|
||||
|
||||
void recomputil::reset_actor_data() {
|
||||
std::lock_guard lock{ actor_data_mutex };
|
||||
actor_data.reset();
|
||||
actor_spawn_count = 0;
|
||||
|
||||
assert(alloc_count == free_count);
|
||||
alloc_count = 0;
|
||||
free_count = 0;
|
||||
}
|
||||
|
||||
constexpr uint32_t round_up_16(uint32_t value) {
|
||||
return (value + 15) & (~15);
|
||||
}
|
||||
|
||||
extern "C" void recomp_register_actor_extension(uint8_t* rdram, recomp_context* ctx) {
|
||||
u32 actor_type = _arg<0, u32>(rdram, ctx);
|
||||
u32 size = _arg<1, u32>(rdram, ctx);
|
||||
|
||||
if (!can_register) {
|
||||
recompui::message_box("Fatal error in mod - attempted to register actor extension data after actors have been spawned.");
|
||||
assert(false);
|
||||
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
if (actor_data_sizes.size() <= actor_type) {
|
||||
actor_data_sizes.resize(2 * actor_type);
|
||||
}
|
||||
|
||||
// Increase the actor type's extension data size by the provided size (rounded up to a multiple of 16).
|
||||
uint32_t data_offset = actor_data_sizes[actor_type];
|
||||
actor_data_sizes[actor_type] += round_up_16(size);
|
||||
|
||||
// Register the extension.
|
||||
uint32_t ret = static_cast<uint32_t>(actor_extensions.size());
|
||||
actor_extensions.emplace_back(ExtensionInfo{.actor_type = actor_type, .data_offset = data_offset});
|
||||
|
||||
// printf("Registered actor extension data for type %u (size 0x%08X, offset 0x%08X)\n", actor_type, size, data_offset);
|
||||
|
||||
_return<u32>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void recomp_register_actor_extension_generic(uint8_t* rdram, recomp_context* ctx) {
|
||||
u32 size = _arg<0, u32>(rdram, ctx);
|
||||
|
||||
// Increase the generic extension data size by the provided size (rounded up to a multiple of 16).
|
||||
uint32_t data_offset = generic_data_size;
|
||||
generic_data_size += round_up_16(size);
|
||||
|
||||
// Register the extension.
|
||||
uint32_t ret = static_cast<uint32_t>(actor_extensions.size());
|
||||
actor_extensions.emplace_back(ExtensionInfo{.actor_type = 0xFFFFFFFFU, .data_offset = data_offset});
|
||||
|
||||
// printf("Registered generic actor extension data (size 0x%08X, offset 0x%08X)\n", size, data_offset);
|
||||
_return<u32>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void recomp_clear_all_actor_data(uint8_t* rdram, recomp_context* ctx) {
|
||||
(void)rdram;
|
||||
(void)ctx;
|
||||
recomputil::reset_actor_data();
|
||||
}
|
||||
|
||||
extern "C" void recomp_create_actor_data(uint8_t* rdram, recomp_context* ctx) {
|
||||
std::lock_guard lock{ actor_data_mutex };
|
||||
|
||||
can_register = false;
|
||||
|
||||
// Determine the number of bytes to allocate based on the actor type's extensions and the generic extensions.
|
||||
u32 actor_type = _arg<0, u32>(rdram, ctx);
|
||||
u32 alloc_size = generic_data_size;
|
||||
[[maybe_unused]] u32 type_data_size = 0;
|
||||
|
||||
if (actor_type < actor_data_sizes.size()) {
|
||||
type_data_size = actor_data_sizes[actor_type];
|
||||
alloc_size += type_data_size;
|
||||
}
|
||||
|
||||
// Allocate the extension data if it's of nonzero size.
|
||||
PTR(void) data_ptr = NULLPTR;
|
||||
if (alloc_size != 0) {
|
||||
void* data = recomp::alloc(rdram, alloc_size);
|
||||
alloc_count++;
|
||||
data_ptr = reinterpret_cast<uint8_t*>(data) - rdram + 0xFFFFFFFF80000000U;
|
||||
// Zero the allocated memory.
|
||||
// A memset should be fine here since this data is aligned, but use a byteswapped loop just to be safe.
|
||||
for (size_t i = 0; i < alloc_size; i++) {
|
||||
MEM_B(i, data_ptr) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the actor's fields to the actor data slotmap.
|
||||
u32 spawn_index = actor_spawn_count++;
|
||||
dod::slot_map_key32<ExtensionData> key = actor_data.emplace(ExtensionData{.actor_spawn_index = spawn_index, .data_addr = data_ptr});
|
||||
|
||||
// printf("Allocated actor data: address 0x%08X with 0x%08X bytes total (0x%08X bytes generic and 0x%08X bytes specific), handle 0x%08X, spawn index %d\n",
|
||||
// data_ptr, alloc_size, generic_data_size, type_data_size, key.raw, spawn_index);
|
||||
|
||||
_return<u32>(ctx, key.raw);
|
||||
}
|
||||
|
||||
extern "C" void recomp_destroy_actor_data(uint8_t* rdram, recomp_context* ctx) {
|
||||
std::lock_guard lock{ actor_data_mutex };
|
||||
|
||||
u32 actor_handle = _arg<0, u32>(rdram, ctx);
|
||||
actor_data_map_t::key actor_key{actor_handle};
|
||||
|
||||
ExtensionData* data = actor_data.get(actor_key);
|
||||
if (data != nullptr) {
|
||||
// printf("Freeing actor data: address 0x%08X handle 0x%08X\n", data->data_addr, actor_handle);
|
||||
if (data->data_addr != NULLPTR) {
|
||||
recomp::free(rdram, TO_PTR(void, data->data_addr));
|
||||
free_count++;
|
||||
}
|
||||
actor_data.erase(actor_data_map_t::key{actor_handle});
|
||||
}
|
||||
else {
|
||||
// Not an irrecoverable error, but catch it in debug mode with an assert to help find bugs.
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void recomp_get_actor_data(uint8_t* rdram, recomp_context* ctx) {
|
||||
std::lock_guard lock{ actor_data_mutex };
|
||||
|
||||
u32 actor_handle = _arg<0, u32>(rdram, ctx);
|
||||
u32 extension_handle = _arg<1, u32>(rdram, ctx);
|
||||
u32 actor_type = _arg<2, u32>(rdram, ctx);
|
||||
|
||||
// Check if the extension handle is valid.
|
||||
if (extension_handle == 0 || extension_handle >= actor_extensions.size()) {
|
||||
_return<PTR(void)>(ctx, NULLPTR);
|
||||
return;
|
||||
}
|
||||
|
||||
ExtensionInfo& extension = actor_extensions[extension_handle];
|
||||
bool generic_extension = extension.actor_type == 0xFFFFFFFFU;
|
||||
|
||||
// Check if the extension is generic or for the provided actor type.
|
||||
if (!generic_extension && extension.actor_type != actor_type) {
|
||||
_return<PTR(void)>(ctx, NULLPTR);
|
||||
return;
|
||||
}
|
||||
|
||||
actor_data_map_t::key actor_key{actor_handle};
|
||||
ExtensionData* data = actor_data.get(actor_key);
|
||||
|
||||
// Check if actor handle is valid.
|
||||
if (data == nullptr) {
|
||||
_return<PTR(void)>(ctx, NULLPTR);
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the address for this specific extension's data.
|
||||
PTR(void) base_address = data->data_addr;
|
||||
u32 offset = extension.data_offset;
|
||||
// Specific actor data is after generic actor data, so increase the offset by the total generic actor data if this isn't generic data.
|
||||
if (!generic_extension) {
|
||||
offset += generic_data_size;
|
||||
}
|
||||
|
||||
PTR(void) ret = base_address + offset;
|
||||
_return<PTR(void)>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void recomp_get_actor_spawn_index(uint8_t* rdram, recomp_context* ctx) {
|
||||
std::lock_guard lock{ actor_data_mutex };
|
||||
|
||||
u32 actor_handle = _arg<0, u32>(rdram, ctx);
|
||||
|
||||
actor_data_map_t::key actor_key{actor_handle};
|
||||
ExtensionData* data = actor_data.get(actor_key);
|
||||
|
||||
// Check if actor handle is valid.
|
||||
if (data == nullptr) {
|
||||
_return<u32>(ctx, 0xFFFFFFFFU);
|
||||
return;
|
||||
}
|
||||
|
||||
_return<u32>(ctx, data->actor_spawn_index);
|
||||
}
|
||||
|
||||
+7
-40
@@ -180,21 +180,6 @@ extern "C" void recomp_set_right_analog_suppressed(uint8_t* rdram, recomp_contex
|
||||
recomp::set_right_analog_suppressed(suppressed);
|
||||
}
|
||||
|
||||
// Function with typo in decomp
|
||||
extern "C" void osWriteBackDCacheAll(uint8_t* rdram, recomp_context* ctx) {}
|
||||
|
||||
extern "C" void boot_osPiRawStartDma(uint8_t* rdram, recomp_context* ctx) {
|
||||
uint32_t direction = ctx->r4;
|
||||
uint32_t device_address = ctx->r5;
|
||||
gpr rdram_address = ctx->r6;
|
||||
uint32_t size = ctx->r7;
|
||||
|
||||
assert(direction == 0); // Only reads
|
||||
|
||||
// Complete the DMA synchronously (the game immediately waits until it's done anyways)
|
||||
recomp::do_rom_read(rdram, rdram_address, device_address + recomp::rom_base, size);
|
||||
}
|
||||
|
||||
constexpr uint32_t k1_to_phys(uint32_t addr) {
|
||||
return addr & 0x1FFFFFFF;
|
||||
}
|
||||
@@ -215,35 +200,10 @@ extern "C" void osPiReadIo_recomp(RDRAM_ARG recomp_context * ctx) {
|
||||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void boot___osInitialize_common(uint8_t* rdram, recomp_context* ctx) {}
|
||||
|
||||
extern "C" void boot_osPiGetStatus(uint8_t* rdram, recomp_context* ctx) {
|
||||
// PI not busy
|
||||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void osPfsInit_recomp(uint8_t * rdram, recomp_context* ctx) {
|
||||
ctx->r2 = 11; // PFS_ERR_DEVICE
|
||||
}
|
||||
|
||||
extern "C" void __ll_lshift_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
uint64_t a = (ctx->r4 << 32) | ((ctx->r5 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t b = (ctx->r6 << 32) | ((ctx->r7 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t ret = a << b;
|
||||
|
||||
ctx->r2 = (int32_t)(ret >> 32);
|
||||
ctx->r3 = (int32_t)(ret >> 0);
|
||||
}
|
||||
|
||||
extern "C" void __ull_rshift_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
uint64_t a = (ctx->r4 << 32) | ((ctx->r5 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t b = (ctx->r6 << 32) | ((ctx->r7 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t ret = a >> b;
|
||||
|
||||
ctx->r2 = (int32_t)(ret >> 32);
|
||||
ctx->r3 = (int32_t)(ret >> 0);
|
||||
}
|
||||
|
||||
// u32 rom_addr, void *ram_addr, u32 size
|
||||
extern "C" void recomp_load_overlays_by_rom(uint8_t* rdram, recomp_context* ctx) {
|
||||
u32 rom_addr = _arg<0, u32>(rdram, ctx);
|
||||
@@ -252,3 +212,10 @@ extern "C" void recomp_load_overlays_by_rom(uint8_t* rdram, recomp_context* ctx)
|
||||
|
||||
load_overlays(rom_addr, ram_addr, size);
|
||||
}
|
||||
|
||||
extern "C" void recomp_abort(uint8_t* rdram, recomp_context* ctx) {
|
||||
std::string msg = _arg_string<0>(rdram, ctx);
|
||||
recompui::message_box(msg.c_str());
|
||||
assert(false);
|
||||
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <deque>
|
||||
|
||||
#include "slot_map.h"
|
||||
|
||||
#include "librecomp/helpers.hpp"
|
||||
#include "librecomp/addresses.hpp"
|
||||
#include "ultramodern/error_handling.hpp"
|
||||
#include "recomp_ui.h"
|
||||
#include "recomp_data.h"
|
||||
#include "../patches/object_extension_funcs.h"
|
||||
|
||||
struct ExtensionInfo {
|
||||
// Either the object's subtype ID, or 0xFFFFFFFF if this is for generic data.
|
||||
uint32_t subtype_index;
|
||||
// The offset from either the start of the object's extension data (for generic extensions) or from the start of the objects's specific extension data.
|
||||
uint32_t data_offset;
|
||||
};
|
||||
|
||||
struct ExtensionData {
|
||||
uint32_t object_spawn_index;
|
||||
PTR(void) data_addr;
|
||||
};
|
||||
|
||||
using extension_data_map_t = dod::slot_map32<ExtensionData>;
|
||||
|
||||
std::mutex extension_mutex;
|
||||
struct ExtensionContext {
|
||||
// The total size of subtype-specific extension data for each subtype.
|
||||
std::vector<uint32_t> data_sizes{};
|
||||
// The total size of all generic extension data.
|
||||
uint32_t generic_data_size = 0;
|
||||
// The registered extensions.
|
||||
std::vector<ExtensionInfo> extensions{};
|
||||
// The extension data for every object.
|
||||
extension_data_map_t extension_data{};
|
||||
// The number of objects spawned since the last reset.
|
||||
uint32_t spawn_count = 0;
|
||||
// Debug counters.
|
||||
size_t alloc_count = 0;
|
||||
size_t free_count = 0;
|
||||
};
|
||||
|
||||
// The extension contexts for each object type. This must be a deque instead of a vector due to a lack of a copy constructor.
|
||||
std::deque<ExtensionContext> type_contexts{};
|
||||
// Whether or not extensions can be registered at this time.
|
||||
bool can_register = false;
|
||||
|
||||
void recomputil::init_extended_object_data(size_t num_types) {
|
||||
type_contexts.clear();
|
||||
|
||||
can_register = true;
|
||||
// Create a dummy extension so the first extension handle is nonzero, should help catch bugs.
|
||||
for (size_t i = 0; i < num_types; i++) {
|
||||
type_contexts.emplace_back(ExtensionContext{});
|
||||
type_contexts[i].extensions.push_back({});
|
||||
}
|
||||
}
|
||||
|
||||
void recomputil::clear_all_object_data(size_t type_index) {
|
||||
ExtensionContext& context = type_contexts[type_index];
|
||||
std::lock_guard lock{ extension_mutex };
|
||||
context.extension_data.reset();
|
||||
context.spawn_count = 0;
|
||||
|
||||
assert(context.alloc_count == context.free_count);
|
||||
context.alloc_count = 0;
|
||||
context.free_count = 0;
|
||||
}
|
||||
|
||||
constexpr uint32_t round_up_16(uint32_t value) {
|
||||
return (value + 15) & (~15);
|
||||
}
|
||||
|
||||
extern "C" void recomp_register_object_extension(uint8_t* rdram, recomp_context* ctx) {
|
||||
u32 type_index = _arg<0, u32>(rdram, ctx);
|
||||
u32 subtype_index = _arg<1, u32>(rdram, ctx);
|
||||
u32 size = _arg<2, u32>(rdram, ctx);
|
||||
|
||||
ExtensionContext& context = type_contexts[type_index];
|
||||
|
||||
if (!can_register) {
|
||||
recompui::message_box("Fatal error in mod - attempted to register object extension data after objects have been spawned.");
|
||||
assert(false);
|
||||
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
if (context.data_sizes.size() <= subtype_index) {
|
||||
context.data_sizes.resize(subtype_index + 1);
|
||||
}
|
||||
|
||||
// Increase the object subtype's extension data size by the provided size (rounded up to a multiple of 16).
|
||||
uint32_t data_offset = context.data_sizes[subtype_index];
|
||||
context.data_sizes[subtype_index] += round_up_16(size);
|
||||
|
||||
// Register the extension.
|
||||
uint32_t ret = static_cast<uint32_t>(context.extensions.size());
|
||||
context.extensions.emplace_back(ExtensionInfo{.subtype_index = subtype_index, .data_offset = data_offset});
|
||||
|
||||
// printf("Registered object extension data for type %u subtype %u (size 0x%08X, offset 0x%08X)\n", type_index, subtype_index, size, data_offset);
|
||||
|
||||
_return<u32>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void recomp_register_object_extension_generic(uint8_t* rdram, recomp_context* ctx) {
|
||||
u32 type_index = _arg<0, u32>(rdram, ctx);
|
||||
u32 size = _arg<1, u32>(rdram, ctx);
|
||||
|
||||
ExtensionContext& context = type_contexts[type_index];
|
||||
|
||||
// Increase the generic extension data size by the provided size (rounded up to a multiple of 16).
|
||||
uint32_t data_offset = context.generic_data_size;
|
||||
context.generic_data_size += round_up_16(size);
|
||||
|
||||
// Register the extension.
|
||||
uint32_t ret = static_cast<uint32_t>(context.extensions.size());
|
||||
context.extensions.emplace_back(ExtensionInfo{.subtype_index = 0xFFFFFFFFU, .data_offset = data_offset});
|
||||
|
||||
// printf("Registered generic object extension data for type %u (size 0x%08X, offset 0x%08X)\n", type_index, size, data_offset);
|
||||
_return<u32>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void recomp_clear_all_object_data(uint8_t* rdram, recomp_context* ctx) {
|
||||
u32 type_index = _arg<0, u32>(rdram, ctx);
|
||||
recomputil::clear_all_object_data(type_index);
|
||||
}
|
||||
|
||||
extern "C" void recomp_create_object_data(uint8_t* rdram, recomp_context* ctx) {
|
||||
u32 type_index = _arg<0, u32>(rdram, ctx);
|
||||
u32 subtype_index = _arg<1, u32>(rdram, ctx);
|
||||
|
||||
ExtensionContext& context = type_contexts[type_index];
|
||||
|
||||
std::lock_guard lock{ extension_mutex };
|
||||
|
||||
can_register = false;
|
||||
|
||||
// Determine the number of bytes to allocate based on the subtype's extensions and the generic extensions.
|
||||
u32 alloc_size = context.generic_data_size;
|
||||
[[maybe_unused]] u32 subtype_data_size = 0;
|
||||
|
||||
if (subtype_index < context.data_sizes.size()) {
|
||||
subtype_data_size = context.data_sizes[subtype_index];
|
||||
alloc_size += subtype_data_size;
|
||||
}
|
||||
|
||||
// Allocate the extension data if it's of nonzero size.
|
||||
PTR(void) data_ptr = NULLPTR;
|
||||
if (alloc_size != 0) {
|
||||
void* data = recomp::alloc(rdram, alloc_size);
|
||||
context.alloc_count++;
|
||||
data_ptr = reinterpret_cast<uint8_t*>(data) - rdram + 0xFFFFFFFF80000000U;
|
||||
// Zero the allocated memory.
|
||||
// A memset should be fine here since this data is aligned, but use a byteswapped loop just to be safe.
|
||||
for (size_t i = 0; i < alloc_size; i++) {
|
||||
MEM_B(i, data_ptr) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the object's data to the type's data slotmap.
|
||||
u32 spawn_index = context.spawn_count++;
|
||||
dod::slot_map_key32<ExtensionData> key = context.extension_data.emplace(ExtensionData{.object_spawn_index = spawn_index, .data_addr = data_ptr});
|
||||
|
||||
// printf("Allocated object data: type %u address 0x%08X with 0x%08X bytes total (0x%08X bytes generic and 0x%08X bytes specific), handle 0x%08X, spawn index %d\n",
|
||||
// type_index, data_ptr, alloc_size, generic_data_size, type_data_size, key.raw, spawn_index);
|
||||
|
||||
_return<u32>(ctx, key.raw);
|
||||
}
|
||||
|
||||
extern "C" void recomp_destroy_object_data(uint8_t* rdram, recomp_context* ctx) {
|
||||
u32 type_index = _arg<0, u32>(rdram, ctx);
|
||||
u32 object_handle = _arg<1, u32>(rdram, ctx);
|
||||
ExtensionContext& context = type_contexts[type_index];
|
||||
|
||||
std::lock_guard lock{ extension_mutex };
|
||||
|
||||
extension_data_map_t::key object_key{object_handle};
|
||||
|
||||
ExtensionData* data = context.extension_data.get(object_key);
|
||||
if (data != nullptr) {
|
||||
// printf("Freeing object data: address 0x%08X handle 0x%08X\n", data->data_addr, object_handle);
|
||||
if (data->data_addr != NULLPTR) {
|
||||
recomp::free(rdram, TO_PTR(void, data->data_addr));
|
||||
context.free_count++;
|
||||
}
|
||||
context.extension_data.erase(extension_data_map_t::key{object_handle});
|
||||
}
|
||||
else {
|
||||
// Not an irrecoverable error, but catch it in debug mode with an assert to help find bugs.
|
||||
// *(volatile int*)object_handle = 0;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void recomp_get_object_data(uint8_t* rdram, recomp_context* ctx) {
|
||||
u32 type_index = _arg<0, u32>(rdram, ctx);
|
||||
u32 subtype_index = _arg<1, u32>(rdram, ctx);
|
||||
u32 object_handle = _arg<2, u32>(rdram, ctx);
|
||||
u32 extension_handle = _arg<3, u32>(rdram, ctx);
|
||||
|
||||
ExtensionContext& context = type_contexts[type_index];
|
||||
std::lock_guard lock{ extension_mutex };
|
||||
|
||||
// Check if the extension handle is valid.
|
||||
if (extension_handle == 0 || extension_handle >= context.extensions.size()) {
|
||||
_return<PTR(void)>(ctx, NULLPTR);
|
||||
return;
|
||||
}
|
||||
|
||||
ExtensionInfo& extension = context.extensions[extension_handle];
|
||||
bool generic_extension = extension.subtype_index == 0xFFFFFFFFU;
|
||||
|
||||
// Check if the extension is generic or for the provided subtype.
|
||||
if (!generic_extension && extension.subtype_index != subtype_index) {
|
||||
_return<PTR(void)>(ctx, NULLPTR);
|
||||
return;
|
||||
}
|
||||
|
||||
extension_data_map_t::key object_key{object_handle};
|
||||
ExtensionData* data = context.extension_data.get(object_key);
|
||||
|
||||
// Check if object handle is valid.
|
||||
if (data == nullptr) {
|
||||
_return<PTR(void)>(ctx, NULLPTR);
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the address for this specific extension's data.
|
||||
PTR(void) base_address = data->data_addr;
|
||||
u32 offset = extension.data_offset;
|
||||
// Specific object data is after generic object data, so increase the offset by the total generic object data if this isn't generic data.
|
||||
if (!generic_extension) {
|
||||
offset += context.generic_data_size;
|
||||
}
|
||||
|
||||
PTR(void) ret = base_address + offset;
|
||||
_return<PTR(void)>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void recomp_get_object_spawn_index(uint8_t* rdram, recomp_context* ctx) {
|
||||
u32 type_index = _arg<0, u32>(rdram, ctx);
|
||||
u32 object_handle = _arg<1, u32>(rdram, ctx);
|
||||
ExtensionContext& context = type_contexts[type_index];
|
||||
|
||||
std::lock_guard lock{ extension_mutex };
|
||||
|
||||
|
||||
extension_data_map_t::key object_key{object_handle};
|
||||
ExtensionData* data = context.extension_data.get(object_key);
|
||||
|
||||
// Check if object handle is valid.
|
||||
if (data == nullptr) {
|
||||
_return<u32>(ctx, 0xFFFFFFFFU);
|
||||
return;
|
||||
}
|
||||
|
||||
_return<u32>(ctx, data->object_spawn_index);
|
||||
}
|
||||
|
||||
+35
-1
@@ -18,6 +18,13 @@
|
||||
#else
|
||||
#include "SDL2/SDL.h"
|
||||
#include "SDL2/SDL_syswm.h"
|
||||
// Undefine x11 macros that get included by SDL_syswm.h.
|
||||
#undef None
|
||||
#undef Status
|
||||
#undef LockMask
|
||||
#undef ControlMask
|
||||
#undef Success
|
||||
#undef Always
|
||||
#endif
|
||||
|
||||
#include "recomp_ui.h"
|
||||
@@ -42,6 +49,7 @@
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <timeapi.h>
|
||||
#include "SDL_syswm.h"
|
||||
#endif
|
||||
|
||||
@@ -543,6 +551,26 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Set up high resolution timing period.
|
||||
timeBeginPeriod(1);
|
||||
|
||||
// Process arguments.
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i], "--show-console") == 0)
|
||||
{
|
||||
if (GetConsoleWindow() == nullptr)
|
||||
{
|
||||
AllocConsole();
|
||||
freopen("CONIN$", "r", stdin);
|
||||
freopen("CONOUT$", "w", stderr);
|
||||
freopen("CONOUT$", "w", stdout);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set up console output to accept UTF-8 on windows
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
|
||||
@@ -607,7 +635,8 @@ int main(int argc, char** argv) {
|
||||
|
||||
banjo::register_bk_overlays();
|
||||
banjo::register_bk_patches();
|
||||
recomputil::init_extended_actor_data();
|
||||
// Register extensions for two types: Props and ActorMarkers.
|
||||
recomputil::init_extended_object_data(2);
|
||||
banjo::load_config();
|
||||
|
||||
recomp::rsp::callbacks_t rsp_callbacks{
|
||||
@@ -682,5 +711,10 @@ int main(int argc, char** argv) {
|
||||
release_preload(preload_context);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// End high resolution timing period.
|
||||
timeEndPeriod(1);
|
||||
#endif
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
#include "ovl_patches.hpp"
|
||||
#include "../../RecompiledPatches/patches_bin.h"
|
||||
#include "../../RecompiledPatches/recomp_overlays.inl"
|
||||
|
||||
#include "librecomp/overlays.hpp"
|
||||
#include "librecomp/game.hpp"
|
||||
|
||||
extern "C" {
|
||||
extern const char bk_patches_bin[];
|
||||
extern const size_t bk_patches_bin_size;
|
||||
}
|
||||
|
||||
void banjo::register_bk_patches() {
|
||||
recomp::overlays::register_patches(bk_patches_bin, sizeof(bk_patches_bin), section_table, ARRLEN(section_table));
|
||||
recomp::overlays::register_patches(bk_patches_bin, bk_patches_bin_size, section_table, ARRLEN(section_table));
|
||||
recomp::overlays::register_base_exports(export_table);
|
||||
recomp::overlays::register_base_events(event_names);
|
||||
recomp::overlays::register_manual_patch_symbols(manual_patch_symbols);
|
||||
|
||||
@@ -56,27 +56,12 @@ unsigned int DPC_BUFBUSY_REG = 0;
|
||||
unsigned int DPC_PIPEBUSY_REG = 0;
|
||||
unsigned int DPC_TMEM_REG = 0;
|
||||
|
||||
unsigned int VI_STATUS_REG = 0;
|
||||
unsigned int VI_ORIGIN_REG = 0;
|
||||
unsigned int VI_WIDTH_REG = 0;
|
||||
unsigned int VI_INTR_REG = 0;
|
||||
unsigned int VI_V_CURRENT_LINE_REG = 0;
|
||||
unsigned int VI_TIMING_REG = 0;
|
||||
unsigned int VI_V_SYNC_REG = 0;
|
||||
unsigned int VI_H_SYNC_REG = 0;
|
||||
unsigned int VI_LEAP_REG = 0;
|
||||
unsigned int VI_H_START_REG = 0;
|
||||
unsigned int VI_V_START_REG = 0;
|
||||
unsigned int VI_V_BURST_REG = 0;
|
||||
unsigned int VI_X_SCALE_REG = 0;
|
||||
unsigned int VI_Y_SCALE_REG = 0;
|
||||
|
||||
void dummy_check_interrupts() {}
|
||||
|
||||
RT64::UserConfiguration::Antialiasing compute_max_supported_aa(RT64::RenderSampleCounts bits) {
|
||||
if (bits & RT64::RenderSampleCount::Bits::COUNT_2) {
|
||||
if (bits & RT64::RenderSampleCount::Bits::COUNT_4) {
|
||||
if (bits & RT64::RenderSampleCount::Bits::COUNT_8) {
|
||||
RT64::UserConfiguration::Antialiasing compute_max_supported_aa(plume::RenderSampleCounts bits) {
|
||||
if (bits & plume::RenderSampleCount::Bits::COUNT_2) {
|
||||
if (bits & plume::RenderSampleCount::Bits::COUNT_4) {
|
||||
if (bits & plume::RenderSampleCount::Bits::COUNT_8) {
|
||||
return RT64::UserConfiguration::Antialiasing::MSAA8X;
|
||||
}
|
||||
return RT64::UserConfiguration::Antialiasing::MSAA4X;
|
||||
@@ -250,20 +235,22 @@ banjo::renderer::RT64Context::RT64Context(uint8_t* rdram, ultramodern::renderer:
|
||||
appCore.DPC_PIPEBUSY_REG = &DPC_PIPEBUSY_REG;
|
||||
appCore.DPC_TMEM_REG = &DPC_TMEM_REG;
|
||||
|
||||
appCore.VI_STATUS_REG = &VI_STATUS_REG;
|
||||
appCore.VI_ORIGIN_REG = &VI_ORIGIN_REG;
|
||||
appCore.VI_WIDTH_REG = &VI_WIDTH_REG;
|
||||
appCore.VI_INTR_REG = &VI_INTR_REG;
|
||||
appCore.VI_V_CURRENT_LINE_REG = &VI_V_CURRENT_LINE_REG;
|
||||
appCore.VI_TIMING_REG = &VI_TIMING_REG;
|
||||
appCore.VI_V_SYNC_REG = &VI_V_SYNC_REG;
|
||||
appCore.VI_H_SYNC_REG = &VI_H_SYNC_REG;
|
||||
appCore.VI_LEAP_REG = &VI_LEAP_REG;
|
||||
appCore.VI_H_START_REG = &VI_H_START_REG;
|
||||
appCore.VI_V_START_REG = &VI_V_START_REG;
|
||||
appCore.VI_V_BURST_REG = &VI_V_BURST_REG;
|
||||
appCore.VI_X_SCALE_REG = &VI_X_SCALE_REG;
|
||||
appCore.VI_Y_SCALE_REG = &VI_Y_SCALE_REG;
|
||||
ultramodern::renderer::ViRegs* vi_regs = ultramodern::renderer::get_vi_regs();
|
||||
|
||||
appCore.VI_STATUS_REG = &vi_regs->VI_STATUS_REG;
|
||||
appCore.VI_ORIGIN_REG = &vi_regs->VI_ORIGIN_REG;
|
||||
appCore.VI_WIDTH_REG = &vi_regs->VI_WIDTH_REG;
|
||||
appCore.VI_INTR_REG = &vi_regs->VI_INTR_REG;
|
||||
appCore.VI_V_CURRENT_LINE_REG = &vi_regs->VI_V_CURRENT_LINE_REG;
|
||||
appCore.VI_TIMING_REG = &vi_regs->VI_TIMING_REG;
|
||||
appCore.VI_V_SYNC_REG = &vi_regs->VI_V_SYNC_REG;
|
||||
appCore.VI_H_SYNC_REG = &vi_regs->VI_H_SYNC_REG;
|
||||
appCore.VI_LEAP_REG = &vi_regs->VI_LEAP_REG;
|
||||
appCore.VI_H_START_REG = &vi_regs->VI_H_START_REG;
|
||||
appCore.VI_V_START_REG = &vi_regs->VI_V_START_REG;
|
||||
appCore.VI_V_BURST_REG = &vi_regs->VI_V_BURST_REG;
|
||||
appCore.VI_X_SCALE_REG = &vi_regs->VI_X_SCALE_REG;
|
||||
appCore.VI_Y_SCALE_REG = &vi_regs->VI_Y_SCALE_REG;
|
||||
|
||||
// Set up the RT64 application configuration fields.
|
||||
RT64::ApplicationConfiguration appConfig;
|
||||
@@ -315,9 +302,9 @@ banjo::renderer::RT64Context::RT64Context(uint8_t* rdram, ultramodern::renderer:
|
||||
// Check if the selected device actually supports MSAA sample positions and MSAA for for the formats that will be used
|
||||
// and downgrade the configuration accordingly.
|
||||
if (app->device->getCapabilities().sampleLocations) {
|
||||
RT64::RenderSampleCounts color_sample_counts = app->device->getSampleCountsSupported(RT64::RenderFormat::R8G8B8A8_UNORM);
|
||||
RT64::RenderSampleCounts depth_sample_counts = app->device->getSampleCountsSupported(RT64::RenderFormat::D32_FLOAT);
|
||||
RT64::RenderSampleCounts common_sample_counts = color_sample_counts & depth_sample_counts;
|
||||
plume::RenderSampleCounts color_sample_counts = app->device->getSampleCountsSupported(plume::RenderFormat::R8G8B8A8_UNORM);
|
||||
plume::RenderSampleCounts depth_sample_counts = app->device->getSampleCountsSupported(plume::RenderFormat::D32_FLOAT);
|
||||
plume::RenderSampleCounts common_sample_counts = color_sample_counts & depth_sample_counts;
|
||||
device_max_msaa = compute_max_supported_aa(common_sample_counts);
|
||||
sample_positions_supported = true;
|
||||
}
|
||||
@@ -338,9 +325,7 @@ void banjo::renderer::RT64Context::send_dl(const OSTask* task) {
|
||||
app->processDisplayLists(app->core.RDRAM, task->t.data_ptr & 0x3FFFFFF, 0, true);
|
||||
}
|
||||
|
||||
void banjo::renderer::RT64Context::update_screen(uint32_t vi_origin) {
|
||||
VI_ORIGIN_REG = vi_origin;
|
||||
|
||||
void banjo::renderer::RT64Context::update_screen() {
|
||||
app->updateScreen();
|
||||
}
|
||||
|
||||
|
||||
+114
-115
@@ -9,7 +9,6 @@
|
||||
#include <concurrentqueue.h>
|
||||
|
||||
#include "rt64_render_hooks.h"
|
||||
#include "rt64_render_interface_builders.h"
|
||||
#include "rt64_texture_cache.h"
|
||||
|
||||
#include "RmlUi/Core/RenderInterfaceCompatibility.h"
|
||||
@@ -29,23 +28,23 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
# define GET_SHADER_BLOB(name, format) \
|
||||
((format) == RT64::RenderShaderFormat::SPIRV ? name##BlobSPIRV : \
|
||||
(format) == RT64::RenderShaderFormat::DXIL ? name##BlobDXIL : nullptr)
|
||||
((format) == plume::RenderShaderFormat::SPIRV ? name##BlobSPIRV : \
|
||||
(format) == plume::RenderShaderFormat::DXIL ? name##BlobDXIL : nullptr)
|
||||
# define GET_SHADER_SIZE(name, format) \
|
||||
((format) == RT64::RenderShaderFormat::SPIRV ? std::size(name##BlobSPIRV) : \
|
||||
(format) == RT64::RenderShaderFormat::DXIL ? std::size(name##BlobDXIL) : 0)
|
||||
((format) == plume::RenderShaderFormat::SPIRV ? std::size(name##BlobSPIRV) : \
|
||||
(format) == plume::RenderShaderFormat::DXIL ? std::size(name##BlobDXIL) : 0)
|
||||
#elif defined(__APPLE__)
|
||||
# define GET_SHADER_BLOB(name, format) \
|
||||
((format) == RT64::RenderShaderFormat::SPIRV ? name##BlobSPIRV : \
|
||||
(format) == RT64::RenderShaderFormat::METAL ? name##BlobMSL : nullptr)
|
||||
((format) == plume::RenderShaderFormat::SPIRV ? name##BlobSPIRV : \
|
||||
(format) == plume::RenderShaderFormat::METAL ? name##BlobMSL : nullptr)
|
||||
# define GET_SHADER_SIZE(name, format) \
|
||||
((format) == RT64::RenderShaderFormat::SPIRV ? std::size(name##BlobSPIRV) : \
|
||||
(format) == RT64::RenderShaderFormat::METAL ? std::size(name##BlobMSL) : 0)
|
||||
((format) == plume::RenderShaderFormat::SPIRV ? std::size(name##BlobSPIRV) : \
|
||||
(format) == plume::RenderShaderFormat::METAL ? std::size(name##BlobMSL) : 0)
|
||||
#else
|
||||
# define GET_SHADER_BLOB(name, format) \
|
||||
((format) == RT64::RenderShaderFormat::SPIRV ? name##BlobSPIRV : nullptr)
|
||||
((format) == plume::RenderShaderFormat::SPIRV ? name##BlobSPIRV : nullptr)
|
||||
# define GET_SHADER_SIZE(name, format) \
|
||||
((format) == RT64::RenderShaderFormat::SPIRV ? std::size(name##BlobSPIRV) : 0)
|
||||
((format) == plume::RenderShaderFormat::SPIRV ? std::size(name##BlobSPIRV) : 0)
|
||||
#endif
|
||||
|
||||
// TODO deduplicate from rt64_common.h
|
||||
@@ -62,8 +61,8 @@ struct RmlPushConstants {
|
||||
};
|
||||
|
||||
struct TextureHandle {
|
||||
std::unique_ptr<RT64::RenderTexture> texture;
|
||||
std::unique_ptr<RT64::RenderDescriptorSet> set;
|
||||
std::unique_ptr<plume::RenderTexture> texture;
|
||||
std::unique_ptr<plume::RenderDescriptorSet> set;
|
||||
bool transitioned = false;
|
||||
};
|
||||
|
||||
@@ -89,11 +88,11 @@ struct ImageFromBytes {
|
||||
namespace recompui {
|
||||
class RmlRenderInterface_RT64_impl : public Rml::RenderInterfaceCompatibility {
|
||||
struct DynamicBuffer {
|
||||
std::unique_ptr<RT64::RenderBuffer> buffer_{};
|
||||
std::unique_ptr<plume::RenderBuffer> buffer_{};
|
||||
uint32_t size_ = 0;
|
||||
uint32_t bytes_used_ = 0;
|
||||
uint8_t* mapped_data_ = nullptr;
|
||||
RT64::RenderBufferFlags flags_ = RT64::RenderBufferFlag::NONE;
|
||||
plume::RenderBufferFlags flags_ = plume::RenderBufferFlag::NONE;
|
||||
};
|
||||
|
||||
static constexpr uint32_t per_frame_descriptor_set = 0;
|
||||
@@ -102,20 +101,20 @@ class RmlRenderInterface_RT64_impl : public Rml::RenderInterfaceCompatibility {
|
||||
static constexpr uint32_t initial_upload_buffer_size = 1024 * 1024;
|
||||
static constexpr uint32_t initial_vertex_buffer_size = 512 * sizeof(Rml::Vertex);
|
||||
static constexpr uint32_t initial_index_buffer_size = 1024 * sizeof(int);
|
||||
static constexpr RT64::RenderFormat RmlTextureFormat = RT64::RenderFormat::R8G8B8A8_UNORM;
|
||||
static constexpr RT64::RenderFormat RmlTextureFormatBgra = RT64::RenderFormat::B8G8R8A8_UNORM;
|
||||
static constexpr RT64::RenderFormat SwapChainFormat = RT64::RenderFormat::B8G8R8A8_UNORM;
|
||||
static constexpr plume::RenderFormat RmlTextureFormat = plume::RenderFormat::R8G8B8A8_UNORM;
|
||||
static constexpr plume::RenderFormat RmlTextureFormatBgra = plume::RenderFormat::B8G8R8A8_UNORM;
|
||||
static constexpr plume::RenderFormat SwapChainFormat = plume::RenderFormat::B8G8R8A8_UNORM;
|
||||
static constexpr uint32_t RmlTextureFormatBytesPerPixel = RenderFormatSize(RmlTextureFormat);
|
||||
static_assert(RenderFormatSize(RmlTextureFormatBgra) == RmlTextureFormatBytesPerPixel);
|
||||
RT64::RenderInterface* interface_;
|
||||
RT64::RenderDevice* device_;
|
||||
plume::RenderInterface* interface_;
|
||||
plume::RenderDevice* device_;
|
||||
int scissor_x_ = 0;
|
||||
int scissor_y_ = 0;
|
||||
int scissor_width_ = 0;
|
||||
int scissor_height_ = 0;
|
||||
int window_width_ = 0;
|
||||
int window_height_ = 0;
|
||||
RT64::RenderMultisampling multisampling_ = RT64::RenderMultisampling();
|
||||
plume::RenderMultisampling multisampling_ = plume::RenderMultisampling();
|
||||
Rml::Matrix4f projection_mtx_ = Rml::Matrix4f::Identity();
|
||||
Rml::Matrix4f transform_ = Rml::Matrix4f::Identity();
|
||||
Rml::Matrix4f mvp_ = Rml::Matrix4f::Identity();
|
||||
@@ -124,46 +123,46 @@ class RmlRenderInterface_RT64_impl : public Rml::RenderInterfaceCompatibility {
|
||||
DynamicBuffer upload_buffer_;
|
||||
DynamicBuffer vertex_buffer_;
|
||||
DynamicBuffer index_buffer_;
|
||||
std::unique_ptr<RT64::RenderSampler> nearestSampler_{};
|
||||
std::unique_ptr<RT64::RenderSampler> linearSampler_{};
|
||||
std::unique_ptr<RT64::RenderShader> vertex_shader_{};
|
||||
std::unique_ptr<RT64::RenderShader> pixel_shader_{};
|
||||
std::unique_ptr<RT64::RenderDescriptorSet> sampler_set_{};
|
||||
std::unique_ptr<RT64::RenderDescriptorSetBuilder> texture_set_builder_{};
|
||||
std::unique_ptr<RT64::RenderPipelineLayout> layout_{};
|
||||
std::unique_ptr<RT64::RenderPipeline> pipeline_{};
|
||||
std::unique_ptr<RT64::RenderPipeline> pipeline_ms_{};
|
||||
std::unique_ptr<RT64::RenderTexture> screen_texture_ms_{};
|
||||
std::unique_ptr<RT64::RenderTexture> screen_texture_{};
|
||||
std::unique_ptr<RT64::RenderFramebuffer> screen_framebuffer_{};
|
||||
std::unique_ptr<RT64::RenderDescriptorSet> screen_descriptor_set_{};
|
||||
std::unique_ptr<RT64::RenderBuffer> screen_vertex_buffer_{};
|
||||
std::unique_ptr<RT64::RenderCommandQueue> copy_command_queue_{};
|
||||
std::unique_ptr<RT64::RenderCommandList> copy_command_list_{};
|
||||
std::unique_ptr<RT64::RenderBuffer> copy_buffer_{};
|
||||
std::unique_ptr<RT64::RenderCommandFence> copy_command_fence_;
|
||||
std::unique_ptr<plume::RenderSampler> nearestSampler_{};
|
||||
std::unique_ptr<plume::RenderSampler> linearSampler_{};
|
||||
std::unique_ptr<plume::RenderShader> vertex_shader_{};
|
||||
std::unique_ptr<plume::RenderShader> pixel_shader_{};
|
||||
std::unique_ptr<plume::RenderDescriptorSet> sampler_set_{};
|
||||
std::unique_ptr<plume::RenderDescriptorSetBuilder> texture_set_builder_{};
|
||||
std::unique_ptr<plume::RenderPipelineLayout> layout_{};
|
||||
std::unique_ptr<plume::RenderPipeline> pipeline_{};
|
||||
std::unique_ptr<plume::RenderPipeline> pipeline_ms_{};
|
||||
std::unique_ptr<plume::RenderTexture> screen_texture_ms_{};
|
||||
std::unique_ptr<plume::RenderTexture> screen_texture_{};
|
||||
std::unique_ptr<plume::RenderFramebuffer> screen_framebuffer_{};
|
||||
std::unique_ptr<plume::RenderDescriptorSet> screen_descriptor_set_{};
|
||||
std::unique_ptr<plume::RenderBuffer> screen_vertex_buffer_{};
|
||||
std::unique_ptr<plume::RenderCommandQueue> copy_command_queue_{};
|
||||
std::unique_ptr<plume::RenderCommandList> copy_command_list_{};
|
||||
std::unique_ptr<plume::RenderBuffer> copy_buffer_{};
|
||||
std::unique_ptr<plume::RenderCommandFence> copy_command_fence_;
|
||||
uint64_t copy_buffer_size_ = 0;
|
||||
uint64_t screen_vertex_buffer_size_ = 0;
|
||||
uint32_t gTexture_descriptor_index;
|
||||
RT64::RenderInputSlot vertex_slot_{ 0, sizeof(Rml::Vertex) };
|
||||
RT64::RenderCommandList* list_ = nullptr;
|
||||
plume::RenderInputSlot vertex_slot_{ 0, sizeof(Rml::Vertex) };
|
||||
plume::RenderCommandList* list_ = nullptr;
|
||||
bool scissor_enabled_ = false;
|
||||
std::vector<std::unique_ptr<RT64::RenderBuffer>> stale_buffers_{};
|
||||
std::vector<std::unique_ptr<plume::RenderBuffer>> stale_buffers_{};
|
||||
moodycamel::ConcurrentQueue<ImageFromBytes> image_from_bytes_queue;
|
||||
std::unordered_map<std::string, ImageFromBytes> image_from_bytes_map;
|
||||
public:
|
||||
RmlRenderInterface_RT64_impl(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
|
||||
RmlRenderInterface_RT64_impl(plume::RenderInterface* interface, plume::RenderDevice* device) {
|
||||
interface_ = interface;
|
||||
device_ = device;
|
||||
|
||||
// Enable 4X MSAA if supported by the device.
|
||||
const RT64::RenderSampleCounts desired_sample_count = RT64::RenderSampleCount::COUNT_8;
|
||||
const plume::RenderSampleCounts desired_sample_count = plume::RenderSampleCount::COUNT_8;
|
||||
if (device_->getSampleCountsSupported(SwapChainFormat) & desired_sample_count) {
|
||||
multisampling_.sampleCount = desired_sample_count;
|
||||
}
|
||||
|
||||
vertex_buffer_.flags_ = RT64::RenderBufferFlag::VERTEX;
|
||||
index_buffer_.flags_ = RT64::RenderBufferFlag::INDEX;
|
||||
vertex_buffer_.flags_ = plume::RenderBufferFlag::VERTEX;
|
||||
index_buffer_.flags_ = plume::RenderBufferFlag::INDEX;
|
||||
|
||||
// Create the texture upload buffer, vertex buffer and index buffer
|
||||
resize_dynamic_buffer(upload_buffer_, initial_upload_buffer_size, false);
|
||||
@@ -171,33 +170,33 @@ public:
|
||||
resize_dynamic_buffer(index_buffer_, initial_index_buffer_size, false);
|
||||
|
||||
// Describe the vertex format
|
||||
std::vector<RT64::RenderInputElement> vertex_elements{};
|
||||
vertex_elements.emplace_back(RT64::RenderInputElement{ "POSITION", 0, 0, RT64::RenderFormat::R32G32_FLOAT, 0, offsetof(Rml::Vertex, position) });
|
||||
vertex_elements.emplace_back(RT64::RenderInputElement{ "COLOR", 0, 1, RT64::RenderFormat::R8G8B8A8_UNORM, 0, offsetof(Rml::Vertex, colour) });
|
||||
vertex_elements.emplace_back(RT64::RenderInputElement{ "TEXCOORD", 0, 2, RT64::RenderFormat::R32G32_FLOAT, 0, offsetof(Rml::Vertex, tex_coord) });
|
||||
std::vector<plume::RenderInputElement> vertex_elements{};
|
||||
vertex_elements.emplace_back(plume::RenderInputElement{ "POSITION", 0, 0, plume::RenderFormat::R32G32_FLOAT, 0, offsetof(Rml::Vertex, position) });
|
||||
vertex_elements.emplace_back(plume::RenderInputElement{ "COLOR", 0, 1, plume::RenderFormat::R8G8B8A8_UNORM, 0, offsetof(Rml::Vertex, colour) });
|
||||
vertex_elements.emplace_back(plume::RenderInputElement{ "TEXCOORD", 0, 2, plume::RenderFormat::R32G32_FLOAT, 0, offsetof(Rml::Vertex, tex_coord) });
|
||||
|
||||
// Create a nearest sampler and a linear sampler
|
||||
RT64::RenderSamplerDesc samplerDesc;
|
||||
samplerDesc.minFilter = RT64::RenderFilter::NEAREST;
|
||||
samplerDesc.magFilter = RT64::RenderFilter::NEAREST;
|
||||
samplerDesc.addressU = RT64::RenderTextureAddressMode::CLAMP;
|
||||
samplerDesc.addressV = RT64::RenderTextureAddressMode::CLAMP;
|
||||
samplerDesc.addressW = RT64::RenderTextureAddressMode::CLAMP;
|
||||
plume::RenderSamplerDesc samplerDesc;
|
||||
samplerDesc.minFilter = plume::RenderFilter::NEAREST;
|
||||
samplerDesc.magFilter = plume::RenderFilter::NEAREST;
|
||||
samplerDesc.addressU = plume::RenderTextureAddressMode::CLAMP;
|
||||
samplerDesc.addressV = plume::RenderTextureAddressMode::CLAMP;
|
||||
samplerDesc.addressW = plume::RenderTextureAddressMode::CLAMP;
|
||||
nearestSampler_ = device_->createSampler(samplerDesc);
|
||||
|
||||
samplerDesc.minFilter = RT64::RenderFilter::LINEAR;
|
||||
samplerDesc.magFilter = RT64::RenderFilter::LINEAR;
|
||||
samplerDesc.minFilter = plume::RenderFilter::LINEAR;
|
||||
samplerDesc.magFilter = plume::RenderFilter::LINEAR;
|
||||
linearSampler_ = device_->createSampler(samplerDesc);
|
||||
|
||||
// Create the shaders
|
||||
RT64::RenderShaderFormat shaderFormat = interface_->getCapabilities().shaderFormat;
|
||||
plume::RenderShaderFormat shaderFormat = interface_->getCapabilities().shaderFormat;
|
||||
|
||||
vertex_shader_ = device_->createShader(GET_SHADER_BLOB(InterfaceVS, shaderFormat), GET_SHADER_SIZE(InterfaceVS, shaderFormat), "VSMain", shaderFormat);
|
||||
pixel_shader_ = device_->createShader(GET_SHADER_BLOB(InterfacePS, shaderFormat), GET_SHADER_SIZE(InterfacePS, shaderFormat), "PSMain", shaderFormat);
|
||||
|
||||
|
||||
// Create the descriptor set that contains the sampler
|
||||
RT64::RenderDescriptorSetBuilder sampler_set_builder{};
|
||||
plume::RenderDescriptorSetBuilder sampler_set_builder{};
|
||||
sampler_set_builder.begin();
|
||||
sampler_set_builder.addImmutableSampler(1, linearSampler_.get());
|
||||
sampler_set_builder.addConstantBuffer(3, 1); // Workaround D3D12 crash due to an empty RT64 descriptor set
|
||||
@@ -205,15 +204,15 @@ public:
|
||||
sampler_set_ = sampler_set_builder.create(device_);
|
||||
|
||||
// Create a builder for the descriptor sets that will contain textures
|
||||
texture_set_builder_ = std::make_unique<RT64::RenderDescriptorSetBuilder>();
|
||||
texture_set_builder_ = std::make_unique<plume::RenderDescriptorSetBuilder>();
|
||||
texture_set_builder_->begin();
|
||||
gTexture_descriptor_index = texture_set_builder_->addTexture(2);
|
||||
texture_set_builder_->end();
|
||||
|
||||
// Create the pipeline layout
|
||||
RT64::RenderPipelineLayoutBuilder layout_builder{};
|
||||
plume::RenderPipelineLayoutBuilder layout_builder{};
|
||||
layout_builder.begin(false, true);
|
||||
layout_builder.addPushConstant(0, 0, sizeof(RmlPushConstants), RT64::RenderShaderStageFlag::VERTEX);
|
||||
layout_builder.addPushConstant(0, 0, sizeof(RmlPushConstants), plume::RenderShaderStageFlag::VERTEX);
|
||||
// Add the descriptor set for descriptors changed once per frame.
|
||||
layout_builder.addDescriptorSet(sampler_set_builder);
|
||||
// Add the descriptor set for descriptors changed once per draw.
|
||||
@@ -222,29 +221,29 @@ public:
|
||||
layout_ = layout_builder.create(device_);
|
||||
|
||||
// Create the pipeline description
|
||||
RT64::RenderGraphicsPipelineDesc pipeline_desc{};
|
||||
plume::RenderGraphicsPipelineDesc pipeline_desc{};
|
||||
// Set up alpha blending for non-premultiplied alpha. RmlUi recommends using premultiplied alpha normally,
|
||||
// but that would require preprocessing all input files, which would be difficult for user-provided content (such as mods).
|
||||
// This blending setup produces similar results as premultipled alpha but for normal assets as it multiplies during blending and
|
||||
// computes the output alpha value the same way that a premultipled alpha blender would.
|
||||
pipeline_desc.renderTargetBlend[0] = RT64::RenderBlendDesc {
|
||||
pipeline_desc.renderTargetBlend[0] = plume::RenderBlendDesc {
|
||||
.blendEnabled = true,
|
||||
.srcBlend = RT64::RenderBlend::SRC_ALPHA,
|
||||
.dstBlend = RT64::RenderBlend::INV_SRC_ALPHA,
|
||||
.blendOp = RT64::RenderBlendOperation::ADD,
|
||||
.srcBlendAlpha = RT64::RenderBlend::ONE,
|
||||
.dstBlendAlpha = RT64::RenderBlend::INV_SRC_ALPHA,
|
||||
.blendOpAlpha = RT64::RenderBlendOperation::ADD,
|
||||
.srcBlend = plume::RenderBlend::SRC_ALPHA,
|
||||
.dstBlend = plume::RenderBlend::INV_SRC_ALPHA,
|
||||
.blendOp = plume::RenderBlendOperation::ADD,
|
||||
.srcBlendAlpha = plume::RenderBlend::ONE,
|
||||
.dstBlendAlpha = plume::RenderBlend::INV_SRC_ALPHA,
|
||||
.blendOpAlpha = plume::RenderBlendOperation::ADD,
|
||||
};
|
||||
pipeline_desc.renderTargetFormat[0] = SwapChainFormat; // TODO: Use whatever format the swap chain was created with.
|
||||
pipeline_desc.renderTargetCount = 1;
|
||||
pipeline_desc.cullMode = RT64::RenderCullMode::NONE;
|
||||
pipeline_desc.cullMode = plume::RenderCullMode::NONE;
|
||||
pipeline_desc.inputSlots = &vertex_slot_;
|
||||
pipeline_desc.inputSlotsCount = 1;
|
||||
pipeline_desc.inputElements = vertex_elements.data();
|
||||
pipeline_desc.inputElementsCount = uint32_t(vertex_elements.size());
|
||||
pipeline_desc.pipelineLayout = layout_.get();
|
||||
pipeline_desc.primitiveTopology = RT64::RenderPrimitiveTopology::TRIANGLE_LIST;
|
||||
pipeline_desc.primitiveTopology = plume::RenderPrimitiveTopology::TRIANGLE_LIST;
|
||||
pipeline_desc.vertexShader = vertex_shader_.get();
|
||||
pipeline_desc.pixelShader = pixel_shader_.get();
|
||||
|
||||
@@ -255,12 +254,12 @@ public:
|
||||
pipeline_ms_ = device_->createGraphicsPipeline(pipeline_desc);
|
||||
|
||||
// Create the descriptor set for the screen drawer.
|
||||
RT64::RenderDescriptorRange screen_descriptor_range(RT64::RenderDescriptorRangeType::TEXTURE, 2, 1);
|
||||
screen_descriptor_set_ = device_->createDescriptorSet(RT64::RenderDescriptorSetDesc(&screen_descriptor_range, 1));
|
||||
plume::RenderDescriptorRange screen_descriptor_range(plume::RenderDescriptorRangeType::TEXTURE, 2, 1);
|
||||
screen_descriptor_set_ = device_->createDescriptorSet(plume::RenderDescriptorSetDesc(&screen_descriptor_range, 1));
|
||||
|
||||
// Create vertex buffer for the screen drawer (full-screen triangle).
|
||||
screen_vertex_buffer_size_ = sizeof(Rml::Vertex) * 3;
|
||||
screen_vertex_buffer_ = device_->createBuffer(RT64::RenderBufferDesc::VertexBuffer(screen_vertex_buffer_size_, RT64::RenderHeapType::UPLOAD));
|
||||
screen_vertex_buffer_ = device_->createBuffer(plume::RenderBufferDesc::VertexBuffer(screen_vertex_buffer_size_, plume::RenderHeapType::UPLOAD));
|
||||
Rml::Vertex *vertices = (Rml::Vertex *)(screen_vertex_buffer_->map());
|
||||
const Rml::ColourbPremultiplied white(255, 255, 255, 255);
|
||||
vertices[0] = Rml::Vertex{ Rml::Vector2f(-1.0f, 1.0f), white, Rml::Vector2f(0.0f, 0.0f) };
|
||||
@@ -269,8 +268,8 @@ public:
|
||||
screen_vertex_buffer_->unmap();
|
||||
}
|
||||
|
||||
copy_command_queue_ = device->createCommandQueue(RT64::RenderCommandListType::COPY);
|
||||
copy_command_list_ = copy_command_queue_->createCommandList(RT64::RenderCommandListType::COPY);
|
||||
copy_command_queue_ = device->createCommandQueue(plume::RenderCommandListType::COPY);
|
||||
copy_command_list_ = copy_command_queue_->createCommandList();
|
||||
copy_command_fence_ = device->createCommandFence();
|
||||
}
|
||||
|
||||
@@ -298,7 +297,7 @@ public:
|
||||
}
|
||||
|
||||
// Create the new buffer, update the size and map it.
|
||||
dynamic_buffer.buffer_ = device_->createBuffer(RT64::RenderBufferDesc::UploadBuffer(new_size, dynamic_buffer.flags_));
|
||||
dynamic_buffer.buffer_ = device_->createBuffer(plume::RenderBufferDesc::UploadBuffer(new_size, dynamic_buffer.flags_));
|
||||
dynamic_buffer.size_ = new_size;
|
||||
dynamic_buffer.bytes_used_ = 0;
|
||||
|
||||
@@ -368,27 +367,27 @@ public:
|
||||
memcpy(vertex_buffer_.mapped_data_ + vertex_buffer_offset, vertices, vert_size_bytes);
|
||||
memcpy(index_buffer_.mapped_data_ + index_buffer_offset, indices, index_size_bytes);
|
||||
|
||||
list_->setViewports(RT64::RenderViewport{ 0, 0, float(window_width_), float(window_height_) });
|
||||
list_->setViewports(plume::RenderViewport{ 0, 0, float(window_width_), float(window_height_) });
|
||||
if (scissor_enabled_) {
|
||||
list_->setScissors(RT64::RenderRect{
|
||||
list_->setScissors(plume::RenderRect{
|
||||
scissor_x_,
|
||||
scissor_y_,
|
||||
(scissor_width_ + scissor_x_),
|
||||
(scissor_height_ + scissor_y_) });
|
||||
}
|
||||
else {
|
||||
list_->setScissors(RT64::RenderRect{ 0, 0, window_width_, window_height_ });
|
||||
list_->setScissors(plume::RenderRect{ 0, 0, window_width_, window_height_ });
|
||||
}
|
||||
|
||||
RT64::RenderIndexBufferView index_view{index_buffer_.buffer_->at(index_buffer_offset), index_size_bytes, RT64::RenderFormat::R32_UINT};
|
||||
plume::RenderIndexBufferView index_view{index_buffer_.buffer_->at(index_buffer_offset), index_size_bytes, plume::RenderFormat::R32_UINT};
|
||||
list_->setIndexBuffer(&index_view);
|
||||
RT64::RenderVertexBufferView vertex_view{vertex_buffer_.buffer_->at(vertex_buffer_offset), vert_size_bytes};
|
||||
plume::RenderVertexBufferView vertex_view{vertex_buffer_.buffer_->at(vertex_buffer_offset), vert_size_bytes};
|
||||
list_->setVertexBuffers(0, &vertex_view, 1, &vertex_slot_);
|
||||
|
||||
TextureHandle &texture_handle = textures_.at(texture);
|
||||
if (!texture_handle.transitioned) {
|
||||
// Prepare the texture for being read from a pixel shader.
|
||||
list_->barriers(RT64::RenderBarrierStage::GRAPHICS, RT64::RenderTextureBarrier(texture_handle.texture.get(), RT64::RenderTextureLayout::SHADER_READ));
|
||||
list_->barriers(plume::RenderBarrierStage::GRAPHICS, plume::RenderTextureBarrier(texture_handle.texture.get(), plume::RenderTextureLayout::SHADER_READ));
|
||||
texture_handle.transitioned = true;
|
||||
}
|
||||
|
||||
@@ -428,7 +427,7 @@ public:
|
||||
}
|
||||
|
||||
RT64::Texture* texture = nullptr;
|
||||
std::unique_ptr<RT64::RenderBuffer> texture_buffer;
|
||||
std::unique_ptr<plume::RenderBuffer> texture_buffer;
|
||||
ImageFromBytes& img = it->second;
|
||||
copy_command_list_->begin();
|
||||
|
||||
@@ -463,8 +462,8 @@ public:
|
||||
texture_dimensions.x = texture->width;
|
||||
texture_dimensions.y = texture->height;
|
||||
|
||||
std::unique_ptr<RT64::RenderDescriptorSet> set = texture_set_builder_->create(device_);
|
||||
set->setTexture(gTexture_descriptor_index, texture->texture.get(), RT64::RenderTextureLayout::SHADER_READ);
|
||||
std::unique_ptr<plume::RenderDescriptorSet> set = texture_set_builder_->create(device_);
|
||||
set->setTexture(gTexture_descriptor_index, texture->texture.get(), plume::RenderTextureLayout::SHADER_READ);
|
||||
textures_.emplace(texture_handle, TextureHandle{ std::move(texture->texture), std::move(set), false });
|
||||
delete texture;
|
||||
|
||||
@@ -482,8 +481,8 @@ public:
|
||||
}
|
||||
|
||||
bool create_texture(Rml::TextureHandle texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions, bool flip_y = false, bool bgra = false) {
|
||||
std::unique_ptr<RT64::RenderTexture> texture =
|
||||
device_->createTexture(RT64::RenderTextureDesc::Texture2D(source_dimensions.x, source_dimensions.y, 1, bgra ? RmlTextureFormatBgra : RmlTextureFormat));
|
||||
std::unique_ptr<plume::RenderTexture> texture =
|
||||
device_->createTexture(plume::RenderTextureDesc::Texture2D(source_dimensions.x, source_dimensions.y, 1, bgra ? RmlTextureFormatBgra : RmlTextureFormat));
|
||||
|
||||
if (texture != nullptr) {
|
||||
uint32_t image_size_bytes = source_dimensions.x * source_dimensions.y * RmlTextureFormatBytesPerPixel;
|
||||
@@ -500,7 +499,7 @@ public:
|
||||
// Allocate room in the upload buffer for the uploaded data.
|
||||
if (uploaded_size_bytes > copy_buffer_size_) {
|
||||
copy_buffer_size_ = (uploaded_size_bytes * 3) / 2;
|
||||
copy_buffer_ = device_->createBuffer(RT64::RenderBufferDesc::UploadBuffer(copy_buffer_size_));
|
||||
copy_buffer_ = device_->createBuffer(plume::RenderBufferDesc::UploadBuffer(copy_buffer_size_));
|
||||
}
|
||||
|
||||
// Copy the source data into the upload buffer.
|
||||
@@ -535,12 +534,12 @@ public:
|
||||
copy_command_list_->begin();
|
||||
|
||||
// Prepare the texture to be a destination for copying.
|
||||
copy_command_list_->barriers(RT64::RenderBarrierStage::COPY, RT64::RenderTextureBarrier(texture.get(), RT64::RenderTextureLayout::COPY_DEST));
|
||||
copy_command_list_->barriers(plume::RenderBarrierStage::COPY, plume::RenderTextureBarrier(texture.get(), plume::RenderTextureLayout::COPY_DEST));
|
||||
|
||||
// Copy the upload buffer into the texture.
|
||||
copy_command_list_->copyTextureRegion(
|
||||
RT64::RenderTextureCopyLocation::Subresource(texture.get()),
|
||||
RT64::RenderTextureCopyLocation::PlacedFootprint(copy_buffer_.get(), RmlTextureFormat, source_dimensions.x, source_dimensions.y, 1, row_width));
|
||||
plume::RenderTextureCopyLocation::Subresource(texture.get()),
|
||||
plume::RenderTextureCopyLocation::PlacedFootprint(copy_buffer_.get(), RmlTextureFormat, source_dimensions.x, source_dimensions.y, 1, row_width));
|
||||
|
||||
// End the command list, execute it and wait.
|
||||
copy_command_list_->end();
|
||||
@@ -548,9 +547,9 @@ public:
|
||||
copy_command_queue_->waitForCommandFence(copy_command_fence_.get());
|
||||
|
||||
// Create a descriptor set with this texture in it.
|
||||
std::unique_ptr<RT64::RenderDescriptorSet> set = texture_set_builder_->create(device_);
|
||||
std::unique_ptr<plume::RenderDescriptorSet> set = texture_set_builder_->create(device_);
|
||||
|
||||
set->setTexture(gTexture_descriptor_index, texture.get(), RT64::RenderTextureLayout::SHADER_READ);
|
||||
set->setTexture(gTexture_descriptor_index, texture.get(), plume::RenderTextureLayout::SHADER_READ);
|
||||
|
||||
textures_.emplace(texture_handle, TextureHandle{ std::move(texture), std::move(set), false });
|
||||
|
||||
@@ -576,17 +575,17 @@ public:
|
||||
mvp_ = projection_mtx_ * transform_;
|
||||
}
|
||||
|
||||
void start(RT64::RenderCommandList* list, int image_width, int image_height) {
|
||||
void start(plume::RenderCommandList* list, int image_width, int image_height) {
|
||||
list_ = list;
|
||||
|
||||
if (multisampling_.sampleCount > 1) {
|
||||
if (window_width_ != image_width || window_height_ != image_height) {
|
||||
screen_framebuffer_.reset();
|
||||
screen_texture_ = device_->createTexture(RT64::RenderTextureDesc::ColorTarget(image_width, image_height, SwapChainFormat));
|
||||
screen_texture_ms_ = device_->createTexture(RT64::RenderTextureDesc::ColorTarget(image_width, image_height, SwapChainFormat, multisampling_));
|
||||
const RT64::RenderTexture *color_attachment = screen_texture_ms_.get();
|
||||
screen_framebuffer_ = device_->createFramebuffer(RT64::RenderFramebufferDesc(&color_attachment, 1));
|
||||
screen_descriptor_set_->setTexture(0, screen_texture_.get(), RT64::RenderTextureLayout::SHADER_READ);
|
||||
screen_texture_ = device_->createTexture(plume::RenderTextureDesc::ColorTarget(image_width, image_height, SwapChainFormat));
|
||||
screen_texture_ms_ = device_->createTexture(plume::RenderTextureDesc::ColorTarget(image_width, image_height, SwapChainFormat, multisampling_));
|
||||
const plume::RenderTexture *color_attachment = screen_texture_ms_.get();
|
||||
screen_framebuffer_ = device_->createFramebuffer(plume::RenderFramebufferDesc(&color_attachment, 1));
|
||||
screen_descriptor_set_->setTexture(0, screen_texture_.get(), plume::RenderTextureLayout::SHADER_READ);
|
||||
}
|
||||
|
||||
list_->setPipeline(pipeline_ms_.get());
|
||||
@@ -616,30 +615,30 @@ public:
|
||||
|
||||
// Set an internal texture as the render target if MSAA is enabled.
|
||||
if (multisampling_.sampleCount > 1) {
|
||||
list->barriers(RT64::RenderBarrierStage::GRAPHICS, RT64::RenderTextureBarrier(screen_texture_ms_.get(), RT64::RenderTextureLayout::COLOR_WRITE));
|
||||
list->barriers(plume::RenderBarrierStage::GRAPHICS, plume::RenderTextureBarrier(screen_texture_ms_.get(), plume::RenderTextureLayout::COLOR_WRITE));
|
||||
list->setFramebuffer(screen_framebuffer_.get());
|
||||
list->clearColor(0, RT64::RenderColor(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
list->clearColor(0, plume::RenderColor(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
}
|
||||
}
|
||||
|
||||
void end(RT64::RenderCommandList* list, RT64::RenderFramebuffer* framebuffer) {
|
||||
void end(plume::RenderCommandList* list, plume::RenderFramebuffer* framebuffer) {
|
||||
// Draw the texture were rendered the UI in to the swap chain framebuffer if MSAA is enabled.
|
||||
if (multisampling_.sampleCount > 1) {
|
||||
RT64::RenderTextureBarrier before_resolve_barriers[] = {
|
||||
RT64::RenderTextureBarrier(screen_texture_ms_.get(), RT64::RenderTextureLayout::RESOLVE_SOURCE),
|
||||
RT64::RenderTextureBarrier(screen_texture_.get(), RT64::RenderTextureLayout::RESOLVE_DEST)
|
||||
plume::RenderTextureBarrier before_resolve_barriers[] = {
|
||||
plume::RenderTextureBarrier(screen_texture_ms_.get(), plume::RenderTextureLayout::RESOLVE_SOURCE),
|
||||
plume::RenderTextureBarrier(screen_texture_.get(), plume::RenderTextureLayout::RESOLVE_DEST)
|
||||
};
|
||||
|
||||
list->barriers(RT64::RenderBarrierStage::COPY, before_resolve_barriers, uint32_t(std::size(before_resolve_barriers)));
|
||||
list->barriers(plume::RenderBarrierStage::COPY, before_resolve_barriers, uint32_t(std::size(before_resolve_barriers)));
|
||||
list->resolveTexture(screen_texture_.get(), screen_texture_ms_.get());
|
||||
list->barriers(RT64::RenderBarrierStage::GRAPHICS, RT64::RenderTextureBarrier(screen_texture_.get(), RT64::RenderTextureLayout::SHADER_READ));
|
||||
list->barriers(plume::RenderBarrierStage::GRAPHICS, plume::RenderTextureBarrier(screen_texture_.get(), plume::RenderTextureLayout::SHADER_READ));
|
||||
list->setFramebuffer(framebuffer);
|
||||
list->setPipeline(pipeline_.get());
|
||||
list->setGraphicsPipelineLayout(layout_.get());
|
||||
list->setGraphicsDescriptorSet(sampler_set_.get(), 0);
|
||||
list->setGraphicsDescriptorSet(screen_descriptor_set_.get(), 1);
|
||||
list->setScissors(RT64::RenderRect{ 0, 0, window_width_, window_height_ });
|
||||
RT64::RenderVertexBufferView vertex_view(screen_vertex_buffer_.get(), screen_vertex_buffer_size_);
|
||||
list->setScissors(plume::RenderRect{ 0, 0, window_width_, window_height_ });
|
||||
plume::RenderVertexBufferView vertex_view(screen_vertex_buffer_.get(), screen_vertex_buffer_size_);
|
||||
list->setVertexBuffers(0, &vertex_view, 1, &vertex_slot_);
|
||||
|
||||
RmlPushConstants constants{
|
||||
@@ -685,7 +684,7 @@ void recompui::RmlRenderInterface_RT64::reset() {
|
||||
impl.reset();
|
||||
}
|
||||
|
||||
void recompui::RmlRenderInterface_RT64::init(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
|
||||
void recompui::RmlRenderInterface_RT64::init(plume::RenderInterface* interface, plume::RenderDevice* device) {
|
||||
impl = std::make_unique<RmlRenderInterface_RT64_impl>(interface, device);
|
||||
}
|
||||
|
||||
@@ -696,13 +695,13 @@ Rml::RenderInterface* recompui::RmlRenderInterface_RT64::get_rml_interface() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void recompui::RmlRenderInterface_RT64::start(RT64::RenderCommandList* list, int image_width, int image_height) {
|
||||
void recompui::RmlRenderInterface_RT64::start(plume::RenderCommandList* list, int image_width, int image_height) {
|
||||
assert(static_cast<bool>(impl));
|
||||
|
||||
impl->start(list, image_width, image_height);
|
||||
}
|
||||
|
||||
void recompui::RmlRenderInterface_RT64::end(RT64::RenderCommandList* list, RT64::RenderFramebuffer* framebuffer) {
|
||||
void recompui::RmlRenderInterface_RT64::end(plume::RenderCommandList* list, plume::RenderFramebuffer* framebuffer) {
|
||||
assert(static_cast<bool>(impl));
|
||||
|
||||
impl->end(list, framebuffer);
|
||||
|
||||
@@ -25,11 +25,11 @@ namespace recompui {
|
||||
RmlRenderInterface_RT64();
|
||||
~RmlRenderInterface_RT64();
|
||||
void reset();
|
||||
void init(RT64::RenderInterface* interface, RT64::RenderDevice* device);
|
||||
void init(plume::RenderInterface* interface, plume::RenderDevice* device);
|
||||
Rml::RenderInterface* get_rml_interface();
|
||||
|
||||
void start(RT64::RenderCommandList* list, int image_width, int image_height);
|
||||
void end(RT64::RenderCommandList* list, RT64::RenderFramebuffer* framebuffer);
|
||||
void start(plume::RenderCommandList* list, int image_width, int image_height);
|
||||
void end(plume::RenderCommandList* list, plume::RenderFramebuffer* framebuffer);
|
||||
void queue_image_from_bytes_file(const std::string &src, const std::vector<char> &bytes);
|
||||
void queue_image_from_bytes_rgba32(const std::string &src, const std::vector<char> &bytes, uint32_t width, uint32_t height);
|
||||
};
|
||||
|
||||
+3
-3
@@ -180,7 +180,7 @@ public:
|
||||
UIState(UIState&& rhs) = delete;
|
||||
UIState& operator=(UIState&& rhs) = delete;
|
||||
|
||||
UIState(SDL_Window* window, RT64::RenderInterface* interface, RT64::RenderDevice* device) {
|
||||
UIState(SDL_Window* window, plume::RenderInterface* interface, plume::RenderDevice* device) {
|
||||
launcher_menu_controller = recompui::create_launcher_menu();
|
||||
config_menu_controller = recompui::create_config_menu();
|
||||
|
||||
@@ -445,7 +445,7 @@ inline const std::string read_file_to_string(std::filesystem::path path) {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void init_hook(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
|
||||
void init_hook(plume::RenderInterface* interface, plume::RenderDevice* device) {
|
||||
#if defined(__linux__)
|
||||
std::locale::global(std::locale::classic());
|
||||
#endif
|
||||
@@ -547,7 +547,7 @@ void recompui::activate_mouse() {
|
||||
ui_state->update_focus(true, false);
|
||||
}
|
||||
|
||||
void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* swap_chain_framebuffer) {
|
||||
void draw_hook(plume::RenderCommandList* command_list, plume::RenderFramebuffer* swap_chain_framebuffer) {
|
||||
|
||||
apply_background_input_mode();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user