User:TimoVM/RAM Writer setups

From Glitch City Wiki
Jump to navigation Jump to search

This page serves as a repository for various RAM writer setups, written and developed by TimoVM, intended for gen 1 or gen 2. the RAM writers used are inspired by various pre-existing RAM writers, especially ZZAZZGlitch's memory writer.

Introduction: What is a RAM writer?

In simple terms, a RAM writer is a program that allows you to visualize and edit values that are stored in memory. In effect, this allows you to easily manipulate stuff like adding/modifying items, changing pokémon data such as making them shiny, triggering instant encounters etc.. This is usually combined with a graphical user interface (GUI) for better readability.

In a sense, you can regard RAM writers as a general tool to greatly expand what you can do with arbitrary code execution, due to granting the ability to easily modify any memory value in RAM at any time.

An unfortunate drawback of this approach is that RAM writers are quite large, memory-wise. For this reason, this guide was developed to document methods to install these RAM writers in a reasonably efficient way. Due to their size, you will always be required to start with building a smaller, more limited RAM writer. These will then be used to build the larger RAM writer.

The setups included in this guide work both for console and VC version, at the moment of writing, these setups are unfortunately only applicable for EN versions.

Red/Blue/Yellow

General installation overview:

  1. Assemble 8 items to form a text converter item code.
  2. Catch 14 pokémon (any species is fine), give 12 of them specific nicknames and store them in the currently loaded box. Use your ACE item.
  3. Use the nickname writer to write the large RAM writer in memory.
  4. The RAM Writer will automatically take care of the final setup upon first execution

Due to differences in memory layout, the nicknames and items used in Yellow will differ slightly from those in Red/Blue.

Requirements

In order to install the RAM writer, you need to have an ACE setup that redirects execution to the 3rd item slot ($D322) using a jp hl instruction. The ACE item has to be either 4F or 8F. -gm is not compatible with this guide.

Alongside this ACE setup, you will also need to set up inventory underflow to access item slots beyond the usual 20 slots available.

Install details

  • The RAM writer itself will be installed in sram bank 3, at address BA53 onward.
  • The setup will automatically add the glitch item 4F to your party, along with the necessary bootstrap to use the RAM writer with 4F.
  • Upon using 4F, the RAM writer will be copied over to a specific temporary location in RAM, then executed.
  • For Red/Blue, the RAM writer will be buffered from C620 onward.
  • For Yellow, the RAM writer will be buffered from C978 onward.

Step 1: Assembling an 8-item code

Head to Celadon city and head to the following spot. Make sure to bring a pokémon with Fly/Teleport.

While standing on this spot, open your item bag and keep scrolling down until you find a Nugget x0 item stack, located at item slot #35. Around item slots #22 through #27 you'll likely encounter glitch items with garbled text. You can scroll past these items by pressing B occasionally while tapping DOWN. Do not select any of these items with the A button, otherwise your game will likely crash.

By walking left or right, you can increment or decrement the item ID in slot #35. By walking up and down we can alternate between an item quantity of x0 and x1. We can safely swap the contents of item slot #35 with other item slots, as long as we use Fly/Teleport afterwards to restore the map back to normal. We can use this to collect all the items we need for the item code.

For every item in the following table, head to the Nugget x0 spot, follow the instructions to obtain an item stack, then Fly back to Celadon and head back to the same spot to obtain the next item stack.

Item ID Item quantity How to acquire
Thunderstone x06/x05 From the Nugget spot, walk 16 steps to the left to get Thunderstone x0. Toss 250 from the stack if you're on Red/Blue or toss 251 if you're on Yellow, then swap with an item from your bag.
TM22 x229 At the Nugget spot, swap the Nugget with the TM23 x64 stack 4 slots below, then toss 63 TM23s. Walk one step left and one step down to get TM22 x0. Toss 27 from the stack, then swap with an item from your bag.
Helix Fossil (x135) At the Nugget spot, toss 121 from the stack to get Nugget x135. Walk 7 steps to the left, then swap with an item from your bag.
B2F x48 At the Nugget spot, swap the Nugget with the TM23 x64 stack 4 slots below, then toss 63 TM23s. Walk leftward (you can use the bicycle two slots above to speed this up) until you've looped through the map twice back to the Nugget spots, then walk 15 steps further to the left to get B2F x0. Toss 208 from the stack, then swap with an item from your bag.
Poké Ball x134 From the Nugget spot, walk 35 steps to the left, 4 steps down and 10 steps left to get Poké Ball x0. Toss 122 from the stack, then swap with an item from your bag.
Hyper Potion x28 From the Nugget spot, walk 30 steps to the left to get Hyper Potion x0. Toss 228 from the stack, then swap with an item from your bag.
HP UP x32 From the Nugget spot, walk 14 steps to the left to get HP UP x0. Toss 224 from the stack, then swap with an item from your bag.
TM45 x201 At the Nugget spot, swap the Nugget with the TM23 x64 stack 4 slots below, then toss 63 TM23s. Every step to the right will increment the TM number by 1. Keep walking rightward until you get TM45 x0. Toss 55 from the stack, then swap with an item from your bag.
Master Ball x00 (Optional for catching later) From the Nugget spot, walk 35 steps to the left, 8 steps down and 13 steps left to get Master Ball x0. Swap with an item from your bag,

Assemble the items you acquired according to the following list:

Item slot Item ID Item Quantity
Slot #1 ACE item (8F or 4F) any
Slot #2 Master Ball x0
Slot #3 Thunderstone x06/051
Slot #4 TM22 x229
Slot #5 Helix Fossil (x135)2
Slot #6 B2F x48
Slot #7 Poké Ball x134
Slot #8 Hyper Potion x28
Slot #9 HP UP x32
Slot #10 TM45 x201

1 x06 on Red/Blue, x05 on Yellow 2 The item quantity for Helix Fossil is invisible for the player.

This item code looks at the nicknames of the pokémon in the currently stored box, then uses pairs of text characters to write a new program. After it finishes, it immediately jumps to execute the newly written program.

Step 2: Catching and nicknaming 14 pokémon to build a nickname writer

The item code we have assembled converts nicknames into code, which means we'll have to catch pokémon with the right nicknames to do something useful. The pokémon we'll be catching will be stored in a storage box. Make sure the box you pick fulfils the following requirements:

  • The box needs to be set as the active box.
  • If on VC, it is recommended to not pick box 1 since that's the box Poké Transporter connects to.

