Screenshot [Star]
#1
Screenshot [Star]

This code will allow you to take a screenshot, anytime, at the press of a button. The steps below illustrate the process of converting the file to a viewable .png file:

Wii:
1) Press the button activator to take a screenshot.
2) Navigate to /screenshots directory on your NAND (I recommend using the homebrew application "WiiXplorer" for this).
3) Find the screenshot file (The file naming convention is YYMMDDHHMMSS according to the date and time the screenshot was taken at).
4) Copy the file onto your SD Card / USB.

Computer:
5) Insert the SD Card / USB into your computer.
6) Move the file into the same directory as the "Screenshot Converter" program (Which can be downloaded here: https://mkwii.com/downloads/ScreenshotCodeConverter.rar).
7) Run the program.

Following this, a viewable .png file of the screenshot will be created in the same directory as the executable.

(NTSC-U)
04009644 818C0020
2834XXXX YYYYZZZZ
C2009644 00000046
818C0020 9421FF30
BC410008 48000015
2F736372 65656E73
686F7473 00000000
7C6802A6 38800000
38A00003 38C00003
38E00003 3FE08016
63EC9DD4 7D8903A6
4E800421 2C03FF97
41A2000C 2C030000
408201D0 3D80801A
618CACBC 7D8903A6
4E800421 38A10080
3D80801A 618CAF08
7D8903A6 4E800421
386100A8 4800002D
2F736372 65656E73
686F7473 2F253032
64253032 64253032
64253032 64253032
64253032 64000000
7C8802A6 80A10094
38C00064 7CE533D6
7CC731D6 7CA62850
80C10090 38C60001
80E1008C 81010088
81210084 81410080
4CC63182 3D808001
618C0ECC 7D8903A6
4E800421 2C030019
40820130 386100A8
38800000 38A00003
38C00003 38E00003
63ECABD4 7D8903A6
4E800421 2C030000
40820108 386100A8
38800002 63ECADBC
7D8903A6 4E800421
2C030000 418000EC
7C7E1B78 38600008
38800020 80ADA358
7CBD2B78 80A50024
7CBC2B78 3D808022
618C9490 7D8903A6
4E800421 2C030000
418200A8 7C7B1B78
3C805354 60844102
90830000 809D0048
80840000 7C9A2378
80840000 90830004
3F20CD80 807900C0
60630020 907900C0
7FC3F378 7F64DB78
38A00008 63ECB220
7D8903A6 4E800421
2C030008 40820030
7FC3F378 809A0004
A0BA0000 A0DA0002
38A5000F 54A50436
7CA531D6 54A5083C
63ECB220 7D8903A6
4E800421 807900C0
546306F2 907900C0
7F63DB78 7F84E378
3D808022 618C9800
7D8903A6 4E800421
7FC3F378 63ECB2E4
7D8903A6 4E800421
B8410008 382100D0
60000000 00000000
E0000000 80008000

(PAL)
04009684 818C0020
2834XXXX YYYYZZZZ
C2009684 00000046
818C0020 9421FF30
BC410008 48000015
2F736372 65656E73
686F7473 00000000
7C6802A6 38800000
38A00003 38C00003
38E00003 3FE08016
63EC9E74 7D8903A6
4E800421 2C03FF97
41A2000C 2C030000
408201D0 3D80801A
618CAD5C 7D8903A6
4E800421 38A10080
3D80801A 618CAFA8
7D8903A6 4E800421
386100A8 4800002D
2F736372 65656E73
686F7473 2F253032
64253032 64253032
64253032 64253032
64253032 64000000
7C8802A6 80A10094
38C00064 7CE533D6
7CC731D6 7CA62850
80C10090 38C60001
80E1008C 81010088
81210084 81410080
4CC63182 3D808001
618C1A2C 7D8903A6
4E800421 2C030019
40820130 386100A8
38800000 38A00003
38C00003 38E00003
63ECAC74 7D8903A6
4E800421 2C030000
40820108 386100A8
38800002 63ECAE5C
7D8903A6 4E800421
2C030000 418000EC
7C7E1B78 38600008
38800020 80ADA360
7CBD2B78 80A50024
7CBC2B78 3D808022
618C9814 7D8903A6
4E800421 2C030000
418200A8 7C7B1B78
3C805354 60844102
90830000 809D0048
80840000 7C9A2378
80840000 90830004
3F20CD80 807900C0
60630020 907900C0
7FC3F378 7F64DB78
38A00008 63ECB2C0
7D8903A6 4E800421
2C030008 40820030
7FC3F378 809A0004
A0BA0000 A0DA0002
38A5000F 54A50436
7CA531D6 54A5083C
63ECB2C0 7D8903A6
4E800421 807900C0
546306F2 907900C0
7F63DB78 7F84E378
3D808022 618C9B84
7D8903A6 4E800421
7FC3F378 63ECB384
7D8903A6 4E800421
B8410008 382100D0
60000000 00000000
E0000000 80008000

