Main Menu
Main Page
Forums
Recent changes
Random page
Help

Databases
GlitchDex
AttackDex
ItemDex
TypeDex
UnownDex
More

Major Glitches
Trainer escape glitch
Old man trick
Celebi trick
Select glitches (Japan)
SRAM glitch
CoolTrainer♀ corruption
LOL glitch
Rival LOL glitch
Super Glitch
ZZAZZ glitch
Pomeg corruption glitch (Glitzer Popping)
Tweaking
Elite Four door glitch (Japan)
Pokémon merge glitch
Pokémon cloning
Time Capsule exploit
Arbitrary code execution
Coin Case glitch
More

Other Glitch Categories
Glitches by generation
Glitches between two generations
Japan-only/language specific glitches
Music glitches
Natural glitches
Non-core series glitches
Non-Pokémon glitches
Officially acknowledged glitches
Recurring glitches
Dead glitches

References
Pokémon GameShark codes
The Big HEX List
GB programming
Curiosities
Debugging features
Easter eggs
Error traps
Glitch areas
Glitch myths
Non-glitch exploits
Placeholder texts
Pokémon glitch terminology
Unused content and prerelease information

Useful Tools
8F Helper
GBz80 to Items
Old man trick name generator
PATH (Prama's Advanced Tweaking Heaven)
Save file editors
Special stat/Pokémon converter
Trainer escape Trainer Pokémon finder

Affiliates
Legendary Star Blob 2 (Hakuda)
Pokémon Speedruns wiki
PRAMA Initiative
Become an affiliate!

Search Wiki

 

Search Forums

 

Author Topic: Full Control: Real-time RAM writing with 8F  (Read 500 times)

0 Members and 1 Guest are viewing this topic.

Cryo

  • Arceus Tamer
  • Distinguished Member
  • Offline Offline
  • Glitch researcher
    • View Profile
Full Control: Real-time RAM writing with 8F
« on: December 20, 2016, 10:58:25 pm »
Whew, it definitely took a few days, and the code may not look all that great, but I've finally come up with a method of using the GameBoy's joypad to write arbitrary bytes to RAM in as little time as possible with as few buttons as possible.

HOW IT WORKS:
When 8F is used, the screen and sound will function as normal, but the controls will lock up and you will now be in INPUT mode. During this mode, any button you press will add that button's value to the specified byte in memory, with two exceptions: If you press the same button twice in a row, it will move on to the next byte; and if you hold (or press) the START and SELECT buttons together at the same time, the program will jump to the specified offset and start executing your code.

This allows for a 1-to-1 mapping of buttons to values for optimal speed while still providing all necessary functionality.

NOTE: Due to space limitations, you must press A once before you enter anything on the joypad. When you press A to select the USE option on 8F, the game registers that as the initial value to be executed. Pressing A before you enter your own code skips this junk byte, and it's also why HL is initially set to $D3FE instead of $D400 in the code below.

ITEM LIST:
Item            Quantity
========================
8F              x1
[Any Item]      xAny
X Accuracy      x254
Escape Rope     x84
Potion          x213
HP Up           x205
TM50            x63
Soda Pop        x240
TM48            x254
Burn Heal       x200
TM40            x178
Guard Spec.     x183
Rare Candy      x241
X Speed         x185
X Defense       x40
TM35            x79
X Attack        x134
Ether           x119
X Special       x24
TM28            xAny


ASM:
Code: [Select]
Start:
    ld l,$FE            ; Destination = $D3FE
    dec e               ; Zero out E
    ld d,h              ; DE = $D300
    inc d               ; DE = $D400 (Code Start)
    push de             ; Push onto the stack for later RET

Next_Byte:
    inc hl              ; Go to the next byte

Check_Input:
    call $3FFA          ; Joypad polling subroutine
    dec a               ; - Padding -
    ldh a,($F8)         ; Get the current held button
    cp $0C              ; START + SELECT = exit
    ret z               ; Jump to arbitrary code ($D400)

Check_Released:
    ldh a,($B2)         ; Get the most recently released button
    scf                 ; - Padding -
    or a                ; Check whether a button was released
    jr z,Check_Input    ; If not, keep looping until one is

Check_Previous:
    ld b,e              ; - Padding -
    cp c                ; Check if the button was pressed twice
    ld b,d              ; - Padding -
    jr z,Next_Byte      ; Move to the next byte if so

Modify_Byte:
    ld c,a              ; Backup the previous button
    ld b,c              ; - Padding -
    add a,(hl)          ; Add button value to current value
    ld d,b              ; - Padding -
    ld (hl),a           ; Save new value in memory
    ld b,h              ; - Padding -
    jr Check_Input      ; Loop until manually RET
End:


EXAMPLE:
One of the things that I use this method for the most has to do with cartridge swapping capabilities. The setup below simply puts P14 to low and enters STOP mode, followed by a RET instruction to continue normal execution. This means that you can enter STOP mode, swap cartridges, then press any button on the D-Pad to return execution.

ASM:
Code: [Select]
ld a,$EF
ldh ($00),a
stop
ret

To execute the code above, simply use the 8F item, then press the buttons below in sequence. Each line represents a byte written to memory, with the first line skipping the junk byte and the last line jumping to the written program.

BUTTON INPUT:
A
LEFT RIGHT START SELECT B B
DOWN UP LEFT START SELECT B A A
DOWN UP LEFT LEFT
LEFT
RIGHT RIGHT
A A
DOWN UP START A A
START + SELECT


NOTE: If you pop the cartridge out, put the same cartridge back in, then exit STOP mode, then the game will continue executing as normally. However, the values written to RAM remain there, so in order to re-run the stop routine above, the only buttons you'd have to press are START + SELECT.

Putting in the same combination twice without resetting will effectively double the existing program's bytes in RAM, since this is an additive approach. One pretty rad workaround is the polymorphic aspect of the setup—you can alter the items in your bag (to remove padding, etc.) and save the game with your new RAM writing bulldozer. ;D


PS: This method was successfully tested on Pokemon Red and Pokemon Blue hardware; I'm not sure about Pokemon Yellow yet, but it should work just fine.
« Last Edit: December 22, 2016, 08:37:41 am by Cryo »

Krys3000

  • The frenchie
  • Distinguished Member
  • *
  • Offline Offline
  • Gender: Male
  • Head admin of the PRAMA Initiative
    • View Profile
    • PRAMA Initiative - Main french pokemon glitch website
Re: Full Control: Real-time RAM writing with 8F
« Reply #1 on: December 22, 2016, 07:58:43 am »
Very Nice, I need to test this!

Cryo

  • Arceus Tamer
  • Distinguished Member
  • Offline Offline
  • Glitch researcher
    • View Profile
Re: Full Control: Real-time RAM writing with 8F
« Reply #2 on: December 22, 2016, 08:42:54 am »
I did have a usage example previously, but it had a few bugs in it and I removed it. I've modified the post with a new example, but an even easier and faster test would be to write the STOP function to RAM, which would just require these button inputs:

A
RIGHT RIGHT
START + SELECT


Of course, the only thing you can do is reset the system after that, but it's a quick and dirty approach if I just want to test how clean a cartridge is when cartridge swapping. Since the system will reset if the game is inserted at the wrong angle or is too dirty, staying in STOP mode after insertion means that the game is (relatively) clean and that it was inserted at the right angle. ;)