< >
Hello, guest! Please log in or register.

The PokéCommunity

Go Back     The PokéCommunity Forums > ROM Hacking > Tools, Tutorials & Resources Tutorial Completely hacking Emerald’s boot screen

Notices

Tools, Tutorials & Resources Various tools to help you develop your hacks can be found here.
New threads in this forum are to be approved by a moderator before they are displayed.

Reply Post Reply
 
Thread Tools
  #1    
Old February 14th, 2016 (11:25 PM).
SSL SSL is offline
Banned
 
Join Date: Feb 2016
Posts: 1
Hello, today I will be giving in-depth instructions on how to completely hack Pokémon Emerald’s boot screen, i.e. the black screen with white text that appears when you very first boot the ROM.

What we’ll be doing

  1. Repointing the tileset and tilemap used for the boot screen
  2. Adjusting the values loaded into the I/O registers to allow for super-large tilesets
  3. Changing the VRAM offset used to calculate the starting offset for the tilemap
  4. Changing the palette :)

The image you need to make must be 4-bit (16 colours), and must be 240 pixels wide and 160 pixels tall. If you are using grit or something you may pad the image to be 256 by 256 and it should work fine.

Academic requirements

  • Capability to directly edit the ROM’s contents in a hex editor
  • Knowledge of how to repoint data
  • The ability to insert LZSS-compressed tile sets and tile maps (without the help of this tutorial)

It would also be beneficial if you have a basic understanding of assembly code and know how to navigate a disassembly in IDA Pro. Throughout the course of this guide I will be using IDA Pro 6.8, and Touched’s Emerald IDB.

I: Locating the right routines


Our traversion leading to the boot screen code is somewhat short, and thankfully I have already found which functions we should continue through so you don’t have to trial-and-error it like I did. Since the boot screen is loaded at the very start of the game, it makes sense to start with the engine’s main loop, at ROM:080003A4:

i.imgur.com/ROyGrt1.png

Some checks are performed up until this point that see if we’re just booting the game, from what I understand. Since we are in theory doing so, all of these functions are branched to, using BL:

i.imgur.com/gpmDWvE.png

