Buongiorno a tutti, oggi ho deciso di creare questa guida per permettere a tutti di creare abbastanza semplicemente un menu personale da inserire al posto dell’originale usando uno script.
Aggiornata alla Versione 2.1
Prima vi spiegherò come creare un semplice menu usando i multichoice, successivamente vedremo come farne uno più “grafico “ e funzionale, infine vedremo come inserire il nostro menu.
Per ora fornirò i valori da modificare per FireRed, successivamente aggiornerò coi valori per Rosso Fuoco e Smeraldo.
Premessa:
Io mostrerò direttamente il solo menu con pokedex e pokemon attivi, per renderlo esattamente come l’originale dovrete creare 4 menu diversi (Zona safari, Normale, No Pokedex, No Pokemon), mettendo i relativi controlli sulle flag/variabile all’inizio dello script, per la zona safari dovrebbe essere la variabile 0x406E (a 0 non siete nella zona safari, a 2 lo siete), l’opzione Pokemon usa la flag 0x828, mentre il Pokedex la 0x829
CREAZIONE:
Con Multichoice (non lo consiglio, ma utile didatticamente)
Esistono 3 tipi di multichoice, quello classico (il medesimo utilizzato dal menu originale), il multichoice2 che è uguale, ma permette di scegliere una posizione di default per il cursore diversa dalla posizione 1 e il multichoice3 che invece vi permette di creare un menu orizzontalmente, su una o più righe.
L'unica limitazione del multichoice3 è che non potete avere numeri diversi di opzioni nelle righe, per esempio se scegliete di avere 3 opzioni per riga e avete 7 o 8 opzioni ne vedrete solo 6, due righe da 3.
Se non sapete come aggiungere un multichoice per FireRed esiste un tools molto semlice, reperibile quì:
https://www.pokecommunity.com/showthread.php?t=335308
Premessa: un menu creato col multichoice non viene chiuso premendo il tasto start, solo premendo b o ,se lo inserite, col tasto esci, inoltre sarete costretti a disattivare il ritorno al menu dopo aver utilizzato una qualunque funzione se usate degli OAM perché al ritorno avrebbero dei colori sballati a causa del fade e purtroppo non potete utilizzare il BG0 col multichoice.
Ora analizziamo lo script:
#dynamic 0x800000 -> Non credo servano spiegazioni
@inizio
lock ->ovviamente bisogna bloccare il pg
setvar 0x4500 0x0 ->Variabili per caricare un'immagine
setvar 0x4501 0x0
setvar 0x4502 0x0
callasm 0x872F501 ->Routine per mostrare l’immagine
multichoice3 0x0 0x3 0xF 0x2 0x0 Il cuore del nostro menu.
0x0 e 0x3 sono le posizioni X e Y
0xF è il numero del multichoice che ho utilizzato, ovviamente dovete usare il vostro

