Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - gcc è impazzito o mi sto perdendo qualcosa?
Forum - C/C++ - gcc è impazzito o mi sto perdendo qualcosa?

Avatar
Bonnox (Member)
Pro


Messaggi: 82
Iscritto: 23/08/2014

Segnala al moderatore
Postato alle 15:29
Martedì, 05/07/2016
Buongiorno, volevo sentire il vostro parere su un paio di stranezze che mi stanno capitando.
Premetto di aver letto il post in alto che dice che i nabbi rischiano il linciaggio se dicono che il compilatore è buggato (o se vogliono fare un sistema operativo, ma questa è un'altra storia...:rofl: ).

Devo compilare del sorgente C in asm, e utilizzo il seguente comando:
Codice sorgente - presumibilmente Plain Text

  1. "D:\devkitPro\devkitARM\bin\arm-none-eabi-gcc.exe" -O1 -Wall -mthumb -mthumb-interwork -S "%~1"



La cosa strana è che ottengo un comportamento differente a seconda che metta le ottimizzazioni (di qualsiasi livello) o meno, ma in teoria ciò che è afflitto, secondo me dovrebbe essere indipendente dalle ottimizzazioni.

Mi spigo meglio illustrando il caso.

All'inizio del codice c'è questo:

Codice sorgente - presumibilmente C++

  1. #define ASM_CMT(str) asm ("@; " str)
  2.  
  3. #define MY_FUNC \
  4. ASM_CMT("-----------------");\
  5. ASM_CMT("-----------------");\
  6. ASM_CMT("-----------------");\
  7. ASM_CMT("-----------------");\
  8. ASM_CMT("-----------------");\
  9. ASM_CMT("-----------------");\
  10. ASM_CMT("-----------------");\
  11. asm  (".align 8, 0x00");\
  12. asm  (".ascii \"MAIN\" " ) ; \
  13. asm  (".align 4, 0x00");\
  14. ASM_CMT("-----------------");\
  15. ASM_CMT("-----------------");\
  16. ASM_CMT("-----------------");\
  17. ASM_CMT("-----------------");\
  18. ASM_CMT("-----------------");\
  19. ASM_CMT("-----------------");\
  20. ASM_CMT("-----------------")



E alla fine c'è questo:

Codice sorgente - presumibilmente C/C++

  1. MY_FUNC;
  2. int main ()
  3. {
  4.  
  5.     return 0;
  6.  
  7. }



ovvero, ho la necessità che prima del codice del main ci sia la scritta "main" in ASCII, preceduta e seguita da molti NOP (0x00 si assembla in una add che non fa niente) grazie alla direttiva align.

Tuttavia, con o senza ottimizzazioni ciò che ottengo non è uguale, mentre secondo me dovrebbe esserlo. Il priblema è che ciò che voglio lo ottengo senza ottimizzazioni, mentre a me farebbero comodo (eliminano fino alla metà delle istruzioni)

ecco il risultato senza ottimizzazioni (giusto):

Codice sorgente - presumibilmente Plain Text

  1. @; -----------------
  2.         @; -----------------
  3.         @; -----------------
  4.         @; -----------------
  5.         @; -----------------
  6.         @; -----------------
  7.         @; -----------------
  8.         .align 8, 0x00
  9.         .ascii "MAIN"
  10.         .align 4, 0x00
  11.         @; -----------------
  12.         @; -----------------
  13.         @; -----------------
  14.         @; -----------------
  15.         @; -----------------
  16.         @; -----------------
  17.         @; -----------------
  18.         .thumb
  19.         .syntax unified
  20.         .align  2
  21.         .global main
  22.         .code   16
  23.         .thumb_func
  24.         .type   main, %function
  25. .main:
  26.         .fnstart
  27. .LFB13:
  28.         push    {r7, lr}
  29.         add     r7, sp, #0
  30.         movs    r3, #0
  31.         movs    r0, r3
  32.         mov     sp, r7
  33.         @ sp needed
  34.         pop     {r7}
  35.         pop     {r1}
  36.         bx      r1
  37.         .cantunwind
  38.         .fnend
  39.         .size   main, .-main
  40.         .ident  "GCC: (devkitARM release 45) 5.3.0"



a parte l'essere "molto sporco" rispetto alla scrittura a mano (e quello si perdona, non è ottimizzato, e poi non è scritto a mano per natura. dopotutto si tollera un piccolo overhead in cambio del lavoro pesante - tra l'altro usa un sacco di direttive che io non avevo mai visto e senza andava sempre tutto bene :rofl: ), ottengo effettivamente la scritta in ascii e le nop.

mentre con le ottimizzazioni attive, all'inizio del file trovo questo:

Codice sorgente - presumibilmente Plain Text

  1. .syntax unified
  2.         .cpu arm7tdmi
  3.         .fpu softvfp
  4.         .eabi_attribute 20, 1
  5.         .eabi_attribute 21, 1
  6.         .eabi_attribute 23, 3
  7.         .eabi_attribute 24, 1
  8.         .eabi_attribute 25, 1
  9.         .eabi_attribute 26, 1
  10.         .eabi_attribute 30, 1
  11.         .eabi_attribute 34, 0
  12.         .eabi_attribute 18, 4
  13.         .thumb
  14.         .syntax unified
  15.         .file   "test.C"
  16.         .syntax divided
  17.         @; -----------------
  18.         @; -----------------
  19.         @; -----------------
  20.         @; -----------------
  21.         @; -----------------
  22.         @; -----------------
  23.         @; -----------------
  24.         .align 8, 0x00
  25.         .ascii "MAIN"
  26.         .align 4, 0x00
  27.         @; -----------------
  28.         @; -----------------
  29.         @; -----------------
  30.         @; -----------------
  31.         @; -----------------
  32.         @; -----------------
  33.         @; -----------------



e alla fine questo:

Codice sorgente - presumibilmente Plain Text

  1. .global main
  2.         .code   16
  3.         .thumb_func
  4.         .type   main, %function
  5. .main:
  6.         .fnstart
  7. .LFB13:
  8.         movs    r0, #0
  9.         @ sp needed
  10.         bx      lr
  11.         .cantunwind
  12.         .fnend
  13.         .size   main, .-main
  14.         .ident  "GCC: (devkitARM release 45) 5.3.0"



Ovvero mette all'inizio del sorgente qualsiasi comando "asm" che si trovi fuori da una funzione. Ho anche provato a farlo senza macro, ma senza successo. Ciononostante il codice è notevolmente migliorato, sembra quasi scritto a mano (anche se rimangono cose che non avrei mai pensato di mettere).

Esiste una soluzione a questo? O dovrò rassegnarmi a metterlo a mano dopo ogni compilazione/fare a meno delle ottimizzazioni??

La seconda stranezza, meno importante e non riguarda direttamente il gcc, è la seguente. Come saprete, ci sono le etichette che sono delle parole seguite dai due punti, e le direttive, che sono dei punti seguiti da parole e talvolta altre cose. Se scrivo del codice asm a mano e compilo nessun problema. ma se compilo il codice venuto fuori dal gcc, l'assemblatore mi fa un loop infinito ad ogni salto.
allora sono stato costretto a sviluppare un programma java che carica in una lista ogni riga dell'output del gcc e aggiunge il punto all'inizio se la riga è un'etichetta. In questo modo ho scoperto che non ho più i cosiddetti "here: B here" dovuti a un'etichetta errata. Il problema è che questa cosa mi sa di "dirty trick" (infatti punto-parola-due punti è utilizzato per i pool di costanti), oltre al fatto che non capisco perchè succeda.

grazie, buona giornata.

Ultima modifica effettuata da Bonnox il 05/07/2016 alle 15:41
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6108
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 16:08
Martedì, 05/07/2016
Potresti specificare manualmente quali ottimizzazioni vuoi usare invece di usare -O1 o -O2:

Testo quotato


