Posts: 44
Threads: 14
Joined: Mar 2018
03-17-2018, 01:45 AM
(This post was last modified: 04-29-2023, 07:12 PM by shygoo.)
Getting C code into N64 ROMs is easier than you might think using n64chain and armips. This thread will show you how to set them up and build a Hello World example for SM64.
Setting up n64chain and armips
Follow these steps to install n64chain and armips and prepare them for command line usage.
- Download n64chain from https://github.com/tj90241/n64chain/releases/ and extract all the files from the 'tools' folder to to C:\n64chain\ (Your directory should look like this)
- Download the latest armips build from https://buildbot.orphis.net/armips/ and extract armips.exe to C:\n64chain\bin\armips.exe
- Download n64crc from https://shygoo.net/storage/n64crc.exe and move it to C:\n64chain\bin\n64crc.exe
- Add n64chain, n64crc, and armips to the system path by doing the following:
- Click the Windows start button, type "environment variables" in the search bar and open "Edit environment variables for your account"
- You should see a variable called "PATH" under user variables, click it and click "Edit..."
- (Win7) Add
;C:\n64chain\bin to the end of the variable value and click OK
(Win10) Click "New", add C:\n64chain\bin and click OK
Note: I could not find an official binary for n64crc so I compiled https://shygoo.net/storage/n64crc.exe myself. Its source code is at http://n64dev.org/n64crc.html. I did not use "Real N64 CRC Tool"/"rn64crc" for this tutorial because it produces invalid checksums for ROMs with the 6103 bootcode (e.g. Paper Mario).
After the path variable has been updated, you may need to restart your computer for the change to take effect.
Simple Hello World
Here is a minimalist Hello World example that overwrites one of the game's useless functions with code of our own. Create a folder containing the following files, and also drop an original SM64 ROM named "Super Mario 64 (U) [!].z64" in the folder.
You can download this archive which contains everything except the ROM.
sm64.h
/*
Here we create declarations for a few functions and variables in SM64 so they can be referenced from our C code.
Later we will tell armips their addresses by defining labels for them in sm64.asm.
*/
extern void PrintStr(int x, int y, const char* text); // 0x802D6554
extern short g_MarioCoins; // 0x8033B218
extern short g_MarioHealth; // 0x8033B21E
sm64.asm
// Tell armips' linker where the assets we declared in sm64.h are located
.definelabel PrintStr, 0x802D6554
.definelabel g_MarioCoins, 0x8033B218
.definelabel g_MarioHealth, 0x8033B21E
hello_world.c
#include "sm64.h"
// This hello_world function will overwrite one of SM64's useless functions, which happens to be called once every frame
void hello_world(void)
{
// Print HELLO WORLD to the screen
PrintStr(20, 20, "HELLO WORLD");
// Also kill Mario if he gets 5 or more coins, for science
if(g_MarioCoins >= 5)
{
g_MarioHealth = 0;
}
}
Note: armips' linker exposes symbols both ways, so if we wanted to make our own call to this function from custom assembly code we could just use jal hello_world .
main.asm
.n64 // Let armips know we're coding for the N64 architecture
.open "Super Mario 64 (U) [!].z64", "Super Mario 64 (U) [!].mod.z64", 0 // Open the ROM file
.include "sm64.asm" // Include sm64.asm to tell armips' linker where to find the game's function(s)
.headersize 0x80245000 // Set the displacement between ROM and RAM addresses
.org 0x802CB1C0 // Set the origin to the RAM address of the useless debug function
.area 0xA4, 0 // Define an area the size of the useless function to ensure we can't overwrite anything else
.importobj "hello_world.o" // Import and link the compiled C object, overwriting the useless function with our new code
.endarea
.close // Close the ROM file
build.bat
mips64-elf-gcc -Wall -O1 -mtune=vr4300 -march=vr4300 -mabi=32 -fomit-frame-pointer -G0 -c hello_world.c
armips main.asm
n64crc "Super Mario 64 (U) [!].mod.z64"
After the files are prepared, run build.bat. This should build a new ROM file called "Super Mario 64 (U) [!].mod.z64" which contains the Hello World program. If you run the ROM and go to the castle grounds, you should see this:
Spoiler alert: Mario does die if he grabs 5 coins.
For reference, here's the assembly and data n64chain generates. Note that armips' linker will put the data sections (in this case, the "HELLO WORLD" text) immediately after the code.
Posts: 44
Threads: 14
Joined: Mar 2018
I made a more advanced makefile setup here: https://github.com/shygoo/sm64-c-injection. This setup combines all C objects into a single library and imports it over the padding bytes in ROM / the unused 80370000 area in RAM. It can be configured to load elsewhere by editing this line. (So no need to import over unused functions!)
This was very helpful, great work!
Posts: 1
Threads: 0
Joined: Mar 2019
03-14-2019, 06:39 AM
(This post was last modified: 03-14-2019, 06:43 AM by frauber.)
old notes:
Code: /* Constants - struct pointers */
#define M64_CURR_OBJ_PTR 0x80361160 /* Pointer to object being currectly processed */
#define M64_FIRST_OBJ_STRUCT 0x8033D488 /* Pointer to the first object (out of 240) in the circular linked list */
#define M64_MARIO_STRUCT 0x8033B170 /* you can read it from 0x8032d93c */
#define M64_MARIO_OBJ_PTR 0x80361158 /* Pointer to Mario OBJ struct in RAM */
#define M64_LEVEL_STRUCT 0x8033B90c
/* Constants - misc pointers */
#define M64_DISPLAY_STATS_FLAGS 0x8032b26a
#define M64_SEGMENT_TABLE 0x8033b400
#define M64_CURRENT_LEVEL_ID 0x8032ddf8 /* u16 */
#define M64_GEO_LAYOUT_PTR_TABLE 0x8032ddc4 /* Pointer to pointer */
#define DEBUG_FLAG1 0x8032d598
/* graph flags */
#define BILLBOARD 4
#define INVISIBLE 0 /* recheck */
#define VISIBLE 1 /* recheck */
//library function:
extern int sprintf ( char * str, const char * format, ... );
/* Functions */
extern int CreateMessageBox(u16 flags, u16 rotate_to_mario, u16 type_of_dialog, u16 message_id);
/* CreateMessageBox */
/* return value = 0x00 -> dialog is happening */
/* 0x01 -> dialog is over (choice #1) */
/* 0x02 -> dialog is over (choice #2) */
/* 0x03 -> normal dialog is over */
/* type of dialog = 0xA1 -> save related (wing blocks?) */
/* 0xA2 -> regular dialog */
/* 0xA3 -> two choices */
/* You may want to set an wrapper function for */
/* CreateMessageBox (check yoshi.c for an example) */
extern int CreateStar(float x, float y, float z); /* returns pointer for spawned object */
extern void CopyObjParams(u32 *dest, u32 *source); /* copies X,Y,Z + rotation from another object */
extern void CopyObjPosition(u32 *dest, u32 *source);
extern void CopyObjRotation(u32 *dest, u32 *source);
extern void CopyObjScaling(u32 *dest, u32 *source);
extern int DeactivateObject(u32 obj_pointer); /* kills current object */
extern float DistanceFromObject(u32 object1, u32 object2); /* usually object 1 = (*Obj) and object 2 = Mario */
extern void DmaCopy(u32 dst, u32 bottom, u32 top);
extern void ExplodeObject(u32 obj_ptr);
extern void PlaySound(u32 argument);
extern void HideObject(); /* hides current object by ORing 0x01 at offset 0x02 */
extern void UnHideObject(); /* ORs 0x10*/
extern int RotateTorwardsMario(int current_rotation, int rotation_speed, int arg2);
extern void ScaleObject(float global_scaling_factor);
extern void ScaleXYZ(u32 obj_pointer, float x, float y, float z);
extern void SetModel(u16 model_ID); /* change how the object looks */
extern int SetObjAnimation(u16 animation_index);
extern int ShakeScreen(u16 argument); /* argument = 1 to 4 (?) */
extern int SpawnObj(u32 obj_pointer, u16 model_id, u32 behavior); /* returns pointer for spawned object */
extern int CheckObjBehavior(u32 behavior_segmented_pointer); /* return 1 if behavior == arg, else 0 */
extern int CheckObjBehavior2(u32 obj_pointer, u32 behavior_segmented_pointer); /* return 1 if behavior == arg, else 0 */
extern void SetObjBehavior(u32 obj_pointer, u32 behavior_segmented_pointer); /* 0x802a14c4 */
extern int IsMarioStepping(); /* returns 1 if Mario is on TOP of a solid object, else 0 */
extern void ProcessCollision(); /* 0x803938cc, usually called from behaviors */
extern int SetMarioAction(u32 mario_struct_pointer, u32 action, u32 unk_arg); /* to Do: check return values */
extern int ProcessGeoLayout(u32 *dest, u32 segmented_address); /* 0x8037e0b4 */
/* Music Related */
extern int SetMusic(u32 layer, u16 song_index, u32 a2); /* possible layers = 0 (main bgmusic), 1 (other musics) or 2 (sfx) */
extern int SetInstrument(u32 *chan_ptr, u8 instrument_index);
/* these functions need to be tested further */
extern void CreateTextBox(u16 msg_ID);
extern int PrintText(u32 x_pos, char *text, u32 fade); /* used in Credits. a2 = a float value ? */
extern int PrintRegularText(u32 x, u32 y, char *table_text_pointer); /* needs to be tested */
extern int StopMario(u16 arg); /* 1 = stop mario 2 = do nothing??
/* print functions */
extern void PrintInt (u16 x, u16 y, char* text, u32 value);
extern int PrintRegularText(u32 x, u32 y, char *table_text_pointer); /* needs to be tested more, used at credits?*/
extern void PrintXY(u16 x, u16 y, char* text);
/* memory functions */
extern int SegmentedToVirtual(u32 segmented_pointer); /* returns RAM pointer of a segmented address*/
extern int GetSegmentBase(int segment);
extern int SetSegmentBase(int segment, void *base); /* sets segment pointer table */
extern u8 *DynamicIndexCopy(u32 index, u32 begin, u32 end, u32 what);
/* math stuff */
extern float sqrtf(float x);
extern float sinf(float x);
extern float cosf(float x);
typedef struct anim /* unfinishied */
{
u16 framecount; /* 0x08 */
u32 pointer; /* 0x0c */
u32 pointer2; /* 0x10 */
} Animation;
typedef struct anim2
{
u32 *AnimationDMATable; // 0xd1 items, each item 8 bytes in lenght
u32 Current_DMA; // not sure
u32 TargetAnimationPtr; // 0x80060030 - gets copied to MarioObj->animation (that's where's animation data is DMAed)
u32 padding;
} MarioAnimation;
extern int SetMarioAnimation(MarioAnimation *AnimStruct, u16 index); /* returns 1 if animation has changed, 0 if its the same as before) */
typedef struct Music2
{
u32 _0x00;
u32 _0x04;
u32 _0x08;
u32 _0x0c;
u32 _0x10;
u32 _0x14;
u32 _0x18;
u32 _0x1c;
f32 volume; /* 1 = 0x7f - 0x20 */
f32 _0x024_maybe_pan;
f32 _0x028;
f32 pitch_transposition;
u32 _0x30;
u32 _0x34;
u32 _0x38;
u32 instrument; /* pointer to instrument */
/* stuff missing here */
u32 Vibrato; /* 0x70 */
} ChannelStruct;
typedef struct Music1
{
u32 _0x00;
u32 _0x04;
u16 _0x08;
u16 tempo; /* 0x0a */
u32 _0x0c;
u32 _0x10;
u32 pointer_seq_head;
f32 volume;
u32 _0x1c;
f32 _0x20;
f32 _0x24;
u32 _0x28;
ChannelStruct *Channel[15];
u32 _0x7c_sequence_pointer;
} MusicController; /* Layer 0 = 0x80222618 */
typedef struct collision_triangle
{
u16 collision_type; /* check collision.txt */
u16 _0x02;
u8 flag;
u8 _0x05;
s16 ymin;
s16 ymax;
s16 vertex1_x, vertex1_y, vertex1_z; /* 0x0a */
s16 vertex2_x, vertex2_y, vertex2_z; /* 0x10 */
s16 vertex3_x, vertex3_y, vertex3_z; /* 0x16 */
float normal_x;
float normal_y;
float normal_z;
float negdot;
u32 _0x2c; /* unused? */
} CollisionTriangle;
typedef struct pad_struct /* from nagra */
{
s16 stick_x;
s16 stick_y;
float x;
float y;
float z;
u16 currentButton; /* 0x10 */
u16 previousButton;
u32 *statusData; /* 0x14 */
u32 *controllerData; /* 0x18 */
} Pad;
typedef struct camera_struct /* mario->camera (0x8033C520) */
{
u32 mario_action; /* copied from mario->action */
float x; /* also copied from Mario struct */
float y;
float z;
s16 _0x10_mario_0x2c; /* 0x10 */
u16 rotation; /* again copied from Mario struct */
s16 _0x14_mario_0x30;
s16 _0x16_mario_0x32;
u32 _0x18;
u16 _0x1c;
u16 camera_setting; /* 0x06 = door opening 0x09 = triggers initial peach animation */
/* incomplete, many other members left ?? */
} Camera;
typedef struct level_struct /* 0x8033B90c, from Cellar Dweller's notes */
{
s16 _0x00;
s16 terrain_type;
u32 geo_layout_ptr;
u32 collision_ptr;
u32 _0x0c;
u32 mini_objects_ptr; /* 0x10 pointer to an array of objects defined by command 0x39 */
u32 warp_links_head;
u32 _0x18;
u32 _0x1c;
u32 *objects_head; /* 0x24 objects linked list head */
u32 LevelCameraPointer; /* Level Camera Pointer (generated at run-time) */
u32 _0x28;
u32 _0x2c;
u32 _0x30;
u8 _0x34; /* set by level command 0x30 */
u8 _0x35;
s16 music_param; /* 0x36 */
s16 music_param2; /* 0x38 title screen,etc) */
/* more? */
} Level;
typedef struct object_struct /* Regular objects, Mario also has its own struct like this */
{
u16 graph_node_type; /* 0x00 */
u16 graph_flags;
struct object_struct *prev; /* previous linked list object */
struct object_struct *next; /* next linked list object */
u32 graph_parent;
u32 graph_child; /* 0x10 */
u32 geo_layout_ptr; /* 0x14 */
u32 _0x18;
u32 _0x1c;
float _0x20; /* 0x20 */
float _0x24;
float _0x28;
float x_scaling; /* 0x2c */
float y_scaling; /* 0x30 */
float z_scaling;
u16 _0x38;
u16 _0x3a;
u32 animation; /* 0x3c - current animation */
u16 anim_current_frame; /* 0x40 */
u16 anim_timer; /* timer, animation related? */
u16 anim_current_frame_copy;
u16 _0x46;
u32 _0x48;
u32 _0x4c;
u32 matrix_ptr; /* 0x50 */
float float_0x54;
float float_0x58;
float float_0x5c;
struct object_struct *next_object_ptr; /* 0x60: re-check this */
u32 _0x64;
struct object_struct *next_object_ptr2; /* 0x68: re-check this (child_obj) */
u32 _0x6c;
u32 _0x70; /* 0x70 */
u16 active; /* 0x0000 = inactive, 0x0101 = active */
u16 _0x76; /* collision flag according to YE */
struct object_struct *collided_obj_ptr; /* according to YE, pointer to object collided with */
u32 _0x7c;
u32 _0x80; /* 0x80 */
u32 _0x84;
u32 _0x88;
u32 obj_flags;
u32 _0x90; /* 0x90 */
u32 _0x94;
u32 _0x98;
u32 _0x9c;
float x_pos; /* 0xa0 */
float y_pos;
float z_pos;
float x_speed; /* x increment? */
float y_speed; /* 0xb0 */
float z_speed; /* z_increment? */
float speed;
u32 _0xbc;
u32 _0xc0; /* 0xc0 */
u32 x_rotation; /* 0xc4 - rotation triplet */
u32 y_rotation; /* 0xc8 */
u32 z_rotation;
u32 x_rotation2; /* rotation copy (collision?) 0xd0 */
u32 y_rotation2; /* 0xd4 */
u32 z_rotation2;
u32 _0xd8;
u32 _0xe0; /* 0xe0 */
float _0xe4; /* gravity related? y_speed - 0xe4 ? */
u32 _0xe8;
u32 _0xec;
u32 _0xf0; /* 0xf0 */
u32 _0xf4; /* obj type for some behaviors (ie, ice bully), for AMPS, radius of rotation */
u32 _0xf8;
u32 _0xfc;
u32 _0x100; /* 0x100 */
u32 _0x104;
u32 _0x108;
u32 _0x10c;
u32 _0x110; /* 0x110 */
u32 _0x114;
u32 _0x118;
u32 _0x11c;
u32 animation_ptr; /* 0x120 = (set by 0x27 26 behavior command) entry for animation? */
u32 _0x124; /* in some behaviors, action related? */
float _0x128;
float _0x12c;
u32 interaction; /* 0x130
00 = Something Solid. Can't grab. Mario walks around, Can jump over.
01 = Crashed when jumping at it, Used by Hoot.
02 = Grabbing
04 = Going through door
08 = Knocks mario back and dissappears. No damage.
10 = Something Solid, Can't grab, Mario walks around, Can't jump over, Seems somewhat thin..
40 = Climbing
*/
u32 _0x134;
u32 _0x138;
u32 _0x13c;
u32 _0x140; /* 0x140 */
u32 behav_param; /* behav param */
u32 _0x148;
u32 action;
u32 _0x150; /* 0x150 = also reset when action changes */
u32 timer; /* always incremented. When action changes, it's set to 0 */
float _0x158;
float distance_from_mario;
u32 _0x160; /* 0x160 */
float _0x164_x;
float _0x168_y;
float _0x16c_z;
float _0x170; /* 0x170 */
float _0x174;
u32 _0x178;
u32 transparency;
u32 damage_to_mario; /* According to YE, "How many segments of damage to do to Mario for objects that cause him harm" */
u32 health; /* Health (ie, for King bob-omb and whomp */
u32 behav_param2; /* re-check */
u32 previous_action; /* used to reset the 0x154 timer */
u32 _0x190; /* 0x190 */
float collision_distance; /* NOTE: if collision_distance < disappear_distance then disappear_distance = collision_distance */
u32 _0x198;
float drawing_distance;
u32 _0x1a0; /* 0x1a0 */
u32 _0x1a4;
u32 _0x1a8;
u32 _0x1ac;
u32 _0x1b0; /* 0x1b0 */
u32 _0x1b4;
u32 _0x1b8;
u32 _0x1bc;
u32 _0x1c0; /* 0x1c0 */
u32 _0x1c4;
u32 _0x1c8;
u32 script_ptr;
u32 stack_index; /* 0x1d0 */
u32 stack;
u32 _0x1d8;
u32 _0x1dc;
u32 _0x1e0; /* 0x1e0 */
u32 _0x1e4;
u32 _0x1e8;
u32 _0x1ec;
u32 _0x1f0; /* 0x1f0 */
u16 _0x1f4;
u16 _0x1f6;
float col_sphere_x;
float col_sphere_y;
float _0x200; /* 0x200 */
float _0x204;
float _0x208;
u32 behavior_script_entry;
u32 _0x210; /* 0x210 */
u32 collide_obj_ptr; /* pointer to another object (collision happening)?.
Can be used to detect if Mario is on top of the object by comparing
value with Mario's pointer */
u32 collision_ptr; /* set by behavior script (0x2A command) */
u32 _0x21c;
u32 _0x220; /* 0x220 */
u32 _0x224;
u32 _0x228;
u32 _0x22c;
u32 _0x230; /* 0x230 */
u32 _0x234;
u32 _0x238;
u32 _0x23c;
u32 _0x240; /* 0x240 */
u32 _0x244;
u32 _0x248;
u32 _0x24c;
u32 _0x250; /* 0x250 */
u32 _0x254;
u32 _0x258;
u32 behav_param_copy_ptr;
} Object;
typedef struct mario_struct /* 8033b170 */
{
u32 status;
u32 flags; /* cap & other flags */
u32 _0x08;
u32 action; /* see Romanian Girl list */
u32 previous_action; /* 0x10 */
u32 _0x14;
u16 _0x18;
u16 _0x1a;
u32 _0x1c;
float _0x20; /* 0x20 */
u16 _0x24; /* rotation related, if bit 1 of status is set, 0x24 is copied to 0x2e */
s16 hitstun; /* hitstun counter (how long Mario stays invencible after getting hit */
u32 _0x28;
s16 _0x2c;
u16 rotation; /* divide it by 180 to get the angle? */
s16 _0x30; /* 0x30 */
s16 _0x32;
u32 _0x34;
u32 _0x38;
float x_pos; /* 0x3c */
float y_pos; /* 0x40 */
float z_pos;
float x_speed;
float y_speed;
float z_speed; /* 0x50. The next four floats are related to speed/acelleration */
float speed;
float _0x58;
float _0x5c;
u32 _0x60; /* 0x60 */
u32 _0x64;
CollisionTriangle *curr_collision_triangle; /* current triangle mario is stepping in */
float _0x6c;
float ground_y; /* 0x70 - ground Y */
u32 _0x74;
u32 _0x78;
u32 _0x7c;
u32 _0x80; /* 0x80 */
u32 _0x84;
Object *MarioObj;
u32 _0x8c_ptr;
u32 Mario_level_command; /* 0x90 = 8033b4b0 = Information read from the Level command that sets Mario*/
Camera *camera;
u32 _0x98_ptr; /* 0x8033B3B0 */
Pad *pad; /* pointer to controller struct controller 1 = 8033AF90 controller2 = 8033AFAC*/
MarioAnimation *MarioAnimationStruct; /* 0x8033B080 */
u32 _0xa4;
s16 coins; /* 0xa8 */
s16 stars; /* 0xaa */
s16 lifes; /* 0xac */
s16 power; /* 0xae */
u16 constant_ground_distance; /* usually 0xBD */
u16 misc_timer; /* on any value other than zero it will decrease until zero (also, drains mario energy?) */
u32 cap_timer;
u32 _0xb8;
float _0xbc;
float _0xc0; /* 0xc0 */
} MarioStruct;
Code: sprintf = 0x8032255c ;
CreateMessageBox = 0x802A4BE4 ;
CreateTextBox = 0x802d8d08 ;
CreateStar = 0x802F2B88 ;
CheckObjBehavior = 0x802a14fc;
CheckObjBehavior2 = 0x802A1554;
SetObjBehavior = 0x802a14c4;
CopyObjParams = 0x8029F0E0 ;
CopyObjPosition = 0x8029F120 ;
CopyObjRotation = 0x8029F148 ;
CopyObjScaling = 0x8029F3A4 ;
DistanceFromObject = 0x8029e27c ;
DeactivateObject = 0x802a0568 ;
DmaCopy = 0x80278504 ;
ExplodeObject = 0x802e6af8 ;
GetSegmentBase = 0x80277f20 ;
HideObject = 0x8029F620 ;
UnHideObject = 0x8029f6bc ;
PlaySound = 0x802ca190;
PrintInt = 0x802d62d8 ;
PrintXY = 0x802d66c0 ;
RotateTorwardsMario = 0x8029e530 ;
ScaleObject = 0x8029F430;
ScaleXYZ = 0x8029F3D0;
SegmentedToVirtual = 0x80277f50;
SetModel = 0x802a04c0;
SetSegmentBase = 0x80277ee0 ;
SetObjAnimation = 0x8029f464;
ShakeScreen = 0x802a50fc ;
SpawnObj = 0x8029edcc ;
SetMarioAction = 0x80252cf4;
SetMarioAnimation = 0x80279084;
IsMarioStepping = 0x802A3CFC ;
DynamicIndexCopy = 0x8027868c ;
ProcessGeoLayout = 0x8037e0b4;
MoveRelated = 0x802a2320 ;
PreMoveObj = 0x802a1308;
MoveObj = 0x802A2348 ;
MoveObj2 = 0x802A2644 ;
UnknownMove = 0x8029E714 ;
_8037a9a8 = 0x8037a9a8;
StopMario = 0x8028bd34 ;
PrintText = 0x802d8844;
PrintRegularText = 0x802d7e88;
sinf = 0x80325480;
cosf = 0x80325310;
sqrtf = 0x80323a50;
ProcessCollision = 0x803839cc;
SetMusic = 0x80320544;
SetInstrument = 0x8031cfd4;
Posts: 4
Threads: 0
Joined: Apr 2018
05-24-2019, 10:34 PM
(This post was last modified: 05-25-2019, 08:14 AM by aglab2.)
You can also use regular LLVM clang instead of gcc. No building from source or toolchain is required, just download it from here: Link
It has very good linker unlike armips that can do proper Link-Time Optimization and has C++ support from box.
I am using the following set of files to build things, I will notice several important things in forum: GitHub Repository
I mostly similar to GCC CFLAGS but I also add several important flags to remove exceptions, RTTI and some other useless MIPS stuff. Here are they
Code: CFLAGS = -Wall -Wdouble-promotion -Os -mtune=vr4300 -march=mips2 --target=mips-img-elf -fomit-frame-pointer -G0 -I $(INCLUDE_PATH) -mno-check-zero-division -fno-exceptions -fno-builtin -fno-rtti -fno-common -mno-abicalls
For linking I use ld.ldd with custom ldscript. You might want to change if you would like to make behaviors be at static place for example. In my example, I use the fact that 0x1200000 is DMACopy'd to 0x80400000 and I put my binaries to 0x1208000 with behavior being at the beginning. Extern symbols are specified in symbols.ld file which is based on frauber's answer and could be enlarged on demand. Headers I use are made to be C++ compliable with float triplet being put as a struct for convenience.
This is LD script I use for linking, to specify object file you could add another section and set it to needed object file like xd.o(.data)
Code: INCLUDE symbols.ld
ENTRY(_start)
SECTIONS
{
.sm64 0x80408000 :
{
*(.data)
*(.data.*)
*(.bss)
*(.bss.*)
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.*)
}
/DISCARD/ :
{
*(.MIPS.abiflags)
*(.gnu.attributes)
*(.mdebug.abi32)
*(.comment)
*(.pdr)
*(.reginfo)
}
}
The following way might be a bit harder in general for beginner but it has more power than armips+gcc. One can follow Makefile in repo for more in-depth information
Posts: 3
Threads: 0
Joined: Jun 2019
Say I wanted to add more functions/variables. Would I need to find the functions and add the addresses to the header file and asm?
Posts: 20
Threads: 0
Joined: Mar 2018
06-06-2019, 11:47 AM
(This post was last modified: 06-06-2019, 11:48 AM by RobiNERD.)
(06-06-2019, 09:09 AM)nole Wrote: Say I wanted to add more functions/variables. Would I need to find the functions and add the addresses to the header file and asm?
just compile it to mips assembly then load the mips code to ram and jal to its ram address youre loading it in from some other function you want to jump to your custom function from
Posts: 3
Threads: 0
Joined: Jun 2019
I honestly don't know anything about jal. I've done some basic hacking with cheatEngine and can code in c. Would learning more about mips help?
Posts: 4
Threads: 0
Joined: Apr 2018
(06-14-2019, 03:33 AM)nole Wrote: I honestly don't know anything about jal. I've done some basic hacking with cheatEngine and can code in c. Would learning more about mips help? For sure, general mips hacking knowledge applies and it will help you with debugging
|