(NTSC-J)
040095E0 818C0020
2834XXXX YYYYZZZZ
C20095E0 00000046
818C0020 9421FF30
BC410008 48000015
2F736372 65656E73
686F7473 00000000
7C6802A6 38800000
38A00003 38C00003
38E00003 3FE08016
63EC9D94 7D8903A6
4E800421 2C03FF97
41A2000C 2C030000
408201D0 3D80801A
618CAC7C 7D8903A6
4E800421 38A10080
3D80801A 618CAEC8
7D8903A6 4E800421
386100A8 4800002D
2F736372 65656E73
686F7473 2F253032
64253032 64253032
64253032 64253032
64253032 64000000
7C8802A6 80A10094
38C00064 7CE533D6
7CC731D6 7CA62850
80C10090 38C60001
80E1008C 81010088
81210084 81410080
4CC63182 3D808001
618C1950 7D8903A6
4E800421 2C030019
40820130 386100A8
38800000 38A00003
38C00003 38E00003
63ECAB94 7D8903A6
4E800421 2C030000
40820108 386100A8
38800002 63ECAD7C
7D8903A6 4E800421
2C030000 418000EC
7C7E1B78 38600008
38800020 80ADA360
7CBD2B78 80A50024
7CBC2B78 3D808022
618C9734 7D8903A6
4E800421 2C030000
418200A8 7C7B1B78
3C805354 60844102
90830000 809D0048
80840000 7C9A2378
80840000 90830004
3F20CD80 807900C0
60630020 907900C0
7FC3F378 7F64DB78
38A00008 63ECB1E0
7D8903A6 4E800421
2C030008 40820030
7FC3F378 809A0004
A0BA0000 A0DA0002
38A5000F 54A50436
7CA531D6 54A5083C
63ECB1E0 7D8903A6
4E800421 807900C0
546306F2 907900C0
7F63DB78 7F84E378
3D808022 618C9AA4
7D8903A6 4E800421
7FC3F378 63ECB2A4
7D8903A6 4E800421
B8410008 382100D0
60000000 00000000
E0000000 80008000

(NTSC-K)
0400978C 818C0020
2833XXXX YYYYZZZZ
C200978C 00000046
818C0020 9421FF30
BC410008 48000015
2F736372 65656E73
686F7473 00000000
7C6802A6 38800000
38A00003 38C00003
38E00003 3FE08016
63EC9F10 7D8903A6
4E800421 2C03FF97
41A2000C 2C030000
408201D0 3D80801A
618CB0B8 7D8903A6
4E800421 38A10080
3D80801A 618CB304
7D8903A6 4E800421
386100A8 4800002D
2F736372 65656E73
686F7473 2F253032
64253032 64253032
64253032 64253032
64253032 64000000
7C8802A6 80A10094
38C00064 7CE533D6
7CC731D6 7CA62850
80C10090 38C60001
80E1008C 81010088
81210084 81410080
4CC63182 3D808001
618C1A94 7D8903A6
4E800421 2C030019
40820130 386100A8
38800000 38A00003
38C00003 38E00003
63ECAD10 7D8903A6
4E800421 2C030000
40820108 386100A8
38800002 63ECAEF8
7D8903A6 4E800421
2C030000 418000EC
7C7E1B78 38600008
38800020 80ADA380
7CBD2B78 80A50024
7CBC2B78 3D808022
618C9B88 7D8903A6
4E800421 2C030000
418200A8 7C7B1B78
3C805354 60844102
90830000 809D0048
80840000 7C9A2378
80840000 90830004
3F20CD80 807900C0
60630020 907900C0
7FC3F378 7F64DB78
38A00008 63ECB35C
7D8903A6 4E800421
2C030008 40820030
7FC3F378 809A0004
A0BA0000 A0DA0002
38A5000F 54A50436
7CA531D6 54A5083C
63ECB35C 7D8903A6
4E800421 807900C0
546306F2 907900C0
7F63DB78 7F84E378
3D808022 618C9EF8
7D8903A6 4E800421
7FC3F378 63ECB420
7D8903A6 4E800421
B8410008 382100D0
60000000 00000000
E0000000 80008000