Once that is done, we will fill the box with nicknamed pokémon. We'll be making a list with nicknames using Scottey's nickname converter tool. Simply copy paste the entire code below into the converter, then press the "Run" button to display the list of nicknames. Ignore the checksums for now.

If you'll be manually depositing pokémon, follow the list from top to bottom. If you're catching pokémon and sending them to the PC through a full party, follow the list from bottom to top.

Codes to be used with Scotteh's mail code tool
Red/Blue Yellow
Nickname writer (14 codes) Nickname writer (14 codes)
00 00 00 00 00 11 9C D8 D5 D5 
06 01 21 5C 65 CD D6 35 0E 80 
21 4B CF D1 2A 87 30 09 86 12 
13 23 81 12 4F 18 F3 21 29 C4 
0E 01 D5 CD DF 15 CD 31 38 D1 
F0 B5 A7 28 EE 0F 38 CF 1B 0F 
38 E7 0F D0 1B 1B 1B 1B 18 C3 
00 00 00 00 00 11 9B D8 D5 D5 
06 01 21 CD 62 CD 84 3E 0E 80 
21 4A CF D1 2A 87 30 09 86 12 
13 23 81 12 4F 18 F3 21 29 C4 
0E 01 D5 CD BF 13 CD 1E 38 D1 
F0 B5 A7 28 EE 0F 38 CF 1B 0F 
38 E7 0F D0 1B 1B 1B 1B 18 C3 

After you've double checked everything, make sure to save. Once you activate the mail writer, you'll need to write up to 40 nicknames to form the full RAM writer. You will not be able to save during this time.

Step 3: Using the nickname writer

Once you activate your ACE item, you should be able to open the nickname writer. Make sure to only use the nickname writer inside a pokémon center to ensure that the checksums are correctly displayed.

The program works as follows:

  • The program opens the nickname screen and asks you to input a nickname.
  • This nickname then gets converted to a sequence of five bytes.
  • All five bytes are written starting from the starting location
  • The program displays a checksum (sum of all written byte values) to confirm that you correctly entered the code. If the printed checksum doesn't match the expected checksum, you made a mistake entering a code.
  • Afterwards, it waits for the user to decide what to do.

During the input phase, the controls are as follows:

  • Press A for the program to ask for a new nickname and convert that to the next five bytes to be written.
  • Press SELECT to go back five bytes and ask for a new nickname to correct errors. Use this if the printed checksum does not match the predicted checksum and the last written nickname contained ten characters.
  • Press B to go back one byte at a time. The checksum will automatically be overwritten by the value written at the current selected address, giving you a measure of how far back you're going. This function is only needed if you accidentally confirmed a nickname without writing all 10 characters.
  • Press any other button (except A) to immediately start executing the newly written program. Only do this when you've finished writing everything.
Write mode Input mode
Press select to switch between uppercase/lowercase Checksum is displayed right next to ITEM

We will be installing the full RAM writer using a series of nickname codes. These nickname codes will be assembled using Scotteh's mail code tool. Simply copy paste the entire code below into the converter, then press the "Run" button to display the list of nicknames. Ensure you are entering the mail codes that are appropriate for the location you're installing the program to. The generated nicknames need to be entered from top to bottom.

Codes to be used with Scotteh's mail code tool
Installation for Red/Blue (50 codes) Installation for Yellow (50 codes)
3E 03 CD 7A D9 21 1E D3 36 59 
01 C8 00 11 53 BA 21 BB D8 CD 
B5 00 11 65 DA D5 0E 13 C3 B5 
00 AF 3C E0 B6 E0 B7 21 00 DA 
CD 74 C6 E5 11 F8 FF 19 54 5D 
01 0C 00 CD DD C6 21 A9 C3 CD 
65 C6 3E 7C 22 7A CD 65 C6 7B 
CD 65 C6 3E E3 22 1A CD 65 C6 
36 7C 09 13 7D FE 13 20 E5 26 
00 74 21 50 C4 36 ED E1 18 C4 
F5 CB 37 CD 6C C6 F1 E6 0F C6 
F6 F6 80 22 C9 CD BE C6 CB 5F 
20 39 CB 57 28 0A 0F 30 01 E9 
F0 FE 83 E0 FE C9 0F 30 2A E5 
CD DD C6 4E CD BE C6 0F 38 12 
0F 30 01 4B 79 83 4F 21 50 C4 
36 EC 23 CD 65 C6 18 E8 E1 71 
E5 06 1C 21 CE 77 CD D6 35 E1 
C9 0F 30 03 53 1E 00 19 C9 CD 
31 38 F0 B5 76 11 00 00 F5 07 
30 01 13 07 30 01 1B 07 30 03 
11 F0 FF 07 30 02 1E 10 F1 C9 
F0 FE E5 26 0A 74 26 40 77 E1 
C9 21 43 0A 74 65 36 03 0E C8 
11 20 C6 D5 21 53 BA C3 B5 00 
21 43 0A 74 65 75 21 1D D3 36 
59 01 C8 00 11 53 BA 21 BB D8 
CD B1 00 11 64 DA D5 0E 12 C3 
B1 00 AF 3C E0 B6 E0 B7 21 00 
DA CD CC C9 E5 11 F8 FF 19 54 
5D 01 0C 00 CD 35 CA 21 A9 C3 
CD BD C9 3E 7C 22 7A CD BD C9 
7B CD BD C9 3E E3 22 1A CD BD 
C9 36 7C 09 13 7D FE 13 20 E5 
26 00 74 21 50 C4 36 ED E1 18 
C4 F5 CB 37 CD C4 C9 F1 E6 0F 
C6 F6 F6 80 22 C9 CD 16 CA CB 
5F 20 39 CB 57 28 0A 0F 30 01 
E9 F0 FE 83 E0 FE C9 0F 30 2A 
E5 CD 35 CA 4E CD 16 CA 0F 38 
12 0F 30 01 4B 79 83 4F 21 50 
C4 36 EC 23 CD BD C9 18 E8 E1 
71 E5 06 1C 21 46 7B CD 84 3E 
E1 C9 0F 30 03 53 1E 00 19 C9 
CD 1E 38 F0 B5 76 11 00 00 F5 
07 30 01 13 07 30 01 1B 07 30 
03 11 F0 FF 07 30 02 1E 10 F1 
C9 E5 F0 FE 26 0A 74 26 40 77 
E1 C9 21 43 0A 74 65 75 0E C8 
11 78 C9 D5 21 53 BA C3 B1 00 

