This commit is contained in:
Fazana
2021-08-22 13:39:47 +01:00
parent 2469b9e67d
commit ccfa157455
12 changed files with 301 additions and 47 deletions

View File

@@ -402,6 +402,8 @@ export LD_LIBRARY_PATH=./tools
AS := $(CROSS)as
ifeq ($(COMPILER),gcc)
CC := $(CROSS)gcc
$(BUILD_DIR)/actors/%.o: OPT_FLAGS := -O2 -mlong-calls
$(BUILD_DIR)/levels/%.o: OPT_FLAGS := -O2 -mlong-calls
else ifeq ($(COMPILER),clang)
CC := clang
endif

61
include/farcall.h Normal file
View File

@@ -0,0 +1,61 @@
#ifndef __FARCALL_H__
#define __FARCALL_H__
#ifdef __GNUC__
#define farcall(x) x
#define far __attribute__(( long_call ))
#pragma GCC diagnostic ignored "-Wattributes" // Workaround for a bug that produces errant warnings in gcc
#define near __attribute(( near ))
#else
#define farcall(x) (*(&(x)))
#define far
#define near
#endif
#endif
/*
How to use:
Simply place any code you want in any groupX_geo.c or any level's script.c (see the first note for a potential gotcha when using code in level script segments).
To call segment code from normal code or vice versa (or segment code from other segmented code)
- Add `#include "farcall.h"` to the given file
- Declare any functions that are not in that file like so (with far)
`far void print_text(s32, s32, const char*);`
- Call any functions that are not in the file like so:
`farcall(print_text)(10, 10 "test");`
If you forget any of the above 3 steps, you will get an error during linking your ROM that looks something like:
`script.c:(.text+0x24): relocation truncated to fit: R_MIPS_26 against ...`
So if you see that error, make sure you've followed the above three steps.
If you're using gcc, you don't need to use farcall to call far functions, as declaring a function as far is enough.
Additionally if using gcc, you don't need to declare any functions as far in segmented code due to a change in the makefile.
Instead, you can declare local functions as `near` to optimize local calls, but this is not required.
If you have code in a groupX_geo.c file, you must load it in level scripts by doing LOAD_RAW_WITH_CODE instead of the normal LOAD_RAW.
This has two extra arguments, which should be passed as `_groupX_geoSegmentNoloadStart` and `_groupX_geoSegmentNoloadEnd`.
For example, if you added code to group3's geo segment:
LOAD_RAW_WITH_CODE(0x0C, _group3_geoSegmentRomStart, _group3_geoSegmentRomEnd, _group3_geoSegmentNoloadStart, _group3_geoSegmentNoloadEnd),
For convenience, included is a new header: src/game/obj_behaviors_2_nonstatic.h. In addition to effectively removing
the static keyword from object_behaviors_2.c, this header defines prototypes for all functions in that file. This
allows you to reference those functions elsewhere, which is convenient for segmented behavior callbacks.
Notes:
- As of right now, Fast64 will not retain LOAD_RAW_WITH_CODE commands in the level script.
This means that you will have to readd those on each export, but this may change in a future Fast64 version.
The same is true for any code in the level file, so I suggest making a code.inc.c file in the level's folder
and adding an `#include "levels/x/code.inc.c"` into the level script file.
That include will also be wiped on each export, but is easy enough to add after an export.
- Variables in segments will get reset to their defaults every time a segment is loaded.
Use variables declared in normal code and extern them if this isn't desirable.
- Because of the limited number of TLB entries, at most 256kB of segmented memory can be mapped with this patch.
If you want to be sure that everything is being mapped, use the TLB entries view in PJ64 2.4's debugger.
- TLB mapping requires at least 4kB alignment, so memory allocations for segments with code are automatically padded to meet this alignment.
This means that potentially up to 4kB of RAM can be wasted when a given segment with code is loaded.
This should be far less than the potential savings from using this patch, but is something that should be kept in mind.
*/

View File

