27 Commits

Author SHA1 Message Date
Mr-Wiseguy 116b58c444 WIP conversion of CPU texture mixing to color combiner for textured fonts 2025-12-12 00:13:39 -05:00
Mr-Wiseguy 8fa0dd559f Fix vanilla memory corruption bug with invalid vector defrag call 2025-12-10 20:43:51 -05:00
Mr-Wiseguy d331f4e5cb Add transform tagging for map models and fix build after updating RT64 2025-12-09 19:48:25 -05:00
Wiseguy 9b93be22eb Merge pull request #5 from BanjoRecomp/plume
Switch to plume.
2025-12-09 19:24:06 -05:00
Dario 2783e3416f Update RT64 to fix matrix group macros. 2025-12-09 20:53:59 -03:00
Dario 9f39b6bf69 Fix aspect ratio on jiggy transition patch. 2025-12-09 20:44:56 -03:00
Dario 937fce9dec Switch to plume. 2025-12-09 20:20:52 -03:00
Mr-Wiseguy 377ba80628 Transform tagging for projectile particles 2025-12-09 02:53:06 -05:00
Mr-Wiseguy 5a596e22db Add zoombox tagging and fix leaked model transform ID in __marker_draw 2025-12-09 02:16:37 -05:00
Mr-Wiseguy 1b67b628c1 Update modern runtime for clang 20 fix 2025-12-03 02:53:46 -05:00
Mr-Wiseguy cf486ad7d7 Remove slotmap submodule and integrate header directly after submodule URL changed, fix X11 defines 2025-12-03 02:21:20 -05:00
Mr-Wiseguy b71479aeae Enhance jiggy puzzle framebuffer effect to use direct framebuffer sampling to work with high res and widescreen 2025-11-30 01:15:44 -05:00
Mr-Wiseguy 7f4e38d732 Tagging for skybox and most projections, skip interpolation on the frame after all markers are reset to avoid glitches on scene load 2025-11-30 01:14:46 -05:00
Mr-Wiseguy e13245c57c Enable rotation interpolation for sprite props 2025-11-29 23:05:02 -05:00
Mr-Wiseguy a97c09db86 Remove remaining frustum culling 2025-11-29 23:03:39 -05:00
Mr-Wiseguy cfb0e32e76 Particle transform tagging 2025-11-29 23:01:29 -05:00
Mr-Wiseguy d424ef949e Update runtime to support BPS patch files in mods 2025-11-29 22:56:01 -05:00
Mr-Wiseguy facb4d3047 Fix build system issue that requires building twice after a patch change 2025-11-21 23:50:06 -05:00
Mr-Wiseguy cdd25e5bf7 Implement prop extension API, SpriteProp and ModelProp transform tagging 2025-09-09 22:14:30 -04:00
Mr-Wiseguy d7d9a39c74 Disable map model transform tagging temporarily, begin work on prop transform tagging 2025-09-08 01:56:32 -04:00
Mr-Wiseguy 462471063d Update symbols for missing function sizes 2025-09-08 00:34:59 -04:00
Mr-Wiseguy dd61fa8953 Add --show-console option 2025-09-08 00:01:45 -04:00
Mr-Wiseguy 79321e7f86 Genericize object extension to allow for multiple extension contexts (e.g. Props and ActorMarkers) 2025-09-07 22:42:09 -04:00
Mr-Wiseguy fbe26b7a63 Reorganize transform tagging and add tagging to level models 2025-09-07 19:12:04 -04:00
Mr-Wiseguy c8fac11c42 Update decomp and symbols 2025-09-07 00:17:30 -04:00
Mr-Wiseguy 212374cdba Update to latest runtime and RT64, switch actor API to use ActorMarkers instead 2025-09-06 23:47:25 -04:00
Mr-Wiseguy 07998cb006 Moved core1 overlay load into boot___osInitialize_common and reset inverse view matrix for ortho view matrices 2025-09-06 23:47:24 -04:00
53 changed files with 5325 additions and 1117 deletions
-3
View File
@@ -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
+3 -3
View File
@@ -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
View File
@@ -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",
+1 -1
View File
@@ -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 -2
View File
@@ -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
View File
@@ -7,7 +7,8 @@
"project": "CMakeLists.txt",
"projectTarget": "BanjoRecompiled.exe",
"name": "BanjoRecompiled.exe",
"currentDir": "${workspaceRoot}"
"currentDir": "${workspaceRoot}",
"args": ["--show-console"]
}
]
}
+257
View File
@@ -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
[![Actions Status](https://github.com/SergeyMakeev/slot_map/workflows/build/badge.svg)](https://github.com/SergeyMakeev/slot_map/actions)
[![Build status](https://ci.appveyor.com/api/projects/status/i00kv17e3ia5jr7q?svg=true)](https://ci.appveyor.com/project/SergeyMakeev/slot-map)
[![codecov](https://codecov.io/gh/SergeyMakeev/slot_map/branch/main/graph/badge.svg?token=3GRAFTRYQU)](https://codecov.io/gh/SergeyMakeev/slot_map)
![MIT](https://img.shields.io/badge/license-MIT-blue.svg)
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
Submodule lib/slot_map deleted from b8ac8ebd89
+1 -1
View File
@@ -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
View File
@@ -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
-14
View File
@@ -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
-379
View File
@@ -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
View File
@@ -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
+151
View File
@@ -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;
}
+32
View File
@@ -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;
}
+3
View File
@@ -121,4 +121,7 @@ RECOMP_PATCH void game_draw(s32 arg0){
scissorBox_setDefault();
}
}
// Allow interpolation for the next frame.
set_all_interpolation_skipped(FALSE);
}
+3
View File
@@ -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();
}
}
+203
View File
@@ -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);
}
}
+123
View File
@@ -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);
}
+76
View File
@@ -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);
}
-14
View File
@@ -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
+14
View File
@@ -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
+5 -34
View File
@@ -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);
+295
View File
@@ -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
View File
@@ -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
+9
View File
@@ -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);
}
+350
View File
@@ -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);
}
+406
View File
@@ -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;
}
+121
View File
@@ -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
}
+48
View File
@@ -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
}
+64
View File
@@ -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
View File
@@ -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;
+525
View File
@@ -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;
}
}
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+452
View File
@@ -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
View File
@@ -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];
+3
View File
@@ -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"
-237
View File
@@ -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
View File
@@ -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__);
}
+260
View File
@@ -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
View File
@@ -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;
}
+6 -2
View File
@@ -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);
+24 -39
View File
@@ -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
View File
@@ -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);
+3 -3
View File
@@ -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
View File
@@ -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();