Once all codes have been entered and verified, you can press any button (with the exception of A, B and DOWN) during input mode to start up the full RAM writer.

Step 4: Using the full RAM writer

Assuming the program was entered correctly, the game should open up one of the screens as seen in the below screenshots. The RAM writer will draw various values on the screen. The leftmost 4 columns describe the addresses that are currently in view. The rightmost two columns describe the values at each of these addresses. All values on screen are represented in hexadecimal format.

For example: DA01>05 means that the address $DA01 is currently holding the value of $05.

Make sure to save the game after you've confirmed that the RAM writer is fully functional.

The RAM writer can also be used during battle. Opening and closing the RAM writer in battle will pass your turn to the enemy and cause the battle to continue as usual.

Due to the location the RAM writer is buffered, upon closing the RAM writer in battle in Red/Blue, you will see a slight graphical corruption at the bottom of the screen that will immediately be overwritten by the battle text box. This corruption is purely cosmetic and temporary, meaning that it will not cause any harm to your game.

Full Writer Controls

The RAM writer uses two modes of operation. In Read mode you are able to navigate memory and view the values at specific addresses. in Write mode you'll lock in a single address and manipulate the value at that address. By default, the RAM writer will open in Read mode.

RAM writer in Read mode RAM writer in Write mode.

Read mode controls

up: address -1
down: address +1
left: address -10
right: address +10
    
B + up: address -1
B + down: address +1
B + left: address -10
B + right: address +10
    
start: exit program    
A: toggle write mode

select + up: sram bank -1
select + down: sram bank +1
select + left: sram bank -10
select + right: sram bank +10
select + A: start executing code from current address onwards (use with caution!)

Write mode controls

up: value -1
down: value +1
left: value -10
right: value +10
B: set current value to 0
A: exit write mode and load final value into the address

Asm translation of included programs/codes

Note: these are not yet up to date

7-item code nickname converter

Hex values Opcodes Labels/notes
26 DE ld h, $DE
2A ldi a, (hl) .loop
87 add a
44 ld b, h
30 04 jr nc, .notChar
86 add (hl)
02 ld (bc), a
2C inc l
03 inc bc
20 F5 jr nz, .loop .notChar
E9 jp hl
Transcript

26 DE 2A 87 44 30 04 86 02 2C 03 20 F5 E9

Nickname writer

Hex values Opcodes Labels/notes
11 96 DA / 11 53 BA ld de, $DA96 / ld de, $BA53 ;defines the address to write to
D5 push de
D5 push de .loop
AF xor a
47 ld b, a
21 5C 65 ld hl, DisplayNameRaterScreen
CD D6 35 Call BankSwitch
21 4B 0A ld hl, 0A4B
74 ld (hl), h
65 ld h, l
77 ld (hl), a
26 CF ld h, CF ; hl now holds the address of wStringBuffer
D1 pop de
2A ldi a, (hl) .not@
87 add a
30 09 jr nc, .@
86 add (hl)
12 ld (de), a
13 inc de
23 inc hl
81 add c
12 ld (de), a
4F ld c, a
18 F3 jr, .not@
21 00 C4 ld hl, $C400 .@
0E 01 ld c, $01
D5 push de
CD DF 15 Call PrintBCDNumber.loop
CD 31 38 Call JoypadLowSensitivity
D1 pop de
F0 B5 ld a, hJoy5
BD cp l
28 CF jr z, .loop
38 EC jr c, .@
07 rlca
D0 ret nc
1B dec de
18 E7 jr, .@
Transcript

11 96 DA D5 D5 AF 47 21 5C 65 CD D6 35 21 4B 0A 74 65 77 26 CF D1 2A 87 30 09 86 12 13 23 81 12 4F 18 F3 21 00 C4 0E 01 D5 CD DF 15 CD 31 38 D1 F0 B5 BD 28 CF 38 EC 07 D0 1B 18 E7

Full RAM writer (DA96)

setup
AF
3C
E0 B6
E0 B7
21 00 DA	ld hl, DA00

resolveDisplay
CD EA DA	call resolveInput
E5		push hl
11 F8 FF	ld de, FFF8
19		add hl, de
54		ld d, h
5D		ld e, l
01 0C 00	ld bc, 000C
CD 53 DB	call openSramBank
21 A9 C3	ld hl, C3A9
CD DB DA	call printHex
.displayLoop
3E 7C		ld a, 7C
22		ldi (hl), a
7A 		ld a, d
CD DB DA	call printHex
7B		ld a, e
CD DB DA	call printHex
3E E3		ld a, E3
22 		ldi (hl), a
1A 		ld a, (de)
CD DB DA	call printHex
36 7C		ld a, 7C
09		add hl, bc
13		inc de
7D		ld a, l
FE 13		cp 13
20 E5		jr nz, .displayLoop
26 00		ld h, 00
74		ld (hl), h
21 50 C4	ld hl, C450
36 ED		ld (hl), ED
E1		pop hl
18 C4		jr, resolveDisplay

printHex
F5		push af
CB 37		swap a
CD E2 DA	call .firstHex
F1		pop af
.firstHex	DAE2
E6 0F		and 0F
C6 F6		add a, F6
F6 60		or a, 60
22		ldi (hl), a
C9		ret

ResolveInput DAEA
CD 34 DB	call sampleDpad
CB 5F		bit 3, a
20 39		jr nz, .noStartButton
.noStartButton
CB 57		bit 2, a
28 0A		jr z, noSelectButton
0F		rrca
30 01		jr nc, .changeSramBank
E9		jp hl
.changeSramBank
F0 FE		ldh a, (FE)
83		add e
E0 FE		ldh (FE), a
C9		ret
.noSelectButton
0F		rrca		
30 2A		jr nc, .noAButton
CD 53 DB	call openSramBank
4E		ld c, (hl)
E5		push hl
.inputALoop
CD 34 DB	call sampleDpad
0F		rrca
38 12		jr c, .AButtonPressed
0F		rrca
30 01		jr nc , .BButtonNotPressed
4B		ld c, e
.BButtonNotPressed
79		ld a, c
83		add e
4F		ld c, a
21 50 C4	ld hl, C450
36 EC		ld (hl), EC
23		inc hl
CD DB DA	call printHex
18 E8		jr, .inputALoop
.AButtonPressed
E1		pop hl	
71		ld (hl), c
E5		push hl
3E 1C		ld a, 1C
21 CE 77	ld hl, 77CE
CD D6 35	Call Bankswitch
E1		pop hl
C9		ret
.noAButton
0F		rrca
30 03		jr nc, noBButton
53		ld d, e
1E 00		ld e, 00
19		add hl, de
C9		ret