0x2 sono il numero di opzioni per riga (non presente nel miltichoice1 e 2)
l’ultimo valore (0x0) va lasciato zero se volete dare la possibilità di uscire premendo b.
copyvar 0x8000 LASTRESULT Questa sfilza di comandi semplicemente controlla la selezione e rimanda alla giusta parte del nostro script
compare 0x8000 0x0
if 0x1 goto @dex
compare 0x8000 0x1
if 0x1 goto @poke
compare 0x8000 0x2
if 0x1 goto @zaino
compare 0x8000 0x3
if 0x1 goto @trainer
compare 0x8000 0x4
if 0x1 goto @salva
compare 0x8000 0x5
if 0x1 goto @opzioni
callasm 0x872f631
compare 0x8000 0x7F
if 0x1 goto @B
end
'---------------
#org @dex
fadescreen 0x1
pause 0x1 Fadescreen e pause servono per avere un passaggio più “morbido” alla funzione, è fondamentale solo per lo zaino (altrimenti fa un glitch grafico prima di aprire la funzione), ma consiglio di metterlo a tutti, tranne al salvataggio.
callasm 0x806F411 ->Routine Pokedex
return
'---------------
#org @poke
fadescreen 0x1
pause 0x1
callasm 0x806F44D ->Routine Pokemon
return
#org @zaino
fadescreen 0x1 ->Fondamentale per lo zaino
pause 0x1
callasm 0x806F481 ->Routine Zaino
return
#org @trainer
fadescreen 0x1
pause 0x1
callasm 0x806F4B5 ->Routine Allenatore
return
#org @salva -> Al salvataggio NON mettete il fadescreen + pause
#org 0x7A12b0
callasm 0x872F631 ->Routine per cancellare immani (se l'avete usate)
nop ->niente, ma mi piace separare

special 0x23 ->Salvataggio
waitstate ->Fondamentale, altrimenti non attenderà che abbiate finito
return
#org @opzioni
fadescreen 0x1
pause 0x1
callasm 0x806F4FD ->Routine Opzioni
return
#org @b
callasm 0x872F631->Routine per cancellare immani (se le avete usate)
return
Io non ho inserito il tasto esci, non l'ho mai trovato molto utile, ma nel caso basta rimandare alle stesse funzioni del tasto B
Potete aggiungere o modificare l’ordine delle funzioni a vostro piacimento molto semplicemente o renderne alcune non funzionanti in base a delle flag.
Per abbellirlo potete inserire delle icone o caricare altre immagini, potete usare sia showpokepic che funzioni per immagini mugshot (come ho fatto io), a voi la scelta, l’unica limitazione è che non potete usare immagini BG0, non funzionano con il multichoice e di conseguenza dovrete disabilitare il ritorno al menu.
Un piccolo consiglio nel caso vogliate inserire delle icone davanti o direttamente al posto del testo del menu… Quando create la tabella da usare nel multichoice lasciate degli spazi vuoti prima del testo se le icone le volete davanti o nel caso le vogliate senza il testo mettete tutto vuoto ma almeno in un elemento mettete 3-4 spazi o più (a seconda delle dimensioni).
Menu senza multichoice (Consigliato):
Questa volta non useremo il multichoice, perciò abbiamo bisogno di inserire una funzione per controllare i tasti premuti, usiamo questa Routine di FBI:
Controllo Tasti:
Code:
.text
.align 2
.thumb
.thumb_func
main:
ldr r0, =(0x30030F0)
ldrh r1, [r0, #0x2E] @byte in super state for keypress
cmp r1, #0x0
beq cont
ldr r0, =(0x20370B8) @var 0x8000 location
strh r1, [r0]
ldr r4, =(0x806B922 +1)
bx r4
cont:
mov r0, #0x1
and r0, r0, r1
cmp r0, #0x0
beq section
ldr r1, =(0x806B922 +1)
bx r1
section:
ldr r0, =(0x806B8A6 +1)
bx r0
.align 2
Andate all’offset 6B89A scrivete:
00 00 00 48 00 47 XX XX XX 08
XX XX XX è il puntatore alla routine +1
Questi sono i valori che ci restituirà in base al tasto premuto, che verranno salvati nella var 8000:
Giù: 0x80
Su: 0x40
Sinistra: 0x20
Destra: 0x10
A: 0x1
B: 0x2
Select: 0x4
Start: 0x8
L’autore ci informa che se più tasti verranno premuti contemporaneamente il valore che ci sarà restituito sarà la somma, ma anche premendo b + start , visto che lavoriamo in esadecimale, sarà 8+2=A , dunque non ci saranno problemi.
thread originale ->
https://www.pokecommunity.com/showpost.p...tcount=531
Veniamo ora alla parte grafica.
Avremo bisogno di caricare 2 immagini:
>una trasparente, per nascondere il menu originale (tranquilli, diventerà un fantasma molto gentile)
>una per il nostro menu.
Per farlo possiamo usare la stessa routine, con opportune modifiche, io ve le fornirò separate, ma niente vi vieta di inserire un controllo su una flag e unirle in un’unica.
La routine che ho usato per caricare un'immagine bg0 è questa, realizzata dall'utente jiangzhengwenjz ->
https://wahackforo.com/t-40368-pag2
Potete utilizzare altre routine ovviamente, l’importante però è che utilizzino il BG0 e non gli OAM se volete lasciare abilitato il ritorno al menu dopo aver avviato una funzione (come l’originale), perché gli OAM non apprezzano molto i fadescreen.
Creazione Immagini:
Innanzitutto create un’immagine vuota, con solo il colore della trasparenza, 72 x 120 (L x H), usate le stesse palette che utilizzate per le immagini del vostro menu (perché mai farne altre).
Successivamente create le immagini del vostro menu delle dimensioni che preferite, ma tutte delle stesse dimensioni.
Inserite le immagini e le palette compresse LZ77, con unLZ o NamelessSpriteEd e inserite i relativi puntatori nella vostra tabella (potete creare 2 tabelle diverse per l’immagine che ci servirà per coprire il menu originale e quelle dei vostri menu o usare la stessa, a voi la scelta)
La tabella deve essere in questo formato
[Puntatore immagine] [Puntatore palette]
potete inserirne fino a 65536
Ora compilate queste routine e inseritele in qualunque posizione
Nascondere il menu originale:
.equiv table_location, 0x08XXXXXX @sostituite con la vostra tabella
.thumb
push {r4-r5, lr}
sub sp, sp, #0x18
mov r1, #0
mov r2, #20 @coordinata X/8
mov r3, #0 @coordinata y/8
mov r0, #9 @larghezza /8 -> 72
str r0, [sp]
mov r0, #15 @altezza/8 ->120
str r0, [sp, #4]
mov r0, #0xD
str r0, [sp, #8]
mov r0, #0x40
str r0, [sp, #0xC]
add r0, sp, #0x10
ldr r4, =0x810FE51
bl bx_r4
add r0, sp, #0x10
ldr r4, =0x8003CE5
bl bx_r4
ldr r4, =0x2039990
strb r0, [r4]
ldr r4, =0x8003FA1
bl bx_r4
ldr r0, =0x20370C0
ldrh r0, [r0]
ldr r1, =table_location
lsl r0, r0, #3
add r0, r0, r1
ldr r5, [r0, #4]
ldr r0, [r0]
ldr r1, =0x6008800
swi 0x12
mov r0, r5
mov r1, #0xd0
mov r2, #0x20
ldr r4, =0x80703A9
bl bx_r4
mov r0, #0
ldr r4, =0x80020BD
bl bx_r4
add sp, sp, #0x18
pop {r4-r5, pc}
bx_r4: bx r4
Mostrare l’immagine del nostro menu:
.equiv table_location, 0x08XXXXXX @sostituite con la vostra tabella
.thumb
push {r4-r5, lr}
sub sp, sp, #0x18
mov r1, #0
mov r2, #0 @coordinata X/8 Inserite la posizione X, Yche preferite
mov r3, #45 @coordinata y/8
mov r0, #15 @larghezza/8 Inserite larghezza e altezza delle immagini del vostro menu che avete creato
str r0, [sp]
mov r0, #7 @altezza/8 E’ importante che vi ricordiate di inserire il valore diviso 8.
str r0, [sp, #4]
mov r0, #0xD
str r0, [sp, #8]
mov r0, #0x40
str r0, [sp, #0xC]
add r0, sp, #0x10
ldr r4, =0x810FE51
bl bx_r4
add r0, sp, #0x10
ldr r4, =0x8003CE5
bl bx_r4
ldr r4, =0x2039990
strb r0, [r4]
ldr r4, =0x8003FA1
bl bx_r4
ldr r0, =0x20370C0
ldrh r0, [r0]
ldr r1, =table_location
lsl r0, r0, #3
add r0, r0, r1
ldr r5, [r0, #4]
ldr r0, [r0]
ldr r1, =0x6008800
swi 0x12
mov r0, r5
mov r1, #0xd0
mov r2, #0x20
ldr r4, =0x80703A9
bl bx_r4
mov r0, #0
ldr r4, =0x80020BD
bl bx_r4
add sp, sp, #0x18
pop {r4-r5, pc}
bx_r4: bx r4
Eliminare l'immagine (serve per entrambe le precedenti):
.thumb
push {r4, lr}
ldr r4, =0x2039990
ldrb r4, [r4]
mov r1, #0
mov r0, r4
ldr r3, =0x810F4D9
bl bx_r3
mov r0, r4
mov r1, #2
ldr r3, =0x8003F21
bl bx_r3
mov r0, r4
ldr r3, =0x8003E3D
bl bx_r3
pop {r4, pc}
bx_r3: bx r3
Per utilizzarle nello script:
setvar 0x8004 0x(numero immagine nella tabella, la prima posizione è 0)
callasm 0x8(offset in cui avete inserito la routine per mostrare l'immagine +1)
Per cancellare l'immagine basta usare
callasm 0x8(offset in cui avete inserito la routine per cancellare l'immagine +1)
Dopo aver cancellato un'immagine è necessario che mettiate una pausa, altrimenti non verrà mostrata l'immagine che andrete a caricare successivamente (se non per un breve istante forse
E se proverete a non far cancellare l'immagine prima di mostrare la nuova...
funzionerà magnificamente, senza creare nessun effetto flash, ma intorno ai 25-26 cambi immagine potranno succedere due cose:
-Il gioco potrebbe freezare
-si aprirà una specie di msgbox invisibile (lo vedrete nel map view del VBA) che vi cancellerà l'immagine, o parte di essa se si trova nello stesso punto, ma in ogni caso non vi permetterà di cancellare correttamente l'immagine, solo un warp o l'apertura di una funzione può sistemare il problema
perciò.... usate la pausa finché non analizzo accuratamente la routine o ne trovo un' altra
FUNZIONAMENTO:
Prima dello script vediamo di capire a grandi linee il funzionamento.
Si comincia caricando l’immagine in bg0 per nascondere il menu originale, poi si entra nel ciclo, partendo dalla prima funzione del menu. Ciò che si farà in ogni ciclo sarà cancellare l’immagine del vostro menu (nel primo caso cancellerà l'immagine che abbiamo inserito per cancellare il menu originale, ma non comparirà, tranquilli, successivamente cancellerà quella precedente del vostro menu), usare sound 0x5 per avere il suono del cursore, dopodiché il gioco attenderà che premiate un tasto e vi manderà alla parte di script relativa.
Sta a voi decidere come volete che sia il vostro menu, se si sviluppera in orizzontale, verticale, circolare o con forme misteriose, con o senza cursore, basta modificare adeguatamente i controlli e le immagini da caricare.
Analizziamo il primo ciclo:
Il ciclo inizia sempre con il suono del cursore, cancelliamo l’immagine e dopo la pausa viene caricata la nuova immagine, sovrascrivendo la vecchia
#org @dex
sound 0x5 -> suono movimento cursore
callasm 0x872ed11 -> routine per cancellare l’immagine
pause 0x1 -> con la routine che utilizzo è necessario, altrimenti non mostra la nuova immagine
setvar 0x8004 0x1 -> variabile relativa all’immagine da caricare
callasm 0x872F1C1 -> routine per mostrare la nuova immagine
waitkeypress -> Ecco, questo è il comando più importante, il sistema resta in attesa che premiate
un tasto
compare 0x8000 0x1 ora controlliamo cosa è stato premuto e andiamo alla giusta funzione, ovviamente
dipende da come avete deciso di sviluppare il menu
if 0x1 goto @dexprem -> premuto il tasto A
compare 0x8000 0x10
if 0x1 goto @poke ->Premuto destra
compare 0x8000 0x20
if 0x1 goto @opzioni -> Premuto sinistra (se non volete lo scrolling infinito semplicemente eliminate questo caso dalla posizione più a sinistra e il caso precedente dalla posizione più a destra)
compare 0x8000 0x2 ->premuto il tasto B esce dal menu
if 0x1 goto @exit
compare 0x8000 0x8 ->premuto il tasto start esce da menu
if 0x1 goto @exit
goto @dex -> questo è fondamentale, se viene premuto un tasto diverso rimandiamo
all’inizio di questa sezione, attendendo nuovamente la pressione di un tasto
return
Ora vediamo se è stato selezionato il Pokedex
#org @dexprem
sound 0x5 -> suono movimento cursore
callasm 0x872ed11 ->cancello l’immagine o le immagini se più di una… in realtà non è fondamentale, visto che una qualunque funzione, tranne il salvataggio, cancellerà direttamente tutto (come un warp).
fadescreen 0x1 come
pause 0x1 -> Fadescreen e pause servono per avere un passaggio più “morbido” alla funzione, è fondamentale solo per lo zaino (altrimenti fa un glitch grafico prima di aprire la funzione), ma consiglio di metterlo a tutti, tranne al salvataggio.
callasm 0x806F411 ->Routine pokedex
release
return
Analizziamo ora il salvataggio, l’unico diverso
#org @salvarprem
sound 0x5 -> il solito suono
callasm 0x872ed11 ->Rimuovo le immagini
special 0x23 ->Lo special 23 è proprio il salvataggio
waitstate ->Fondamentale, altrimenti non attenderà che abbiate finito
release
return
E ora un esempio completo:
#dynamic 0x7A0000
#org @inizio
lock
setvar 0x8004 0x1
callasm 0x872F1C1
goto @dex
#org @dex
sound 0x5
callasm 0x872ed11
pause 0x1
setvar 0x8004 0x1
callasm 0x872F1C1
waitkeypress
compare 0x8000 0x1
if 0x1 goto @dexprem
compare 0x8000 0x10
if 0x1 goto @poke
compare 0x8000 0x20
if 0x1 goto @opzioni
compare 0x8000 0x2
if 0x1 goto @exit
compare 0x8000 0x8
if 0x1 goto @exit
goto @dex
return
end
#org @dexprem
sound 0x5
callasm 0x872ed11
fadescreen 0x1
pause 0x1
callasm 0x806F411
release
return
#org @poke
sound 0x5
callasm 0x872ed11
pause 0x1
setvar 0x8004 0x2
callasm 0x872F1C1
waitkeypress
compare 0x8000 0x1
if 0x1 goto @pokeprem
compare 0x8000 0x10
if 0x1 goto @zaino
compare 0x8000 0x20
if 0x1 goto @dex
compare 0x8000 0x2
if 0x1 goto @exit
compare 0x8000 0x8
if 0x1 goto @exit
goto @poke
return
#org @pokeprem
sound 0x5
callasm 0x872ed11
fadescreen 0x1
pause 0x1
callasm 0x806F44D
release
return
#org @zaino
sound 0x5
callasm 0x872ed11
pause 0x1
setvar 0x8004 0x3
callasm 0x872F1C1
waitkeypress
compare 0x8000 0x1
if 0x1 goto @zainoprem
compare 0x8000 0x10
if 0x1 goto @player
compare 0x8000 0x20
if 0x1 goto @poke
compare 0x8000 0x2
if 0x1 goto @exit
compare 0x8000 0x8
if 0x1 goto @exit
goto @zaino
return
#org @zainoprem
sound 0x5
callasm 0x872ed11
fadescreen 0x1
pause 0x1
callasm 0x806F481
release
return
#org @player
sound 0x5
callasm 0x872ed11
pause 0x1
setvar 0x8004 0x4
callasm 0x872F1C1
waitkeypress
compare 0x8000 0x1
if 0x1 goto @playerprem
compare 0x8000 0x10
if 0x1 goto @salva
compare 0x8000 0x20
if 0x1 goto @zaino
compare 0x8000 0x2
if 0x1 goto @exit
compare 0x8000 0x8
if 0x1 goto @exit
goto @player
return
#org @playerprem
sound 0x5
callasm 0x872ed11
fadescreen 0x1
pause 0x1
callasm 0x806F4B5
release
return
#org @salva
sound 0x5
callasm 0x872ed11
pause 0x1
setvar 0x8004 0x5
callasm 0x872F1C1
waitkeypress
compare 0x8000 0x1
if 0x1 goto @salvarprem
compare 0x8000 0x10
if 0x1 goto @opzioni
compare 0x8000 0x20
if 0x1 goto @player
compare 0x8000 0x2
if 0x1 goto @exit
compare 0x8000 0x8
if 0x1 goto @exit
goto @salva
return
#org @salvarprem
sound 0x5
callasm 0x872ed11
special 0x23
waitstate
release
return
#org @opzioni
sound 0x5
callasm 0x872ed11
pause 0x1
setvar 0x8004 0x6
callasm 0x872F1C1
waitkeypress
compare 0x8000 0x1
if 0x1 goto @opzioniprem
compare 0x8000 0x10
if 0x1 goto @dex
compare 0x8000 0x20
if 0x1 goto @salva
compare 0x8000 0x2
if 0x1 goto @exit
compare 0x8000 0x8
if 0x1 goto @exit
goto @opzioni
return
#org @opzioniprem
sound 0x5
callasm 0x872ed11
fadescreen 0x1
pause 0x1
callasm 0x806F4FD
release
return
#org @exit
sound 0x5
callasm 0x872ed11
release
return
E il mio risultato: (Ho volutamente lasciato un'immagine OAM per farvi vedere cosa succede al ritorno)
INSERIMENTO:
Ora vediamo come poter utilizzare il nostro nuovo menu al posto dell’originale….
Il metodo non sarà il più elegante, ma è funzionale, ecco le semplici modifiche da effettuare:
Compilate questa Routine da qualche parte
.text
.align 2
.thumb
.thumb_func
main:
ldr r0, = 0x8XXXXXX @Sostituite con l’offset del vostro script
ldr r1, =(0x8069AE4 +1)
bl linker
end:
mov r0, #0x1
ldr r1, =(0x806ED70 +1)
bx r1
linker:
bx r1
.align 2
Andate all’offset 6ED5C e scrivete:
00 48 00 47 XX XX XX 08
XX XX XX è il puntatore alla routine +1
Successivamente fate ancora questa modifica:
0806F36C in questo offset c’è un puntatore a una posizione sulla ram in cui vengono salvate le funzioni da avere attive nel menu in questo modo-> 00 01 02 03 04 05 06
00 Pokedex
01 Pokemon
02 Zaino
03 Scheda allenatore
04 Salva
05 Opzioni
06 Esci
Vi basterà cambiare quel puntatore con un offset in cui ci sia 06 ripetuto sette volte, vi consiglierei di scriverlo voi da qualche parte, ma potete usare una qualunque posizione già presente, visto che si limiterà a leggere i valori, per esempio ->00B11F08, in questo modo ogni voce del menu “fantasma” sarà esci, perciò non ci darà più nessun problema.
E infine, per evitare che si apra in basso la striscia blu con le spiegazioni delle funzioni del menu cambiate all’offset 06F103 da D1 a E0. Ora qualunque opzione sia selezionata nel button mode (HELP, LR o L=A) non aprirà più quelle spiegazioni, aprendo comunque l’help premendo L o R se sceglierete l’opzione HELP.
Disabilitare ritorno al Menu:
Se volete che dopo aver utilizzato una funzione non si riapra il menu seguite la spiegazione di Emme 97
(07-05-2018 09:01 AM)eMMe97 Ha scritto:
Codice:
Offset 0x80568AF inserisci 00 00 00 00
BUG:
Attualmente non ne ho trovati, anche il segna passi/Ball della zona Safari se non ci mettete immagini BG0 Sopra

, ma se ne trovate segnalate pure.
Spero di aver fatto cosa gradita e di non aver commesso troppi errori, i concetti sono semplici, ma c'è molto da scrivere