-fauto-inc-dec
-fbranch-count-reg
-fcombine-stack-adjustments
-fcompare-elim
-fcprop-registers
-fdce
-fdefer-pop
-fdelayed-branch
-fdse
-fforward-propagate
-fguess-branch-probability
-fif-conversion2
-fif-conversion
-finline-functions-called-once
-fipa-pure-const
-fipa-profile
-fipa-reference
-fmerge-constants
-fmove-loop-invariants
-freorder-blocks
-fshrink-wrap
-fsplit-wide-types
-fssa-backprop
-fssa-phiopt
-ftree-bit-ccp
-ftree-ccp
-ftree-ch
-ftree-coalesce-vars
-ftree-copy-prop
-ftree-dce
-ftree-dominator-opts
-ftree-dse
-ftree-forwprop
-ftree-fre
-ftree-phiprop
-ftree-sink
-ftree-slsr
-ftree-sra
-ftree-pta
-ftree-ter
-funit-at-a-time
-fthread-jumps
-falign-functions  -falign-jumps
-falign-loops  -falign-labels
-fcaller-saves
-fcrossjumping
-fcse-follow-jumps  -fcse-skip-blocks
-fdelete-null-pointer-checks
-fdevirtualize -fdevirtualize-speculatively
-fexpensive-optimizations
-fgcse  -fgcse-lm  
-fhoist-adjacent-loads
-finline-small-functions
-findirect-inlining
-fipa-cp
-fipa-cp-alignment
-fipa-sra
-fipa-icf
-fisolate-erroneous-paths-dereference
-flra-remat
-foptimize-sibling-calls
-foptimize-strlen
-fpartial-inlining
-fpeephole2
-freorder-blocks-algorithm=stc
-freorder-blocks-and-partition -freorder-functions
-frerun-cse-after-loop  
-fsched-interblock  -fsched-spec
-fschedule-insns  -fschedule-insns2
-fstrict-aliasing -fstrict-overflow
-ftree-builtin-call-dce
-ftree-switch-conversion -ftree-tail-merge
-ftree-pre
-ftree-vrp
-fipa-ra



Una (o più) di queste sono quelle responsabili per il cambio di posizione da te illustrato.

https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

Non ho capito la seconda "stranezza", forse potresti spiegarci con un esempio?


Seguimi su Twitter: http://www.twitter.com/pierotofy

Fai quello che ti piace, e fallo bene.
PM Quote
Avatar
lumo (Member)
Expert


Messaggi: 413
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 19:01
Martedì, 05/07/2016
Ma quale sarebbe il risultato che vuoi ottenere?
In generale non puoi sperare che il compilatore produca l'assembly che vuoi tu, quindi se vuoi qualcosa di preciso devi fare in altro modo.

PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1452
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 19:18
Martedì, 05/07/2016
a naso direi che:
Codice sorgente - presumibilmente Plain Text

  1. -freorder-blocks-algorithm=stc
  2. -freorder-blocks-and-partition -freorder-functions


queste sono le ottimizzazioni incriminate

PM Quote
Avatar
Bonnox (Member)
Pro


Messaggi: 82
Iscritto: 23/08/2014

Segnala al moderatore
Postato alle 20:32
Martedì, 05/07/2016
grazie a tutti, è stata una lettura molto utile.

ho trovato una possibile flag "-fno-toplevel-reorder"

ora provo e faccio sapere

Testo quotato

Postato originariamente da lumo:

Ma quale sarebbe il risultato che vuoi ottenere?
In generale non puoi sperare che il compilatore produca l'assembly che vuoi tu, quindi se vuoi qualcosa di preciso devi fare in altro modo.



vorrei semplicemente che prima di una funzione ci sia dello spazio vuoto con una scritta, perchè mi serve sapere il punto di inizio del codice nel file binario compilato, senza stare a guardare manualmente con il disassemblatore.

Ultima modifica effettuata da Bonnox il 05/07/2016 alle 20:54
PM Quote
Avatar
Bonnox (Member)
Pro


Messaggi: 82
Iscritto: 23/08/2014

Segnala al moderatore
Postato alle 20:49
Martedì, 05/07/2016
grazie mille, la flag che ho scovato grazie a quella pagina funziona a meraviglia!!:k:

spiego la seconda stranezza.

di norma nello gnu assembler ci sono le direttive, tipo questa:

Codice sorgente - presumibilmente Plain Text

  1. .align 2



che iniziano con un punto.

poi ci sono le etichette:

Codice sorgente - presumibilmente Plain Text

  1. loop:



che terminano con i due punti.

non so perchè, ma quando compilo l'output datomi con lo switch -S, l'assemblatore sembra che non accetti le etichette, per cui qualsiasi salto in realtà salta a sè stesso. Giuro, lo so che è incredibile. Infatti quando scrivo del codice asm a mano, che è mooolto più corto, va tutto bene. inspiegabile.

comunque ho fatto un programma (in java perchè con poche righe fai il mondo) che legge il listato e sostituisce le etichette con queste cose che sono un misto tra etichetta e direttiva:

Codice sorgente - presumibilmente Plain Text

  1. .nome:




che è usato per indicare dei luoghi da cui prendere valori (pool).
Infatti ho scoperto che se cambio le etichette in questo nuovo formato, l'assemblatore non genera più salti a sè stessi.

con salti a sè stessi intendo delle istruzioni di salto che in qualche modo cambiano di 0 il PC.

tipo

Codice sorgente - presumibilmente Plain Text

  1. here: B here




ciao e grazie


ho fatto un doppio post, come cancello questo per unirlo al precedente?

Ultima modifica effettuata da Bonnox il 05/07/2016 alle 20:53
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6108
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 17:00
Mercoledì, 06/07/2016
Potresti postarci il programma in C, il comando gcc che compila il programma, e il risultante assembly?


Seguimi su Twitter: http://www.twitter.com/pierotofy

Fai quello che ti piace, e fallo bene.
PM Quote
Avatar
Bonnox (Member)
Pro


Messaggi: 82
Iscritto: 23/08/2014

Segnala al moderatore
Postato alle 16:44
Giovedì, 21/07/2016
signori scusatemi , sono riuscito a risolvere il "grosso problema" che citerò più sotto.
Come? ricordandomi che il tizio da cui ho preso l'idea aveva scritto "static inline", mentre io pensai qualcosa come " che significa static? è C, non C++, io so che in java (e dunque presumo in C++) static significa che non dipende da un oggetto, ma qui non so cosa faccia, dunque non lo metterò, ecco." invece ora ho pensato "ma se il tizio l'ha messo, ci sarà un motivo? ok non so cosa vuol dire, ma proviamo giusto per curiosità"... e vaa!

unici 2 problemi:
- peccato che però non "inlinea" comunque la funzione :_doubt:
- cosa significa "static"? :_doubt:


per chi è curioso di sapere come andava a finire prima di "questa notizia bomba" (alla top gear), lascio sotto il post originale.

(ma si può fare uno spoiler?)




all'inizio avevo detto che uso questo comando (qui ho semplificato le parti inutili):

Codice sorgente - presumibilmente Plain Text

  1. "D:\devkitPro\devkitARM\bin\arm-none-eabi-gcc.exe" -Wall -mthumb -mthumb-interwork -S nomedelfile.c



uso il devkitpro per sviluppare sul gameboy advance.

poi, dopo aver ottenuto il file s, lo assemblo (il comando dell'assemblatore l'ho copiato da internet):

Codice sorgente - presumibilmente C/C++

  1. as -a -mthumb -mthumb-interwork "%src%"
  2. objcopy --verbose -O binary a.out "%dest%"




e lo innesto in un gioco già compilato (lo so che è un comportamento demoniaco, ma mi serve).

prendendo un semplice file C tipo questo:
Codice sorgente - presumibilmente C++

  1. int chiamata (char, short);
  2.  
  3. void prova ()
  4. {
  5.         int a = chiamata (0xB, 10);
  6. }
  7.  
  8. int chiamata(char a, short b)
  9. {
  10.         return ((short) a + b);
  11. }




