Draw Text To Screen [SwareJonge]
#1
Draw Text To Screen [SwareJonge]

This code displays text on screen

(PAL)
04009680 4BFF7E30
060014B0 00000054
9421FF80 BC610008
3CA0802A 80A573FC
A0850004 A0A50008
481B965D 48020965
38600000 388000DC
38A00001 4800000D
54657374 00000000
7CC802A6 480209A5
48020981 B8610008
38210080 81830000
48008184 00000000

(NTSC-U)
04009640 4BFF7E70
060014B0 00000054
9421FF80 BC610008
3CA0802A 80A5307C
A0850004 A0A50008
481B95BD 480208C5
38600000 388000DC
38A00001 4800000D
54657374 00000000
7CC802A6 48020905
480208E1 B8610008
38210080 81830000
48008144 00000000

(NTSC-J)
040095DC 4BFF7ED4
060014B0 00000054
9421FF80 BC610008
3CA0802A 80A56D7C
A0850004 A0A50008
481B957D 48020885
38600000 388000DC
38A00001 4800000D
54657374 00000000
7CC802A6 480208C5
480208A1 B8610008
38210080 81830000
480080E0 00000000

(NTSC-K)
04009788 4BFF7D28
060014B0 00000054
9421FF80 BC610008
3CA08029 80A553FC
A0850004 A0A50008
481B99B9 480209C5
38600000 388000DC
38A00001 4800000D
54657374 00000000
7CC802A6 48020A05
480209E1 B8610008
38210080 81830000
4800828C 00000000



Code Creator: SwareJonge
Code Credits: Star, Riidefi(Orignal Draw Text to Screen Code), Vega(Improvements to source)



Source: 

Code:
.set region, ''
.set codePosition, 0x800014B0 # change this to the address you want to write this function to

.if     (region == 'E' || region == 'e') # RMCE
        .set drawDebugBar, 0x80009640
        .set nw4r_db_DirectPrint_ChangeXfb, 0x80021D90
        .set nw4r_db_DirectPrint_Printf, 0x80021DF0
        .set nw4r_db_DirectPrint_StoreCache, 0x80021DD0
        .set VIGetNextFrameBuffer, 0x801BAA84
        .set r28thing, 0x802A307C
.elseif (region == 'P' || region == 'p') # RMCP
        .set drawDebugBar, 0x80009680
        .set nw4r_db_DirectPrint_ChangeXfb, 0x80021e30
        .set nw4r_db_DirectPrint_Printf, 0x80021E90
        .set nw4r_db_DirectPrint_StoreCache, 0x80021E70
        .set VIGetNextFrameBuffer, 0x801BAB24
        .set r28thing, 0x802A73FC
.elseif (region == 'J' || region == 'j') # RMCJ
        .set drawDebugBar, 0x800095DC
        .set nw4r_db_DirectPrint_ChangeXfb, 0x80021D50
        .set nw4r_db_DirectPrint_Printf, 0x80021DB0
        .set nw4r_db_DirectPrint_StoreCache, 0x80021D90
        .set VIGetNextFrameBuffer, 0x801BAA44
        .set r28thing, 0x802A6D7C
.elseif (region == 'K' || region == 'k') # RMCK
        .set drawDebugBar, 0x80009788
        .set nw4r_db_DirectPrint_ChangeXfb, 0x80021E90
        .set nw4r_db_DirectPrint_Printf, 0x80021EF0
        .set nw4r_db_DirectPrint_StoreCache, 0x80021ED0
        .set VIGetNextFrameBuffer, 0x801BAE80
        .set r28thing, 0x802953FC
.else # Invalid Region
        .abort
.endif

.macro push_stack size, registers
      stwu r1, \size(r1)
      stmw \registers, 8(r1)
.endm

.macro pop_stack registers, size
      lmw \registers, 8(r1)
      addi r1, r1, \size
.endm

# 04 Write
#b 0x800014B0 - drawDebugBar # branch to the 06 code

# 06 Write
# Function Prologue...
push_stack -128, r3

lis r5, r28thing@ha
lwz r5, r28thing@l(r5)
lhz r4, 0x4(r5) # width
lhz r5, 0x8(r5) # height

bl -((codePosition + 0x18) - VIGetNextFrameBuffer)
bl -((codePosition + 0x1C) - nw4r_db_DirectPrint_ChangeXfb)

li r3, 0   # X coordinate of text start
li r4, 220 # Y coordinate of text start
li r5, 1   # Wrap text

bl branch_link_write_printf_statement
.string "Test\0\0\0"
branch_link_write_printf_statement:

mflr r6 # Store the pointer to the String into r6
bl -((codePosition + 0x3C) - nw4r_db_DirectPrint_Printf)
bl -((codePosition + 0x40) - nw4r_db_DirectPrint_StoreCache)

# Function Epilogue...
pop_stack r3, 128

lwz r12, 0(r3) # original instruction
b -((codePosition + 0x50) - (drawDebugBar+4)) # branch back

Same Code but in C2 format:

Code:
# Address Ports:
# PAL: 0x80009680
# NTSC-U: 0x80009640
# NTSC-J: 0x800095DC
# NTSC-K: 0x80009788

.set region, ''
.set codePosition, 0x800014B0

.if     (region == 'E' || region == 'e') # RMCE
        .set nw4r_db_DirectPrint_ChangeXfb, 0x80021D90
        .set nw4r_db_DirectPrint_Printf, 0x80021DF0
        .set nw4r_db_DirectPrint_StoreCache, 0x80021DD0
        .set VIGetNextFrameBuffer, 0x801BAA84
        .set r28thing, 0x802A307C
.elseif (region == 'P' || region == 'p') # RMCP
        .set nw4r_db_DirectPrint_ChangeXfb, 0x80021e30
        .set nw4r_db_DirectPrint_Printf, 0x80021E90
        .set nw4r_db_DirectPrint_StoreCache, 0x80021E70
        .set VIGetNextFrameBuffer, 0x801BAB24
        .set r28thing, 0x802A73FC
.elseif (region == 'J' || region == 'j') # RMCJ
        .set nw4r_db_DirectPrint_ChangeXfb, 0x80021D50
        .set nw4r_db_DirectPrint_Printf, 0x80021DB0
        .set nw4r_db_DirectPrint_StoreCache, 0x80021D90
        .set VIGetNextFrameBuffer, 0x801BAA44
        .set r28thing, 0x802A6D7C
.elseif (region == 'K' || region == 'k') # RMCK
        .set nw4r_db_DirectPrint_ChangeXfb, 0x80021E90
        .set nw4r_db_DirectPrint_Printf, 0x80021EF0
        .set nw4r_db_DirectPrint_StoreCache, 0x80021ED0
        .set VIGetNextFrameBuffer, 0x801BAE80
        .set r28thing, 0x802953FC
.else # Invalid Region
        .abort
.endif

.macro call_nw4r register, address
    ori \register, r31, \address@l
    mtctr  \register
    bctrl
.endm

.macro push_stack size, registers
      stwu r1, \size(r1)
      stmw \registers, 8(r1)
.endm

.macro pop_stack registers, size
      lmw \registers, 8(r1)
      addi r1, r1, \size
.endm

# Function Prologue...
push_stack -128, r3

lis r31, 0x8002

# region bound instruction for the pointer to the next framebuffer
.if (region == 'K' || region == 'k') # RMCK
    lwz r3, -0x6040(r13)
.else
    lwz r3, -0x6060(r13)
.endif

lis r5, r28thing@ha
lwz r5, r28thing@l(r5)
lhz r4, 0x4(r5) # width
lhz r5, 0x8(r5) # height

call_nw4r r12, nw4r_db_DirectPrint_ChangeXfb

li r3, 0   # X coordinate of text start
li r4, 220 # Y coordinate of text start
li r5, 1   # Wrap text

bl branch_link_write_printf_statement
.string "Test\0\0\0"
branch_link_write_printf_statement:
mflr r6 # Store the pointer to the String into r6

call_nw4r r12, nw4r_db_DirectPrint_Printf
call_nw4r r12, nw4r_db_DirectPrint_StoreCache

# Function Epilogue...
pop_stack r3, 128

lwz r12, 0(r3) # original instruction
Reply
#2
Nice work on this new version.

USA, Japan and Korea versions are freezing on Dolphin
Reply
#3
(01-02-2021, 03:39 PM)Vega Wrote: Nice work on this new version.

Japan and Korea versions are freezing on Dolphin

I'll take a look at it, i guess it's the pointer for the next framebuffer
Reply
#4
Made an update to my reply. NTSC-U also not working.
Reply
#5
(01-02-2021, 03:59 PM)Vega Wrote: Made an update to my reply. NTSC-U also not working.

yep, i found the issue, the first 2 instructions and the pointer to the next framebuffer aren't region free
Reply
#6
I managed to Fix NTSC-K and NTSC-J, why NTSC-U doesn't work is to me a mystery.
EDIT: Welp, that was me being an idiot, i didn't have the 04 write set correctly
Reply
#7
All ports are working. Nice to have the Draw Code updated to where there are no more framebuffer issues.
Reply
#8
Due to my curiosity, I stepped by stepped your code to see how you were able to get this Draw Code to work w/o flickers on the console. I ended up with a better understanding of what you did, but was still left with some questions. I ended up removing some items and was still able to draw perfectly fine.