Code:
#============================================================#
#                          Source                            #
#------------------------------------------------------------#
# Draw Debug Bar Call Address Ports:                         #
# RMCE - 0x80009644                                          #
# RMCP - 0x80009684                                          #
# RMCJ - 0x800095E0                                          #
# RMCK - 0x8000978C                                          #
#============================================================#

#============================================================#
#                    Assembler Directives                    #
#============================================================#

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

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

.macro absolute_bl register, address
      lis \register, \address@h
      ori \register, \register, \address@l
      mtctr \register
      bctrl
.endm

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

.set region, ''

#                                          S T A
.set SCREENSHOT_FILE_MAGIC_AND_VERSION, 0x53544102

.if     (region == 'E' || region == 'e') # RMCE
        .set sprintf, 0x80010ECC
        .set ISFS_CreateDir, 0x80169DD4
        .set ISFS_CreateFile, 0x8016ABD4
        .set ISFS_Open, 0x8016ADBC
        .set ISFS_Write, 0x8016B220
        .set ISFS_Close, 0x8016B2E4
        .set OSGetTime, 0x801AACBC
        .set OSTicksToCalendarTime, 0x801AAF08
        .set EGG_Heap_alloc, 0x80229490
        .set EGG_Heap_free, 0x80229800
.elseif (region == 'P' || region == 'p') # RMCP
        .set sprintf, 0x80011A2C
        .set ISFS_CreateDir, 0x80169E74
        .set ISFS_CreateFile, 0x8016AC74
        .set ISFS_Open, 0x8016AE5C
        .set ISFS_Write, 0x8016B2C0
        .set ISFS_Close, 0x8016B384
        .set OSGetTime, 0x801AAD5C
        .set OSTicksToCalendarTime, 0x801AAFA8
        .set EGG_Heap_alloc, 0x80229814
        .set EGG_Heap_free, 0x80229B84
.elseif (region == 'J' || region == 'j') # RMCJ
        .set sprintf, 0x80011950
        .set ISFS_CreateDir, 0x80169D94
        .set ISFS_CreateFile, 0x8016AB94
        .set ISFS_Open, 0x8016AD7C
        .set ISFS_Write, 0x8016B1E0
        .set ISFS_Close, 0x8016B2A4
        .set OSGetTime, 0x801AAC7C
        .set OSTicksToCalendarTime, 0x801AAEC8
        .set EGG_Heap_alloc, 0x80229734
        .set EGG_Heap_free, 0x80229AA4
.elseif (region == 'K' || region == 'k') # RMCK
        .set sprintf, 0x80011A94
        .set ISFS_CreateDir, 0x80169F10
        .set ISFS_CreateFile, 0x8016AD10
        .set ISFS_Open, 0x8016AEF8
        .set ISFS_Write, 0x8016B35C
        .set ISFS_Close, 0x8016B420
        .set OSGetTime, 0x801AB0B8
        .set OSTicksToCalendarTime, 0x801AB304
        .set EGG_Heap_alloc, 0x80229B88
        .set EGG_Heap_free, 0x80229EF8
.else # Invalid Region
        .abort
.endif

.set NULL, 0x0

.set STACK_FRAME_SIZE, 0xD0
.set STACK_FRAME_PRESERVED_REGISTERS_OFFSET, 0x0
.set STACK_FRAME_OSTICKSTOCALENDARTIME_STRUCT_OFFSET, 0x80
.set STACK_FRAME_SCREENSHOT_FILEPATH_BUFFER_OFFSET, 0xA8

.set OSTICKSTOCALENDARTIME_STRUCT_SECONDS_OFFSET, 0x0
.set OSTICKSTOCALENDARTIME_STRUCT_MINUTES_OFFSET, 0x4
.set OSTICKSTOCALENDARTIME_STRUCT_HOURS_OFFSET, 0x8
.set OSTICKSTOCALENDARTIME_STRUCT_DAY_OFFSET, 0xC
.set OSTICKSTOCALENDARTIME_STRUCT_MONTH_OFFSET, 0x10
.set OSTICKSTOCALENDARTIME_STRUCT_YEAR_OFFSET, 0x14

.set ISFS_EOK, 0
.set ISFS_EEXIST, -105

.set SCREENSHOT_FILE_PATHNAMELEN, 0x19

.set ISFS_OPEN_READ, 0x1
.set ISFS_OPEN_WRITE, 0x2
.set ISFS_OPEN_RW, (ISFS_OPEN_READ | ISFS_OPEN_WRITE)

.set SLOT_LED_ON_BITS, 0x20