sampleDpad
CD 31 38	call JoypadLowSensitivity
F0 B5		ldh a, (B5)
76		halt
11 00 00	ld de, 0000
F5		push af
07		rlca
30 01		jp nc, .noDown
13		inc de
.noDown
07		rlca
30 01		jr nc, .noUp	
1B		dec de
.noUp
07		rlca
30 03		jr nc, .noLeft
11 F0 FF	ld de, FFF0
.noLeft
07		rlca
30 02		jr nc, .noRight
1E 10		ld e, 10
.noRight
F1		pop af
c9		ret

opensrambank
E5		push hl
F0 FE		ldh a, (FE)
26 0A		ld h, 0A
74		ld (hl), h
26 40		ld h, 40
77		ld (hl), a
E1 		pop hl
c9		ret
Transcript

3E 01 E0 B6 E0 B7 21 00 DA CD EA DA E5 11 F8 FF 19 54 5D 01 0C 00 CD 53 DB 21 A9 C3 CD DB DA 3E 7C 22 7A CD DB DA 7B CD DB DA 3E E3 22 1A CD DB DA 36 7C 09 13 7D FE 13 20 E5 26 00 74 21 50 C4 36 ED E1 18 C4 F5 CB 37 CD E2 DA F1 E6 0F C6 F6 F6 60 22 C9 CD 34 DB CB 5F 20 39 CB 57 28 0A 0F 30 01 E9 F0 FE 83 E0 FE C9 0F 30 2A E5 CD 53 DB 4E CD 34 DB 0F 38 12 0F 30 01 4B 79 83 4F 21 50 C4 36 EC 23 CD DB DA 18 E8 E1 71 E5 06 1C 21 CE 77 CD D6 35 E1 C9 0F 30 03 53 1E 00 19 C9 CD 31 38 F0 B5 76 11 00 00 F5 07 30 01 13 07 30 01 1B 07 30 03 11 F0 FF 07 30 02 1E 10 F1 C9 E5 F0 FE 26 0A 74 26 40 77 E1 C9

Full RAM writer (BA53)

setup
3E 01		ld a, 01
E0 B6		ldh (B6), a
E0 B7		ldh (B7), a
21 00 DA	ld hl, DA00

resolveDisplay
CD 9E BA	call resolveInput
E5		push hl
11 F8 FF	ld de, FFF8
19		add hl, de
54		ld d, h
5D		ld e, l
01 0C 00	ld bc, 000C
21 AB C3	ld hl, C3AB
.displayLoop
3E 7C		ld a, 7C
22		ldi (hl), a
7A 		ld a, d
CD 8F BA	call printHex
7B		ld a, e
CD 8F BA	call printHex
3E E3		ld a, E3
22 		ldi (hl), a
1A 		ld a, (de)
CD 8F BA	call printHex
36 7C		ld a, 7C
09		add hl, bc
13		inc de
7D		ld a, l
FE 13		cp 13
20 E5		jr nz, .displayLoop
21 50 C4	ld hl, C450
36 ED		ld (hl), ED
E1		pop hl
18 CD		jr, resolveDisplay

printHex
F5		push af
CB 37		swap a
CD 94 ba	call .firstHex
F1		pop af
.firstHex	BA96
E6 0F		and 0F
C6 F6		add a, F6
F6 60		or a, 60
22		ldi (hl), a
C9		ret

ResolveInput
CD D4 BA	call sampleDpad
CB 5F		bit 3, a
28 02		jr z, .noStartButton
C1		pop bc
C9		ret
.noStartButton
CB 57		bit 2, a
28 01		jr z, noSelectButton
E9		jp hl
.noSelectButton
0F		rrca		
30 1D		jr nc, .noAButton
4E		ld c, (hl)
E5		push hl
.inputALoop
CD D4 BA	call sampleDpad
0F		rrca
38 12		jr c, .AButtonPressed
0F		rrca
30 01		jr nc , .BButtonNotPressed
4B		ld c, e
.BButtonNotPressed
79		ld a, c
83		add e
4F		ld c, a
21 50 C4	ld hl, C450
36 EC		ld (hl), EC
23		inc hl
CD 8F BA	call printHex
18 E8		jr, .inputALoop
.AButtonPressed
E1		pop hl	
71		ld (hl), c
C9		ret
.noAButton
0F		rrca
30 03		jr nc, noBButton
53		ld d, e
1E 00		ld e, 00
19		add hl, de
C9		ret

sampleDpad
CD 31 38	call JoypadLowSensitivity
F0 B5		ldh a, (B5)
76		halt
11 00 00	ld de, 0000
F5		push af
07		rlca
30 01		jp nc, .noDown
13		inc de
.noDown
07		rlca
30 01		jr nc, .noUp	
1B		dec de
.noUp
07		rlca
30 03		jr nc, .noLeft
11 F0 FF	ld de, FFF0
.noLeft
07		rlca
30 02		jr nc, .noRight
1E 10		ld e, 10
.noRight
F1		pop af
c9		ret
Transcript

3E 01 E0 B6 E0 B7 21 00 DA CD 9E BA E5 11 F8 FF 19 54 5D 01 0C 00 21 AB C3 3E 7C 22 7A CD 8F BA 7B CD 8F BA 3E E3 22 1A CD 8F BA 36 7C 09 13 7D FE 13 20 E5 21 50 C4 36 ED E1 18 CD F5 CB 37 CD 96 BA F1 E6 0F C6 F6 F6 60 22 C9 CD D4 BA CB 5F 28 02 C1 C9 CB 57 28 01 E9 0F 30 1D 4E E5 CD D4 BA 0F 38 12 0F 30 01 4B 79 83 4F 21 50 C4 36 EC 23 CD 8F BA 18 E8 E1 71 C9 0F 30 03 53 1E 00 19 C9 CD 31 38 F0 B5 76 11 00 00 F5 07 30 01 13 07 30 01 1B 07 30 03 11 F0 FF 07 30 02 1E 10 F1 C9