Source (PAL only):
Code:
#Address (PAL) = 80009680

#Push Stack
stwu sp, -0x80 (sp)
stmw r3, 0x8 (sp)

#Set r31 for Direct Print Calling
lis r31, 0x8002

#Get current XFB (alternates between two FB's)
lwz r3, -0x6060 (r13)

#Get width and height for XFB
lis r5, 0x802A #Memory constant
lwz r5, 0x73FC (r5) #Load XFB Width Height Pointer
lhz r4, 0x4 (r5)
lhz r5, 0x8 (r5)

#Change XFB for Direct Print (r3 = FB, r4 = Width, r5 = Height)
ori r12, r31, 0x1E30
mtctr r12
bctrl

#Setup Args for Direct Print
li r3, 0
li r4, 0xDC
li r5, 1

bl our_text
.string "Hey"
our_text:
mflr r6

#Print to Screen
ori r12, r31, 0x1E90
mtctr r12
bctrl

#Store Cache
ori r12, r31, 0x1E70
mtctr r12
bctrl

#Pop Stack
lmw r3, 0x8 (sp)
addi sp, sp, 0x80

#Default Instruction
lwz r12, 0 (r3)

Some questions I have:
I notice you use a memory constant then load a pointer to get the width and height for the buffer, is this the only way to do it? Seems 'hacky'. Is there not a VI based function call to get those halfword values?

What was the purpose for calling the DirectPrintIsActive function? I removed it and didn't notice any changes.

What's the reasoning for checking if r0 equals 0 after the calling DirectPrintChangeXFB? Function calls only put return parameters in r3 or r3 & r4. And with multiple testing, I never once had a single time where r0 was 0 after calling DirectPrintChangeXFB.

Thank you in advance for any feedback.
Reply
#9
Functions can also return in f1
Super Mario Eclipse, what Super Mario Sunshine could've been.
Reply
#10
(01-16-2021, 02:46 AM)Vega Wrote: Due to my curiosity, I stepped by stepped your code to see how you were able to get this Draw Code to work w/o flickers on the console. I ended up with a better understanding of what you did, but was still left with some questions. I ended up removing some items and was still able to draw perfectly fine.

Source (PAL only):
Code:
#Address (PAL) = 80009680

#Push Stack
stwu sp, -0x80 (sp)
stmw r3, 0x8 (sp)

#Set r31 for Direct Print Calling
lis r31, 0x8002

#Get current XFB (alternates between two FB's)
lwz r3, -0x6060 (r13)

#Get width and height for XFB
lis r5, 0x802A #Memory constant
lwz r5, 0x73FC (r5) #Load XFB Width Height Pointer
lhz r4, 0x4 (r5)
lhz r5, 0x8 (r5)

#Change XFB for Direct Print (r3 = FB, r4 = Width, r5 = Height)
ori r12, r31, 0x1E30
mtctr r12
bctrl

#Setup Args for Direct Print
li r3, 0
li r4, 0xDC
li r5, 1

bl our_text
.string "Hey"
our_text:
mflr r6

#Print to Screen
ori r12, r31, 0x1E90
mtctr r12
bctrl

#Store Cache
ori r12, r31, 0x1E70
mtctr r12
bctrl

#Pop Stack
lmw r3, 0x8 (sp)
addi sp, sp, 0x80

#Default Instruction
lwz r12, 0 (r3)

Some questions I have:
I notice you use a memory constant then load a pointer to get the width and height for the buffer, is this the only way to do it? Seems 'hacky'. Is there not a VI based function call to get those halfword values?

What was the purpose for calling the DirectPrintIsActive function? I removed it and didn't notice any changes.

What's the reasoning for checking if r0 equals 0 after the calling DirectPrintChangeXFB? Function calls only put return parameters in r3 or r3 & r4. And with multiple testing, I never once had a single time where r0 was 0 after calling DirectPrintChangeXFB.

Thank you in advance for any feedback.

I did it this way because that's how nw4r_db_Exception_Printf_ does it and basically copied everything from there, i was probably just careless and didn't optimize the source any further until i remade it in C++.

To answer your question: there is no point for these checks and i believe there's no function that returns these halfwords(even if they did, it wouldn't optimize the code).

also i saw you replaced the bl to VIGetNexFrameBuffer with lwz r3, -0x6060(r13),  this instruction isn't region free(NTSC-K is slightly different: lwz r3, -0x6040) and because i was thinking in C++ and converting that back to assembly, i just used a bl to VIGetNextFrameBuffer.
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)