senza ottimizzazioni (perchè se no mi segava questo esempio con la variabile non utilizzata) si genera una cosa del genere:
Codice sorgente - presumibilmente C/C++

  1. .syntax unified
  2.         .cpu arm7tdmi
  3.         .fpu softvfp
  4.         .eabi_attribute 20, 1
  5.         .eabi_attribute 21, 1
  6.         .eabi_attribute 23, 3
  7.         .eabi_attribute 24, 1
  8.         .eabi_attribute 25, 1
  9.         .eabi_attribute 26, 1
  10.         .eabi_attribute 30, 6
  11.         .eabi_attribute 34, 0
  12.         .eabi_attribute 18, 4
  13.         .thumb
  14.         .syntax unified
  15.         .file   "provablpiero.c"
  16.         .text
  17.         .align  2
  18.         .global prova
  19.         .code   16
  20.         .thumb_func
  21.         .type   prova, %function
  22. prova:
  23.         push    {r7, lr}
  24.         sub     sp, sp, #8
  25.         add     r7, sp, #0
  26.         movs    r1, #10
  27.         movs    r0, #11
  28.         bl      chiamata
  29.         movs    r3, r0
  30.         str     r3, [r7, #4]
  31.         nop
  32.         mov     sp, r7
  33.         add     sp, sp, #8
  34.         @ sp needed
  35.         pop     {r7}
  36.         pop     {r0}
  37.         bx      r0
  38.         .size   prova, .-prova
  39.         .align  2
  40.         .global chiamata
  41.         .code   16
  42.         .thumb_func
  43.         .type   chiamata, %function
  44. chiamata:
  45.         push    {r7, lr}
  46.         sub     sp, sp, #8
  47.         add     r7, sp, #0
  48.         movs    r2, r0
  49.         adds    r3, r7, #7
  50.         strb    r2, [r3]
  51.         adds    r3, r7, #4
  52.         adds    r2, r1, #0
  53.         strh    r2, [r3]
  54.         adds    r3, r7, #7
  55.         ldrb    r2, [r3]
  56.         adds    r3, r7, #4
  57.         movs    r1, #0
  58.         ldrsh   r3, [r3, r1]
  59.         adds    r3, r2, r3
  60.         movs    r0, r3
  61.         mov     sp, r7
  62.         add     sp, sp, #8
  63.         @ sp needed
  64.         pop     {r7}
  65.         pop     {r1}
  66.         bx      r1
  67.         .size   chiamata, .-chiamata
  68.         .ident  "GCC: (devkitARM release 45) 5.3.0"



tralasciando tutte le cose inutili tipo eabi attribute che manco so cosa sia e il walzer dello stack pointer, si vede chiaramente che chiama con un BL la funzione identificata con l'etichetta.

tuttavia l'assemblatore ha qualche problema:

https://postimg.org/image/pony0yz6p/

la riga evidenziata salta a sé stessa.

ma in realtà non è questo il mio vero problema, in quanto una passata con un semplice programma che legge l'output e lo corregge mettendo il punto all'inizio dell'etichetta basta a far funzionare il tutto.

Vorrei tuttavia approfittare dell'occasione per chiedervi un'altra cosa, ma sempre riguardante questi argomenti.

Forse sbaglio qualcosa io, ma procediamo con ordine. vi spiego tutto il setup.

voglio inserire nel gioco GBA delle mie funzioni in C, e avevo pensato di facilitare lo sviluppo mettendole tutte una di seguito all'altra, e avere una specie di main richiamato dal gioco che legge in una locazione di ram (indirizzo 0x02......) il numero della funzione da richiamare. In questo modo avrei potuto aggiornare facilmente le funzioni nel caso ci fossero stati problemi o per aggiungere funzionalità, senza stare troppo a trafficare con i files.
il trucco sta nel mettere una parola chiave tipo 0xCAFEBABE (ho usato uno stupido "start of frame" come parola chiave, in onore del TCP :rotfl: ), che il mio programma java avrebbe rilevato nel file binario, e grazie a questo aggiustato un altro piccolo file ad offset fisso che ha solo il compito di "linkare" (da branch and link) al finto main che seleziona la funzione da avviare.
Infine il programma java assembla nella ROM questa piccola routine insieme al file binario compilato.

Tuttavia ho alcuni problemi, di diversa entità. Quello più grave, per cui chiedo a voi una mano, è che se metto "troppe" funzioni nel sorgente C (al momento circa 16), quando assemblo il tutto e faccio il debug con l'emulatore, vedo che quando bisogna fare un branch and link il program counter "va per i campi", termine simpatico che ho inventato per dire che va ad un offset dove non c'è assolutamente alcuna funzione. In quel punto capita sempre di trovare parecchie istruzioni di LSR/LSL (logical shift), ed è molto curioso. potrebbe trattarsi di padding, ma ne dubito. E ovviamente il gioco crasha. Questo è un comportamento molto misterioso, perchè ho ricontrollato più volte il sorgente asm. Forse ho sbagliato qualche parametro dei vari compilatori/assemblatori? Non vorrei aver sbagliato qualcosa nel programmino java, anche se mi sembra strano, perchè fino a 10-12 funzioni va perfettamente! Adesso mentre sto scrivendo sono andato a controllare: ho eseguito il passaggio manualmente (prima mi affidavo ai tools di code blocks e ai batch), assemblando il file .S. e in effetti è sbagliato: non corrisponde.
Ho pensato sbagliassi qualcosa nella funzione, così ne ho creata una completamente diversa, ma ancora il problema si ripresenta (branch and link dove non v'è niente).
Ancora, ho provato a mettere il main prima di tutte le implementazioni delle funzioni, e dopo le dichiarazioni, ma senza successo.
Vi segnalo inoltre che aggiungere le funzioni non causa problema di esecuzione, ma soltanto chiamarle.

Cosa sbaglio? ve ne sarei tanto grato. (scusate la figura nabba e alcune probabili oscenità nel codice) :_doubt:

va beh, senza ulteriori indugi vi passo tutto il materiale.

piccola routine collocata ad un offset fisso nella ROM, verrà chiamata dal gioco e caricherà le mie funzioni:

Codice sorgente - presumibilmente Plain Text

  1. .THUMB
  2. .ALIGN 2
  3.  
  4.  
  5. PUSH {r0-r7, lr}
  6.  
  7. ldr r1, .base
  8. BL LINKER
  9.  
  10. POP {r0-r7, pc}
  11.  
  12.  
  13. LINKER:
  14. BX R1
  15.  
  16. .align 2, 0x00
  17. .base:
  18. .word 0xAABBCCDD



la word verrà cambiata dal programma java che mette insieme tutto.

programmino in java, nel caso servisse (in generale non dovrebbe servire, lo metto lo stesso però non deridetemi, è stato programmato molto "alla buona", se non rispetta certi canoni stilistici, skippate al paragrafo successivo per non subire danni agli occhi :)

Codice sorgente - presumibilmente Java

  1. package it.bonnox.asmdeployer;
  2.  
  3.  
  4. import java.io.File;
  5. import java.io.FileNotFoundException;
  6. import java.io.IOException;
  7.  
  8. import java.nio.file.Files;
  9. import java.nio.file.Paths;
  10.  
  11.  
  12. import it.bonnox.myLibPers.basicBytesLibrary.CoreLibrary;
  13. import it.bonnox.myLibPers.basicBytesLibrary.Pointer;
  14. import it.bonnox.myLibPers.utils.*;
  15.  
  16.  
  17. public class MainDeployer
  18. {
  19.        
  20.         private static final int                SCOSTAMENTO_ALIGN                               = 64;
  21.         private static final int                DIMENSIONE_AREA_COMPILAZIONE    = 6 * 1024 * 1024;
  22.         private static final int                ARG_OFFSETINSERIMENTO   = 2;
  23.         private static final int                ARG_PERCORSOCOMPILATO   = 1;
  24.         private static final int                ARG_PERCORSOROM                 = 0;
  25.         private static byte[]                   LINKERROUTINEBINARY                             = { (byte) 0xFF, (byte) 0xB5, (byte) 0x02, (byte) 0x49, (byte) 0x00, (byte) 0xF0, (byte) 0x01, (byte) 0xF8, (byte) 0xFF, (byte) 0xBD, (byte) 0x08, (byte) 0x47, (byte) 0xDD, (byte) 0xCC, (byte) 0xBB, (byte) 0xAA };
  26.         private static final int                ARG_DEFINE                              = 3;
  27.         private static final boolean    DEBUG                                                   = false;
  28.                                                                                                                        
  29.         @SuppressWarnings ("unused")
  30.         public static void main(String[] args) throws IOException
  31.         {
  32.                 System.out.println("\ndeploying...");
  33.                 if (DEBUG) System.err.println(" *** DEBUG ***");
  34.                
  35.                 if (args.length != ARG_DEFINE && !DEBUG)
  36.                         {
  37.                                 System.err.println("WRONG NUMBER OF PARAMERERS\n" + "usage:\n" + "rom\n" + "filebin\n" + "offset\n");
  38.                                 System.exit(-1);
  39.                         }
  40.                
  41.                
  42.  
  43.                 String percorsoROM;
  44.                 String percorsoCompilato;
  45.                 int offsetInserimento;
  46.                
  47.                 if (DEBUG)
  48.                         {
  49.                                 percorsoROM = "D:\\GXX-XDS\\C Environment Deployment\\out\\test.gba";
  50.                                 percorsoCompilato = "D:\\GXX-XDS\\C Environment Deployment\\middle\\test.s.bin";
  51.                                 offsetInserimento = 0x1c00000;
  52.                         }
  53.                 else
  54.                         {
  55.                                 percorsoROM = args[ARG_PERCORSOROM];
  56.                                 percorsoCompilato = args[ARG_PERCORSOCOMPILATO];
  57.                                 offsetInserimento = Integer.parseInt(args[ARG_OFFSETINSERIMENTO], 16);
  58.                         }
  59.                        
  60.  
  61.                
  62.                 byte[] bytesROM = Files.readAllBytes(Paths.get(new File(percorsoROM).toURI()));
  63.                
  64.                 System.out.println("opening compiled...");
  65.                 byte[] bytesCompilato = Files.readAllBytes(Paths.get(new File(percorsoCompilato).toURI()));
  66.                
  67.                 int indirizzoMain = getMainCompilato(bytesCompilato, offsetInserimento);
  68.                
  69.                 if (indirizzoMain < 0) System.exit(indirizzoMain);
  70.                
  71.                 sostituisciLinker(LINKERROUTINEBINARY, indirizzoMain);
  72.                
  73.                 // unisce le parti
  74.                
  75.                 byte[] inserimento = new byte[DIMENSIONE_AREA_COMPILAZIONE];
  76.                
  77.                 // copia il linker
  78.                 for (int i = 0; i < LINKERROUTINEBINARY.length; i++)
  79.                         {
  80.                                 inserimento[i] = LINKERROUTINEBINARY[i];
  81.                         }
  82.                 // copia la compilazione
  83.                 for (int i = LINKERROUTINEBINARY.length; i < bytesCompilato.length; i++)
  84.                         {
  85.                                 inserimento[i] = bytesCompilato[i];
  86.                         }
  87.                        
  88.                 noppa(inserimento, LINKERROUTINEBINARY.length, bytesCompilato.length);
  89.                
  90.                 scriviROM(bytesROM, percorsoROM, offsetInserimento, inserimento);
  91.                
  92.         }
  93.        
  94.        
  95.  
  96.         private static void noppa(byte[] inserimento, int length, int length2)
  97.         {
  98.                 for (int i = length + length2; i < inserimento.length; i += 2)
  99.                         {
  100.                                 if (i == inserimento.length)
  101.                                         {
  102.                                                 // se i è uguale all ultimo , vuol dire che e dispari
  103.                                                 // (?)
  104.                                                 inserimento[i] = (byte) 0xC0;
  105.                                         }
  106.                                 else
  107.                                         {
  108.                                                 inserimento[i] = (byte) 0xC0;
  109.                                                 inserimento[i + 1] = (byte) 0x46;
  110.                                         }
  111.                         }
  112.                
  113.         }
  114.        
  115.         private static void sostituisciLinker(byte[] lINKERROUTINEBINARY2, int indirizzo)
  116.         {
  117.                 Pointer nuovo = new Pointer(indirizzo);
  118.                 it.bonnox.myLibPers.basicBytesLibrary.CoreLibrary.writeBytes(lINKERROUTINEBINARY2, lINKERROUTINEBINARY2.length - 4, nuovo.getBinaryGBA());
  119.                
  120.         }
  121.        
  122.         private static int getMainCompilato(byte[] bytesCompilato, int offsetinserimento)
  123.         {
  124.                
  125.                 int ritorno = -1;
  126.                 for (int i = 0; i < bytesCompilato.length; i += SCOSTAMENTO_ALIGN)
  127.                         {
  128.                                 if (DEBUG)
  129.                                         {
  130.                                        
  131.                                         }
  132.                                 if (bytesCompilato[i] == 'S') if (bytesCompilato[i + 1] == 'T') if (bytesCompilato[i + 2] == 'A') if (bytesCompilato[i + 3] == 'R') if (bytesCompilato[i + 4] == 'T') if (bytesCompilato[i + 5] == (byte) 0x20) if (bytesCompilato[i + 6] == 'O') if (bytesCompilato[i + 7] == 'F') if (bytesCompilato[i + 8] == ' ') if (bytesCompilato[i + 9] == 'F') if (bytesCompilato[i + 10] == 'R') if (bytesCompilato[i + 11] == 'A') if (bytesCompilato[i + 12] == 'M') if (bytesCompilato[i + 13] == 'E') if (bytesCompilato[i + 14] == ' ') if (bytesCompilato[i + 15] == ' ')
  133.                                         {
  134.                                                 ritorno = i;
  135.                                         }
  136.                                        
  137.                         }
  138.                 return ritorno + LINKERROUTINEBINARY.length + offsetinserimento;
  139.         }
  140.        
  141.         private static void scriviROM(byte[] ROMfile, String percorso, int offsetInserimento, byte[] nuovi) throws FileNotFoundException, IOException
  142.         {
  143.                
  144.                 System.out.println("finalizing...");
  145.                 CoreLibrary.writeBytes(ROMfile, offsetInserimento, nuovi);
  146.                 Misc.salvaFile(new File(percorso), ROMfile);
  147.                 System.out.println("successfully deployed.");
  148.                
  149.         }
  150.        
  151. }



ecco il codice sorgente. cerco di spiegare il tutto, ma avviso che è un'adattamento di un mio appunto.
quando dirò "variabile 0x800D" significa essenzialmente "indirizzo di memoria inutilizzato".

Testo quotato


il file "test.c" è quello che unisce tutto: contiene sia la libreria che le funzioni. il metodo main legge la variabile 0x800D  ed esegue la routine corrispondente!
poi quando le singole routine raggiungeranno una certa complessità verranno pure loro separate nel loro file C e incluse. So che per certa gente seria è impensabile, abominevole, demoniaco, #includere i file C e ricompilare il mondo. è naive ma funziona; non so i makefiles, e poi la ROM è una struttura parecchio statica: bisogna cercare di prevedere cosa uscirà pena errori orribili! Ecco cosa mi ha portato a questa scelta.

il file header è unico, ho scelto così perchè tanto la libreria se uno la vuole se la include tutta, non è che risparmi chissà chi se non vuole qualche modulo; prima ogni pezzetto in C aveva il suo header, ben schermato con l'#ifdef, per carità, ma poi ovviamente è successo il fattaccio (prima o poi sarebbe dovuto accadere, era una questione di tempo) :p sicuramente colpa di qualche stupido punto e virgola, mi ha mandato a lucciole tutti gli include.... così poi li ho uniti! ahaha ^^

ogni pezzetto svolge precisi compiti:

- math è nato come utilità per fixed floating point (anche se non ne troverai traccia perchè devo ancora studiarci su :p ), poi ho deciso di mettere anche i div, poi ne ho tolto uno, poi li ho uniti, boh i div sono un casino.

- bios contiene principalmente asm per usare il bios del GBA. i div sono problematici, non so come farlo ritornare, eccetera. poi ne ho messi ancora pochi altri (anche sotto forma di #define se non prendono argomenti, così sono più leggeri :) ). ovviamente bisognerà metterli quasi tutti, a parte il suono e gli affini che non interessano a nessuno.

- util contiene... utilità. non saprei definirlo in altro modo. occhio che ha il vizio di ritornare le cose nella variabile 800D (e byte seguenti)

- video dovrebbe contenere robe tipo inizializza i modi grafici, mostra immagini, copia i tils.... ma per ora contiene solo un orrenda funzione con un casino di parametri short che quadruplicano il listato asm a forza di shift per conversioni forzate... e non va bene.

[...]




da qui in poi, se aggiungo una funzione, succede il patatrak, ovvero non la chiama e va in posti sperduti del binario.
al momento c'è il file "text", che contiene una specie di sistema di testo. è ancora tutto in fase embrionale, c'è un po' di disordine e mancano funzionalità (tipo c'è il put carattere ma non il put stringa, e nemmeno la gestione della console).

la mia idea era di ricreare la libreria tipo tonc o libgba, non essendo riuscito a farle funzionare.
tanto comunque saranno pochi altri i metodi che dovrò inserire.

grazie ancora.
non fate caso a scritte strane

file test.c:

Codice sorgente - presumibilmente C++

  1. #include "libonnox.h"
  2.  
  3. #include "libonnox/bios.c"
  4. #include "libonnox/math.c"
  5. #include "libonnox/util.c"
  6. #include "libonnox/video.c"
  7. #include "libonnox/text.c"
  8.  
  9.  
  10.  
  11. /* TODO
  12.  
  13. problemi:
  14. - se metto troppe funzioni, l'as va per campi.
  15. - fascia nera a sx del gba
  16.  
  17. problemi risolti:
  18.  
  19. ----------
  20.  
  21. problemi boh:
  22. - gcc ottimizz sbaglia a tradurre blockfill in versione c. mentre in versione asm da qualche tempo mi fa un b here che non riesco a evitare. vedere tale file x dettagli
  23. mettendo la flag da -O2 a -O1, il C funge :)
  24. non e' vero, ora non va piu, devo toglierle del tutto :c
  25. */
  26.  
  27. void metodo()
  28. {
  29.  
  30. u16 tmp= DISPCNT;
  31.  
  32.  
  33. //util_blockfill(0x04000000, 256, 0x0);
  34.  
  35. *(unsigned int*)0x04000000 = 0x0403;
  36. //util_memAlloc32(0x8);
  37. /*
  38. OFFSET_AS_POINTER8(0x4000021)=(u8)1;
  39. OFFSET_AS_POINTER8(0x4000027)=(u8)1;
  40. OFFSET_AS_POINTER8(0x4000031)=(u8)1;
  41. OFFSET_AS_POINTER8(0x4000037)=(u8)1;
  42. OFFSET_AS_POINTER8(0x4000082)=(u8)0xe;
  43. OFFSET_AS_POINTER8(0x4000089)=(u8)0x2;
  44.  
  45. */
  46.  
  47. util_blockFill(0x06000000, 5600, 0x7fff7fff);
  48. /*u32 color=RGB16(9, 1, 2);
  49. color=color<<16;
  50. color+=RGB16(5, 5, 5);
  51. util_blockFill(0x06000000+9600*4, 9600, color);//BREAKPOINT;*/
  52.  
  53. //util_blockFill(0x04000010, 4, 0x0);
  54.  
  55.  
  56. //draw_line (1, 50, 0x3456);
  57.  
  58.  
  59. text_putc16bpp ('a', 30, 4, 0x3333);
  60.  
  61.  
  62. //DISPCNT=tmp;
  63.  
  64.  
  65. }
  66.  
  67. void linker(u16 nf)
  68. {
  69.  
  70.  
  71.  
  72.  
  73.     switch (nf)
  74.     {
  75.  
  76.     case 0:
  77.          metodo();
  78.         break;
  79.  
  80.     }
  81.  
  82.  
  83.  
  84. }
  85.  
  86. NEW_FUNC;
  87. void hackMain()
  88.  
  89. {
  90.  
  91.     linker(OFFSET_AS_POINTER16(var_0x800D));
  92. }



libonnox.h

Codice sorgente - presumibilmente C++

  1. /**
  2. ---------------
  3.     USEFUL
  4. ---------------
  5. */
  6.  
  7.  
  8. #define ASM_CMT(str) asm ("@; " str)
  9.  
  10.  
  11. #define CALL(str) asm("bl ." str )
  12.  
  13. #define NEW_FUNC \
  14. ASM_CMT("-----------------");\
  15. ASM_CMT("-----------------");\
  16. asm  (".align 6, 0x00");\
  17. asm  (".ascii \"START OF FRAME  \" " ) ; \
  18. asm  (".align 4, 0x00");\
  19. ASM_CMT("-----------------");\
  20. ASM_CMT("-----------------")
  21.  
  22. #define MY_FUNC \
  23. ASM_CMT("-----------------");\
  24. ASM_CMT("-----------------");\
  25. asm  (".align 8, 0x00");\
  26. asm  (".ascii \"MAIN\" " ) ; \
  27. asm  (".align 4, 0x00");\
  28. ASM_CMT("-----------------");\
  29. ASM_CMT("-----------------")
  30.  
  31.  
  32. #define BREAKPOINT asm (".align 1");\
  33. asm (".byte 0xfe, 0x0");\
  34. asm (".byte 0xe7");\
  35. asm (".align 1, 0x0")
  36.  
  37. /* asm (".align 1");\
  38. asm (".byte 0xfe");\
  39. asm (".byte 0xde");\
  40. asm (".align 1")
  41.  
  42. */
  43.  
  44. #define OFFSET_AS_POINTER8(num) (*(u8*)num)
  45. #define OFFSET_AS_POINTER16(num) (*(u16*)num)
  46. #define OFFSET_AS_POINTER32(num) (*(u32*)num)
  47.  
  48. typedef unsigned int u32;
  49. typedef unsigned short u16;
  50. typedef unsigned char u8;
  51.  
  52. #define ASM_800D_R4 \
  53.     asm ("mov r4, #2");\
  54. asm (" lsl r4, #0x8");\
  55. asm ("add r4, r4, #2");\
  56.     asm ("lsl r4, #0x4");\
  57.     asm ("add r4, r4, #14");\
  58.     asm ("lsl r4, #0x4");\
  59.     asm ("add r4, r4, #8");\
  60.     asm ("lsl r4, #0x4");\
  61.     asm ("add r4, r4, #13");\
  62.     asm ("lsl r4, #0x4");\
  63.     asm ("add r4, r4, #12")
  64.  
  65.  
  66.  
  67. /**
  68. ---------------
  69.     BOOL
  70. ---------------
  71. */
  72.  
  73.  
  74. typedef u32 boolean;
  75.  
  76. #define TRUE 1
  77. #define FALSE 0
  78.  
  79. /**
  80. ---------------
  81.     BIOS
  82. ---------------
  83. */
  84.  
  85.  
  86. #define bios_vBlankIntrWait() asm ("swi 0x5")
  87.  
  88. #define bios_halt() asm ("swi 0x2")
  89. #define bios_intrWait() asm ("swi 0x4")
  90.  
  91.  
  92.  
  93. #define bios_div_single_DIV 1
  94. #define bios_div_single_MOD 2
  95. void bios_div_single (u32 num, u32 den, u32 func);
  96.  
  97. void bios_div_multi (u32 num, u32 den, u32* alloc);
  98.  
  99.  
  100.  
  101. /**
  102. ---------------
  103.     VIDEO
  104. ---------------
  105. */
  106.  
  107. #define RGB16(r,g,b) (r+(g<<5)+(b<<10))
  108.  
  109.  
  110. #define MAX_COLOR_VALUE 31 // i colori sono 0-bbbbb-ggggg-rrrrr
  111. #define SCREEN_WIDTH   240
  112. #define SCREEN_HEIGHT  160
  113.  
  114.  
  115. #define DISPCNT_BGMODE_PROPERTY 0
  116. #define DISPCNT_FRAME_PROPERTY 3
  117. #define DISPCNT_H_BLANK_PROPERTY 5
  118. #define DISPCNT_OBJMAP_PROPERTY 6
  119. #define DISPCNT_FORCEDBLANK_PROPERTY 7
  120. #define DISPCNT_BG0_PROPERTY 8
  121. #define DISPCNT_BG1_PROPERTY 9
  122. #define DISPCNT_BG2_PROPERTY 10
  123. #define DISPCNT_BG3_PROPERTY 11
  124. #define DISPCNT_OBJ_PROPERTY 12
  125. #define DISPCNT_WIN0_PROPERTY 13
  126. #define DISPCNT_WIN1_PROPERTY 14
  127. #define DISPCNT_WINOBJ_PROPERTY 15
  128.  
  129. #define CLR_BLACK   0x0000
  130. #define CLR_RED     0x001F
  131. #define CLR_LIME    0x03E0
  132. #define CLR_YELLOW  0x03FF
  133. #define CLR_BLUE    0x7C00
  134. #define CLR_MAG     0x7C1F
  135. #define CLR_CYAN    0x7FE0
  136. #define CLR_WHITE   0x7FFF
  137. typedef u16 T_COLOR;
  138.  
  139. //void initM3();
  140.  
  141.  
  142.  
  143. void video_initDispCntGlobal(u8 bgMode, boolean frame, boolean hBlank, boolean objMapping, boolean forceBlank, boolean bg0, boolean bg1, boolean bg2, boolean bg3, boolean obj, boolean win0, boolean win1, boolean winObj);
  144. void video_setDispCntProperties(u8 property, u8 bgMode, boolean flag);
  145. u16 video_createDispCnt(u8 bgMode, boolean frame, boolean hBlank, boolean objMapping, boolean forceBlank, boolean bg0, boolean bg1, boolean bg2, boolean bg3, boolean obj, boolean win0, boolean win1, boolean winObj);
  146. T_COLOR video_alphaBlend(T_COLOR source, T_COLOR newcol, u8 coef);
  147.  
  148.  
  149. void video_plotPixelM3(u8 x, u8 y, T_COLOR color, boolean transp);
  150.  
  151. inline void video_plotPixelM3inline (int x, int y, T_COLOR clr);
  152.  
  153. inline int video_getR(T_COLOR clr);
  154. inline int video_getG(T_COLOR clr);
  155. inline int video_getB(T_COLOR clr);
  156.  
  157.  
  158.  
  159. /**
  160. ---------------
  161.     UTIL
  162. ---------------
  163. */
  164. #define var_0x800D 0x0202E8DC
  165.  
  166. void util_memcpy32(u32 dst,  u32 src, u32 wdcount);
  167. void util_blockFill(u32 dest, u32 lung, u32 filler);
  168. void util_memAlloc32(u32 lung);
  169. void util_memFree32(u32 offs);
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176. /**
  177. ---------------
  178.     TEXT
  179. ---------------
  180. */
  181.  
  182. void text_putc16bpp (u8 chr, u8 x, u8 y, T_COLOR clr);
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191. /**
  192. ---------------
  193.     MATH
  194. ---------------
  195. */
  196.  
  197. u32* math_div_multiple(u32 n, u32 d, boolean allocNeed, u32* offs);
  198.  
  199.  
  200.  
  201. /**
  202. ---------------
  203.     IOREG
  204. ---------------
  205. */
  206.  
  207.  
  208.  
  209.  
  210. #define DEFINEREG16(num) (*(volatile u16*) num)
  211. #define DEFINEREG32(num) (*(volatile u32*) num)
  212.  
  213. #define BASE_REG 0x4000000
  214.  
  215.  
  216. #define DISPCNT     DEFINEREG16(0x4000000)
  217. #define DISPSTAT    DEFINEREG16(0x4000004)
  218. #define VCOUNT      DEFINEREG16(0x4000006)
  219. #define BG0CNT      DEFINEREG16(0x4000008)
  220. #define BG1CNT      DEFINEREG16(0x400000A)
  221. #define BG2CNT      DEFINEREG16(0x400000C)
  222. #define BG3CNT      DEFINEREG16(0x400000E)
  223. #define BG0HOFS     DEFINEREG16(0x4000010)
  224. #define BG0VOFS     DEFINEREG16(0x4000012)
  225. #define BG1HOFS     DEFINEREG16(0x4000014)
  226. #define BG1VOFS     DEFINEREG16(0x4000016)
  227. #define BG2HOFS     DEFINEREG16(0x4000018)
  228. #define BG2VOFS     DEFINEREG16(0x400001A)
  229. #define BG3HOFS     DEFINEREG16(0x400001C)
  230. #define BG3VOFS     DEFINEREG16(0x400001E)
  231. #define BG2PA       DEFINEREG16(0x4000020)
  232. #define BG2PB       DEFINEREG16(0x4000022)
  233. #define BG2PC       DEFINEREG16(0x4000024)
  234. #define BG2PD       DEFINEREG16(0x4000026)
  235. #define BG2X        DEFINEREG32(0x4000028)
  236. #define BG2Y        DEFINEREG32(0x400002C)
  237. #define BG3PA       DEFINEREG16(0x4000030)
  238. #define BG3PB       DEFINEREG16(0x4000032)
  239. #define BG3PC       DEFINEREG16(0x4000034)
  240. #define BG3PD       DEFINEREG16(0x4000036)
  241. #define BG3X        DEFINEREG32(0x4000038)
  242. #define BG3Y        DEFINEREG32(0x400003C)
  243. #define WIN0H       DEFINEREG16(0x4000040)
  244. #define WIN1H       DEFINEREG16(0x4000042)
  245. #define WIN0V       DEFINEREG16(0x4000044)
  246. #define WIN1V       DEFINEREG16(0x4000046)
  247. #define WININ       DEFINEREG16(0x4000048)
  248. #define WINOUT      DEFINEREG16(0x400004A)
  249. #define MOSAIC      DEFINEREG16(0x400004C)
  250. #define BLDCNT      DEFINEREG16(0x4000050)
  251. #define BLDALPHA    DEFINEREG16(0x4000052)
  252. #define BLDY        DEFINEREG16(0x4000054)
  253.  
  254. // TODO SOUND REGS
  255.  
  256. #define DMA0SAD     DEFINE_REG32(0x40000B0)
  257. #define DMA0DAD     DEFINE_REG32(0x40000B4)
  258. #define DMA0CNTL    DEFINE_REG16(0X40000B8)
  259. #define DMA0CNTH    DEFINE_REG16(0X40000BA)
  260. #define DMA1SAD     DEFINE_REG32(0X40000BC)
  261. #define DMA1DAD     DEFINE_REG32(0X40000C0)
  262. #define DMA1CNTL    DEFINE_REG16(0X40000C4)
  263. #define DMA1CNTH    DEFINE_REG16(0X40000C6)
  264. #define DMA2SAD     DEFINE_REG32(0X40000C8)
  265. #define DMA2DAD     DEFINE_REG32(0X40000CC)
  266. #define DMA2CNTL    DEFINE_REG16(0X40000D0)
  267. #define DMA2CNTH    DEFINE_REG16(0X40000D2)
  268. #define DMA3SAD     DEFINE_REG32(0X40000D4)
  269. #define DMA3DAD     DEFINE_REG32(0X40000D8)
  270. #define DMA3CNTL    DEFINE_REG16(0X40000DC)
  271. #define DMA3CNTH    DEFINE_REG16(0X40000DE)
  272.  
  273.  
  274.  
  275. /*
  276. #define
  277. #define
  278. #define
  279. #define
  280. #define
  281. #define
  282. #define
  283. #define
  284. #define
  285. #define
  286. #define
  287. #define
  288. #define
  289. #define
  290. #define
  291. #define
  292. #define
  293. #define
  294. #define
  295. #define
  296. #define
  297. #define
  298. #define
  299. #define
  300. #define
  301. #define
  302. #define
  303. #define
  304. #define
  305. #define
  306. #define
  307. #define
  308. #define
  309. #define
  310. #define
  311. #define
  312. #define
  313. #define
  314. #define
  315. #define
  316. #define
  317. #define
  318. #define
  319. #define
  320. #define
  321. #define
  322. #define
  323. #define
  324. #define
  325. #define
  326. */
  327.  
  328. #undef DEFINE_REG16()
  329. #undef DEFINE_REG32()



bios.c

Codice sorgente - presumibilmente Delphi

  1. /**
  2.  
  3. divisione hardware
  4. ritorna in 800d TODO pointer
  5. 0 div
  6. 1 mod
  7. 2 abs div
  8.  
  9. */
  10. __attribute__ ((noinline)) void bios_div_single (u32 num, u32 den, u32 func)
  11.  
  12. {
  13.     asm ("push {r0-r4}");
  14.  
  15.     ASM_800D_R4;
  16.  
  17.  
  18.     asm ("swi 0x7");
  19.  
  20.  
  21.     asm ("cmp r2, #0");
  22.     asm ("bne bios_div_single_cmp1");
  23.     asm ("str r0, [r4]");
  24.  
  25.     asm (".bios_div_single_cmp1:");
  26.     asm ("cmp r2, #1");
  27.     asm ("bne bios_div_single_cmp2");
  28.     asm ("str r1, [r4]");
  29.     asm (".bios_div_single_cmp2:");
  30.     asm ("cmp r2, #2");
  31.     asm ("bne .bios_div_single_exit");
  32.     asm ("str r3, [r4]");
  33.  
  34.  
  35.     asm (".bios_div_single_exit:");
  36.     asm ("push {r0-r4}");
  37.  
  38. }
  39.  
  40.  
  41. __attribute__ ((noinline)) void bios_div_multi (u32 num, u32 den, u32* alloc)
  42.  
  43. {
  44.     asm ("push {r0-r4}");
  45.  
  46.  
  47.  
  48.  
  49.     asm ("swi 0x7");
  50.  
  51.  
  52.     asm("str r0, [r2]");
  53.     asm("str r1, [r2,#4]");
  54.     asm("str r3, [r2,#8]");
  55.     asm ("push {r0-r4}");
  56.  
  57. }
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67. /*
  68. BIOS Function Summary
  69.  
  70.  
  71.   GBA  NDS7 NDS9 DSi7 DSi9 Basic Functions
  72.   00h  00h  00h  -    -    SoftReset
  73.   01h  -    -    -    -    RegisterRamReset
  74.   02h  06h  06h  06h  06h  Halt
  75.   03h  07h  -    07h  -    Stop/Sleep
  76.   04h  04h  04h  04h  04h  IntrWait       ;DSi7/DSi9: both bugged?
  77.   05h  05h  05h  05h  05h  VBlankIntrWait ;DSi7/DSi9: both bugged?
  78.   06h  09h  09h  09h  09h  Div
  79.   07h  -    -    -    -    DivArm
  80.   08h  0Dh  0Dh  0Dh  0Dh  Sqrt
  81.   09h  -    -    -    -    ArcTan
  82.   0Ah  -    -    -    -    ArcTan2
  83.   0Bh  0Bh  0Bh  0Bh  0Bh  CpuSet
  84.   0Ch  0Ch  0Ch  0Ch  0Ch  CpuFastSet
  85.   0Dh  -    -    -    -    GetBiosChecksum
  86.   0Eh  -    -    -    -    BgAffineSet
  87.   0Fh  -    -    -    -    ObjAffineSet
  88.   GBA  NDS7 NDS9 DSi7 DSi9 Decompression Functions
  89.   10h  10h  10h  10h  10h  BitUnPack
  90.   11h  11h  11h  11h  11h  LZ77UnCompReadNormalWrite8bit   ;"Wram"
  91.   12h  -    -    -    -    LZ77UnCompReadNormalWrite16bit  ;"Vram"
  92.   -    -    -    01h  01h  LZ77UnCompReadByCallbackWrite8bit
  93.   -    12h  12h  02h  02h  LZ77UnCompReadByCallbackWrite16bit
  94.   -    -    -    19h  19h  LZ77UnCompReadByCallbackWrite16bit (same as above)
  95.   13h  -    -    -    -    HuffUnCompReadNormal
  96.   -    13h  13h  13h  13h  HuffUnCompReadByCallback
  97.   14h  14h  14h  14h  14h  RLUnCompReadNormalWrite8bit     ;"Wram"
  98.   15h  -    -    -    -    RLUnCompReadNormalWrite16bit    ;"Vram"
  99.   -    15h  15h  15h  15h  RLUnCompReadByCallbackWrite16bit
  100.   16h  -    16h  -    16h  Diff8bitUnFilterWrite8bit       ;"Wram"
  101.   17h  -    -    -    -    Diff8bitUnFilterWrite16bit      ;"Vram"
  102.   18h  -    18h  -    18h  Diff16bitUnFilter
  103.   GBA  NDS7 NDS9 DSi7 DSi9 Sound (and Multiboot/HardReset/CustomHalt)
  104.   19h  08h  -    08h  -    SoundBias
  105.   1Ah  -    -    -    -    SoundDriverInit
  106.   1Bh  -    -    -    -    SoundDriverMode
  107.   1Ch  -    -    -    -    SoundDriverMain
  108.   1Dh  -    -    -    -    SoundDriverVSync
  109.   1Eh  -    -    -    -    SoundChannelClear
  110.   1Fh  -    -    -    -    MidiKey2Freq
  111.   20h  -    -    -    -    SoundWhatever0
  112.   21h  -    -    -    -    SoundWhatever1
  113.   22h  -    -    -    -    SoundWhatever2
  114.   23h  -    -    -    -    SoundWhatever3
  115.   24h  -    -    -    -    SoundWhatever4
  116.   25h  -    -    -    -    MultiBoot
  117.   26h  -    -    -    -    HardReset
  118.   27h  1Fh  -    1Fh  -    CustomHalt
  119.   28h  -    -    -    -    SoundDriverVSyncOff
  120.   29h  -    -    -    -    SoundDriverVSyncOn
  121.   2Ah  -    -    -    -    SoundGetJumpList
  122.   GBA  NDS7 NDS9 DSi7 DSi9 New NDS Functions
  123.   -    03h  03h  03h  03h  WaitByLoop
  124.   -    0Eh  0Eh  0Eh  0Eh  GetCRC16
  125.   -    0Fh  0Fh  -    -    IsDebugger
  126.   -    1Ah  -    1Ah  -    GetSineTable
  127.   -    1Bh  -    1Bh  -    GetPitchTable (DSi7: bugged)
  128.   -    1Ch  -    1Ch  -    GetVolumeTable
  129.   -    1Dh  -    1Dh  -    GetBootProcs (DSi7: only 1 proc)
  130.   -    -    1Fh  -    1Fh  CustomPost
  131.   GBA  NDS7 NDS9 DSi7 DSi9 New DSi Functions (RSA/SHA1)
  132.   -    -    -    20h  20h  RSA_Init_crypto_heap
  133.   -    -    -    21h  21h  RSA_Decrypt
  134.   -    -    -    22h  22h  RSA_Decrypt_Unpad
  135.   -    -    -    23h  23h  RSA_Decrypt_Unpad_GetChunk04
  136.   -    -    -    24h  24h  SHA1_Init
  137.   -    -    -    25h  25h  SHA1_Update
  138.   -    -    -    26h  26h  SHA1_Finish
  139.   -    -    -    27h  27h  SHA1_Init_update_fin
  140.   -    -    -    28h  28h  SHA1_Compare_20_bytes
  141.   -    -    -    29h  29h  SHA1_Random_maybe
  142.   GBA  NDS7 NDS9 DSi7 DSi9 Invalid Functions
  143.   2Bh+ 20h+ 20h+ -    -    Crash (SWI xxh..FFh do jump to garbage addresses)
  144.   -    xxh  xxh  -    -    Jump to 0   (on any SWI numbers not listed above)
  145.   -    -    -    12h  12h  No function (ignored)
  146.   -    -    -    2Bh  2Bh  No function (ignored)
  147.   -    -    -    40h+ 40h+ Mirror      (SWI 40h..FFh mirror to 00h..3Fh)
  148.   -    -    -    xxh  xxh  Hang        (on any SWI numbers not listed above)
  149.  
  150.  
  151. */



ho scelto l'attributo noinline perchè pensavo che magari senza mi avrebbe incasinato i registri delle funzioni in asm...

math.c

Codice sorgente - presumibilmente Delphi

  1. /**
  2.  
  3. divisione hardware
  4. ritorna in 800d TODO pointer
  5. 0 div
  6. 1 mod
  7. 2 abs div
  8.  
  9. */
  10. void math_div_single(int a)
  11. {
  12. }
  13.  
  14.  
  15.  
  16. void math_div_multiple(u32 n, u32 d, boolean allocNeed, u32 offs)
  17. {
  18.  
  19. /*
  20. if (allocNeed)
  21. {
  22. util_memAlloc32(3);
  23. offs =(u32*) OFFSET_AS_POINTER32(var_0x800D);
  24.  
  25.  
  26. }
  27. else
  28. {
  29. }
  30. */
  31. //bios_div_multi(n, d, offs);
  32.  
  33.  
  34.  
  35.  
  36. // return offs;
  37.  
  38. }




text.c

Codice sorgente - presumibilmente C/C++

  1. /**
  2. scrive un carattere. USO INTERNO.
  3. x e y del gba, non della console.
  4. */
  5. void text_putc16bpp(u8 chr, u8 x, u8 y, T_COLOR clr)
  6. {
  7.  
  8.  
  9.     u32 chra=0;
  10.     u32 chrb=0;
  11. // rendere funzione o lut o vram
  12.  
  13.  
  14. //tonc
  15.  
  16.     if (chr== 'a')
  17.     {
  18.         chra=0x7E66663C;
  19.         chrb=0x00666666;
  20.     }
  21.  
  22.  
  23. // FINE RENDERE
  24.  
  25.         util_memAlloc32(3);
  26.         u32* div =(u32*) OFFSET_AS_POINTER32(var_0x800D);
  27.  
  28.  
  29. u32 i =0;
  30.  
  31.  
  32.     for (; i<32; i++)
  33.       {
  34. BREAKPOINT;
  35.       //math_div_multiple (i,8, FALSE, div);
  36. bios_div_multi(i, 8, div);
  37.         video_plotPixelM3inline(x+*(div++), y+*(div--),clr*(chra&1) );
  38. //fare in ++ e if 8 =0
  39. // TODO SVUOTA IL LOOP
  40.  
  41.         chra>>=1;
  42.       }
  43.  
  44.       for (int i=0; i<32; i++)
  45.       {
  46.  
  47.           //math_div_multiple (i,8, FALSE, div);
  48.  
  49.     bios_div_multi(i, 8, div);
  50.  
  51.  
  52.         video_plotPixelM3inline(x+*(div++), y+4+*(div--),clr*(chrb&1) );
  53.  
  54. // TODO SVUOTA IL LOOP
  55.  
  56.         chrb>>=1;
  57.       }
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64. //TODO DISEGNA 2 PX ALLA VOLTA
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.     }



util.c

Codice sorgente - presumibilmente C/C++

  1. void util_memcpy32(u32 dst, u32 src, u32 wdcount)
  2. {
  3.     while (wdcount--)
  4.     {
  5.         OFFSET_AS_POINTER32(dst)=OFFSET_AS_POINTER32(src);
  6.         dst+=4;
  7.         src+=4;
  8.  
  9.     }
  10. }
  11.  
  12. __attribute__ ((noinline)) void util_blockFill(u32 dest, u32 lung, u32 filler)
  13. {
  14.     //memAlloc(12);
  15.     //u32 ofpoint=OFFSET_AS_POINTER32(var_0x800D);
  16.     //u32* mem =(u32*) ofpoint;
  17.     //u32* mem =(u32*) OFFSET_AS_POINTER32(var_0x800D);
  18.     //mem[0]=dest;
  19.     //mem[1]=lung;
  20.     //mem[2]=filler;
  21.  
  22.     //VERSIONE C
  23.     //eppure mi sembra giusto :c
  24.  
  25.     while(lung--)
  26.     {
  27.     *((u32*)dest)=filler;
  28.     dest+=4;
  29.     }
  30.  
  31.  
  32. /*
  33.     asm ("push {r0-r3}");
  34.  
  35.  
  36.     asm ("mov r0, #2");
  37.     asm (" lsl r0, #0x8");
  38.     asm ("add r0, r0, #2");
  39.     asm ("lsl r0, #0x4");
  40.     asm ("add r0, r0, #14");
  41.     asm ("lsl r0, #0x4");
  42.     asm ("add r0, r0, #8");
  43.     asm ("lsl r0, #0x4");
  44.     asm ("add r0, r0, #13");
  45.     asm ("lsl r0, #0x4");
  46.     asm ("add r0, r0, #12");
  47.     //fin qui ho creato la var 800D 0202E8DC
  48.     asm ("ldr r0, [r0]");
  49.     //carico il vettore nei reg:
  50.     asm ("add r0, r0, #8");
  51.     asm ("ldr r2,[r0]");
  52.     asm ("sub r0, r0, #4");
  53.     asm ("ldr r1,[r0]");
  54.     asm ("sub r0, r0, #4");
  55.     asm ("ldr r0, [r0]");
  56.     //loop che scrive e decrementa:
  57.     // r0 dest r1 lung r2 fill
  58.     asm ("lsl r1, #0x2");
  59.     asm ("add r1, r0, r1");
  60.     asm (".util_blockfill_main_loop:");
  61.     asm ("str r2, [r0]");
  62.     asm ("add r0, r0, #4");
  63.     asm ("cmp r0, r1"); // TODO QUA LOOPA
  64.     asm ("bne util_blockfill_main_loop");
  65.  
  66.  
  67.     asm ("pop {r0-r3}");
  68.  
  69. */
  70.     //memFree((u32)mem);
  71. }
  72.  
  73.  
  74. /**
  75. mette in 800d+f l'indirizzo di uno spazio di ram
  76. grande almeno lung parole da 32 bit
  77. */
  78. __attribute__ ((noinline)) void util_memAlloc32 (u32 lung)
  79. {
  80.  
  81. // NOTA: IN ASM GIUSTO
  82. //asm ("push {r0-r4}");
  83.  
  84. //asm ("mov r3, #0");
  85.  
  86.  
  87. //asm ("mov r1, #1");
  88. //asm ("lsl r1, #0x19");
  89. // 1<<25=0x2000000
  90. //asm (".util_memAlloc32_loop:");
  91. //asm ("ldr r2, [r1]");
  92. //asm ("cmp r2, #0");
  93. //asm ("beq .util_memAlloc32_trovato"); // piu probabilr ke sia != percio non svuoto la pipeline
  94. //asm ("mov r3, #0");//resetto il counter
  95. //asm ("add r1, r1, #4");
  96. /*
  97. asm ("b .util_memAlloc32_loop");
  98. asm (".util_memAlloc32_trovato:");
  99. asm ("add r3, r3, #1");
  100. asm ("add r1, r1, #4");
  101. asm ("cmp r3, r0");
  102.  
  103. asm ("bne .util_memAlloc32_loop");
  104. //-------
  105. asm ("mov r3, #4");
  106. asm ("mul r0, r3");
  107. asm ("sub r1, r1, r0");
  108.  
  109. //-----------------
  110. asm ("mov r4, #2");
  111. asm (" lsl r4, #0x8");
  112. asm ("add r4, r4, #2");
  113.     asm ("lsl r4, #0x4");
  114.     asm ("add r4, r4, #14");
  115.     asm ("lsl r4, #0x4");
  116.     asm ("add r4, r4, #8");
  117.     asm ("lsl r4, #0x4");
  118.     asm ("add r4, r4, #13");
  119.     asm ("lsl r4, #0x4");
  120.     asm ("add r4, r4, #12");
  121.     //fin qui ho creato la var 800D 0202E8DC
  122.  
  123. */
  124. //asm("str r0, [r4]");
  125. //mette il risultato nella var 800d e seguente f
  126. //asm ("pop {r0-r4}");
  127.  
  128. u32 ofs=0x2000000;
  129. u32 count=1;
  130. count--;
  131. while (ofs<256*1024)
  132. {
  133.     if (!(OFFSET_AS_POINTER32(ofs))) //se a ofs c'e zero
  134.     {    count++;
  135.  
  136.     }
  137.     else
  138.     {    count=0;
  139.  
  140.     }
  141.     if (lung==count) break;
  142.     ofs++;
  143. }
  144.  
  145. OFFSET_AS_POINTER32(var_0x800D)=ofs-lung*4;
  146.  
  147.  
  148. }
  149. void util_memFree32(u32 offs, u32 size)
  150. {
  151.     util_blockFill(offs, size, 0x0);
  152. }



video.c

Codice sorgente - presumibilmente C/C++

  1. //==================  DICHIARAZIONI  ==================
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8. //==================  DEFINIZIONI  ==================
  9.  
  10. /**
  11. BG Mode                 (0-5=Video Mode 0-5, 6-7=Prohibited)
  12. Display Frame Select    (0-1=Frame 0-1) (for BG Modes 4,5 only)
  13. H-Blank Interval Free   (1=Allow access to OAM during H-Blank)
  14. OBJ Character VRAM Mapping  (0=Two dimensional, 1=One dimensional)
  15. Forced Blank            (1=Allow FAST access to VRAM,Palette,OAM)
  16. Screen Display BG0      (0=Off, 1=On)
  17. Screen Display BG1      (0=Off, 1=On)
  18. Screen Display BG2      (0=Off, 1=On)
  19. Screen Display BG3      (0=Off, 1=On)
  20. Screen Display OBJ      (0=Off, 1=On)
  21. Window 0 Display Flag   (0=Off, 1=On)
  22. Window 1 Display Flag   (0=Off, 1=On)
  23. OBJ Window Display Flag (0=Off, 1=On)
  24. */
  25. void video_initDispCntGlobal(u8 bgMode, boolean frame, boolean hBlank, boolean objMapping, boolean forceBlank, boolean bg0, boolean bg1, boolean bg2, boolean bg3, boolean obj, boolean win0, boolean win1, boolean winObj)
  26. {
  27.     u16 newreg=video_createDispCnt(bgMode, frame, hBlank, objMapping, forceBlank, bg0, bg1, bg2, bg3, obj, win0, win1, winObj);
  28.     if (newreg!=0)
  29.         DISPCNT=newreg;
  30.  
  31.  
  32.  
  33. }
  34. /**
  35.  
  36. choose the property to set between DISPCNT_XXX_PROPERTY
  37.  
  38. if bgmode, flag ignored
  39. if other property, bgmode ignored
  40.  
  41. */
  42.  
  43. void video_setDispCntProperties(u8 property, u8 bgMode, boolean flag)
  44. {
  45.  
  46.  
  47.  
  48.     u16 newreg=0;
  49.     u16 oldreg = DISPCNT;
  50.     if (property!=DISPCNT_BGMODE_PROPERTY)
  51.         newreg=flag<<property;
  52.    // else if (!(bgMode>5)) newreg = bgMode;
  53.     DISPCNT= (oldreg^newreg);
  54.  
  55.  
  56.  
  57.  
  58.  
  59. }
  60.  
  61. /**
  62.     PRIVATE USE
  63. */
  64. u16 video_createDispCnt(u8 bgMode, boolean frame, boolean hBlank, boolean objMapping, boolean forceBlank, boolean bg0, boolean bg1, boolean bg2, boolean bg3, boolean obj, boolean win0, boolean win1, boolean winObj)
  65. {
  66.     if (!(bgMode>5))
  67.         return (bgMode|(frame<<4)|(hBlank<<5)|(objMapping<<6)|(forceBlank<<7)|(bg0<<7)|(bg1<<8)|(bg2<<9)|(bg2<<10)|(bg3<<11)|(obj<<12)|(win0<<13)|(win1<<14)|(winObj<<15));
  68.  
  69.     else return 0;
  70. }
  71.  
  72. T_COLOR video_alphaBlend(T_COLOR source, T_COLOR newcol, u8 coef)
  73. {
  74.  
  75. /*
  76.     float alpha=coef/255;
  77.     {
  78.         float ra = getR(source)/MAX_COLOR_VALUE;
  79.         float ga = getG(source)/MAX_COLOR_VALUE;
  80.         float ba = getB(source)/MAX_COLOR_VALUE;
  81.  
  82.         float rb = getR(newcol)/MAX_COLOR_VALUE;
  83.         float gb = getG(newcol)/MAX_COLOR_VALUE;
  84.         float bb = getB(newcol)/MAX_COLOR_VALUE;
  85.  
  86.         float rt= alpha * (rb - ra) + ra;
  87.         float gt= alpha * (gb - ga) + ga;
  88.         float bt= alpha * (bb - ba) + ba;
  89.  
  90.         int rd =(int)(rt*MAX_COLOR_VALUE);
  91.         int gd=(int)(gt*MAX_COLOR_VALUE);
  92.         int bd=(int)(bt*MAX_COLOR_VALUE);
  93.  
  94.         return RGB16(rd,gd,bd);
  95.     }
  96.     else<*/ return 0x8000; //colore invalido
  97. }
  98.  
  99. void video_plotPixelM3(u8 x, u8 y, T_COLOR color, boolean transp)
  100. {
  101.     if (!((transp)&&(color>0x7fff )))
  102. ((u16*)0x06000000)[x+y*SCREEN_WIDTH] = color;
  103. }
  104.  
  105.  
  106.  
  107. inline void video_plotPixelM3inline (int x, int y, T_COLOR clr)
  108. {   (( u16*)0x06000000)[y*SCREEN_WIDTH+x]= clr;    }
  109.  
  110. int video_getR(T_COLOR c)
  111. {   return (c&31);   }
  112. int video_getG(T_COLOR c)
  113. {   return ((c&992)>>5);    }
  114. int video_getB(T_COLOR c)
  115. {   return ((c&31744)>>10); }



grazie e buonasera


Ultima modifica effettuata da Bonnox il 21/07/2016 alle 18:24
PM Quote