Welcome, Guest
You have to register before you can post on our site.

Username
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 647
» Latest member: shaymcn02
» Forum threads: 1,816
» Forum posts: 14,009

Full Statistics

Online Users
There are currently 107 online users.
» 2 Member(s) | 103 Guest(s)
Bing, Google, matfawcett, _Ro

Latest Threads
Make it to 10,000
Forum: General Discussion
Last Post: Vega
56 minutes ago
» Replies: 7,344
» Views: 5,675,206
Textures/texture packs in...
Forum: Coding & Hacking General Discussion
Last Post: Vega
2 hours ago
» Replies: 1
» Views: 8
MKW Coder/Developer of th...
Forum: Coding & Hacking General Discussion
Last Post: Fifty
Today, 05:06 AM
» Replies: 11
» Views: 13,905
Allow Pausing Before Race...
Forum: Offline Non-Item
Last Post: Vega
Yesterday, 07:47 PM
» Replies: 0
» Views: 38
Top 10 Most Influential C...
Forum: Coding & Hacking General Discussion
Last Post: Vega
Yesterday, 03:27 PM
» Replies: 2
» Views: 7,366
Show Ice Cube on Online P...
Forum: Online Non-Item
Last Post: _Ro
Yesterday, 08:23 AM
» Replies: 0
» Views: 46
CPU Control Cycler [Ro]
Forum: Offline Non-Item
Last Post: _Ro
Yesterday, 07:56 AM
» Replies: 7
» Views: 1,039
Thunder Cloud Effect Modi...
Forum: Offline; Item
Last Post: JerryHatrick
01-10-2025, 11:13 PM
» Replies: 11
» Views: 1,141
Miniturbos and Inside Dri...
Forum: Coding & Hacking General Discussion
Last Post: JerryHatrick
01-10-2025, 09:54 AM
» Replies: 1
» Views: 864
Code request???
Forum: Code Support / Help / Requests
Last Post: DrTap
01-09-2025, 06:06 PM
» Replies: 3
» Views: 4,975

 
  Load File From SD Card [Bushing / Segher]
Posted by: Star - 01-15-2020, 07:03 PM - Forum: Misc/Other - Replies (13)

Load File From SD Card [Bushing / Segher]

This code loads the contents of a file located on the SD card into RAM. The steps below illustrate how to use the code:
1) The function takes two arguments. The first argument (r3) is a pointer to a string that contains the path to the file to read in. The second argument (r4) is a pointer to a buffer to write the full contents of the file to.
- An example string of a file that is located on the root of the SD card would be "name.ext".
- An example string of a file that is located in a directory on the root of the SD card would be "dir/name.ext".
2) Call the function at the address that corresponds to your game's region (NTSC-U = 0x802583E0, PAL = 0x80258700, NTSC-J = 0x802580A0, NTSC-K = 0x802584E0).
3) Upon completion of the function, one must check the return value (r3). A return value of zero indicates that the file contents were successfully loaded into RAM. A non-zero value indicates failure.

Print this item

  Extend GCT Limit for USB Loader GX
Posted by: Vega - 01-14-2020, 06:59 PM - Forum: Coding (Non-ASM) and Dolphin - Replies (2)

NOTE: This method will cause any codes that hook via memory addresses of the StaticR.rel to no longer work!!!

Quick guide to increase the GCT limit if you play Mariokart Wii on USB Loader GX.

1. Make a txt file named gameconfig.txt using the following contents


Code:
RMCE01:
codeliststart = 80394E00
codelistend = 8039CDE0
poke(8019FD30, 38037FFF)

RMCP01:
codeliststart = 80399180
codelistend = 803A1160
poke(8019FDD0, 38037FFF)

RMCJ01:
codeliststart = 80398B00
codelistend = 803A0AE0
poke(8019FCF0, 38037FFF)

RMCK01:
codeliststart = 803871A0
codelistend = 8038F180
poke(801A012C, 38037FFF)


2. Place the gameconfig.txt file on the root of your SD/USB device (whichever device where your apps, codes, etc folders are located at)
3. Your GCT limit has been increased from 256 total lines to 32736 total lines!

Print this item

  Get Square Root of Any Hex Value: PPC ASM
Posted by: Vega - 01-13-2020, 02:11 AM - Forum: Coding & Hacking General Discussion - Replies (9)

https://github.com/VegaASM/SquareRootHex-PPCASM

Another small function I wrote up in my free time. It can take in any Hex value and spit out the square root result. The user can modify r4 to select what type of rounding will be done. Licensed under the Apache 2 License.