The function we want is set_bootscreen_callback. All that does (as I'm sure you guessed by the name) is set a callback for the main loop to execute the function that shows the boot screen when it’s ready. Don’t worry too much about callbacks if you don’t yet know what they are (yes, it’s the same principle in JavaScript). I’ll skip over that code to the function set in the callback, so we end up here:

i.imgur.com/FxHwRGh.png

This function does some magic stuff after our golden code we don’t really care about, so we want to pay attention to that first function, copyright_do_graphics.

II: Finding our first edit


This handles the loading of the graphics for our boot screen image. Here's the ASM for that function that gets called:

Code:
ROM:0816CCC8                 @ =============== S U B R O U T I N E =======================================
ROM:0816CCC8
ROM:0816CCC8
ROM:0816CCC8                 copyright_do_graphics:                  @ CODE XREF: c2_copyright_1+2
ROM:0816CCC8                                                         @ c2_080EC864+2
ROM:0816CCC8
ROM:0816CCC8                 var_20  = -0x20
ROM:0816CCC8                 var_1C  = -0x1C
ROM:0816CCC8                 var_18  = -0x18
ROM:0816CCC8                 var_14  = -0x14
ROM:0816CCC8
ROM:0816CCC8 000 70 B5               PUSH    {R4-R6,LR}
ROM:0816CCCA 010 84 B0               SUB     SP, SP, #0x10
ROM:0816CCCC 020 06 48               LDR     R0, =super
ROM:0816CCCE 020 87 21 C9 00         MOVS    R1, #0x438
ROM:0816CCD2 020 45 18               ADDS    R5, R0, R1
ROM:0816CCD4 020 2C 78               LDRB    R4, [R5]
ROM:0816CCD6 020 8C 2C               CMP     R4, #0x8C @ 'î'
ROM:0816CCD8 020 00 D1               BNE     loc_0816CCDC
ROM:0816CCD8
ROM:0816CCDA 020 91 E0               B       loc_0816CE00
ROM:0816CCDA
ROM:0816CCDC                 @ ---------------------------------------------------------------------------
ROM:0816CCDC
ROM:0816CCDC                 loc_0816CCDC:                           @ CODE XREF: copyright_do_graphics+10
ROM:0816CCDC 020 8C 2C               CMP     R4, #0x8C @ 'î'
ROM:0816CCDE 020 05 DC               BGT     loc_0816CCEC
ROM:0816CCDE
ROM:0816CCE0 020 00 2C               CMP     R4, #0
ROM:0816CCE2 020 07 D0               BEQ     loc_0816CCF4
ROM:0816CCE2
ROM:0816CCE4 020 6A E0               B       loc_0816CDBC
ROM:0816CCE4
ROM:0816CCE4                 @ ---------------------------------------------------------------------------
ROM:0816CCE6 020 00 00               .align 4
ROM:0816CCE8 020 C0 22 00 03 off_0816CCE8:.long super                @ DATA XREF: copyright_do_graphics+4
ROM:0816CCEC                 @ ---------------------------------------------------------------------------
ROM:0816CCEC
ROM:0816CCEC                 loc_0816CCEC:                           @ CODE XREF: copyright_do_graphics+16
ROM:0816CCEC 020 8D 2C               CMP     R4, #0x8D @ 'ì'
ROM:0816CCEE 020 00 D1               BNE     loc_0816CCF2
ROM:0816CCEE
ROM:0816CCF0 020 9C E0               B       loc_0816CE2C
ROM:0816CCF0
ROM:0816CCF2                 @ ---------------------------------------------------------------------------
ROM:0816CCF2
ROM:0816CCF2                 loc_0816CCF2:                           @ CODE XREF: copyright_do_graphics+26
ROM:0816CCF2 020 63 E0               B       loc_0816CDBC
ROM:0816CCF2
ROM:0816CCF4                 @ ---------------------------------------------------------------------------
ROM:0816CCF4
ROM:0816CCF4                 loc_0816CCF4:                           @ CODE XREF: copyright_do_graphics+1A
ROM:0816CCF4 020 00 20               MOVS    R0, #0                  @ value
ROM:0816CCF6 020 93 F6 FB FC         BL      vblank_handler_set
ROM:0816CCF6 020
ROM:0816CCFA 020 50 20               MOVS    R0, #0x50 @ 'P'         @ ioreg
ROM:0816CCFC 020 00 21               MOVS    R1, #0                  @ value
ROM:0816CCFE 020 94 F6 D9 F9         BL      lcd_io_set
ROM:0816CCFE 020
ROM:0816CD02 020 52 20               MOVS    R0, #0x52 @ 'R'         @ ioreg
ROM:0816CD04 020 00 21               MOVS    R1, #0                  @ value
ROM:0816CD06 020 94 F6 D5 F9         BL      lcd_io_set
ROM:0816CD06 020
ROM:0816CD0A 020 54 20               MOVS    R0, #0x54 @ 'T'         @ ioreg
ROM:0816CD0C 020 00 21               MOVS    R1, #0                  @ value
ROM:0816CD0E 020 94 F6 D1 F9         BL      lcd_io_set
ROM:0816CD0E 020
ROM:0816CD12 020 A0 21 C9 04         MOVS    R1, #0x5000000
ROM:0816CD16 020 30 4A               LDR     R2, =0x7FFF
ROM:0816CD18 020 10 1C               MOVS    R0, R2
ROM:0816CD1A 020 08 80               STRH    R0, [R1]
ROM:0816CD1C 020 00 20               MOVS    R0, #0                  @ ioreg
ROM:0816CD1E 020 00 21               MOVS    R1, #0                  @ value
ROM:0816CD20 020 94 F6 C8 F9         BL      lcd_io_set
ROM:0816CD20 020
ROM:0816CD24 020 10 20               MOVS    R0, #0x10               @ ioreg
ROM:0816CD26 020 00 21               MOVS    R1, #0                  @ value
ROM:0816CD28 020 94 F6 C4 F9         BL      lcd_io_set
ROM:0816CD28 020
ROM:0816CD2C 020 12 20               MOVS    R0, #0x12               @ ioreg
ROM:0816CD2E 020 00 21               MOVS    R1, #0                  @ value
ROM:0816CD30 020 94 F6 C0 F9         BL      lcd_io_set
ROM:0816CD30 020
ROM:0816CD34 020 01 94               STR     R4, [SP,#0x20+var_1C]
ROM:0816CD36 020 C0 21 C9 04         MOVS    R1, #0x6000000
ROM:0816CD3A 020 28 4A               LDR     R2, =0x5006000
ROM:0816CD3C 020 01 A8               ADD     R0, SP, #0x20+var_1C
ROM:0816CD3E 020 7A F1 A1 F9         BL      CpuSet
ROM:0816CD3E 020
ROM:0816CD42 020 02 94               STR     R4, [SP,#0x20+var_18]
ROM:0816CD44 020 02 A8               ADD     R0, SP, #0x20+var_18
ROM:0816CD46 020 E0 21 C9 04         MOVS    R1, #0x7000000
ROM:0816CD4A 020 25 4A               LDR     R2, =(pal_bg+0x100)
ROM:0816CD4C 020 7A F1 9A F9         BL      CpuSet
ROM:0816CD4C 020
ROM:0816CD50 020 03 A8               ADD     R0, SP, #0x20+var_14
ROM:0816CD52 020 04 80               STRH    R4, [R0]
ROM:0816CD54 020 23 49               LDR     R1, =0x5000002
ROM:0816CD56 020 24 4A               LDR     R2, =0x10001FF
ROM:0816CD58 020 7A F1 94 F9         BL      CpuSet
ROM:0816CD58 020
ROM:0816CD5C 020 34 F7 8A FE         BL      boot_fade_sequence
ROM:0816CD5C 020
ROM:0816CD60 020 E0 21 89 01         MOVS    R1, #0x3800
ROM:0816CD64 020 00 20               MOVS    R0, #0
ROM:0816CD66 020 00 22               MOVS    R2, #0
ROM:0816CD68 020 FF F7 82 FF         BL      bootscreen_load_into_vram
ROM:0816CD68 020
ROM:0816CD6C 020 4D F7 24 F9         BL      dma_task_delete_something
ROM:0816CD6C 020
ROM:0816CD70 020 3C F7 EE F8         BL      tasks_init
ROM:0816CD70 020
ROM:0816CD74 020 99 F6 FE FD         BL      obj_and_aux_reset_all
ROM:0816CD74 020
ROM:0816CD78 020 9B F6 C8 FC         BL      gpu_pal_allocator_reset
ROM:0816CD78 020
ROM:0816CD7C 020 01 20               MOVS    R0, #1
ROM:0816CD7E 020 40 42               NEGS    R0, R0
ROM:0816CD80 020 1A 49               LDR     R1, =0xFFFF
ROM:0816CD82 020 00 91               STR     R1, [SP,#0x20+var_20]
ROM:0816CD84 020 00 21               MOVS    R1, #0
ROM:0816CD86 020 10 22               MOVS    R2, #0x10
ROM:0816CD88 020 00 23               MOVS    R3, #0
ROM:0816CD8A 020 34 F7 A3 FE         BL      sub_080A1AD4
ROM:0816CD8A 020
ROM:0816CD8E 020 E0 21 C9 00         MOVS    R1, #0x700              @ value
ROM:0816CD92 020 08 20               MOVS    R0, #8                  @ ioreg
ROM:0816CD94 020 94 F6 8E F9         BL      lcd_io_set
ROM:0816CD94 020
ROM:0816CD98 020 01 20               MOVS    R0, #1
ROM:0816CD9A 020 94 F6 5F FA         BL      sub_0800125C
ROM:0816CD9A 020
ROM:0816CD9E 020 14 48               LDR     R0, =(sub_0816CBE8+1)   @ value
ROM:0816CDA0 020 93 F6 A6 FC         BL      vblank_handler_set
ROM:0816CDA0 020
ROM:0816CDA4 020 80 21 C9 04         MOVS    R1, #0x4000000
ROM:0816CDA8 020 A0 22 52 00         MOVS    R2, #0x140
ROM:0816CDAC 020 10 1C               MOVS    R0, R2
ROM:0816CDAE 020 08 80               STRH    R0, [R1]
ROM:0816CDB0 020 10 48               LDR     R0, =(sub_0816CCB8+1)
ROM:0816CDB2 020 93 F6 BB FC         BL      set_callback1_plus_x18
ROM:0816CDB2 020
ROM:0816CDB6 020 10 48               LDR     R0, =(word_03006210+0xA0)
ROM:0816CDB8 020 72 F1 6E F8         BL      sub_082DEE98
ROM:0816CDB8 020
ROM:0816CDBC
ROM:0816CDBC                 loc_0816CDBC:                           @ CODE XREF: copyright_do_graphics+1C
ROM:0816CDBC                                                         @ copyright_do_graphics:loc_0816CCF2
ROM:0816CDBC 020 34 F7 2E FE         BL      fade_and_return_progress_probably
ROM:0816CDBC 020
ROM:0816CDC0 020 0E 48               LDR     R0, =super
ROM:0816CDC2 020 87 21 C9 00         MOVS    R1, #0x438
ROM:0816CDC6 020 40 18               ADDS    R0, R0, R1
ROM:0816CDC8 020 01 78               LDRB    R1, [R0]
ROM:0816CDCA 020 01 31               ADDS    R1, #1
ROM:0816CDCC 020 01 70               STRB    R1, [R0]
ROM:0816CDCE 020 0A 48               LDR     R0, =(word_03006210+0xA0)
ROM:0816CDD0 020 71 F1 D8 FF         BL      sub_082DED84
ROM:0816CDD0 020
ROM:0816CDD4 020 64 E0               B       loc_0816CEA0
ROM:0816CDD4
ROM:0816CDD4                 @ ---------------------------------------------------------------------------
ROM:0816CDD6 020 00 00               .align 4
ROM:0816CDD8 020 FF 7F 00 00 dword_0816CDD8:.long 0x7FFF             @ DATA XREF: copyright_do_graphics+4E
ROM:0816CDDC 020 00 60 00 05 dword_0816CDDC:.long 0x5006000          @ DATA XREF: copyright_do_graphics+72
ROM:0816CDE0 020 00 01 00 05 off_0816CDE0:.long pal_bg+0x100         @ DATA XREF: copyright_do_graphics+82
ROM:0816CDE4 020 02 00 00 05 dword_0816CDE4:.long 0x5000002          @ DATA XREF: copyright_do_graphics+8C
ROM:0816CDE8 020 FF 01 00 01 dword_0816CDE8:.long 0x10001FF          @ DATA XREF: copyright_do_graphics+8E
ROM:0816CDEC 020 FF FF 00 00 dword_0816CDEC:.long 0xFFFF             @ DATA XREF: copyright_do_graphics+B8
ROM:0816CDF0                 @ uint32_t off_0816CDF0
ROM:0816CDF0 020 E9 CB 16 08 off_0816CDF0:.long sub_0816CBE8+1       @ DATA XREF: copyright_do_graphics+D6
ROM:0816CDF4 020 B9 CC 16 08 off_0816CDF4:.long sub_0816CCB8+1       @ DATA XREF: copyright_do_graphics+E8
ROM:0816CDF8 020 B0 62 00 03 off_0816CDF8:.long word_03006210+0xA0   @ DATA XREF: copyright_do_graphics+EE
ROM:0816CDF8 020                                                     @ copyright_do_graphics+106
ROM:0816CDFC 020 C0 22 00 03 off_0816CDFC:.long super                @ DATA XREF: copyright_do_graphics+F8
ROM:0816CE00                 @ ---------------------------------------------------------------------------
ROM:0816CE00
ROM:0816CE00                 loc_0816CE00:                           @ CODE XREF: copyright_do_graphics+12
ROM:0816CE00 020 09 4C               LDR     R4, =(word_03006210+0xA0)
ROM:0816CE02 020 20 1C               MOVS    R0, R4
ROM:0816CE04 020 71 F1 BE FF         BL      sub_082DED84
ROM:0816CE04 020
ROM:0816CE08 020 A0 78               LDRB    R0, [R4,#(word_03006210+0xA2 - 0x30062B0)]
ROM:0816CE0A 020 01 28               CMP     R0, #1
ROM:0816CE0C 020 48 D0               BEQ     loc_0816CEA0
ROM:0816CE0C
ROM:0816CE0E 020 01 20               MOVS    R0, #1
ROM:0816CE10 020 40 42               NEGS    R0, R0
ROM:0816CE12 020 00 21               MOVS    R1, #0
ROM:0816CE14 020 00 91               STR     R1, [SP,#0x20+var_20]
ROM:0816CE16 020 00 22               MOVS    R2, #0
ROM:0816CE18 020 10 23               MOVS    R3, #0x10
ROM:0816CE1A 020 34 F7 5B FE         BL      sub_080A1AD4
ROM:0816CE1A 020
ROM:0816CE1E 020 28 78               LDRB    R0, [R5]
ROM:0816CE20 020 01 30               ADDS    R0, #1
ROM:0816CE22 020 28 70               STRB    R0, [R5]
ROM:0816CE24 020 3C E0               B       loc_0816CEA0
ROM:0816CE24
ROM:0816CE24                 @ ---------------------------------------------------------------------------
ROM:0816CE26 020 00 00               .align 4
ROM:0816CE28 020 B0 62 00 03 off_0816CE28:.long word_03006210+0xA0   @ DATA XREF: copyright_do_graphics:loc_0816CE00
ROM:0816CE2C                 @ ---------------------------------------------------------------------------
ROM:0816CE2C
ROM:0816CE2C                 loc_0816CE2C:                           @ CODE XREF: copyright_do_graphics+28
ROM:0816CE2C 020 34 F7 F6 FD         BL      fade_and_return_progress_probably
ROM:0816CE2C 020
ROM:0816CE30 020 00 06               LSLS    R0, R0, #0x18
ROM:0816CE32 020 00 28               CMP     R0, #0
ROM:0816CE34 020 34 D1               BNE     loc_0816CEA0
ROM:0816CE34
ROM:0816CE36 020 0F 48               LDR     R0, =(sub_0816CF18+1)
ROM:0816CE38 020 00 21               MOVS    R1, #0
ROM:0816CE3A 020 3C F7 B9 F8         BL      task_add
ROM:0816CE3A 020
ROM:0816CE3E 020 0E 48               LDR     R0, =(sub_0816CC00+1)
ROM:0816CE40 020 93 F6 7E FB         BL      set_callback2
ROM:0816CE40 020
ROM:0816CE44 020 0D 4D               LDR     R5, =(word_03006210+0xA0)
ROM:0816CE46 020 A8 78               LDRB    R0, [R5,#(word_03006210+0xA2 - 0x30062B0)]
ROM:0816CE48 020 00 28               CMP     R0, #0
ROM:0816CE4A 020 1F D0               BEQ     loc_0816CE8C
ROM:0816CE4A
ROM:0816CE4C 020 A8 78               LDRB    R0, [R5,#(word_03006210+0xA2 - 0x30062B0)]
ROM:0816CE4E 020 02 28               CMP     R0, #2
ROM:0816CE50 020 21 D1               BNE     loc_0816CE96
ROM:0816CE50
ROM:0816CE52 020 0B 4E               LDR     R6, =dword_020000AC
ROM:0816CE54 020 34 68               LDR     R4, [R6]
ROM:0816CE56 020 0B 48               LDR     R0, =0x65366347
ROM:0816CE58 020 84 42               CMP     R4, R0
ROM:0816CE5A 020 07 D1               BNE     loc_0816CE6C
ROM:0816CE5A
ROM:0816CE5C 020 0A 48               LDR     R0, =dword_089AA144
ROM:0816CE5E 020 80 21 89 04         MOVS    R1, #0x2000000
ROM:0816CE62 020 A0 22 52 02         MOVS    R2, #0x14000
ROM:0816CE66 020 7A F1 0D F9         BL      CpuSet
ROM:0816CE66 020
ROM:0816CE6A 020 34 60               STR     R4, [R6]
ROM:0816CE6A
ROM:0816CE6C
ROM:0816CE6C                 loc_0816CE6C:                           @ CODE XREF: copyright_do_graphics+192
ROM:0816CE6C 020 28 1C               MOVS    R0, R5
ROM:0816CE6E 020 72 F1 09 F8         BL      sub_082DEE84
ROM:0816CE6E 020
ROM:0816CE72 020 10 E0               B       loc_0816CE96
ROM:0816CE72
ROM:0816CE72                 @ ---------------------------------------------------------------------------
ROM:0816CE74 020 19 CF 16 08 off_0816CE74:.long sub_0816CF18+1       @ DATA XREF: copyright_do_graphics+16E
ROM:0816CE78 020 01 CC 16 08 off_0816CE78:.long sub_0816CC00+1       @ DATA XREF: copyright_do_graphics+176
ROM:0816CE7C 020 B0 62 00 03 off_0816CE7C:.long word_03006210+0xA0   @ DATA XREF: copyright_do_graphics+17C
ROM:0816CE80 020 AC 00 00 02 off_0816CE80:.long dword_020000AC       @ DATA XREF: copyright_do_graphics+18A
ROM:0816CE84 020 47 63 36 65 dword_0816CE84:.long 0x65366347         @ DATA XREF: copyright_do_graphics+18E
ROM:0816CE88 020 44 A1 9A 08 off_0816CE88:.long dword_089AA144       @ DATA XREF: copyright_do_graphics+194
ROM:0816CE8C                 @ ---------------------------------------------------------------------------
ROM:0816CE8C
ROM:0816CE8C                 loc_0816CE8C:                           @ CODE XREF: copyright_do_graphics+182
ROM:0816CE8C 020 72 F1 C1 F8         BL      sub_082DF012
ROM:0816CE8C 020
ROM:0816CE90 020 02 48               LDR     R0, =(sub_0800BA38+1)
ROM:0816CE92 020 93 F6 4B FC         BL      set_callback1_plus_x18
ROM:0816CE92 020
ROM:0816CE96
ROM:0816CE96                 loc_0816CE96:                           @ CODE XREF: copyright_do_graphics+188
ROM:0816CE96                                                         @ copyright_do_graphics+1AA
ROM:0816CE96 020 00 20               MOVS    R0, #0
ROM:0816CE98 020 03 E0               B       loc_0816CEA2
ROM:0816CE98
ROM:0816CE98                 @ ---------------------------------------------------------------------------
ROM:0816CE9A 020 00 00               .align 4
ROM:0816CE9C 020 39 BA 00 08 off_0816CE9C:.long sub_0800BA38+1       @ DATA XREF: copyright_do_graphics+1C8
ROM:0816CEA0                 @ ---------------------------------------------------------------------------
ROM:0816CEA0
ROM:0816CEA0                 loc_0816CEA0:                           @ CODE XREF: copyright_do_graphics+10C
ROM:0816CEA0                                                         @ copyright_do_graphics+144
ROM:0816CEA0                                                         @ copyright_do_graphics+15C
ROM:0816CEA0                                                         @ copyright_do_graphics+16C
ROM:0816CEA0 020 01 20               MOVS    R0, #1
ROM:0816CEA0
ROM:0816CEA2
ROM:0816CEA2                 loc_0816CEA2:                           @ CODE XREF: copyright_do_graphics+1D0
ROM:0816CEA2 020 04 B0               ADD     SP, SP, #0x10
ROM:0816CEA4 010 70 BC               POP     {R4-R6}
ROM:0816CEA6 004 02 BC               POP     {R1}
ROM:0816CEA8 000 08 47               BX      R1
ROM:0816CEA8
ROM:0816CEA8                 @ End of function copyright_do_graphics
ROM:0816CEA8
ROM:0816CEA8                 @ ---------------------------------------------------------------------------
In that excerpt, navigate to ROM:0816CD60. I know that it says MOVS, but it is the same as MOV because there are no signed opcodes in Thumb mode (which is what the S signifies) Here you can see a MOV opcode that loads... 0x3800? If you’re at least somewhat proficient in Thumb-1 ASM, you’d know that the MOV opcode can only load values up to 0xFF. Let me explain.

IDA Pro sometimes combines opcodes together to improve comprehensibility - as I'm sure you noticed next to the MOV command right after the offset is its bytecode - there’s a 32-bit number and MOV is certainly not 32-bit. Here we see two real opcodes.

If you use VBA or VBA-M to view the plainly decompiled version of this part of the ROM, you will see that what IDA Pro shows as MOVS 0x3800, is actually a normal MOV opcode followed by a LSL, all using the same register.

So what is this code for? What is it MOVing and LSLing, you ask? The result of these opcodes is the offset in which the tilemap for our boot screen will be placed, relative to the beginning of the VRAM space. To compute that all in your head, the tilemap will be loaded to VRAM:06003800 by default.

Since your tileset may be larger than 0x3800 bytes when uncompressed into VRAM, we must change this data to allow for larger tilesets lest the data overlap when it is loaded. In your hex editor, navigate to the offset where those opcodes are at (shown above), and place these instructions:

Code:
13 21 C9 02
This is the machine code for MOV R1, #0x13 followed by LSL R1, R1, #0x0B. If you’re wondering, this math produces 0x9800 instead of 0x3800. This amount of space between the start of the tileset and the start of the tilemap allows for a 240x160 image with no duplicate tiles in both 4-bit mode and 8-bit mode, however this tutorial will only cover how to use a 4-bit image as I’ve yet to go through using an 8-bit image successfully (not that I've needed to anyway).

III: Adding our tileset and tilemap


Here’s the fun part: adding your image to the ROM. First you’ll need to insert your tileset and tilemap into some free space in the ROM (and be sure the starting offset is word-aligned). Note those offsets for a little later.

Editing the pointers that reference your tileset and tilemap is as simple as editing the literal pool for boot_screen_load_into_vram (which you can see in the above disassembled routine, for reference it starts at ROM:0816CC70). Change the word located at ROM:0816CCAC to a little endian pointer of the offset you put your tileset at; similarly, change the word located at ROM:0816CCB0 to a little endian pointer of the offset you put your tilemap at. Save and exit.

IV: Changing the I/O register


It’s nice that our new tileset and tilemap get loaded into big, hefty spaces of VRAM, but the GBA hardware has to be told where to look for it. Lucky for us, the value we wish to set the I/O register to fits inside a MOV + LSL operation, so we don’t have the pain in the neck of using LDR and scraping the floor for space to put a literal pool.

We want to do MOV R1, #0x13 and then LSL R1, R1, #0x8. The LSL of R1 by 8 bits is the equivalent of multiplying by 0x100 in this case, but is much much faster than using the MUL opcode. You will need to copy over the machine code for the two opcodes to ROM:0816CD8E:

Code:
13 21 09 02
This tells the GBA to start reading from VRAM:06009800 instead of VRAM:06003800 when it looks for the tilemap, which is in sync with the values we passed to the image data loading routine before.

V: Changing the palette


Unlike before, there’s not really anything very complex to do to accomplish this. Simply navigate to ROM:08DC3D54 in a palette (or hex) editor and change the 16 colours there to the ones you used in making your new boot screen image.
Reply With Quote

Relevant Advertising!

Reply Post Reply
Quick Reply

Sponsored Links
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


  All times are GMT -8. The time now is 5:05 PM.


Contact Us Archive Privacy Statement Terms of Service Top