Main Menu
Main Page
Forums
New pages
Recent changes
Random page
Help

Glitches
Arbitrary code execution
Pokémon cloning
Pomeg glitch and Glitzer Popping
Tweaking and voiding
Glitches by generation
Glitch categories

References/Resources
Databases
Disassembly projects
The Big HEX List
Pokémon cheat codes
Pokémon glitch terminology
Useful tools
More

Affiliates
Legendary Star Blob 2 (Hakuda) (日本語/Japanese)
Pokémon Speedruns wiki (English)
PRAMA Initiative (Français/French)
MissingNo. Glitch City (Italiano/Italian)
Become an affiliate!

Technical
Site source code

Search Wiki

 

Search Forums

 

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

0 Members and 1 Guest are viewing this topic.

Ganix

  • 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

  • French living dexer
  • Distinguished Member
  • *
  • Offline Offline
  • Gender: Male
  • Head admin of the PRAMA Initiative
    • View Profile
    • PRAMA Initiative - French Pokémon 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!

Admin of the PRAMA Initiative, the main french Pokémon glitch website
https://www.prama-initiative.com
“Anti-intellectualism has been a constant thread winding its way through our political and cultural life, nurtured by the false notion that democracy means that 'my ignorance is just as good as your knowledge.'” - Isaac Asimov

Ganix

  • 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. ;)

libjet

  • GCLF Member
  • Offline Offline
  • Gender: Male
  • Hi!
    • View Profile
Re: Full Control: Real-time RAM writing with 8F
« Reply #3 on: June 08, 2019, 09:56:54 pm »
Hello! This is my first post, so I'm sorry if i'm necroposting and I really can't be bothered to make a new thread :P

Anyway, onto the point of my post, there's a flaw in this RAM writer that I find pretty major. It's to do with the fact that once you've entered a program and saved the game, there is no apparent
way to delete it or overwrite without a memory editor and that is pretty bad news for a save file on a cartridge.
And so, I present you my "enhanced" version of this program. This is my first try at modifying ASM to do something cool, so the code is pretty messy, but it werks.

ITEM LIST:
Item            Quantity
========================
8F               x1
[Any Item]       xAny
X Accuracy       x254
Escape Rope      x84
Potion           x213
HP Up            x115
TM13             x205
TM50             x63
TM09             x240
TM48             x254
Burn Heal        x200
TM40             x178
Poke Ball        x183
Guard Spec.      x40
TM39             x185
Rare Candy       x234
PP Up            x134
X Attack         x119
X Speed          x24
TM29             xAny

2E FE 1D 54 14 D5 23 73 D5 CD FA 3F D1 F0 F8 FE 0C C8 F0 B2 04 B7 37 28 EF B9 28 EA 4F 86 41 77 43 18 E5 01
2EFE1D5414D52373D5CDFA3FD1F0F8FE0CC8F0B204B73728EFB928EA4F8641774318E501

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
    ld (hl),e           ; Clear the byte

Check_Input:
    push de             ; 'e'=$00 here, but after calling $3FFA,'e'=$01. Not good!
    call $3FFA          ; Joypad polling subroutine
    pop de              ; 'e' now equals $00 again
    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
    inc b               ; - Padding -
    or a                ; Check whether a button was released
    scf                 ; - Padding -
    jr z,Check_Input    ; If not, keep looping until one is

Check_Previous:
    cp c                ; Check if the button was pressed twice
    jr z,Next_Byte      ; Move to the next byte if so

Modify_Byte:
    ld c,a              ; Backup the previous button
    add a,(hl)          ; Add button value to current value
    ld b,c              ; - Padding -
    ld (hl),a           ; Save new value in memory
    ld b,e              ; - Padding -
    jr Check_Input      ; Loop until manually RET
End:
;This took way too long to do

What my modification does is set the (HL) to 0, prior to writing to it. This means that you can write a new program over an old one, whereas the older version
of "Full Control" added the input on top of the value already present. In other words, the older version didn't care what byte was in there before, it just added over it instead of
overwriting it. My version doesn't remove the (arguably) best feature of this either, which is the fact that the program persists in SaveRAM, and you can still press start+select
to run the program as many times as you want.
Feel free to point out any errors. (God I hope there are none)
« Last Edit: June 09, 2019, 08:55:14 am by libjet »
BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO BENKYO

Sherkel

  • Ringsome on the aquaface
  • Administrator
  • *****
  • Offline Offline
  • Gender: Male
  • PSYNCIN' IN THE VaiN
    • View Profile
Re: Full Control: Real-time RAM writing with 8F
« Reply #4 on: June 10, 2019, 12:15:26 am »
Nobody's said anything? They must have just been busy over the weekend. This is one heck of an introduction, to say the least, and of course it's great to see a new spin on a program like this one. In case you plan on sticking around, the general rule is that if it could be a new thread, it's not an unnecessary bump, so you're fine there.

I come and go. Apparently still more than most of the other regulars, so hard to say it's a semi-hiatus of some sort. Suggestions for wiki organization are appreciated here if you haven't seen this thread yet.
I don't have a habit of keeping Discord open, so direct inquiries are still preferred through here.