.set HOLLYWOOD_REGISTERS_BASE, 0xCD800000
.set HOLLYWOOD_GPIOB_OUT_OFFSET, 0xC0

.set SCREENSHOT_FILE_MAGIC_SIZE, 0x3
.set SCREENSHOT_FILE_VERSION_SIZE, 0x1
.set XFB_WIDTH_SIZE, 0x2
.set XFB_HEIGHT_SIZE, 0x2
.set SCREENSHOT_FILE_OFFSET_TO_XFB, 0x8

#============================================================#
#                            Start                           #
#============================================================#

.globl screenshot
screenshot:

# Original Instruction
lwz r12, 0x20(r12)

# Function Prologue...
push_stack STACK_FRAME_SIZE, r2

# ISFS_CreateDir arguments
bl branch_link_write_screenshot_directory
.string "/screenshots\0\0\0"
branch_link_write_screenshot_directory:
mflr r3 # Pointer to the filepath
li r4, 0 # attributes
li r5, 3 # owner_perm
li r6, 3 # group_perm
li r7, 3 # other_perm

lis r31, 0x8016

ISFS_absolute_bl r12, ISFS_CreateDir
cmpwi r3, ISFS_EEXIST
beq+ branch_screenshot_directory_already_exists
cmpwi r3, ISFS_EOK
bne- branch_isfs_createdir_failed

branch_screenshot_directory_already_exists:
# OSTicksToCalendarTime arguments
absolute_bl r12, OSGetTime
addi r5, r1, STACK_FRAME_OSTICKSTOCALENDARTIME_STRUCT_OFFSET

absolute_bl r12, OSTicksToCalendarTime

# sprintf arguments
addi r3, r1, STACK_FRAME_SCREENSHOT_FILEPATH_BUFFER_OFFSET

bl branch_link_write_screenshot_filepath
#                       YY  MM  DD  HH  MM  SS
.string "/screenshots/%02d%02d%02d%02d%02d%02d\0\0"
branch_link_write_screenshot_filepath:
mflr r4 # Pointer to format String

lwz r5, STACK_FRAME_OSTICKSTOCALENDARTIME_STRUCT_OFFSET + OSTICKSTOCALENDARTIME_STRUCT_YEAR_OFFSET(r1)

# Derive the last two digits from the year
li r6, 100
divw r7, r5, r6
mullw r6, r7, r6
subf 5, r6, r5

lwz r6, STACK_FRAME_OSTICKSTOCALENDARTIME_STRUCT_OFFSET + OSTICKSTOCALENDARTIME_STRUCT_MONTH_OFFSET(r1)
addi r6, r6, 1
lwz r7, STACK_FRAME_OSTICKSTOCALENDARTIME_STRUCT_OFFSET + OSTICKSTOCALENDARTIME_STRUCT_DAY_OFFSET(r1)
lwz r8, STACK_FRAME_OSTICKSTOCALENDARTIME_STRUCT_OFFSET + OSTICKSTOCALENDARTIME_STRUCT_HOURS_OFFSET(r1)
lwz r9, STACK_FRAME_OSTICKSTOCALENDARTIME_STRUCT_OFFSET + OSTICKSTOCALENDARTIME_STRUCT_MINUTES_OFFSET(r1)
lwz r10, STACK_FRAME_OSTICKSTOCALENDARTIME_STRUCT_OFFSET + OSTICKSTOCALENDARTIME_STRUCT_SECONDS_OFFSET(r1)

crclr 4*cr1+eq
absolute_bl r12, sprintf
cmpwi r3, SCREENSHOT_FILE_PATHNAMELEN
bne- branch_sprintf_failed

# ISFS_CreateFile arguments
addi r3, r1, STACK_FRAME_SCREENSHOT_FILEPATH_BUFFER_OFFSET # Pointer to the filepath
li r4, 0 # attributes
li r5, 3 # owner_perm
li r6, 3 # group_perm
li r7, 3 # other_perm

ISFS_absolute_bl r12, ISFS_CreateFile
cmpwi r3, ISFS_EOK
bne- branch_isfs_createfile_failed

# ISFS_Open arguments
addi r3, r1, STACK_FRAME_SCREENSHOT_FILEPATH_BUFFER_OFFSET # Pointer to the filepath
li r4, ISFS_OPEN_WRITE # Mode

ISFS_absolute_bl r12, ISFS_Open
cmpwi r3, 0 # if (fd < 0)
blt- branch_isfs_open_failed
mr r30, r3 # Preserve the fd in r30