Gold/Silver/Crystal

General installation overview:

  1. Use a box name code to set every TM quantity to 255.
  2. Write out a mail writer program by changing TM quantities. Use a box name code to use the mail writer.
  3. Enter a series of mail codes in order to write the full RAM writer.
  4. Use the full RAM writer to automatically it to the data of box 14.

Requirements

In order to install the RAM writer, you need to have an ACE setup that redirects execution to the 1st or 2nd character of box name 1. Available options are:

For Gold & Silver:

  • Coin Case ACE which uses a pokémon's EVs to redirect to the last read mail, which fixes the stack and then redirects to the start of box names.
  • Wrong Pocket TM17 ACE using a Quagsire holding TM01 and with Return as first move.

For Crystal:

  • TMless 0x1500 ACE setup which uses a bad clone and a pokémon with specific EVs to redirect to the last read mail, which redirects to the start of box names.
  • (TODO: add Zodiac's page and/or LuckyTyphlosion's setup)

Next, make sure to take care of the following:

  • Make sure to empty box 14 of any pokémon you wish to keep. We'll be installing the full RAM writer in the data for box 14, meaning everything inside it will have its data overwritten.
  • For Crystal, put any item that you can afford to lose in the first slot of your item pack. This item will be changed to a TM15 during the setup.

Step 1: Setting all TM quantities to 255

Enter the following box names. After preparations are complete, execute ACE.

Caption text
Gold & Silver Crystal
Box 1: A p 'v C é 2 2 5
Box 2: 'v j 'v u é 1 2 5
Box 3: 'v ♂ é 5 2 p 'v 9
Box 4: é 4 2 p é 6 2 5
Box 5: 'v u é 8 2 'v {space} 5
Box 6: é 7 2 'v : é 9 2
Box 7: 0 9 ♀ 5 ♀ 5 5 5
Box 8: 5 5 5 5 5 5 x 'd
Box 1: p 'v 9 é 'd 5 'v *
Box 2: é H 5 'v ♂ é G 5
Box 3: A 4 é m 5 'v 9 5
Box 4: é k 5 F é 'l 5 F
Box 5: 0 B 's 'v 5 u 'v c
Box 6: é n 5 's k 5 'v B
Box 7: 'd 5 5 2 p é 'm 5
Box 8: 'v 'd é 't 5 'v ♂ 5
Box 9: é 's 5 é n 5 v 5
Box 10: 'v L é T 2 0 9 5
Box 11: 5 5 5 5 'm 5 5 ♀
Box 12: 'v F 's k 5 F ? E
Box 13: 's k 5 * 'm k 5 5

This will set the quantities of all 50 TMs to 255. For Crystal, this will also change the first item to a TM15 and install a bootstrap to redirect execution to the TM/HM pocket. Do not use this TM15 yet.

What to do now you have 255 of every TM

At this moment, there are two main options.

  1. You can use the quantities in the TM/HM pocket to easily write out simple codes. A list of TM codes can be found on this page. (Currently only supported for Gold/Silver)
  2. You can continue with the guide and build a RAM writer in order to achieve near-complete ACE control.

Step 2: Selling TMs to form a mail writer

Sell TMs such that you get the following quantities:

Version independent TMs

TM Final Quantity Sell value
TM01 DYNAMICPUNCH x17 357000
TM02 HEADBUTT SEE NEXT TABLE
TM03 CURSE SEE NEXT TABLE
TM04 ROLLOUT x213 42000
TM05 ROAR x213 21000
TM06 TOXIC x213 63000
TM07 ZAP CANNON x33 222000
TM08 ROCK SMASH SEE NEXT TABLE
TM09 PSYCH UP SEE NEXT TABLE
TM10 HIDDEN POWER x207 72000
TM11 SUNNY DAY x225 30000
TM12 SWEET SCENT x209 23000
TM13 SNORE x42 106500
TM14 BLIZZARD x254 1500
TM15 HYPER BEAM x80 262500
TM16 ICY WIND x56 298500
TM17 PROTECT x251 6000
TM18 RAIN DANCE x40 215000
TM19 GIGA DRAIN x10 367500
TM20 ENDURE x135 180000
TM21 FRUSTRATION x134 60500
TM22 SOLARBEAM x18 355500
TM23 IRON TAIL x19 354000
TM24 DRAGONBREATH x35 330000
TM25 THUNDER x129 126000
TM26 EARTHQUAKE x79 264000
TM27 RETURN x18 118500
TM28 DIG x24 231000
TM29 PSYCHIC x239 16000
TM30 SHADOW BALL x33 333000
TM31 MUD-SLAP x1 381000
TM32 DOUBLE TEAM SEE NEXT TABLE
TM33 ICE PUNCH x77 267000
TM34 SWAGGER x205 25000
TM35 SLEEP TALK SEE NEXT TABLE
TM36 SLUDGE BOMB SEE NEXT TABLE
TM37 SANDSTORM x27 228000
TM38 FIRE BLAST x205 50000
TM39 SWIFT SEE NEXT TABLE
TM40 DEFENSE CURL SEE NEXT TABLE
TM41 THUNDERPUNCH x189 99000
TM42 DREAM EATER x40 322500
TM43 DETECT x217 19000
TM44 REST x56 298500
TM45 ATTRACT x240 22500
TM46 THIEF x254 1500
TM47 STEEL WING x08 370500
TM48 FIRE PUNCH x200 82500
TM49 FURY CUTTER x24 346500
TM50 NIGHTMARE x242 13000

Version dependent TMs

TM Gold & Silver Crystal
Final Quantity Sell value Final Quantity Sell value
TM02 HEADBUTT x85 170000 x128 127000
TM03 CURSE x221 51000 x210 67500
TM08 ROCK SMASH x66 94500 x117 69000
TM09 PSYCH UP x98 78500 x94 80500
TM32 DOUBLE TEAM x196 59000 x197 58000
TM35 SLEEP TALK x239 8000 x204 25500
TM36 SLUDGE BOMB x58 98500 x56 99500
TM39 SWIFT x144 111000 x75 180000
TM40 DEFENSE CURL x55 100000 x53 101000

What to do now you have sold TMs

Once you've finished selling TMs, set up box names according to the following codes. This code will redirect execution from box names to TMs.

For Crystal, you already have a TM15 that will redirect execution to the TM/HM pocket, meaning you can skip setting up this box code.