@@ -49,16 +49,36 @@
CMD_PTR(entry)
#else
#define EXECUTE(seg, script, scriptEnd, entry) \
CMD_BBH(0x00, 0x10, seg), \
CMD_BBH(0x00, 0x18, seg), \
CMD_PTR(script), \
CMD_PTR(scriptEnd), \
CMD_PTR(entry)
CMD_PTR(entry), \
CMD_PTR(NULL), \
CMD_PTR(NULL)
#define EXIT_AND_EXECUTE(seg, script, scriptEnd, entry) \
CMD_BBH(0x01, 0x10, seg), \
CMD_BBH(0x01, 0x18, seg), \
CMD_PTR(script), \
CMD_PTR(scriptEnd), \
CMD_PTR(entry)
CMD_PTR(entry), \
CMD_PTR(NULL), \
CMD_PTR(NULL)
#define EXECUTE_WITH_CODE(seg, script, scriptEnd, entry, bssStart, bssEnd) \
CMD_BBH(0x00, 0x18, seg), \
CMD_PTR(script), \
CMD_PTR(scriptEnd), \
CMD_PTR(entry), \
CMD_PTR(bssStart), \
CMD_PTR(bssEnd)
#define EXIT_AND_EXECUTE_WITH_CODE(seg, script, scriptEnd, entry, bssStart, bssEnd) \
CMD_BBH(0x01, 0x18, seg), \
CMD_PTR(script), \
CMD_PTR(scriptEnd), \
CMD_PTR(entry), \
CMD_PTR(bssStart), \
CMD_PTR(bssEnd)
#endif
#define EXIT() \
@@ -160,9 +180,18 @@
CMD_PTR(romEnd)
#define LOAD_RAW(seg, romStart, romEnd) \
CMD_BBH(0x17, 0x0C, seg), \
CMD_BBH(0x17, 0x14, seg), \
CMD_PTR(romStart), \
CMD_PTR(romEnd)
CMD_PTR(romEnd), \
CMD_PTR(0), \
CMD_PTR(0)
#define LOAD_RAW_WITH_CODE(seg, romStart, romEnd, bssStart, bssEnd) \
CMD_BBH(0x17, 0x14, seg), \
CMD_PTR(romStart), \
CMD_PTR(romEnd), \
CMD_PTR(bssStart), \
CMD_PTR(bssEnd)
#define LOAD_YAY0(seg, romStart, romEnd) \
CMD_BBH(0x18, 0x0C, seg), \

View File

