Sending input via joypad using 8F
Posted by: ISSOtm
Date: 2016-08-18 21:13:52
I was wondering if a 8F setup coud get the job done.
WARNING : this post is composed of huge chunks of text WITHOUT ANY TL;DR.
If feeling bored, get medical advice && GTFO. Thanks.
I wrote some code that should get the job done. I didn't test it, so I have totally zero proof that it works fine.
I guess having an empty active box before running this is better.
ld hl, $DA80 ; start of current box data
ld b, 1
mainloop:
; VBlank interrupt calls ReadJoypad for us, yay !
call Joypad ; located early in ROM0, so no bank switch, yay !
ld a, ($FF00 + $B3) ; hJoyPressed
rla ; Down
jr nc, $+2
srl b ; halves B
rla ; Up
jr nc, $+3
sla b ; doubles B since C = 0
rla ; Left
jr nc, $+1
dec b
rla ; Right
jr nc, $+1
inc b
rla ; Start
jp c, $DA80 ; jump to written code
rla ; Select
jr nc, $+2
ld (hl), b
inc hl
rla ; B
ret c ; quit if then
; there's room for code for B and A.
jr mainloop
User manual :
How to operate
1. Set up the thing
Optional : empty your current PC box / switch to one you don't care about. The box open as 8F is ran will be heavily damaged :)
2. Run 8F ; the value will be set to 1
3. Write values :
* Press Right to increment the value
* Press Left to decrement the value
* Press Up to halve the value
* Press Down to double the value
* Press Select to place the value and advance forwards
* Press Start to run the values as code
* Press B to abort
4. ???
5. Profit.
Size limit
You should avoid writing too many bytes, otherwise expect crashes. $452 (1152) bytes is a reasonable limit.
Explanation of joypad routines :
ReadJoypad reads joypad input and transfers it into a more "readable" format to hJoyInput
Joypad updates three variables containing the state of the joypad keys basing itself on hJoyInput ; hJoyPressed contains the keys that were pressed since last time (1 = just pressed)
Format :
Bit 7 - Down
Bit 6 - Up
Bit 5 - Left
Bit 4 - Right
Bit 3 - Start
Bit 2 - Select
Bit 1 - B
Bit 0 - A
Compiled, that'd give
06 01
21 80 DA
CD ?? ??
F0 B3
17
30 02
CB 38
17
30 03
CB 20
17
30 01
04
17
30 01
05
17
DA 80 DA
17
30 02
70
23
17
D0
18 DD
This is 43 bytes large as-is. There is a chance that could fit in one inventory item list.
Another option would be to have one part of the code set to be in the item pack, and the rest sitting in the PC.
The final jr mainloop would then become a jp mainloop, though.
Also, the code could be written to SRAM bank 0, in the sprite decompression data zone.
That'd require to enable SRAM R/W plus switching to bank 0 (I recall some actions cause this bank to be loaded ? I can't remember which, though)
Other ideas for storing :
-> Pokémans (party is prohibited due to 8F setup)
Could store to Daycare or current box.
Opening SRAM also allows using other boxes.
Pokémon data :
[table]
[tr]
[td]Data[/td][td]Usability[/td][td]Comments[/td]
[/tr]
[tr]
[td]Pokémon ID[/td][td]Good[/td][td]Unless using hybrids, linked to ID list.[/td]
[/tr]
[tr]
[td]HP[/td][td]Good[/td][td]High HP usually requires high levels.[/td]
[/tr]
[tr]
[td]Level[/td][td]Good[/td][td]> 100 is tedious[/td]
[/tr]
[tr]
[td]Status[/td][td]Low[/td][td]Only a few values are possible.[/td]
[/tr]
[tr]
[td]Types[/td][td]Medium[/td][td]linked to ID[/td]
[/tr]
[tr]
[td]Held item (???)[/td][td]???[/td][td]Is this set in Gen 1 ? Catch rate maybe ?[/td]
[/tr]
[tr]
[td]Moves[/td][td]Medium[/td][td]Restricted to a specific learnset, I guess. Plus, 00 can't be created nor moved around, except with Metamorph (maybe Mew). Dammit.[/td]
[/tr]
[tr]
[td]Trainer ID[/td][td]Super low[/td][td]… duh.[/td][/tr]
[tr]
[td]Experience[/td][td]Low[/td][td]No one likes manipulating EXP. Except Metarkrai, I guess.[/td]
[/tr]
[tr]
[td]EVs[/td][td]Low[/td][td]Same as above, i guess.[/td]
[/tr]
[tr]
[td]IVs[/td][td]Super low[/td][td]Even Metarkrai doesn't manipulate IVs.[/td]
[/tr]
[tr][td]PP[/td][td]Medium[/td][td]Depend on the mon's moves.[/td]
[/tr]
[tr]
[td]Trainer name[/td][td]Super low[/td][td]Restricted values set, repeating pattern… nope.[/td]
[/tr]
[tr][td]Mon's name[/td][td]Low[/td][td]Same value restrictions, but patterns are different. Careful of the $50, though.[/td][/tr][/table]
So, at best, using one Pokémon's PP and the following's ID, HP and level, that'd give us 8 bytes per Pokémon.
-> Using parts of the game as "gadgets".
I don't think that's going to work. But maybe…
We're already using the game's joypad routines ; the rest of the code is, to me, too specific to be gadget-able.
-> Names
Most letters perform arithmetics… but it looks like lowercase x pops bc, y is jp nz, and z is jp.
Other than that, it seems pretty useless. The other guess would be using glitch mon names ?
-> Stack
Immediately following the mon nicks is the stack… yet :
1. the stack is in RAM, but I don't think this RAM is zero'ed when booting (=> quitting the nicks won't nicely NOP slide to the stack
2. jumping to the stack would imply manipulaing it… but that requires code : dismissed.
3. ROP (Return-Oriented Programming) seems like an option, but I don't think this game has the right gadgets for our purposes, as stated above.
[EDIT]
Aldrasio suggested not to disable VBlank, so I edited the code accordingly. Saves 4 bytes.
[EDIT 2]
Aldrasio suggested using sla b instead of ccf/rl b. Saves 1 byte.