# EGG::Heap::alloc arguments
li r3, SCREENSHOT_FILE_OFFSET_TO_XFB # Size of the memory block
li r4, 32 # Alignment of the memory block

# Get the pointer to the System Heap (RKSystem->mpSystemHeap)
.if     (region == 'E' || region == 'e') # RMCE
        lwz r5, -0x5CA8(r13)
.elseif (region == 'P' || region == 'p') # RMCP
        lwz r5, -0x5CA0(r13)
.elseif (region == 'J' || region == 'j') # RMCJ
        lwz r5, -0x5CA0(r13)
.elseif (region == 'K' || region == 'k') # RMCK
        lwz r5, -0x5C80(r13)
.endif

mr r29, r5 # Preserve the pointer to RKSystem in r29

lwz r5, 0x24(r5) # Pointer to the heap to allocate the memory block in
mr r28, r5 # Preserve the pointer to the System Heap in r28

absolute_bl r12, EGG_Heap_alloc
cmpwi r3, NULL
beq- branch_isfs_write_egg_heap_alloc_failed

mr r27, r3 # Preserve the pointer to the allocated memory block in r27

# Write the magic and version in the allocated memory block
lis r4, SCREENSHOT_FILE_MAGIC_AND_VERSION@h
ori r4, r4, SCREENSHOT_FILE_MAGIC_AND_VERSION@l
stw r4, 0(r3)

# Write the Width and Height of Xfb1 in the allocated memory block (RKSystem->mpXfbManager->mpHeadXfb->mWidth, RKSystem->mpXfbManager->mpHeadXfb->mHeight)
lwz r4, 0x48(r29)
lwz r4, 0(r4)

mr r26, r4 # Preserve the pointer to the HeadXfb in r26

lwz r4, 0(r4)
stw r4, 4(r3)

lis r25, HOLLYWOOD_REGISTERS_BASE@h

# Turn on the Wii's Disc Slot LED
lwz r3, HOLLYWOOD_GPIOB_OUT_OFFSET(r25)
ori r3, r3, SLOT_LED_ON_BITS
stw r3, HOLLYWOOD_GPIOB_OUT_OFFSET(r25)

# ISFS_Write arguments
mr r3, r30 # fd
mr r4, r27 # Pointer to the buffer to write from
li r5, SCREENSHOT_FILE_OFFSET_TO_XFB # Number of bytes to write

ISFS_absolute_bl r12, ISFS_Write
cmpwi r3, SCREENSHOT_FILE_OFFSET_TO_XFB
bne- branch_isfs_write_failed

# ISFS_Write arguments
mr r3, r30 # fd

# Get the pointer to the data of Xfb1 (RKSystem->mpXfbManager->mpHeadXfb->mpBuffer)
lwz r4, 4(r26)

# Calculate the size of Xfb1
lhz r5, 0(r26) # Width of the frame
lhz r6, 2(r26) # Height of the frame

addi r5, r5, 0xF
rlwinm r5, r5, 0, 16, 27
mullw r5, r5, r6
slwi r5, r5, 1

ISFS_absolute_bl r12, ISFS_Write

branch_isfs_write_failed:
# Turn off the Wii's Disc Slot LED
lwz r3, HOLLYWOOD_GPIOB_OUT_OFFSET(r25)
rlwinm r3, r3, 0, 27, 25
stw r3, HOLLYWOOD_GPIOB_OUT_OFFSET(r25)

# EGG::Heap::free arguments
mr r3, r27 # Pointer to the block of memory to free
mr r4, r28 # Pointer to the heap where the block of memory to free is located

absolute_bl r12, EGG_Heap_free

branch_isfs_write_egg_heap_alloc_failed:
# ISFS_Close argument
mr r3, r30 # fd

ISFS_absolute_bl r12, ISFS_Close

branch_isfs_createdir_failed:
branch_sprintf_failed:
branch_isfs_createfile_failed:
branch_isfs_open_failed:
# Function Epilogue...
pop_stack r2, STACK_FRAME_SIZE

Notes:
- Extreme overuse of this code may cause wear to the Wii's NAND memory. As per the NAND Manual:

"Wear on Wii Console NAND Memory

Write operations will wear out Wii console NAND memory, so please avoid frequent writing. (Use as virtual memory is prohibited.)
Please limit its average frequency to less than once per minute."

- Screenshot files are not automatically deleted, you are responsible for maintaining them.
- The Wii's Disc Slot LED will turn on when the code is attempting to write the file.

Code Creator: Star
Code Credits: Riidefi (MKWDecompilation)
[Image: GiVNKqR.png]
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)