@@ -6,13 +6,19 @@
extern u8 _##name##SegmentRomStart[]; \
extern u8 _##name##SegmentRomEnd[];
#define DECLARE_NOLOAD(name) \
extern u8 _##name##SegmentBssStart[]; \
extern u8 _##name##SegmentBssEnd[];
#define DECLARE_ACTOR_SEGMENT(name) \
DECLARE_SEGMENT(name##_mio0) \
DECLARE_SEGMENT(name##_yay0) \
DECLARE_SEGMENT(name##_geo)
DECLARE_SEGMENT(name##_geo) \
DECLARE_NOLOAD(name##_geo)
#define DECLARE_LEVEL_SEGMENT(name) \
DECLARE_SEGMENT(name) \
DECLARE_NOLOAD(name) \
DECLARE_SEGMENT(name##_segment_7)
DECLARE_ACTOR_SEGMENT(common0)

View File

@@ -17,13 +17,15 @@
#include "make_const_nonconst.h"
#include "levels/intro/header.h"
#include "farcall.h"
#include "config.h"
#include "game/print.h"
const LevelScript level_intro_splash_screen[] = {
INIT_LEVEL(),
#ifdef SKIP_TITLE_SCREEN
EXIT_AND_EXECUTE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_mario_head_regular),
EXIT_AND_EXECUTE_WITH_CODE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_mario_head_regular, _introSegmentBssStart, _introSegmentBssEnd),
#endif
FIXED_LOAD(/*loadAddr*/ _goddardSegmentStart, /*romStart*/ _goddardSegmentRomStart, /*romEnd*/ _goddardSegmentRomEnd),
LOAD_RAW(/*seg*/ 0x13, _behaviorSegmentRomStart, _behaviorSegmentRomEnd),
@@ -45,7 +47,7 @@ const LevelScript level_intro_splash_screen[] = {
CMD2A(/*unk2*/ 1),
CLEAR_LEVEL(),
SLEEP(/*frames*/ 2),
EXIT_AND_EXECUTE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_mario_head_regular),
EXIT_AND_EXECUTE_WITH_CODE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_mario_head_regular, _introSegmentBssStart, _introSegmentBssEnd),
};
const LevelScript level_intro_mario_head_regular[] = {
@@ -143,7 +145,7 @@ const LevelScript script_intro_L2[] = {
SLEEP(/*frames*/ 16),
CLEAR_LEVEL(),
SLEEP(/*frames*/ 2),
EXIT_AND_EXECUTE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_entry_4),
EXIT_AND_EXECUTE_WITH_CODE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_entry_4, _introSegmentBssStart, _introSegmentBssEnd),
};
const LevelScript script_intro_L3[] = {
@@ -169,5 +171,5 @@ const LevelScript script_intro_L5[] = {
SLEEP(/*frames*/ 16),
CLEAR_LEVEL(),
SLEEP(/*frames*/ 2),
EXIT_AND_EXECUTE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_splash_screen),
EXIT_AND_EXECUTE_WITH_CODE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_splash_screen, _introSegmentBssStart, _introSegmentBssEnd),
};

View File

@@ -44,14 +44,14 @@ static const LevelScript script_exec_level_table[2
#undef DEFINE_LEVEL
#undef STUB_LEVEL
static const LevelScript script_L1[4];
static const LevelScript script_L2[4];
static const LevelScript goto_mario_head_regular[4];
static const LevelScript goto_mario_head_dizzy[4];
static const LevelScript script_L5[4];
static const LevelScript script_L1[6];
static const LevelScript script_L2[6];
static const LevelScript goto_mario_head_regular[6];
static const LevelScript goto_mario_head_dizzy[6];
static const LevelScript script_L5[6];
#define STUB_LEVEL(_0, _1, _2, _3, _4, _5, _6, _7, _8)
#define DEFINE_LEVEL(_0, _1, _2, folder, _4, _5, _6, _7, _8, _9, _10) static const LevelScript script_exec_ ## folder [4 + 1];
#define DEFINE_LEVEL(_0, _1, _2, folder, _4, _5, _6, _7, _8, _9, _10) static const LevelScript script_exec_ ## folder [6 + 1];
#include "level_defines.h"
@@ -61,8 +61,8 @@ static const LevelScript script_L5[4];
const LevelScript level_main_scripts_entry[] = {
LOAD_YAY0(/*seg*/ 0x04, _group0_yay0SegmentRomStart, _group0_yay0SegmentRomEnd),
LOAD_YAY0(/*seg*/ 0x03, _common1_yay0SegmentRomStart, _common1_yay0SegmentRomEnd),
LOAD_RAW( /*seg*/ 0x17, _group0_geoSegmentRomStart, _group0_geoSegmentRomEnd),
LOAD_RAW( /*seg*/ 0x16, _common1_geoSegmentRomStart, _common1_geoSegmentRomEnd),
LOAD_RAW_WITH_CODE( /*seg*/ 0x17, _group0_geoSegmentRomStart, _group0_geoSegmentRomEnd, _group0_geoSegmentBssStart, _group0_geoSegmentBssEnd),
LOAD_RAW_WITH_CODE( /*seg*/ 0x16, _common1_geoSegmentRomStart, _common1_geoSegmentRomEnd, _common1_geoSegmentBssStart, _common1_geoSegmentBssEnd),
LOAD_RAW( /*seg*/ 0x13, _behaviorSegmentRomStart, _behaviorSegmentRomEnd),
ALLOC_LEVEL_POOL(),
LOAD_MODEL_FROM_GEO(MODEL_MARIO, mario_geo),
@@ -127,23 +127,23 @@ const LevelScript level_main_scripts_entry[] = {
};
static const LevelScript script_L1[] = {
EXIT_AND_EXECUTE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_splash_screen),
EXIT_AND_EXECUTE_WITH_CODE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_splash_screen, _introSegmentBssStart, _introSegmentBssEnd),
};
static const LevelScript script_L2[] = {
EXIT_AND_EXECUTE(/*seg*/ 0x0E, _endingSegmentRomStart, _endingSegmentRomEnd, level_ending_entry),
EXIT_AND_EXECUTE_WITH_CODE(/*seg*/ 0x0E, _endingSegmentRomStart, _endingSegmentRomEnd, level_ending_entry, _endingSegmentBssStart, _endingSegmentBssEnd),
};
static const LevelScript goto_mario_head_regular[] = {
EXIT_AND_EXECUTE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_mario_head_regular),
EXIT_AND_EXECUTE_WITH_CODE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_mario_head_regular, _introSegmentBssStart, _introSegmentBssEnd),
};
static const LevelScript goto_mario_head_dizzy[] = {
EXIT_AND_EXECUTE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_mario_head_dizzy),
EXIT_AND_EXECUTE_WITH_CODE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_mario_head_dizzy, _introSegmentBssStart, _introSegmentBssEnd),
};
static const LevelScript script_L5[] = {
EXIT_AND_EXECUTE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_entry_4),
EXIT_AND_EXECUTE_WITH_CODE(/*seg*/ 0x14, _introSegmentRomStart, _introSegmentRomEnd, level_intro_entry_4, _introSegmentBssStart, _introSegmentBssEnd),
};
// Include the level jumptable.
@@ -161,7 +161,7 @@ static const LevelScript script_exec_level_table[] = {
#define DEFINE_LEVEL(_0, _1, _2, folder, _4, _5, _6, _7, _8, _9, _10) \
static const LevelScript script_exec_ ## folder [] = { \
EXECUTE(0x0E, _ ## folder ## SegmentRomStart, _ ## folder ## SegmentRomEnd, level_ ## folder ## _entry), \
EXECUTE_WITH_CODE(0x0E, _ ## folder ## SegmentRomStart, _ ## folder ## SegmentRomEnd, level_ ## folder ## _entry, _ ## folder ## SegmentBssStart, _ ## folder ## SegmentBssEnd), \
RETURN(), \
};

34
sm64.ld
View File

@@ -52,10 +52,20 @@ OUTPUT_ARCH (mips)
END_SEG(name##_segment_7) \
BEGIN_SEG(name, 0x0E000000) \
{ \
KEEP(BUILD_DIR/levels/name/script.o(.data)); \
KEEP(BUILD_DIR/levels/name/geo.o(.data)); \
KEEP(BUILD_DIR/levels/name/script.o(.*data*)); \
KEEP(BUILD_DIR/levels/name/script.o(.text)); \
KEEP(BUILD_DIR/levels/name/script.o(.rodata*)); \
KEEP(BUILD_DIR/levels/name/geo.o(.*data*)); \
KEEP(BUILD_DIR/levels/name/geo.o(.text)); \
KEEP(BUILD_DIR/levels/name/geo.o(.rodata*)); \
} \
END_SEG(name)
END_SEG(name) \
BEGIN_NOLOAD(name) \
{ \
KEEP(BUILD_DIR/levels/name/script.o(.bss*)); \
KEEP(BUILD_DIR/levels/name/geo.o(.bss*)); \
} \
END_NOLOAD(name)
#define STANDARD_OBJECTS(name, segAddr, geoAddr) \
BEGIN_SEG(name##_yay0, segAddr) \
@@ -66,9 +76,16 @@ OUTPUT_ARCH (mips)
END_SEG(name##_yay0) \
BEGIN_SEG(name##_geo, geoAddr) \
{ \
KEEP(BUILD_DIR/actors/name##_geo.o(.data)); \
KEEP(BUILD_DIR/actors/name##_geo.o(.*data*)); \
KEEP(BUILD_DIR/actors/name##_geo.o(.rodata*)); \
KEEP(BUILD_DIR/actors/name##_geo.o(.text)); \
} \
END_SEG(name##_geo) \
BEGIN_NOLOAD(name##_geo) \
{ \
KEEP(BUILD_DIR/actors/name##_geo.o(.bss*)); \
} \
END_NOLOAD(name##_geo) \
_##name##_mio0SegmentRomStart = _##name##_yay0SegmentRomStart; \
_##name##_mio0SegmentRomEnd = _##name##_yay0SegmentRomEnd;
@@ -356,10 +373,17 @@ SECTIONS
/* 0x268020 0x268020-0 [0] */
BEGIN_SEG(intro, 0x14000000)
{
KEEP(BUILD_DIR/levels/intro/script.o(.data));
KEEP(BUILD_DIR/levels/intro/script.o(.*data));
KEEP(BUILD_DIR/levels/intro/script.o(.rodata*));
KEEP(BUILD_DIR/levels/intro/script.o(.text));
KEEP(BUILD_DIR/levels/intro/geo.o(.data));
}
END_SEG(intro)
BEGIN_NOLOAD(intro)
{
KEEP(BUILD_DIR/levels/intro/script.o(.bss*));
}
END_NOLOAD(intro)
BEGIN_SEG(intro_segment_7, 0x07000000)
{
KEEP(BUILD_DIR/levels/intro/leveldata.szp.o(.data));

View File

@@ -93,7 +93,7 @@ static s32 eval_script_op(s8 op, s32 arg) {
static void level_cmd_load_and_execute(void) {
main_pool_push_state();
load_segment(CMD_GET(s16, 2), CMD_GET(void *, 4), CMD_GET(void *, 8), MEMORY_POOL_LEFT);
load_segment(CMD_GET(s16, 2), CMD_GET(void *, 4), CMD_GET(void *, 8), MEMORY_POOL_LEFT, CMD_GET(void *, 16), CMD_GET(void *, 20));
*sStackTop++ = (uintptr_t) NEXT_CMD;
*sStackTop++ = (uintptr_t) sStackBase;
@@ -109,7 +109,7 @@ static void level_cmd_exit_and_execute(void) {
main_pool_push_state();
load_segment(CMD_GET(s16, 2), CMD_GET(void *, 4), CMD_GET(void *, 8),
MEMORY_POOL_LEFT);
MEMORY_POOL_LEFT, CMD_GET(void *, 16), CMD_GET(void *, 20));
sStackTop = sStackBase;
sCurrentCmd = segmented_to_virtual(targetAddr);
@@ -274,7 +274,7 @@ static void level_cmd_load_to_fixed_address(void) {
static void level_cmd_load_raw(void) {
load_segment(CMD_GET(s16, 2), CMD_GET(void *, 4), CMD_GET(void *, 8),
MEMORY_POOL_LEFT);
MEMORY_POOL_LEFT, CMD_GET(void *, 12), CMD_GET(void *, 16));
sCurrentCmd = CMD_NEXT;
}
@@ -313,11 +313,15 @@ static void level_cmd_init_level(void) {
sCurrentCmd = CMD_NEXT;
}
extern s32 gTlbEntries;
static void level_cmd_clear_level(void) {
clear_objects();
clear_area_graph_nodes();
clear_areas();
main_pool_pop_state();
gTlbEntries = 0;
osUnmapTLBAll();
sCurrentCmd = CMD_NEXT;
}

View File

@@ -0,0 +1,80 @@
#ifndef OBJ_BEHAVIORS_2_NONSTATIC_H
#define OBJ_BEHAVIORS_2_NONSTATIC_H
#include "object_fields.h"
#include "object_constants.h"
#include "object_helpers.h"
#include "object_collision.h"
#include "obj_behaviors.h"
#include "object_list_processor.h"
#include "interaction.h"
#include "behavior_data.h"
#include "engine/behavior_script.h"
#include "engine/math_util.h"
#include "engine/surface_load.h"
#include "engine/surface_collision.h"
#include "sound_init.h"
#include "spawn_sound.h"
#include "farcall.h"
#include "audio/external.h"
#include "level_update.h"
#include "mario.h"
#include "save_file.h"
#define o gCurrentObject
s32 obj_is_rendering_enabled(void);
s16 obj_get_pitch_from_vel(void);
s32 obj_update_race_proposition_dialog(s16 dialogID);
void obj_set_dist_from_home(f32 distFromHome);
s32 obj_is_near_to_and_facing_mario(f32 maxDist, s16 maxAngleDiff);
void obj_perform_position_op(s32 op);
void platform_on_track_update_pos_or_spawn_ball(s32 ballIndex, f32 x, f32 y, f32 z);
void cur_obj_spin_all_dimensions(f32 arg0, f32 arg1);
void obj_rotate_yaw_and_bounce_off_walls(s16 targetYaw, s16 turnAmount);
s16 obj_get_pitch_to_home(f32 latDistToHome);
void obj_compute_vel_from_move_pitch(f32 speed);
s32 clamp_s16(s16 *value, s16 minimum, s16 maximum);
s32 clamp_f32(f32 *value, f32 minimum, f32 maximum);
void cur_obj_init_anim_extend(s32 arg0);
s32 cur_obj_init_anim_and_check_if_end(s32 arg0);
s32 cur_obj_init_anim_check_frame(s32 arg0, s32 arg1);
s32 cur_obj_set_anim_if_at_end(s32 arg0);
s32 cur_obj_play_sound_at_anim_range(s8 arg0, s8 arg1, u32 sound);
s16 obj_turn_pitch_toward_mario(f32 targetOffsetY, s16 turnAmount);
s32 approach_f32_ptr(f32 *px, f32 target, f32 delta);
s32 obj_forward_vel_approach(f32 target, f32 delta);
s32 obj_y_vel_approach(f32 target, f32 delta);
s32 obj_move_pitch_approach(s16 target, s16 delta);
s32 obj_face_pitch_approach(s16 targetPitch, s16 deltaPitch);
s32 obj_face_yaw_approach(s16 targetYaw, s16 deltaYaw);
s32 obj_face_roll_approach(s16 targetRoll, s16 deltaRoll);
s32 obj_smooth_turn(s16 *angleVel, s32 *angle, s16 targetAngle, f32 targetSpeedProportion,
s16 accel, s16 minSpeed, s16 maxSpeed);
void obj_roll_to_match_yaw_turn(s16 targetYaw, s16 maxRoll, s16 rollSpeed);
s16 random_linear_offset(s16 base, s16 range);
s16 random_mod_offset(s16 base, s16 step, s16 mod);
s16 obj_random_fixed_turn(s16 delta);
s32 obj_grow_then_shrink(f32 *scaleVel, f32 shootFireScale, f32 endScale);
s32 oscillate_toward(s32 *value, f32 *vel, s32 target, f32 velCloseToZero, f32 accel,
f32 slowdown);
void obj_update_blinking(s32 *blinkTimer, s16 baseCycleLength, s16 cycleLengthRange,
s16 blinkLength);
s32 obj_resolve_object_collisions(s32 *targetYaw);
s32 obj_bounce_off_walls_edges_objects(s32 *targetYaw);
s32 obj_resolve_collisions_and_turn(s16 targetYaw, s16 turnSpeed);
void obj_die_if_health_non_positive(void);
void obj_unused_die(void);
void obj_set_knockback_action(s32 attackType);
void obj_set_squished_action(void);
s32 obj_die_if_above_lava_and_health_non_positive(void);
s32 obj_handle_attacks(struct ObjectHitbox *hitbox, s32 attackedMarioAction,
u8 *attackHandlers);
void obj_act_knockback(UNUSED f32 baseScale);
void obj_act_squished(f32 baseScale);
s32 obj_update_standard_actions(f32 scale);
s32 obj_check_attacks(struct ObjectHitbox *hitbox, s32 attackedMarioAction);
s32 obj_move_for_one_second(s32 endAction);
void treat_far_home_as_mario(f32 threshold);
#endif

View File

@@ -703,7 +703,7 @@ void setup_game_memory(void) {
set_segment_base_addr(24, (void *) gDemoInputsMemAlloc);
setup_dma_table_list(&gDemoInputsBuf, gDemoInputs, gDemoInputsMemAlloc);
// Setup Level Script Entry
load_segment(0x10, _entrySegmentRomStart, _entrySegmentRomEnd, MEMORY_POOL_LEFT);
load_segment(0x10, _entrySegmentRomStart, _entrySegmentRomEnd, MEMORY_POOL_LEFT, NULL, NULL);
// Setup Segment 2 (Fonts, Text, etc)
load_segment_decompress(2, _segment2_mio0SegmentRomStart, _segment2_mio0SegmentRomEnd);
}

View File

@@ -28,6 +28,7 @@
#define ALIGN4(val) (((val) + 0x3) & ~0x3)
#define ALIGN8(val) (((val) + 0x7) & ~0x7)
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
#define ALIGN(val, alignment) (((val) + ((alignment) - 1)) & ~((alignment) - 1))
struct MainPoolState {
u32 freeSpace;
@@ -285,31 +286,76 @@ void dma_read(u8 *dest, u8 *srcStart, u8 *srcEnd) {
* Perform a DMA read from ROM, allocating space in the memory pool to write to.
* Return the destination address.
*/
static void *dynamic_dma_read(u8 *srcStart, u8 *srcEnd, u32 side) {
static void *dynamic_dma_read(u8 *srcStart, u8 *srcEnd, u32 side, u32 alignment, u32 bssLength) {
void *dest;
u32 size = ALIGN16(srcEnd - srcStart);
u32 offset = 0;
dest = main_pool_alloc(size, side);
if (alignment && side == MEMORY_POOL_LEFT)
{
offset = ALIGN((uintptr_t)sPoolListHeadL + 16, alignment) - ((uintptr_t)sPoolListHeadL + 16);
}
dest = main_pool_alloc(offset + size + bssLength, side);
if (dest != NULL) {
dma_read(dest, srcStart, srcEnd);
dma_read((u8 *)dest + offset, srcStart, srcEnd);
if (bssLength)
bzero((u8 *)dest + offset + size, bssLength);
}
return dest;
}
#define TLB_PAGE_SIZE 4096 //Blocksize of TLB transfers. Larger values can be faster to transfer, but more wasteful of RAM.
s32 gTlbEntries = 0;
void mapTLBPages(uintptr_t virtualAddress, uintptr_t physicalAddress, s32 length)
{
while (length > 0)
{
if (length > TLB_PAGE_SIZE)
{
osMapTLB(gTlbEntries++, OS_PM_4K, (void *)virtualAddress, physicalAddress, physicalAddress + TLB_PAGE_SIZE, -1);
virtualAddress += TLB_PAGE_SIZE;
physicalAddress += TLB_PAGE_SIZE;
length -= TLB_PAGE_SIZE;
}
else
{
osMapTLB(gTlbEntries++, OS_PM_4K, (void *)virtualAddress, physicalAddress, -1, -1);
}
virtualAddress += TLB_PAGE_SIZE;
physicalAddress += TLB_PAGE_SIZE;
length -= TLB_PAGE_SIZE;
}
}
#ifndef NO_SEGMENTED_MEMORY
/**
* Load data from ROM into a newly allocated block, and set the segment base
* address to this block.
*/
void *load_segment(s32 segment, u8 *srcStart, u8 *srcEnd, u32 side) {
void *addr = dynamic_dma_read(srcStart, srcEnd, side);
void *load_segment(s32 segment, u8 *srcStart, u8 *srcEnd, u32 side, u8 *bssStart, u8 *bssEnd) {
void *addr;
if (bssStart != NULL && side == MEMORY_POOL_LEFT)
{
addr = dynamic_dma_read(srcStart, srcEnd, side, TLB_PAGE_SIZE, (uintptr_t)bssEnd - (uintptr_t)bssStart);
if (addr != NULL) {
u8 *realAddr = (u8 *)ALIGN((uintptr_t)addr, TLB_PAGE_SIZE);
set_segment_base_addr(segment, realAddr);
mapTLBPages(segment << 24, VIRTUAL_TO_PHYSICAL(realAddr), (srcEnd - srcStart) + ((uintptr_t)bssEnd - (uintptr_t)bssStart));
}
}
else
{
addr = dynamic_dma_read(srcStart, srcEnd, side, 0, 0);
if (addr != NULL) {
set_segment_base_addr(segment, addr);
}
}
#ifdef PUPPYPRINT
ramsizeSegment[segment+nameTable-2] = (s32)srcEnd- (s32)srcStart;
#endif
if (addr != NULL) {
set_segment_base_addr(segment, addr);
}
return addr;
}
@@ -606,12 +652,12 @@ void *alloc_display_list(u32 size) {
static struct DmaTable *load_dma_table_address(u8 *srcAddr) {
struct DmaTable *table = dynamic_dma_read(srcAddr, srcAddr + sizeof(u32),
MEMORY_POOL_LEFT);
u32 size = table->count * sizeof(struct OffsetSizePair) +
MEMORY_POOL_LEFT, NULL, NULL);
u32 size = table->count * sizeof(struct OffsetSizePair) +
sizeof(struct DmaTable) - sizeof(struct OffsetSizePair);
main_pool_free(table);
table = dynamic_dma_read(srcAddr, srcAddr + size, MEMORY_POOL_LEFT);
table = dynamic_dma_read(srcAddr, srcAddr + size, MEMORY_POOL_LEFT, NULL, NULL);
table->srcAddr = srcAddr;
return table;
}

View File

@@ -60,7 +60,7 @@ u32 main_pool_push_state(void);
u32 main_pool_pop_state(void);
#ifndef NO_SEGMENTED_MEMORY
void *load_segment(s32 segment, u8 *srcStart, u8 *srcEnd, u32 side);
void *load_segment(s32 segment, u8 *srcStart, u8 *srcEnd, u32 side, u8 *bssStart, u8 *bssEnd);
void *load_to_fixed_pool_addr(u8 *destAddr, u8 *srcStart, u8 *srcEnd);
void *load_segment_decompress(s32 segment, u8 *srcStart, u8 *srcEnd);
void *load_segment_decompress_heap(u32 segment, u8 *srcStart, u8 *srcEnd);