Box number Box name
Box 1 A p 'v C é 'd 2 5
Box 2 5 5 5 p 'v 6 h 'm
Box 3
Other Can be left as they are

Step 3: Using the mail writer

Once everything has been double checked, you can use your ACE item (In Crystal, use TM15) in order to start up the mail writer. Make sure to save prior to this step. Once you start the mail writer you'll need to finish writing all mail codes before you have an opportunity to save again.

Controls

The mail writer will open a screen that asks you to write the contents of a mail. This is where you'll need to enter mail codes. Once done, use the "END" option to finish the mail.

This will cause the mail writer to convert the newly written code into assembly. It will also print a checksum (sum of all written values) on the screen just to the right of the lower row. This can be used to verify if a code was entered correctly.

Alongside these actions, the mail writer will now request user input:

  • Press SELECT together to open a new mail and continue writing data.
  • Press START to immediately jump to and start executing the newly written program. Only use this when you've finished every mail.
  • Press any other button to go back one byte at a time to correct errors. If the printed checksum doesn't match the expected checksum, press DOWN 16 times to retry the last mail. This will also overwrite the printed checksum with the value at the currently selected address, giving you a method to check how far back you're going.
Enter your mail code, then press "END". It prints the checksum and waits for input.

Building the full RAM writer

We will be installing the full RAM writer using a series of mail codes. These mail codes will be assembled using Scotteh's mail code tool. Copy paste the entire code in the text box on the mail code tool's page, then press "Run".

Codes to be used with Scotteh's mail code tool
Gold & Silver (18 codes) Crystal (18 codes)
3E 03 CD E1 30 0E CE 11 E1 B9 21 7A DD CD 1A 31 
0E 2D 11 18 D4 D5 CD 1A 31 21 E1 D5 34 7D 4E 09 
22 AF 3D 22 C9 AF 3C E0 D6 21 00 DA CD 21 DF E5 
11 F8 FF 19 54 5D 01 0C 00 F0 FE 21 A9 C3 CD E1 
30 CD 65 CC 3E 7C 22 7A CD 65 CC 7B CD 65 CC 3E 
E3 22 1A CD 65 CC 36 7C 09 13 7D FE 13 20 E5 CD 
F1 30 21 50 C4 36 ED E1 18 C2 F5 CB 37 CD 6C CC 
F1 E6 0F C6 F6 F6 80 22 C9 CD 90 37 11 00 00 F0 
AB 07 30 01 13 07 30 01 1B 07 30 03 11 F0 FF 07 
30 02 1E 10 07 C9 CD 74 CC 38 41 07 30 0B 07 07 
30 01 E9 F0 FE 83 E0 FE C9 07 30 03 53 1E 00 19 
07 30 2A E5 F0 FE CD E1 30 46 CD 74 CC 07 07 30 
01 43 07 38 0E 78 83 47 21 50 C4 36 EC 23 CD 65 
CC 18 E7 E1 70 E5 3E 05 21 FD 4D CF E1 C9 FA AB 
CE FE E1 C0 FA C2 CE FE 90 C0 3E 0D EA E0 CE C9 
C3 01 DF 3E 03 CD E1 30 0E 71 11 20 CC D5 21 E1 
B9 CD 1A 31 0E 48 11 21 DF CD 1A 31 0E 12 11 0F 
DF CD 1A 31 0E 03 11 8A FF CD 1A 31 AF E0 89 C9 
3E 03 CD CB 2F 0E D0 11 E1 B9 21 A6 D2 CD 26 30 
0E 2A 11 47 DA D5 CD 26 30 21 BC D8 34 3E D0 4E 
09 22 AF 3D 22 C9 AF 3C E0 D4 21 00 DA CD 21 C0 
E5 11 F8 FF 19 54 5D 01 0C 00 F0 FE 21 A9 C4 CD 
CB 2F CD 65 CD 3E 7C 22 7A CD 65 CD 7B CD 65 CD 
3E E3 22 1A CD 65 CD 36 7C 09 13 7D FE 13 20 E5 
CD E1 2F 21 50 C5 36 ED E1 18 C2 F5 CB 37 CD 6C 
CD F1 E6 0F C6 F6 F6 80 22 C9 CD 4B 35 11 00 00 
F0 A9 07 30 01 13 07 30 01 1B 07 30 03 11 F0 FF 
07 30 02 1E 10 07 C9 FA 74 CF FE D0 C0 FA 8B CF 
FE 90 C0 3E 0D EA A9 CF C9 CD 74 CD 38 41 07 30 
0B 07 07 30 01 E9 F0 FE 83 E0 FE C9 07 30 03 53 
1E 00 19 07 30 2A E5 F0 FE CD CB 2F 46 CD 74 CD 
07 07 30 01 43 07 38 0E 78 83 47 21 50 C5 36 EC 
23 CD 65 CD 18 E7 E1 70 E5 3E 05 21 13 4E CF E1 
C9 20 8B C3 00 C0 3E 03 CD CB 2F 0E 71 11 20 CD 
D5 21 E1 B9 CD 26 30 0E 5A 11 0F C0 CD 26 30 0E 
05 11 F9 FF CD 26 30 3E 70 E0 88 3E 18 E0 87 C9 

After you press run, the tool will generate the mail codes that you need to enter in the mail writer.

After entering every code, a new number will appear to the right of the bottom mail row. This is a checksum and is used to verify that you've correctly entered every mail. If a checksum doesn't match the one given by the tool, that means that a code was incorrectly entered, meaning you will need to redo your mail by pressing DOWN enough times (16 times if you’ve entered a full mail code) to return to the starting byte of the last mail, then entering that same mail again.

After you're finished entering all mail codes, you can press any button outside of A, B or DOWN during the user input phase in order to start up the full RAM writer.

Step 4: Activating the RAM writer

After you're finished and have verified that all checksums were valid, press any button outside of A, B or DOWN during the user input phase in order to start up the full RAM writer.

Doing this will activate the following effects:

  • Save the RAM writer to the contents of box 14.
  • Add TM33 (G/S) or TM17 (C) to the Key Item pocket.
  • Install setup to make sure that using TM33/TM17 from the key item pocket will start the RAM writer.
  • Automatically start the RAM writer.

Starting the RAM writer, either automatically or through using wrong pocket TM33/TM17, will activate the following effects:

  • Copy the necessary data to memory to activate the RAM writer.
  • Deploy setup that will enable the use of TM33/TM17 during battle.
  • Start the RAM writer.