Code:
/*
Copyright 2020 VegaASM

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0
    
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#~~~~~~~~~~~~~~~~#
# START ASSEMBLY #
#~~~~~~~~~~~~~~~~#

hex_square_root:

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# If 0/1, return 0/1 respectively. If not, backup r3 #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

cmplwi r3, 1
blelr-
mr r0, r3

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Calculate Word/24bit/Halfword/Byte #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

cntlzw r3, r0

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Calc How Many times Secondary Loop is Done #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

cmplwi r3, 8
li r5, 4
li r6, 24
blt- start_with_msbyte #Word value found

cmplwi r3, 16
li r5, 3
li r6, 16
blt- start_with_msbyte #24-bit value found

cmplwi r3, 24
li r5, 2
li r6, 8
blt- start_with_msbyte #Halfword value found

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Byte value only option left #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

li r5, 1
li r6, 0

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Start with the Most Significant Byte #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

start_with_msbyte:
srw r7, r0, r6

#~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Set One Above Digit Limit #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~#

li r8, 0x10

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# First type of Loop, No matter what Value is, this 1st type is only done once #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Square the r8 value, Proceed once result is less than r7 #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

first_type_loop:
subi r8, r8, 1
mullw r9, r8, r8
cmplw r9, r7
bgt- first_type_loop

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Loop Done, Subtract r9 from r7 to get Remainder, Build r3 Result w/ r8's value #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

sub r7, r7, r9
mr r3, r8

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Take r8's result from the above loop, and add it to itself (aka mul by 2 #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

add r8, r8, r8

#~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Big (Secondary Type) Loop #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Do Certain Rotate Instruction Based on How Many Loops are Left #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

big_secondary_loop:
cmpwi r5, 4
rlwinm r6, r0, 16, 0x000000FF
beq- build_into_leftovers

cmpwi r5, 3
rlwinm r6, r0, 24, 0x000000FF
beq- build_into_leftovers

cmpwi r5, 2
clrlwi r6, r0, 24
beq- build_into_leftovers

li r6, 0 #Fake decimal value

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Shift r7 leftover 8 bits to bring 'down' the next 'group' (byte) #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

build_into_leftovers:
slwi r7, r7, 8
or r7, r7, r6

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Shift r8 left by 4 bits to create the "Space" #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

slwi r8, r8, 4

#~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Set One Above Digit Limit #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~#

li r6, 0x10

small_secondary_loop:
subi r6, r6, 1

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Place r6 into r8's "space", Then Multiply. Proceed on first iteration when r10 is less than r7 #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

or r9, r8, r6
mullw r10, r9, r6
cmplw r10, r7 #Once we get first iteration of r6 < r12 then we can proceed
bgt- small_secondary_loop

#~~~~~~~~~~~~~~~~~~~~#
# Get Next Leftovers #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Adjust the Increasing Number that will be "Spaced" #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

sub r7, r7, r10
add r8, r9, r6

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Find out if we are doing Remainder of Whole Number #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# If so, we don't want to do the upcoming slwi and or instruction #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

cmpwi r5, 1
beq- decrement_loop

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Got Next Digit Result. Move r3 over by 4 bits left. OR in Digit (r6) #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

slwi r3, r3, 4
or r3, r3, r6

#~~~~~~~~~~~~~~~~~~~~#
# Decrement Big Loop #
#~~~~~~~~~~~~~~~~~~~~#

decrement_loop:
subic. r5, r5, 1
bne+ big_secondary_loop

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Check User Option For Rounding #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

cmpwi r4, 1
bnelr- #If User wanted rounding towards lowest zero, then function is done, END function

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Check Remainder Value of Whole Number #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

cmpwi r6, 8
bltlr- #If remainder has most significant digit of less than 8 then nothing needs to be done, END function

addi r3, r3, 1 #If digit is 8 or more, we need to round up

#~~~~~~~~~~~~~~#
# END Function #
#~~~~~~~~~~~~~~#

blr

#~~~~~~~~~~~~~~#
# END ASSEMBLY #
#~~~~~~~~~~~~~~#

Print this item

  Hex to Binary in PPC ASM
Posted by: Vega - 01-12-2020, 12:00 AM - Forum: Coding & Hacking General Discussion - No Replies

I was bored so I wrote up this small snippet of code to take the byte input and return its binary form. The snippet of code is setup as small function meant to be called with the proper arg and a return value is sent. To cut down on source length, there are no checks for null digits.



#r3 = arg (byte; positive only)
#r3 returns the binary representation of the byte, or returns -1 if a valid positive byte wasn't supplied for the arg

Source:
#Convert byte value to its binary representation

#Temporarily place Arg into r0
mr r0, r3

#Check if we actually working on a positive byte
rlwinm. r3, r3, 0, 0xFFFFFF00
li r3, -1
bnelr-

#Place bit 24 of r0 into bit 3 of r3
#Place bit 25 to bit 7
#Place bit 26 to bit 11
#Place bit 27 to bit 15
#First digit completed
rlwinm r3, r0, 21, 3, 3 #Have to use rlwinm because r3 does not start off as null
rlwimi r3, r0, 18, 7, 7
rlwimi r3, r0, 15, 11, 11
rlwimi r3, r0, 12, 15, 15

#Place bit 28 of r0 into bit 19 of r3
#Place bit 29 to bit 23
#Place bit 30 to bit 27
#Place bit 31 of r0 into bit 31 of r3
rlwimi r3, r0, 9, 19, 19
rlwimi r3, r0, 6, 23, 23
rlwimi r3, r0, 3, 27, 27
rlwimi r3, r0, 0, 31, 31

#Done
blr



Raw ASM compiled code~

Code:
7C601B78 5463002F
3860FFFF 4C820020
5403A8C6 500391CE
50037AD6 500363DE
50034CE6 500335EE
50031EF6 500307FE
4E800020

Print this item

  Quick question about Ghidra
Posted by: ComputerBot2016 - 01-11-2020, 12:32 PM - Forum: Coding & Hacking General Discussion - Replies (15)

So, I’ve got Ghidra setup and decompiled the main.dol and StaticR.rel, and I’ve noticed that addresses of functions listed in Ghidra are offset by a specific amount compared to when I find the same functions in memory in dolphin. I’ve figured out that the offset is 187234 in hex, so I can use that value to convert function addresses between the 2. My question is, is there a setting in Ghidra I can change to add this offset automatically, so the functions start at the same addresses as dolphin?

Thanks

Print this item

  Hiya
Posted by: ComputerBot2016 - 01-10-2020, 09:40 AM - Forum: Introductions - Replies (4)

Hey everyone. I already made a post in the help section the other day, but I’m still pretty new here.

As I mentioned in my first post, I’ve found many of the tutorials on this forum very helpful for learning how to make ASM based codes. I’ve already made a couple of simple codes, but nothing that I would consider releasing yet. I’m still learning, but I think I’m making some progress.

Anyway, hiya!

Print this item

  Dynamic Gravity v3.1 (CTGP 200cc) [JoshuaMK]
Posted by: JoshuaMK - 01-08-2020, 02:19 AM - Forum: Offline Non-Item - No Replies

Dynamic Gravity v3.1 (CTGP 200cc) [JoshuaMK]

A modded Dynamic Gravity code made to work as closely to CTGP's dynamic gravity as possible. Only real difference is with this code, you can't cheese blue shells by abusing the gravity, which in my opinion makes this code superior to the one in CTGP.

EDIT: v3.1 released, which fixes the bug of mega mushrooms and stars lasting forever.

IT IS RECOMMENDED TO USE THE TERMINAL VELOCITY CODE HERE ALONG WITH THIS ONE. SET "TERMINAL" TO 3FC00000: https://mkwii.com/showthread.php?tid=1512



(NTSC-U)
C2590400 00000007
48000009 40240000
7D8802A6 C14C0000
C1A3FF90 EDAD02B2
C03F0000 FD400890
EC21682A FF815040
409C0008 FC205090
60000000 00000000

(PAL)
C2596C24 00000007
48000009 40240000
7D8802A6 C14C0000
C1A3FF90 EDAD02B2
C03F0000 FD400890
EC21682A FF815040
409C0008 FC205090
60000000 00000000

(NTSC-J)
C25965A4 00000007
48000009 40240000
7D8802A6 C14C0000
C1A3FF90 EDAD02B2
C03F0000 FD400890
EC21682A FF815040
409C0008 FC205090
60000000 00000000

(NTSC-K)
C2584C7C 00000007
48000009 40240000
7D8802A6 C14C0000
C1A3FF90 EDAD02B2
C03F0000 FD400890
EC21682A FF815040
409C0008 FC205090
60000000 00000000



#~~~~~~~~~~~~#
#Inject > 80590400#
#~~~~~~~~~~~#

.set GRAVITY, 0x40240000

bl float

.long GRAVITY

float:
mflr r12
lfs f10, 0 (r12)
lfs f13, -0x70 (r3)
fmuls f13, f13, f10
lfs f1, 0 (r31)
fmr f10, f1
fadds f1, f1, f13
fcmpo cr7, f1, f10
bge cr7, the_end
fmr f1, f10
the_end:



Code Creator: JoshuaMK  Heart 
Code Contributors: Hamster35000vr (Gravity Float Address)

Print this item

  Dynamic Gravity v3.1 [JoshuaMK]
Posted by: JoshuaMK - 01-08-2020, 01:47 AM - Forum: Offline Non-Item - No Replies

Dynamic Gravity v3.1 [JoshuaMK]

This is the final update to Dynamic Gravity/Fast Falling, which fixes a de-sync bug when racing ghosts, and also shortens the code to almost half of the length of v2.0.

EDIT: v3.1 released, which fixes the bug of mega mushrooms and stars lasting forever.



(NTSC-U)
C2590400 00000005
48000009 GRAVITY
7D8802A6 C14C0000
C1A3FF90 EDAD02B2
C03F0000 EC21682A
60000000 00000000

(PAL)
C2596C24 00000005
48000009 GRAVITY
7D8802A6 C14C0000
C1A3FF90 EDAD02B2
C03F0000 EC21682A
60000000 00000000

(NTSC-J)
C25965A4 00000005
48000009 GRAVITY
7D8802A6 C14C0000
C1A3FF90 EDAD02B2
C03F0000 EC21682A
60000000 00000000

(NTSC-K)
C2584C7C 00000005
48000009 GRAVITY
7D8802A6 C14C0000
C1A3FF90 EDAD02B2
C03F0000 EC21682A
60000000 00000000



GRAVITY = Gravity Multiplier (Recommended value = 40240000 // Values higher than 40480000 WILL cause unwanted side effects)



#~~~~~~~~~~~#
#Inject > 80590400#
#~~~~~~~~~~~#

.set GRAVITY, 0x40240000

bl float

.long GRAVITY

float:
mflr r12
lfs f10, 0 (r12)
lfs f13, -0x70 (r3)
fmuls f13, f13, f10
lfs f1, 0 (r31)
fadds f1, f1, f13



Code Creator: JoshuaMK  Heart
Code Contributors: Hamster35000vr (Gravity Float Address)

Print this item

  Hello to everyone
Posted by: Unnamed - 01-07-2020, 08:11 AM - Forum: Introductions - Replies (4)

Hello to everyone in this community,

my interest in codes started many years ago and i liked to play with codes, but i had no idea what these codes actually mean, how they work and so on.

Then half a year ago I discovered this site and was amazed. Not only by the quality of the codes, but also by the well written and understandable tutorials. These tutorials helped me to understand how codes are structured, what ASM codes do and especially how to port codes. Thanks to everyone who wrote these, especially you Vega.

However, I can't test the codes I make (only those in my region PAL) because I can't install Dolphin due to my limited PC-RAM. Since I have already ported some codes from the Incomlete/Outdated forum, I would like to ask if any of you can test these codes and if so, where I can post them.
 
I'm happy to be a member now and thank you for the answer  Smile .



And please don't be mad at me for my bad english.

Print this item

  Inline ASM HBC Tutorial
Posted by: Vega - 01-06-2020, 08:49 PM - Forum: PowerPC Assembly - No Replies

Inline ASM HBC Tutorial



Credits to WiiBrew.org for original basic Inline ASM tutorial. Wiibrew tutorial is HERE

I've made a few apps using Inline PowerPC Assembly for very basic stuff. This isn't really useful for apps in general as you want to learn C and C++, but nonetheless here's a tutorial utilizing Inline ASM for HBC apps.



Chapter 1: Installing DevkitPro PPC

If you don't have DevkitPro PPC, you need to install it. For Windows and Ubuntu linux, there are tutorials literally everywhere on the Web. If you happen to use Debian Linux like me, I wrote a good tutorial for installation HERE.



Chapter 2: Changes to default project

Make a copy of the Hello World Wii Project (examples/Wii/template), and paste it to a new directory. Go ahead and rename the 'template' directory (the one in your new directory) to assembler. Within your /assembler folder, delete the template.pnproj file, you don't need it.

The Makefile at /assembler needs to be modified. Open up the Makefile on your preferred notepad/text-editor and find this...

Code:
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------

CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE)
CXXFLAGS = $(CFLAGS)

LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map

Depending on your devkit version, this contents here may slightly differ. You need to add a comment (hash tag symbol) on the 'CFLAGS' line. like this..

#CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE)

After that edit, add the following line (place it right above the CFLAGS line)...

CFLAGS = -save-temps -Wall $(MACHDEP) $(INCLUDE)

If you did everything correctly, the Makefile (the portion showed earlier), should look like this..

Code:
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------

CFLAGS = -save-temps -Wall $(MACHDEP) $(INCLUDE)
#CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE)
CXXFLAGS = $(CFLAGS)

LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map

Save your edits, close the file.



Chapter 3: Setting up new Default Project

The edits are made. Now compile the project. For linux, it would be something like this...

cd /path/to/the/folder/assembler
make

When the project gets compiled there will be a new directory present... (/assembler/build). Within the build directory, you should see the template.s file, this is our Inline ASM file. Go ahead and delete the following files
  • template.d
  • template.elf.map
  • template.i
  • template.o

And also delete the newly created dol and elf files. Remember that line for CFLAGS you added to the makefile? Go ahead and comment it out. Uncomment the original CFLAGS line. Now you always have a default Inline ASM project. BACK THIS UP somewhere safe.



Chapter 4: Writing some Inline ASM

We are now actually going to do some Inline ASM work to create a very basic new project. Before we do that, let's make a small edit to the project. Open up the /build/template.s file.

Change "Hello World!" to "Hello ASM!!!". And yes, make sure you use 3 total exclamation marks.

Save changes. Open the /source/template.c file and make the same changes to "Hello World!". Save changes.

Now it's time to write some Inline ASM. Open up template.s. Scroll down until you see something like this (yours may slightly differ)...

Code:
bl WPAD_ScanPads
li 3,0
bl WPAD_ButtonsDown
stw 3,8(31)
lwz 9,8(31)
rlwinm 9,9,0,24,24
cmpwi 7,9,0
beq 7,.L3
li 3,0
bl exit

This is the chunk of ASM responsible for constantly loading the Wii Remote button values and seeing if the Home button is pressed. If it is (r9 not equal to 0), the li 3,0 instruction (only argument upcoming function) is executed and then the exit function is called, thus exiting back to HBC.

We will modify this chunk of ASM to shutdown the Wii instead of exiting to HBC. The Wii has some GPIO lines which you can read about HERE, which we can write basic ASM for to execute a shutdown (NOTE: This will only work on HBC versions 1.1.0 or later or else there may be a permissions error and the shutdown won't be executed).

Here's a small snippet of ASM to shutdown the Wii....

Code:
lis r3, 0xCD80 #Set GPIO_OUT upper 16 bits
lwz r4, 0x00E0 (r3) #Load Pin Connection word value from GPIO_OUT
ori r4, r4, 0x0002 #Toggle the SHUTDOWN Pin
stw r4, 0x00E0 (r3) #Update the GPIO_OUT Pins

Now add this snippet of ASM right underneath the 'beq' instruction (the branch taken if the Home button is NOT pressed). The chunk of ASM should now look like this...

Code:
bl WPAD_ScanPads
li 3,0
bl WPAD_ButtonsDown
stw 3,8(31)
lwz 9,8(31)
rlwinm 9,9,0,24,24
cmpwi 7,9,0
beq 7,.L3

    lis r3, 0xCD80 #Set GPIO_OUT upper 16 bits
    lwz r4, 0x00E0 (r3) #Load Pin Connection word value from GPIO_OUT
    ori r4, r4, 0x0002 #Toggle the SHUTDOWN Pin
    stw r4, 0x00E0 (r3) #Update the GPIO_OUT Pins

li 3,0
bl exit

Onto compiling...



Chapter 5: Compiling the Inline ASM Project

We simply cannot go ahead run make on the Makefile to have this project compiled. We need do some extra steps, which is creating an object file (.o file) from our Inline ASM file. This is done using devkit's binutils. For linux, something like this would be executed in your terminal..

cd /path/to/your/binutils #(devkitpro/devkitPPC/bin)

./powerpc-eabi-as -mregnames -mbroadway /path/to/assembler/build/template.s -o /path/to/assembler/build/template.o

cd /path/to/assembler

make

The project will now compile. Rename the dol file to boot.dol.



Chapter 6: Testing the HBC App

After renaming the dol file. Throw in any xml and png file to make a quick app out of the project. Place the project in the apps folder of your SD/USB device. Launch the app.

Side note: Make sure your XML file has the tag <ahb_access/> tag(right before the final tag of </app>). These is needed to allow Broadway to have full permissions or else the Wii shutdown function won't work.

If you are too lazy to find or make an xml, here's a template you can use, you will still need to get an icon.png btw...

Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<app version="1.1">
<name>NAME OF PROGRAM</name>
<version>0.0</version>
<release_date>20200101</release_date>
<coder>AUTHOR</coder>
<short_description>STUFF</short_description>
<long_description>MORE STUFF</long_description>
<ahb_access/>
</app>

You will see the Hello ASM!!! message. Now press the Home button on your Wii Remote. The Wii will shutdown. Congratz! And there ya go, a quick example of how to run very basic Inline ASM instructions on a HBC project.



Chapter 7: Controller and Console Font Stuff

In this snippet of code, this is the button check for the Wii Remote to see if HOME button was pressed to exit to HBC

Code:
bl WPAD_ScanPads
li 3,0 #Arg for WPAD_ButtonsDown
bl WPAD_ButtonsDown
stw 3,8(31) #Buttons Down returned in r3, Store it
lwz 9,8(31) #Load Buttons-Down into r9
rlwinm 9,9,0,24,24 #Clear all bits except HOME button bit
cmpwi 7,9,0 #Check r9 vs 0, use cr7
beq 7,.L3 #If HOME button bit is 0 (NOT pressed), continue to .L3 (video syncing and keeping app running)

The Rotation instruction shows bit 24 is for the HOME button. Here is all the Wii Remote button bits if you ever need them...
  • Bits 16 thru 18 = unused
  • Plus = Bit 19 (0x00001000)
  • Up = Bit 20 (0x00000800)
  • Down = Bit 21 (0x00000400)
  • Right = Bit 22 (0x00000200)
  • Left = Bit 23 (0x00000100)
  • Home = Bit 24 (0x00000080)
  • Bits 25 & 26 = unused
  • Minus = Bit 27 (0x00000010)
  • A = Bit 28 (0x00000008)
  • B = Bit 29 (0x00000004)
  • 1 = Bit 30 (0x00000002)
  • 2 = Bit 31 (0x00000001)

And if a nunchuck is attached, here's its extra bits
  • C = Bit 14 (0x00020000)
  • Z = Bit 15 (0x00010000)

Fyi, for anything Classic Controller related, you don't need to add any extra functions to call/check, Wii Remote attachments are configured automatically, simply just use these bits. Keep in mind that the nunchuck attachment bits (14 and 15) are also used by the Classic Controller)
  • Right = Bit 0 (0x80000000)
  • Down = Bit 1 (0x40000000)
  • L = Bit 2 (0x20000000)
  • Minus = Bit 3 (0x10000000)
  • Home = Bit 4 (0x08000000)
  • Plus = Bit 5 (0x04000000)
  • R = Bit 6 (0x02000000)
  • Bit 7 = Unused
  • ZL = bit 8 (0x00800000)
  • B = Bit 9 (0x00400000)
  • Y = Bit 10 (0x00200000)
  • A = Bit 11 (0x00100000)
  • X = bit 12 (0x00080000)
  • ZR = bit 13 (0x00040000)
  • Left = bit 14 (0x00020000)
  • Up = bit 15 (0x00010000)


If desired you can easily add GCN compatibility. You can do this via adding the basic functions in C then modifying via Inline or do everything from scratch in the inline file.

Via C file:
Add this right underneath WPAD_Init
Code:
// Initialise GCN
    PAD_Init();

And in the part of the C file that deals with the WPAD scan and exiting to HBC via HOME button, modify it something like this...
Code:
// Call WPAD_ScanPads each loop, this reads the latest controller states
        WPAD_ScanPads();

        // WPAD_ButtonsDown tells us which buttons were pressed in this loop
        // this is a "one shot" state which will not fire again until the button has been released
        u32 pressed = WPAD_ButtonsDown(0);
       
        // Call PAD_ScanPads each loop, this reads the latest GCN controller states
        PAD_ScanPads();
       
        u32 GCNpressed = PAD_ButtonsDown(0);

        // We return to the launcher application via exit
        if ( pressed & WPAD_BUTTON_HOME ) exit(0);
       
        if ( GCNpressed & PAD_TRIGGER_START ) exit(0);

        // Wait for the next frame
        VIDEO_WaitVSync();

Afterwards, just compile with the makefile modified to allow you to edit the .s inline file to what you need.

Via Inline:
If you don't want to modify the C file, just do everything via Inline. In your Inline file, add a "bl PAD_Init" right underneath the "bl WPAD_Init". Then edit the button scanning portion to something like this...


Code:
bl WPAD_ScanPads
li 3,0
bl WPAD_ButtonsDown
stw 3,8(31)
bl PAD_ScanPads #scan the GCN
li 3,0
bl PAD_ButtonsDown #get what buttons are pressed in the GCN
stw 3,12(31) #safe to do. Store GCN buttons


Then do what you need with the WPAD and PAD button values that are stored in reference to r31.

And here are all the GCN button bit values...
  • Start = bit 19 (0x00001000)
  • Y button = bit 20 (0x00000800)
  • X button = bit 21 (0x00000400)
  • B button = bit 22 (0x00000200)
  • A button = bit 23 (0x00000100)
  • bit 24 unused
  • L = bit 25 (0x00000040)
  • R = bit 26 (0x00000020)
  • Z = bit 27 (0x00000010)
  • Up = bit 28 (0x00000008)
  • Down = bit 29 (0x00000004)
  • Right = bit 30 (0x00000002)
  • Left = bit 31 (0x00000001)

Here are some tips/tricks to make printf not so boring...

Start Console (always included in the source by default, simply posted here for completeness)
\033[2;0H

Enter into New Line
\n

Clear Console, Move cursor back to very top left (note: this goes up to being partially out of screen so further messages afterwards start with a double enter \n\n)
\x1b[2J

Set Font Color (XX = color)
\x1b[XXm

30 = Black
31 = Red
32 = Green
33 = Yellow
34 = Blue (not useful as it's very faded/dull)
35 = Purple
36 = Cyan
37 = White/Default

You can also set the Fill Color. Just add 10 to font color XX value, string used is same as font color.




Chapter 8: Intro to Utilizing the SD/USD device

One of the great things about HBC apps is the 'universal' access to working with the SD device. Many Wii games do not include Symbols for the SD card slot, which means you would have to code everything out manually (including the FAT file system).

The NAND file system is used in a lot of Gecko Codes, but it's inferior to operating on files present on the SD device. End users that will use your HBC apps will almost always prefer SD over NAND.

NOTE: I've personally never tested any of this with your files being on a USB stick. May not work.



Chapter 9: Re-doing the default Inline ASM project

You don't need to delete the original saved project you did from the earlier chapters. However we will re-write it since we need extra headers and libraries to interact with the SD/USB device.

We will repeat Chapters 2 and 3 but with some extra steps. When doing the very first edits on the makefile in Chapter 2, some extra changes will need to be made.

Find the line that looks like this...

Code:
LIBS    :=    -lwiiuse -lbte -logc -lm

You will need to add in the -lfat library. Add in the library to update the makefile to look like this...

Code:
LIBS    :=    -lwiiuse -lbte -lfat -logc -lm

Save and close. Now go to the template.c file, we need to add some headers. At the very top of the .c file, you will see this...

Code:
#include <stdio.h>
#include <stdlib.h>
#include <gccore.h>
#include <wiiuse/wpad.h>

Change that portion of the file to be this....

Code:
#include <gccore.h>
#include <wiiuse/wpad.h>

#include <fat.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

Save and close. Complete Chapter 2 (remember to add in the new CFLAGs line in the Makefile). After that, complete Chapter 3 for this project.

Now backup this project somewhere safe, you can name it to something like "SD-Template-Base".



Chapter 10: Initializing the FAT File System

To even begin opening/reading/writing/etc files on the SD/USB device, you need to init the FAT system. If the device isn't in FAT16 and FAT32, this will fail. You can init the FAT system like this...

Code:
bl fatInitDefault
cmpwi r3, 0
beq- error

fatInitDefault should never return null. If so, something went wrong. Be sure to add in some code to handle errors, as you don't want the App to continue with its task when an error occurs or you might be greeted with an Exception Screen output.



Chapter 11: Opening, Creating, & Closing Files on SD

Opening and closing is quite different when compared to how its done on NAND files. Instead of having a file descriptor (fd), you instead have a file pointer (fp).

Opening a file requires the fopen function and it requires 2 args

r3 = Pointer to File Name (must end in null)
r4 = Pointer to Permissions

Regarding the r4 arg, you need a pointer that points to a standard ASCII string (that ends in null). This string (depending on its contents) decides what permissions will be used when opening the file.

Permission Ascii String List:
"rb" = Read permissions
"wb" = Write permssions
"ab" = Write perms & append

The 'b' part of the string stands for binary. Since you are working on this via assembly, you need to include this 'b'.

So for example, let's say you wanted to open up a file called "test.txt" with write permissions. You could do it like this....

Code:
#Establish ASCII strings for file name and perms
file_name:
.string "test.txt"
perms:
.string "rb"

#Other code here

#Open test.txt with read perms
lis r3, file_name@ha
la r3, file_name@l (r3)
lis r4, perms@ha
la r4, perms@l (r4)
bl fopen

fopen is also different than something such as isfs_open (NAND work) when it comes to return values. If fopen is successful, you are returned a memory pointer. This is your File Pointer, aka fp. If r3 = 0, then an error has occurred.

Code:
#Pretend we've called fopen, now we will check r3
cmpwi r3, 0
beq- error

Creating files is very different that ISFS. There is no designated create function. Instead to create a file, you need to open a non-existing file with write perms ("wb").

You can open a file that you intend to append data to the end of it via opening with using an r4 arg with a pointer that points to "ab". When opening a file in this method, any writes you do will start immediately after the end of the file and get appended. Please note that opening a file in this manner renders the fseek and rewind functions as useless (more on that in Chapter 13)

Closing a file is simple, just place the fp into r3, and call fclose. r3 will return as 0 if everything went OK.

Code:
#Pretend fp is in r31
mr r3, r31
fclose
cmpwi r3, 0
bne- error

Unlike utilizing the NAND file system, with SD/USB, you can reopen files with different perms without having to close them beforehand.

The function for that is freopen. There are 3 args to freopen~

r3 = pointer to filename (same as fopen)
r4 = pointer to perms (same as fopen)
r5 = fp from the original use of fopen on the file

If an error occurs on freopen, a null value is returned in r3.



Chapter 12: Reading and Writing Files on SD

For reading a file (dumping it contents to memory), you must have opened the file earlier with read permissions. The function to read a file is called fread. It has 4 arguments.

r3 = Pointer to dump file's contents to (aka called the Buffer)
r4 = size
r5 = count
r6 = fp (file pointer you were given from fopen)

r4 (size) and r5 (count) can be deceptive... to say the least. Since you are working on files via a 'binary' manner, the terms of these are backwards...

For the type of work we do, r4 will always be 1. This is because the file (as being read/written in binary form) only has 1 type of data, therefore the size is 1.

r5 (count) is what you will use for the *real* size of the file.

Example~

Code:
#Dump 100 bytes of a file, pretend we have already opended if with read perms
#Pretend fp is in r31 and our r3 arg will be the EVA spot of 0x80001500
lis r3, 0x8000
ori r3, r3, 0x1500
li r4, 1
li r5, 100
mr r3, r31
bl fread

When the function returns, r3's value should match what was originally used as the r5 arg. If not, then an error occurred.

Writing (function name: fwrite) is the same as Reading except the r3 arg is a pointer to the contents that will be used to write on the file. Return (r3) value works in the same manner as fread. Remember to open the file with write perms before hand.



Chapter 13: Getting the size of a file on the SD

A file may have a dynamic or unknown size. Therefore, if you are needing to allocate memory later for fread or fwrite, you will need a way to know the file's size to know how much memory to allocate. Memory allocation will be discussed in the next Chapter.

fseek, ftell, and rewind are the 3 functions you will need to do this. Please note that fseek and rewind do not work on files that were opened with an r4 arg of "ab" (write perms & append).

When working on a file, you are by default, at the very beginning of said file. You can actually "move" where you are "located" on the file.

fseek allows you to do this. It has 3 args.

r3 = fp
r4 = offset from origin of file
r5 = type of origin

Before you can set r4, you need to know what r5 value you will be using. r5 comes with 3 options.

0 = Beginning of file aka SEEK_SET
1 = Current position of file aka SEEK_CUR
2 = End of file aka SEEK_END

Once you have r5 set, you can then apply an offset value in r4.

For getting the size of the file, we need to use an r4 arg of 0 and an r5 arg of 2 (SEEK_END)

Code:
#pretend fp is in r31
mr r3, r31
li r4, 0
li r5, 2
bl fseek

fseek will return 0 if everything went OK.

After you have executed fseek (r4 as 0, r5 as 2), you will be "located" at the end of the file. At this point, we can use the ftell function. ftell tells us our "location value" of the file. Since we have 'seeked' to the very end, the "location value" after calling ftell will give us our file size.

ftell has only one arg. r3 = fp

Code:
#pretend fp is in r31
mr r3, r31
bl ftell

After ftell has been called, r3 will now contain the file's size (in bytes). You do NOT need to check for errors on ftell. As long as the correct r3 arg was supplied, ftell will NEVER output an unexpected error code.

We're almost done! Be sure to have some code to backup the file's size somewhere safe (such as an unused Global Variable Register). All we have do is call the function rewind (to "move" back to the start of the file) and we're good. The function rewind requires 1 arg (r3 = fp)

Code:
#pretend fp is in r31
mr r3, r31
bl rewind

Similar to ftell, you don't need to check for any errors in rewind.



Chapter 14: Allocating Memory

Sometimes the EVA isn't enough space for reading/writing files. You will need to call a function to give you some free memory to use.

Not only that, since we are working on what is known as input/output streams, we need the memory to be 32-byte aligned (meaning the address to start of the memory block needs to be divisible by 32)

The function we need is called memalign. memalign takes 2 args

r3 = Alignment (based on byte)
r4 = Size

The great thing about memalign, is that you need not need to worry about "aligning" the size so its divisible by the r3 arg. Since we need a 32-byte alignment, our r3 arg is 32. r4 arg will be what you received back from ftell.

Code:
#pretend size we got from ftell was previously saved in r30
li r3, 32
mr r4, r30
bl memalign

memalign will return you a pointer to the allocated memory block if it was successful. r3 will be 0 if an error occurred.



Chapter 15: Renaming and Deleting Files on the SD

The function name for deleting a file is remove. Deleting a file is easy. You just need one arg (r3) and it has the be the file name (must end in null). The file cannot be opened when you are deleting it. If deleting the file was successful, a 0 will be returned.

Renaming a file is simple too. Make sure the file is NOT opened when renaming. Function name for renaming is simply rename. rename requires 2 args.

r3 = pointer to old name (must end in null)
r4 = pointer to new name (must end in null)

r3 will return a 0 if everything went OK.



Chapter 16: Cache Considerations

Unlike ISFS functions, SD functions do not manage Cache for you.

If Cache isn't properly managed, inaccurate data and/or instructions may be present before, after, and/or during a read and/or write. For reading data, the space of memory where you are dumping to, may need to be invalidated (dcbi) BEFORE you call fread. This is because there are may be data sitting in virtual cached memory that hasn't been pushed out to physical memory yet. If you call fread without data invalidation beforehand, the data in virtual cached memory may get pushed onto physical memory AFTER fread has already dumped SD contents to memory.

By invalidating the memory beforehand, it ensures that any data residing in virtual cached memory will be purged (never make it to physical). A data flush or clean for this scenario makes zero sense as any data pushed to physical memory will be replaced by fread's dumped contents anyway.

Example:
Code:
#Pretend r29 points to memory region where fread will dump contents to
#Pretend r30 contains the byte size of this region
mr r3, r29
mr r4, r30
bl DCInvalidateRange
.. .. #Instructions here to setup fread args
bl fread

If you are using fread to dump instructions to memory that will executed after dumping, then the region of memory in question will need to be instruction-invalidated (icbi) AFTER the fread. Data invalidation before the fread still needs to be included as well.

Example:
Code:
#Pretend r29 points to memory region where fread will dump instructions to
#Pretend r30 contains the byte size of this region
mr r3, r29
mr r4, r30
bl DCInvalidateRange
.. .. #Instructions here to setup fread args
bl fread
.. .. #Instructions here to verify fread r3 return value
mr r3, r29
mr r4, r30
bl ICInvalidateRange

For writing data, the space of memory that contains the content should be flushed sometime BEFORE you call fwrite. This is because fwrite (or the SD functions in general) can only interact with physical memory. If you have data in virtual cached memory that hasn't been pushed to physical memory yet, then fwrite will use data in physical memory that is "stale". Therefore you have ended up writing to the SD file with stale content.

Example:
Code:
#Pretend r29 points to memory region where fread will dump contents to
#Pretend r30 contains the byte size of this region
mr r3, r29
mr r4, r30
bl DCFlushRange
.. .. #Instructions here to setup fread args
bl fwrite



Chapter 17: Conclusion; Final Tip

Welp that's it. You now have the knowledge to make/work on HBC apps in an "Inline" manner via Assembly. Also, you have the knowledge to work with the SD device.

Final Tip: To test if a SD file already exists, you will open it using read permissions. Simply check if a valid fp was returned. If so, then you know the file does indeed already exists.

Print this item