After exiting the RAM writer, you can restart the RAM writer by using TM33 from the item pack. In battle, you can activate the RAM writer by using TM33/TM17 and selecting "QUIT". Please note that the setup to enable the use of TM33/TM17 during battle does not persist between resets, you can reenable this function by using the RAM writer outside of battle at least once.

As you can see in the screenshots below, the RAM writer will draw various values on the screen. The leftmost 4 columns describe the addresses that are currently in view. The rightmost two columns describe the values at each of these addresses. All values on screen are represented in hexadecimal format.

For example: DA01>05 means that the address $DA01 is currently holding the value of $05.

Let's go over the controls of the full RAM writer. By default, the RAM writer will open in Read mode.

Full Writer Controls

The RAM writer uses two modes of operation. In Read mode you are able to navigate memory and view the values at specific addresses. in Write mode you'll lock in a single address and manipulate the value at that address.

RAM writer in Read mode RAM writer in Write mode. Note the arrow pointing at the current address turning white.

Read mode controls

up: address -1
down: address +1
left: address -10
right: address +10
    
B + up: address -1
B + down: address +1
B + left: address -10
B + right: address +10
    
start: exit program    
A: toggle write mode

select + up: sram bank -1
select + down: sram bank +1
select + left: sram bank -10
select + right: sram bank +10
select + A: start executing code from current address onwards (use with caution!)

Write mode controls

up: value -1
down: value +1
left: value -10
right: value +10
B: set current value to 0
A: exit write mode and load final value into the address

Asm translation of included programs/codes

Set all TM quantities to x255

Before first execution After first execution
80		add b
AF		xor a
D6 82		sub $82
EA F8 F8	ld $f8f8, a
FB		ei
50		ld d, b
D6 A9		sub $A9
D6 B4		sub $B4
EA F7 F8	ld $F8F7, a
FB		ei
50		ld d, b
D6 EF		sub $EF
EA FB F8	ld $F8FB, a
AF		xor a
D6 FF		sub $FF
50		ld d, b
EA FA F8	ld $F8FA, a
AF		xor a
EA FC F8	ld $F8FC, a
FB		ei
50		ld d, b
D6 B4		sub $B4
EA FE F8	ld $F8FE, a
D6 7F		sub $7F
FB		ei
50		ld d, b
EA FD F8	ld $F8FD, a
D6 9C		sub $9C
EA FF F8	ld $F8FF, a
50		ld d, b
F6 FF		or $FF
F5		push af
FB		ei
F5		push af
FB		ei
FB		ei
FB		ei
50		ld d, b
FB		ei
FB		ei
FB		ei
FB		ei
FB		ei
B7		or a
D0		ret nc
80		add b
AF		xor a
D6 82		sub $82
EA F8 F8	ld $f8f8, a
FB		ei
50		ld d, b
D6 A9		sub $A9
D6 B4		sub $B4
EA F7 F8	ld $F8F7, a
FB		ei
50		ld d, b
D6 EF		sub $EF
EA FB F8	ld $F8FB, a
AF		xor a
D6 FF		sub $FF
50		ld d, b
EA FA F8	ld $F8FA, a
AF		xor a
EA FC F8	ld $F8FC, a
FB		ei
50		ld d, b
D6 B4		sub $B4
EA FE F8	ld $F8FE, a
D6 7F		sub $7F
FB		ei
50		ld d, b
EA FD F8	ld $F8FD, a
D6 9C		sub $9C
EA FF F8	ld $F8FF, a
50		ld d, b
F6 FF		or $FF
21 7E F5	ld hl, $F57E	
01 32 00	ld bc, $0032
CD 4C 31	call ByteFill
FB		ei
FB		ei
FB		ei
B7		or a
D0		ret nc

Redirect to TMs

Before first execution After first execution
80		add b
AF		xor a
D6 82		sub $82
EA D0 F8	ld $F8D0, a
FB		ei
50		ld d, b
FB		ei
FB		ei
FB		ei
FB		ei
FB		ei
FB		ei
A7		and a
D2 50 F5	jp nc, $F550
50		ld d, b
80		add b
AF		xor a
D6 82		sub $82
EA D0 F8	ld $F8D0, a
FB		ei
50		ld d, b
FB		ei
FB		ei
FB		ei
FB		ei
FB		ei
FB		ei
A7		and a
D2 7E F5	jp nc, $F57E
50		ld d, b

Mail writer

11 55 DD	ld de, wOTPartyCount; safe to edit outside of battle
D5		push de
.continue
D5		push de
D5		push de
3E 04		ld a, 04
21 42 62	ld hl, _ComposeMailMessage
CF		rst08
E1		pop hl
D1		pop de
.terminator
2A		ldi a, (hl)
87		add a
30 07		jr nc, .notChar
86		add (hl)
12		ld (de), a
13		inc de
81		add c
4F		ld c, a
12		ld (de), a
2A		ldi a, (hl)
.notChar
27		daa
20 F2		jr nc, .terminator
.loop
21 01 C4	ld hl, C401
4D		ld c, l
CD F0 3A	call PrintBCDNumber.loop
1B		dec DE
CD 90 37	call JoyTextDelay_ForcehJoyDown
F0 AB		ldh a, (hJoyLast)
BD		cp l
28 D8		jr z, .continue
38 EE		jr c, .noloop
07		rlca
D0		ret nc
18 F1		jr, .loop

Known limitations:

  • The first written byte cannot be $00, otherwise the mail writer will prematurely stop converting characters.
  • The first character needs to have a value of $80 or higher.
  • The second character cannot be $A0 or $9A

Full RAM writer

Installer		located at DD55
3E 03		ld a, 03
CD E1 30 	call OpenSRAM	; open sram bank 3 (defined by register a)
0E CE		ld c, CE
11 E1 B9 	ld de, sBox14Species
21 74 DD 	ld hl, DD74
CD 1A 31 	call CopyBytes	; install payload to SRAM
0E 2D 		ld c, 08
11 18 D4 	ld de, D418 	; entry point of wrong pocket TM33
D5		push de
CD 1A 31 	call CopyBytes	; install TM33 bootstrap to D418 
3E E1 		ld a, E1
EA B8 D5 	ld (D5B8), a	; change item slot #1 to TM33
C9		ret		; due to earlier push, jump to Deployer		

RAM writer A

Setup			stored at B9E1, deployed to CC20
AF		xor a
3C		inc a
E0 D6		ldh (D6),a
21 00 DA	ld hl, DA00
resolveDisplay		CC27
CD 21 DF	call resolveInput
E5		push hl
11 F8 FF	ld de, FFF8
19		add hl, de
54		ld d, h
5D		ld e, l
01 0C 00	ld bc, 000C
F0 FE		ldh a, (FE)
21 A9 C3	ld hl, C3A9
CD E1 30	call openSramBank
CD 65 CC	call printHex
.displayLoop
3E 7C		ld a, 7C
22		ldi (hl), a
7A 		ld a, d
CD 65 CC	call printHex
7B		ld a, e
CD 65 CC	call printHex
3E E3		ld a, E3
22 		ldi (hl), a
1A 		ld a, (de)
CD 65 CC	call printHex
36 7C		ld a, 7C
09		add hl, bc
13		inc de
7D		ld a, l
FE 13		cp 13
20 E5		jr nz, .displayLoop
CD F1 30	call closeSramBank
21 50 C4	ld hl, C450
36 ED		ld (hl), ED
E1		pop hl
18 C2		jr, resolveDisplay
printHex		CC65
F5		push af
CB 37		swap a
CD 4C C7	call .firstHex
F1		pop af
.firstHex		CC6C
E6 0F		and 0F
C6 F6		add a, F6
F6 80		or a, 80
22		ldi (hl), a
C9		ret
sampleDpad		CC74
CD 90 37	call JoyTextDelay_ForcehJoyDown
F0 AB		ldh a, (AB)
11 00 00	ld de, 0000
07		rlca
30 01		jp nc, .noDown
13		inc de
.noDown
07		rlca
30 01		jr nc, .noUp	
1B		dec de
.noUp
07		rlca
30 03		jr nc, .noLeft
11 F0 FF	ld de, FFF0
.noLeft
07		rlca
30 02		jr nc, .noRight
1E 10		ld e, 10
.noRight
07		rlca
C9		ret

RAM Writer B

ResolveInput		deployed to DF21
CD 74 CC	call sampleDpad
38 41		jr nc, .startButton
07		rlca
30 0B		jr z, noSelectButton
07		rlca
07		rlca
30 01		jr nc, .changeSramBank
E9		jp hl
.changeSramBank
F0 FE		ldh a, (FE)
83		add e
E0 FE		ldh (FE), a
C9		ret
.noSelectButton
07		rlca
30 03		jr nc, .noBButton
53		ld d, e
1E 00		ld e, 00
19		add hl, de
.noBButton
07		rlca		
30 2A		jr nc, .noAButton
E5		push hl
F0 FE		ldh a, (FE)
CD E1 30	call openSramBank
46		ld b, (hl)
.inputALoop
CD 74 CC	call sampleDpad
07 		rlca
07		rlca
30 01		jr nc , .BButtonNotPressed
43		ld b, e
.BButtonNotPressed					
0F		rrca
38 0E		jr c, .AButtonPressed
78		ld a, b
83		add e
47		ld b, a
21 50 C4	ld hl, C450
36 EC		ld (hl), EC
23		inc hl
CD 65 CC	call printHex
18 E7		jr, .inputALoop
.AButtonPressed
E1		pop hl	
70		ld (hl), b
E5		push hl
3E 05		ld a, 5
21 FD 4D	ld hl, 4DFD
CF		rst08h
.startButton
E1		pop hl
.noAButton
C9		ret

OAM DMA Hijack A
FA AB CE 	ld a, (CEAB)		
FE E1 		cp E1
C0 		ret nz		; is current selected item TM33? If yes, continue
FA C2 CE 	ld a, (CEC2)
FE 90 		cp 90
C0 		ret nz		; Is TM33 chosen while in battle? If yes, continue
3E 0D 		ld a, 0D
EA E0 CE 	ld (CEE0); a	; Force cursor to position #13, enabling use of TM33
C9		ret

OAM DMA Hijack B
C3 01 DF 	jp DF01		; jump to OAM DMA hijack B

Deployer		located at D418
3E 03 		ld a, 03
CD E1 30 	call OpenSRAM
0E 71		ld c, 71
11 20 CC 	ld de, CC20
D5		push de
21 E1 B9 	ld hl, sBox14Species
CD 1A 31 	call CopyBytes	; deploy RAM writer A to CC20
0E 48 		ld c, 48
11 21 DF 	ld de, DF21			
CD 1A 31 	call CopyBytes	; deploy RAM writer B to DF21
0E 12 		ld c, 12
11 0F DF 	ld de, DF0F
CD 1A 31 	call CopyBytes	; deploy OAM DMA hijack A to DF0F
0E 03 		ld c, 03
11 8A FF 	ld de, FF8A
CD 1A 31 	call CopyBytes	; deploy OAM DMA hijack B to FF8A
AF 		xor a
E0 89 		ld (FF89), a	; enable OAM DMA hijack by removing C9
C9		ret		; due to earlier push, jump to CC20	


Old methods for reference

Generation I

Setting up TheZZAZZGlitch's memory editor with coordinates

Main article: Player coordinates RAM writer


Use the player coordinates RAM writer to set up TheZZAZZGlitch's memory editor at DB01.


Setting up TheZZAZZGlitch's memory editor with an item set up

Main article: Reusable RAM writer

The reusable RAM writer can be use to write a byte one address at a time.

Fast sequential RAM writer

See https://archives.glitchcity.info/forums/board-115/thread-8725/page-0.html

Full Control: Real-time RAM writing with 8F

See https://archives.glitchcity.info/forums/board-115/thread-7744/page-0.html

Thanks to bbbbbbbbba and the larger GCRI community for suggesting improvements to the code initially written to determine mail codes.

Thanks to TheZZAZZGlitch and offgao, and k(ry for previous memory editors.

Generation II

Thanks to flag3833753 and Epsilon (Couldntthinkofaname) for previous work on RAM writers and inspiring various kinds of optimisations to be used in the RAM writers included in this guide.

Thanks to Scotteh for writing the mail code webapp.

Thanks to Crystal_ for their memory editor.

Thanks to Sanqui for discovering Coin Case arbitrary code execution.

Crystal

TheZZAZZGlitch's memory editor ported to Pokémon Crystal by Kai mirror (pokecrystal memory editor.sav)