Oppure

Loading
05/07/16 13:29
Bonnox
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:
"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:

#define ASM_CMT(str) asm ("@; " str)

#define MY_FUNC \
ASM_CMT("-----------------");\
ASM_CMT("-----------------");\
ASM_CMT("-----------------");\
ASM_CMT("-----------------");\
ASM_CMT("-----------------");\
ASM_CMT("-----------------");\
ASM_CMT("-----------------");\
asm  (".align 8, 0x00");\
asm  (".ascii \"MAIN\" " ) ; \
asm  (".align 4, 0x00");\
ASM_CMT("-----------------");\
ASM_CMT("-----------------");\
ASM_CMT("-----------------");\
ASM_CMT("-----------------");\
ASM_CMT("-----------------");\
ASM_CMT("-----------------");\
ASM_CMT("-----------------")



E alla fine c'è questo:


MY_FUNC;
int main ()
{

    return 0;

}


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):

@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	.align 8, 0x00
	.ascii "MAIN" 
	.align 4, 0x00
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	.thumb
	.syntax unified
	.align	2
	.global	main
	.code	16
	.thumb_func
	.type	main, %function
.main:
	.fnstart
.LFB13:
	push	{r7, lr}
	add	r7, sp, #0
	movs	r3, #0
	movs	r0, r3
	mov	sp, r7
	@ sp needed
	pop	{r7}
	pop	{r1}
	bx	r1
	.cantunwind
	.fnend
	.size	main, .-main
	.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:

	.syntax unified
	.cpu arm7tdmi
	.fpu softvfp
	.eabi_attribute 20, 1
	.eabi_attribute 21, 1
	.eabi_attribute 23, 3
	.eabi_attribute 24, 1
	.eabi_attribute 25, 1
	.eabi_attribute 26, 1
	.eabi_attribute 30, 1
	.eabi_attribute 34, 0
	.eabi_attribute 18, 4
	.thumb
	.syntax unified
	.file	"test.C"
	.syntax divided
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	.align 8, 0x00
	.ascii "MAIN" 
	.align 4, 0x00
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------
	@; -----------------


e alla fine questo:

.global	main
	.code	16
	.thumb_func
	.type	main, %function
.main:
	.fnstart
.LFB13:
	movs	r0, #0
	@ sp needed
	bx	lr
	.cantunwind
	.fnend
	.size	main, .-main
	.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 05/07/16 13:41
aaa
05/07/16 14:08
pierotofy
Potresti specificare manualmente quali ottimizzazioni vuoi usare invece di usare -O1 o -O2:

-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.

gcc.gnu.org/onlinedocs/gcc/…

Non ho capito la seconda "stranezza", forse potresti spiegarci con un esempio?
Il mio blog: piero.dev
05/07/16 17:01
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.
aaa
05/07/16 17:18
TheDarkJuster
a naso direi che:
-freorder-blocks-algorithm=stc 
-freorder-blocks-and-partition -freorder-functions 

queste sono le ottimizzazioni incriminate
aaa
05/07/16 18:32
Bonnox
grazie a tutti, è stata una lettura molto utile.

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

ora provo e faccio sapere

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 05/07/16 18:54
aaa
05/07/16 18:49
Bonnox
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:

.align 2


che iniziano con un punto.

poi ci sono le etichette:

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:

.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

here: B here



ciao e grazie


ho fatto un doppio post, come cancello questo per unirlo al precedente?
Ultima modifica effettuata da Bonnox 05/07/16 18:53
aaa
06/07/16 15:00
pierotofy
Potresti postarci il programma in C, il comando gcc che compila il programma, e il risultante assembly?
Il mio blog: piero.dev
21/07/16 14:44
Bonnox
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):

"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):

as -a -mthumb -mthumb-interwork "%src%"
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:
int chiamata (char, short);

void prova ()
{
	int a = chiamata (0xB, 10);
}

int chiamata(char a, short b)
{
	return ((short) a + b);
}



senza ottimizzazioni (perchè se no mi segava questo esempio con la variabile non utilizzata) si genera una cosa del genere:
	.syntax unified
	.cpu arm7tdmi
	.fpu softvfp
	.eabi_attribute 20, 1
	.eabi_attribute 21, 1
	.eabi_attribute 23, 3
	.eabi_attribute 24, 1
	.eabi_attribute 25, 1
	.eabi_attribute 26, 1
	.eabi_attribute 30, 6
	.eabi_attribute 34, 0
	.eabi_attribute 18, 4
	.thumb
	.syntax unified
	.file	"provablpiero.c"
	.text
	.align	2
	.global	prova
	.code	16
	.thumb_func
	.type	prova, %function
prova:
	push	{r7, lr}
	sub	sp, sp, #8
	add	r7, sp, #0
	movs	r1, #10
	movs	r0, #11
	bl	chiamata
	movs	r3, r0
	str	r3, [r7, #4]
	nop
	mov	sp, r7
	add	sp, sp, #8
	@ sp needed
	pop	{r7}
	pop	{r0}
	bx	r0
	.size	prova, .-prova
	.align	2
	.global	chiamata
	.code	16
	.thumb_func
	.type	chiamata, %function
chiamata:
	push	{r7, lr}
	sub	sp, sp, #8
	add	r7, sp, #0
	movs	r2, r0
	adds	r3, r7, #7
	strb	r2, [r3]
	adds	r3, r7, #4
	adds	r2, r1, #0
	strh	r2, [r3]
	adds	r3, r7, #7
	ldrb	r2, [r3]
	adds	r3, r7, #4
	movs	r1, #0
	ldrsh	r3, [r3, r1]
	adds	r3, r2, r3
	movs	r0, r3
	mov	sp, r7
	add	sp, sp, #8
	@ sp needed
	pop	{r7}
	pop	{r1}
	bx	r1
	.size	chiamata, .-chiamata
	.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:

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:

.THUMB
.ALIGN 2


PUSH {r0-r7, lr}

ldr r1, .base
BL LINKER

POP {r0-r7, pc}


LINKER:
BX R1

.align 2, 0x00
.base:
.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 :)

package it.bonnox.asmdeployer;


import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import java.nio.file.Files;
import java.nio.file.Paths;


import it.bonnox.myLibPers.basicBytesLibrary.CoreLibrary;
import it.bonnox.myLibPers.basicBytesLibrary.Pointer;
import it.bonnox.myLibPers.utils.*;


public class MainDeployer
{
	
	private static final int		SCOSTAMENTO_ALIGN				= 64;
	private static final int		DIMENSIONE_AREA_COMPILAZIONE	= 6 * 1024 * 1024;
	private static final int		ARG_OFFSETINSERIMENTO	= 2;
	private static final int		ARG_PERCORSOCOMPILATO	= 1;
	private static final int		ARG_PERCORSOROM			= 0;
	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 };
	private static final int		ARG_DEFINE				= 3;
	private static final boolean	DEBUG							= false;
															
	@SuppressWarnings ("unused")
	public static void main(String[] args) throws IOException
	{
		System.out.println("\ndeploying...");
		if (DEBUG) System.err.println(" *** DEBUG ***");
		
		if (args.length != ARG_DEFINE && !DEBUG)
			{
				System.err.println("WRONG NUMBER OF PARAMERERS\n" + "usage:\n" + "rom\n" + "filebin\n" + "offset\n");
				System.exit(-1);
			}
		
		

		String percorsoROM;
		String percorsoCompilato;
		int offsetInserimento;
		
		if (DEBUG)
			{
				percorsoROM = "D:\GXX-XDS\C Environment Deployment\out\test.gba";
				percorsoCompilato = "D:\GXX-XDS\C Environment Deployment\middle\test.s.bin";
				offsetInserimento = 0x1c00000;
			}
		else
			{
				percorsoROM = args[ARG_PERCORSOROM];
				percorsoCompilato = args[ARG_PERCORSOCOMPILATO];
				offsetInserimento = Integer.parseInt(args[ARG_OFFSETINSERIMENTO], 16);
			}
			

		
		byte[] bytesROM = Files.readAllBytes(Paths.get(new File(percorsoROM).toURI()));
		
		System.out.println("opening compiled...");
		byte[] bytesCompilato = Files.readAllBytes(Paths.get(new File(percorsoCompilato).toURI()));
		
		int indirizzoMain = getMainCompilato(bytesCompilato, offsetInserimento);
		
		if (indirizzoMain < 0) System.exit(indirizzoMain);
		
		sostituisciLinker(LINKERROUTINEBINARY, indirizzoMain);
		
		// unisce le parti
		
		byte[] inserimento = new byte[DIMENSIONE_AREA_COMPILAZIONE];
		
		// copia il linker
		for (int i = 0; i < LINKERROUTINEBINARY.length; i++)
			{
				inserimento[i] = LINKERROUTINEBINARY[i];
			}
		// copia la compilazione
		for (int i = LINKERROUTINEBINARY.length; i < bytesCompilato.length; i++)
			{
				inserimento[i] = bytesCompilato[i];
			}
			
		noppa(inserimento, LINKERROUTINEBINARY.length, bytesCompilato.length);
		
		scriviROM(bytesROM, percorsoROM, offsetInserimento, inserimento);
		
	}
	
	

	private static void noppa(byte[] inserimento, int length, int length2)
	{
		for (int i = length + length2; i < inserimento.length; i += 2)
			{
				if (i == inserimento.length)
					{
						// se i è uguale all ultimo , vuol dire che e dispari
						// (?)
						inserimento[i] = (byte) 0xC0;
					}
				else
					{
						inserimento[i] = (byte) 0xC0;
						inserimento[i + 1] = (byte) 0x46;
					}
			}
		
	}
	
	private static void sostituisciLinker(byte[] lINKERROUTINEBINARY2, int indirizzo)
	{
		Pointer nuovo = new Pointer(indirizzo);
		it.bonnox.myLibPers.basicBytesLibrary.CoreLibrary.writeBytes(lINKERROUTINEBINARY2, lINKERROUTINEBINARY2.length - 4, nuovo.getBinaryGBA());
		
	}
	
	private static int getMainCompilato(byte[] bytesCompilato, int offsetinserimento)
	{
		
		int ritorno = -1;
		for (int i = 0; i < bytesCompilato.length; i += SCOSTAMENTO_ALIGN)
			{
				if (DEBUG)
					{
					
					}
				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] == ' ')
					{
						ritorno = i;
					}
					
			}
		return ritorno + LINKERROUTINEBINARY.length + offsetinserimento;
	}
	
	private static void scriviROM(byte[] ROMfile, String percorso, int offsetInserimento, byte[] nuovi) throws FileNotFoundException, IOException
	{
		
		System.out.println("finalizing...");
		CoreLibrary.writeBytes(ROMfile, offsetInserimento, nuovi);
		Misc.salvaFile(new File(percorso), ROMfile);
		System.out.println("successfully deployed.");
		
	}
	
}


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".

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:

#include "libonnox.h"

#include "libonnox/bios.c"
#include "libonnox/math.c"
#include "libonnox/util.c"
#include "libonnox/video.c"
#include "libonnox/text.c"



/* TODO

problemi:
- se metto troppe funzioni, l'as va per campi.
- fascia nera a sx del gba

problemi risolti:

----------

problemi boh:
- 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
mettendo la flag da -O2 a -O1, il C funge :)
non e' vero, ora non va piu, devo toglierle del tutto :c
*/

void metodo()
{

u16 tmp= DISPCNT;


//util_blockfill(0x04000000, 256, 0x0);

*(unsigned int*)0x04000000 = 0x0403;
//util_memAlloc32(0x8);
/*
OFFSET_AS_POINTER8(0x4000021)=(u8)1;
OFFSET_AS_POINTER8(0x4000027)=(u8)1;
OFFSET_AS_POINTER8(0x4000031)=(u8)1;
OFFSET_AS_POINTER8(0x4000037)=(u8)1;
OFFSET_AS_POINTER8(0x4000082)=(u8)0xe;
OFFSET_AS_POINTER8(0x4000089)=(u8)0x2;

*/

util_blockFill(0x06000000, 5600, 0x7fff7fff);
/*u32 color=RGB16(9, 1, 2);
color=color<<16;
color+=RGB16(5, 5, 5);
util_blockFill(0x06000000+9600*4, 9600, color);//BREAKPOINT;*/

//util_blockFill(0x04000010, 4, 0x0);


//draw_line (1, 50, 0x3456);


text_putc16bpp ('a', 30, 4, 0x3333);


//DISPCNT=tmp;


}

void linker(u16 nf)
{




    switch (nf)
    {

    case 0:
         metodo();
        break;

    }



}

NEW_FUNC;
void hackMain()

{

    linker(OFFSET_AS_POINTER16(var_0x800D));
}


libonnox.h

/**
---------------
    USEFUL
---------------
*/


#define ASM_CMT(str) asm ("@; " str)


#define CALL(str) asm("bl ." str )

#define NEW_FUNC \
ASM_CMT("-----------------");\
ASM_CMT("-----------------");\
asm  (".align 6, 0x00");\
asm  (".ascii \"START OF FRAME  \" " ) ; \
asm  (".align 4, 0x00");\
ASM_CMT("-----------------");\
ASM_CMT("-----------------")

#define MY_FUNC \
ASM_CMT("-----------------");\
ASM_CMT("-----------------");\
asm  (".align 8, 0x00");\
asm  (".ascii \"MAIN\" " ) ; \
asm  (".align 4, 0x00");\
ASM_CMT("-----------------");\
ASM_CMT("-----------------")


#define BREAKPOINT asm (".align 1");\
asm (".byte 0xfe, 0x0");\
asm (".byte 0xe7");\
asm (".align 1, 0x0")

/* asm (".align 1");\
asm (".byte 0xfe");\
asm (".byte 0xde");\
asm (".align 1")

*/

#define OFFSET_AS_POINTER8(num) (*(u8*)num)
#define OFFSET_AS_POINTER16(num) (*(u16*)num)
#define OFFSET_AS_POINTER32(num) (*(u32*)num)

typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;

#define ASM_800D_R4 \
    asm ("mov r4, #2");\
asm (" lsl r4, #0x8");\
asm ("add r4, r4, #2");\
    asm ("lsl r4, #0x4");\
    asm ("add r4, r4, #14");\
    asm ("lsl r4, #0x4");\
    asm ("add r4, r4, #8");\
    asm ("lsl r4, #0x4");\
    asm ("add r4, r4, #13");\
    asm ("lsl r4, #0x4");\
    asm ("add r4, r4, #12")



/**
---------------
    BOOL
---------------
*/


typedef u32 boolean;

#define TRUE 1
#define FALSE 0

/**
---------------
    BIOS
---------------
*/


#define bios_vBlankIntrWait() asm ("swi 0x5")

#define bios_halt() asm ("swi 0x2")
#define bios_intrWait() asm ("swi 0x4")



#define bios_div_single_DIV 1
#define bios_div_single_MOD 2
void bios_div_single (u32 num, u32 den, u32 func);

void bios_div_multi (u32 num, u32 den, u32* alloc);



/**
---------------
    VIDEO
---------------
*/

#define RGB16(r,g,b) (r+(g<<5)+(b<<10))


#define MAX_COLOR_VALUE 31 // i colori sono 0-bbbbb-ggggg-rrrrr
#define SCREEN_WIDTH   240
#define SCREEN_HEIGHT  160


#define DISPCNT_BGMODE_PROPERTY 0
#define DISPCNT_FRAME_PROPERTY 3
#define DISPCNT_H_BLANK_PROPERTY 5
#define DISPCNT_OBJMAP_PROPERTY 6
#define DISPCNT_FORCEDBLANK_PROPERTY 7
#define DISPCNT_BG0_PROPERTY 8
#define DISPCNT_BG1_PROPERTY 9
#define DISPCNT_BG2_PROPERTY 10
#define DISPCNT_BG3_PROPERTY 11
#define DISPCNT_OBJ_PROPERTY 12
#define DISPCNT_WIN0_PROPERTY 13
#define DISPCNT_WIN1_PROPERTY 14
#define DISPCNT_WINOBJ_PROPERTY 15

#define CLR_BLACK   0x0000
#define CLR_RED     0x001F
#define CLR_LIME    0x03E0
#define CLR_YELLOW  0x03FF
#define CLR_BLUE    0x7C00
#define CLR_MAG     0x7C1F
#define CLR_CYAN    0x7FE0
#define CLR_WHITE   0x7FFF
typedef u16 T_COLOR;

//void initM3();



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);
void video_setDispCntProperties(u8 property, u8 bgMode, boolean flag);
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);
T_COLOR video_alphaBlend(T_COLOR source, T_COLOR newcol, u8 coef);


void video_plotPixelM3(u8 x, u8 y, T_COLOR color, boolean transp);

inline void video_plotPixelM3inline (int x, int y, T_COLOR clr);

inline int video_getR(T_COLOR clr);
inline int video_getG(T_COLOR clr);
inline int video_getB(T_COLOR clr);



/**
---------------
    UTIL
---------------
*/
#define var_0x800D 0x0202E8DC

void util_memcpy32(u32 dst,  u32 src, u32 wdcount);
void util_blockFill(u32 dest, u32 lung, u32 filler);
void util_memAlloc32(u32 lung);
void util_memFree32(u32 offs);






/**
---------------
    TEXT
---------------
*/

void text_putc16bpp (u8 chr, u8 x, u8 y, T_COLOR clr);








/**
---------------
    MATH
---------------
*/

u32* math_div_multiple(u32 n, u32 d, boolean allocNeed, u32* offs);



/**
---------------
    IOREG
---------------
*/




#define DEFINEREG16(num) (*(volatile u16*) num)
#define DEFINEREG32(num) (*(volatile u32*) num)

#define BASE_REG 0x4000000


#define DISPCNT     DEFINEREG16(0x4000000)
#define DISPSTAT    DEFINEREG16(0x4000004)
#define VCOUNT      DEFINEREG16(0x4000006)
#define BG0CNT      DEFINEREG16(0x4000008)
#define BG1CNT      DEFINEREG16(0x400000A)
#define BG2CNT      DEFINEREG16(0x400000C)
#define BG3CNT      DEFINEREG16(0x400000E)
#define BG0HOFS     DEFINEREG16(0x4000010)
#define BG0VOFS     DEFINEREG16(0x4000012)
#define BG1HOFS     DEFINEREG16(0x4000014)
#define BG1VOFS     DEFINEREG16(0x4000016)
#define BG2HOFS     DEFINEREG16(0x4000018)
#define BG2VOFS     DEFINEREG16(0x400001A)
#define BG3HOFS     DEFINEREG16(0x400001C)
#define BG3VOFS     DEFINEREG16(0x400001E)
#define BG2PA       DEFINEREG16(0x4000020)
#define BG2PB       DEFINEREG16(0x4000022)
#define BG2PC       DEFINEREG16(0x4000024)
#define BG2PD       DEFINEREG16(0x4000026)
#define BG2X        DEFINEREG32(0x4000028)
#define BG2Y        DEFINEREG32(0x400002C)
#define BG3PA       DEFINEREG16(0x4000030)
#define BG3PB       DEFINEREG16(0x4000032)
#define BG3PC       DEFINEREG16(0x4000034)
#define BG3PD       DEFINEREG16(0x4000036)
#define BG3X        DEFINEREG32(0x4000038)
#define BG3Y        DEFINEREG32(0x400003C)
#define WIN0H       DEFINEREG16(0x4000040)
#define WIN1H       DEFINEREG16(0x4000042)
#define WIN0V       DEFINEREG16(0x4000044)
#define WIN1V       DEFINEREG16(0x4000046)
#define WININ       DEFINEREG16(0x4000048)
#define WINOUT      DEFINEREG16(0x400004A)
#define MOSAIC      DEFINEREG16(0x400004C)
#define BLDCNT      DEFINEREG16(0x4000050)
#define BLDALPHA    DEFINEREG16(0x4000052)
#define BLDY        DEFINEREG16(0x4000054)

// TODO SOUND REGS

#define DMA0SAD     DEFINE_REG32(0x40000B0)
#define DMA0DAD     DEFINE_REG32(0x40000B4)
#define DMA0CNTL    DEFINE_REG16(0X40000B8)
#define DMA0CNTH    DEFINE_REG16(0X40000BA)
#define DMA1SAD     DEFINE_REG32(0X40000BC)
#define DMA1DAD     DEFINE_REG32(0X40000C0)
#define DMA1CNTL    DEFINE_REG16(0X40000C4)
#define DMA1CNTH    DEFINE_REG16(0X40000C6)
#define DMA2SAD     DEFINE_REG32(0X40000C8)
#define DMA2DAD     DEFINE_REG32(0X40000CC)
#define DMA2CNTL    DEFINE_REG16(0X40000D0)
#define DMA2CNTH    DEFINE_REG16(0X40000D2)
#define DMA3SAD     DEFINE_REG32(0X40000D4)
#define DMA3DAD     DEFINE_REG32(0X40000D8)
#define DMA3CNTL    DEFINE_REG16(0X40000DC)
#define DMA3CNTH    DEFINE_REG16(0X40000DE)



/*
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
*/

#undef DEFINE_REG16()
#undef DEFINE_REG32()


bios.c

/**

divisione hardware
ritorna in 800d TODO pointer
0 div
1 mod
2 abs div

*/
__attribute__ ((noinline)) void bios_div_single (u32 num, u32 den, u32 func)

{
    asm ("push {r0-r4}");

    ASM_800D_R4;


    asm ("swi 0x7");


    asm ("cmp r2, #0");
    asm ("bne bios_div_single_cmp1");
    asm ("str r0, [r4]");

    asm (".bios_div_single_cmp1:");
    asm ("cmp r2, #1");
    asm ("bne bios_div_single_cmp2");
    asm ("str r1, [r4]");
    asm (".bios_div_single_cmp2:");
    asm ("cmp r2, #2");
    asm ("bne .bios_div_single_exit");
    asm ("str r3, [r4]");


    asm (".bios_div_single_exit:");
    asm ("push {r0-r4}");

}


__attribute__ ((noinline)) void bios_div_multi (u32 num, u32 den, u32* alloc)

{
    asm ("push {r0-r4}");




    asm ("swi 0x7");


    asm("str r0, [r2]");
    asm("str r1, [r2,#4]");
    asm("str r3, [r2,#8]");
    asm ("push {r0-r4}");

}









/*
BIOS Function Summary


  GBA  NDS7 NDS9 DSi7 DSi9 Basic Functions
  00h  00h  00h  -    -    SoftReset
  01h  -    -    -    -    RegisterRamReset
  02h  06h  06h  06h  06h  Halt
  03h  07h  -    07h  -    Stop/Sleep
  04h  04h  04h  04h  04h  IntrWait       ;DSi7/DSi9: both bugged?
  05h  05h  05h  05h  05h  VBlankIntrWait ;DSi7/DSi9: both bugged?
  06h  09h  09h  09h  09h  Div
  07h  -    -    -    -    DivArm
  08h  0Dh  0Dh  0Dh  0Dh  Sqrt
  09h  -    -    -    -    ArcTan
  0Ah  -    -    -    -    ArcTan2
  0Bh  0Bh  0Bh  0Bh  0Bh  CpuSet
  0Ch  0Ch  0Ch  0Ch  0Ch  CpuFastSet
  0Dh  -    -    -    -    GetBiosChecksum
  0Eh  -    -    -    -    BgAffineSet
  0Fh  -    -    -    -    ObjAffineSet
  GBA  NDS7 NDS9 DSi7 DSi9 Decompression Functions
  10h  10h  10h  10h  10h  BitUnPack
  11h  11h  11h  11h  11h  LZ77UnCompReadNormalWrite8bit   ;"Wram"
  12h  -    -    -    -    LZ77UnCompReadNormalWrite16bit  ;"Vram"
  -    -    -    01h  01h  LZ77UnCompReadByCallbackWrite8bit
  -    12h  12h  02h  02h  LZ77UnCompReadByCallbackWrite16bit
  -    -    -    19h  19h  LZ77UnCompReadByCallbackWrite16bit (same as above)
  13h  -    -    -    -    HuffUnCompReadNormal
  -    13h  13h  13h  13h  HuffUnCompReadByCallback
  14h  14h  14h  14h  14h  RLUnCompReadNormalWrite8bit     ;"Wram"
  15h  -    -    -    -    RLUnCompReadNormalWrite16bit    ;"Vram"
  -    15h  15h  15h  15h  RLUnCompReadByCallbackWrite16bit
  16h  -    16h  -    16h  Diff8bitUnFilterWrite8bit       ;"Wram"
  17h  -    -    -    -    Diff8bitUnFilterWrite16bit      ;"Vram"
  18h  -    18h  -    18h  Diff16bitUnFilter
  GBA  NDS7 NDS9 DSi7 DSi9 Sound (and Multiboot/HardReset/CustomHalt)
  19h  08h  -    08h  -    SoundBias
  1Ah  -    -    -    -    SoundDriverInit
  1Bh  -    -    -    -    SoundDriverMode
  1Ch  -    -    -    -    SoundDriverMain
  1Dh  -    -    -    -    SoundDriverVSync
  1Eh  -    -    -    -    SoundChannelClear
  1Fh  -    -    -    -    MidiKey2Freq
  20h  -    -    -    -    SoundWhatever0
  21h  -    -    -    -    SoundWhatever1
  22h  -    -    -    -    SoundWhatever2
  23h  -    -    -    -    SoundWhatever3
  24h  -    -    -    -    SoundWhatever4
  25h  -    -    -    -    MultiBoot
  26h  -    -    -    -    HardReset
  27h  1Fh  -    1Fh  -    CustomHalt
  28h  -    -    -    -    SoundDriverVSyncOff
  29h  -    -    -    -    SoundDriverVSyncOn
  2Ah  -    -    -    -    SoundGetJumpList
  GBA  NDS7 NDS9 DSi7 DSi9 New NDS Functions
  -    03h  03h  03h  03h  WaitByLoop
  -    0Eh  0Eh  0Eh  0Eh  GetCRC16
  -    0Fh  0Fh  -    -    IsDebugger
  -    1Ah  -    1Ah  -    GetSineTable
  -    1Bh  -    1Bh  -    GetPitchTable (DSi7: bugged)
  -    1Ch  -    1Ch  -    GetVolumeTable
  -    1Dh  -    1Dh  -    GetBootProcs (DSi7: only 1 proc)
  -    -    1Fh  -    1Fh  CustomPost
  GBA  NDS7 NDS9 DSi7 DSi9 New DSi Functions (RSA/SHA1)
  -    -    -    20h  20h  RSA_Init_crypto_heap
  -    -    -    21h  21h  RSA_Decrypt
  -    -    -    22h  22h  RSA_Decrypt_Unpad
  -    -    -    23h  23h  RSA_Decrypt_Unpad_GetChunk04
  -    -    -    24h  24h  SHA1_Init
  -    -    -    25h  25h  SHA1_Update
  -    -    -    26h  26h  SHA1_Finish
  -    -    -    27h  27h  SHA1_Init_update_fin
  -    -    -    28h  28h  SHA1_Compare_20_bytes
  -    -    -    29h  29h  SHA1_Random_maybe
  GBA  NDS7 NDS9 DSi7 DSi9 Invalid Functions
  2Bh+ 20h+ 20h+ -    -    Crash (SWI xxh..FFh do jump to garbage addresses)
  -    xxh  xxh  -    -    Jump to 0   (on any SWI numbers not listed above)
  -    -    -    12h  12h  No function (ignored)
  -    -    -    2Bh  2Bh  No function (ignored)
  -    -    -    40h+ 40h+ Mirror      (SWI 40h..FFh mirror to 00h..3Fh)
  -    -    -    xxh  xxh  Hang        (on any SWI numbers not listed above)


*/


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

math.c

/**

divisione hardware
ritorna in 800d TODO pointer
0 div
1 mod
2 abs div

*/
void math_div_single(int a)
{
}



void math_div_multiple(u32 n, u32 d, boolean allocNeed, u32 offs)
{

/*
if (allocNeed)
{
util_memAlloc32(3);
offs =(u32*) OFFSET_AS_POINTER32(var_0x800D);


}
else
{
}
*/
//bios_div_multi(n, d, offs);




// return offs;

}



text.c

/**
scrive un carattere. USO INTERNO.
x e y del gba, non della console.
*/
void text_putc16bpp(u8 chr, u8 x, u8 y, T_COLOR clr)
{


    u32 chra=0;
    u32 chrb=0;
// rendere funzione o lut o vram


//tonc

    if (chr== 'a')
    {
        chra=0x7E66663C;
        chrb=0x00666666;
    }


// FINE RENDERE

        util_memAlloc32(3);
        u32* div =(u32*) OFFSET_AS_POINTER32(var_0x800D);


u32 i =0;


    for (; i<32; i++)
      {
BREAKPOINT;
      //math_div_multiple (i,8, FALSE, div);
bios_div_multi(i, 8, div);
        video_plotPixelM3inline(x+*(div++), y+*(div--),clr*(chra&1) );
//fare in ++ e if 8 =0
// TODO SVUOTA IL LOOP

        chra>>=1;
      }

      for (int i=0; i<32; i++)
      {

          //math_div_multiple (i,8, FALSE, div);

    bios_div_multi(i, 8, div);


        video_plotPixelM3inline(x+*(div++), y+4+*(div--),clr*(chrb&1) );

// TODO SVUOTA IL LOOP

        chrb>>=1;
      }






//TODO DISEGNA 2 PX ALLA VOLTA






    }


util.c

void util_memcpy32(u32 dst, u32 src, u32 wdcount)
{
    while (wdcount--)
    {
        OFFSET_AS_POINTER32(dst)=OFFSET_AS_POINTER32(src);
        dst+=4;
        src+=4;

    }
}

__attribute__ ((noinline)) void util_blockFill(u32 dest, u32 lung, u32 filler)
{
    //memAlloc(12);
    //u32 ofpoint=OFFSET_AS_POINTER32(var_0x800D);
    //u32* mem =(u32*) ofpoint;
    //u32* mem =(u32*) OFFSET_AS_POINTER32(var_0x800D);
    //mem[0]=dest;
    //mem[1]=lung;
    //mem[2]=filler;

    //VERSIONE C
    //eppure mi sembra giusto :c

    while(lung--)
    {
    *((u32*)dest)=filler;
    dest+=4;
    }


/*
    asm ("push {r0-r3}");


    asm ("mov r0, #2");
    asm (" lsl r0, #0x8");
    asm ("add r0, r0, #2");
    asm ("lsl r0, #0x4");
    asm ("add r0, r0, #14");
    asm ("lsl r0, #0x4");
    asm ("add r0, r0, #8");
    asm ("lsl r0, #0x4");
    asm ("add r0, r0, #13");
    asm ("lsl r0, #0x4");
    asm ("add r0, r0, #12");
    //fin qui ho creato la var 800D 0202E8DC
    asm ("ldr r0, [r0]");
    //carico il vettore nei reg:
    asm ("add r0, r0, #8");
    asm ("ldr r2,[r0]");
    asm ("sub r0, r0, #4");
    asm ("ldr r1,[r0]");
    asm ("sub r0, r0, #4");
    asm ("ldr r0, [r0]");
    //loop che scrive e decrementa:
    // r0 dest r1 lung r2 fill
    asm ("lsl r1, #0x2");
    asm ("add r1, r0, r1");
    asm (".util_blockfill_main_loop:");
    asm ("str r2, [r0]");
    asm ("add r0, r0, #4");
    asm ("cmp r0, r1"); // TODO QUA LOOPA
    asm ("bne util_blockfill_main_loop");


    asm ("pop {r0-r3}");

*/
    //memFree((u32)mem);
}


/**
mette in 800d+f l'indirizzo di uno spazio di ram
grande almeno lung parole da 32 bit
*/
__attribute__ ((noinline)) void util_memAlloc32 (u32 lung)
{

// NOTA: IN ASM GIUSTO
//asm ("push {r0-r4}");

//asm ("mov r3, #0");


//asm ("mov r1, #1");
//asm ("lsl r1, #0x19");
// 1<<25=0x2000000
//asm (".util_memAlloc32_loop:");
//asm ("ldr r2, [r1]");
//asm ("cmp r2, #0");
//asm ("beq .util_memAlloc32_trovato"); // piu probabilr ke sia != percio non svuoto la pipeline
//asm ("mov r3, #0");//resetto il counter
//asm ("add r1, r1, #4");
/*
asm ("b .util_memAlloc32_loop");
asm (".util_memAlloc32_trovato:");
asm ("add r3, r3, #1");
asm ("add r1, r1, #4");
asm ("cmp r3, r0");

asm ("bne .util_memAlloc32_loop");
//-------
asm ("mov r3, #4");
asm ("mul r0, r3");
asm ("sub r1, r1, r0");

//-----------------
asm ("mov r4, #2");
asm (" lsl r4, #0x8");
asm ("add r4, r4, #2");
    asm ("lsl r4, #0x4");
    asm ("add r4, r4, #14");
    asm ("lsl r4, #0x4");
    asm ("add r4, r4, #8");
    asm ("lsl r4, #0x4");
    asm ("add r4, r4, #13");
    asm ("lsl r4, #0x4");
    asm ("add r4, r4, #12");
    //fin qui ho creato la var 800D 0202E8DC

*/
//asm("str r0, [r4]");
//mette il risultato nella var 800d e seguente f
//asm ("pop {r0-r4}");

u32 ofs=0x2000000;
u32 count=1;
count--;
while (ofs<256*1024)
{
    if (!(OFFSET_AS_POINTER32(ofs))) //se a ofs c'e zero
    {    count++;

    }
    else
    {    count=0;

    }
    if (lung==count) break;
    ofs++;
}

OFFSET_AS_POINTER32(var_0x800D)=ofs-lung*4;


}
void util_memFree32(u32 offs, u32 size)
{
    util_blockFill(offs, size, 0x0);
}


video.c

//==================  DICHIARAZIONI  ==================






//==================  DEFINIZIONI  ==================

/**
BG Mode                 (0-5=Video Mode 0-5, 6-7=Prohibited)
Display Frame Select    (0-1=Frame 0-1) (for BG Modes 4,5 only)
H-Blank Interval Free   (1=Allow access to OAM during H-Blank)
OBJ Character VRAM Mapping  (0=Two dimensional, 1=One dimensional)
Forced Blank            (1=Allow FAST access to VRAM,Palette,OAM)
Screen Display BG0      (0=Off, 1=On)
Screen Display BG1      (0=Off, 1=On)
Screen Display BG2      (0=Off, 1=On)
Screen Display BG3      (0=Off, 1=On)
Screen Display OBJ      (0=Off, 1=On)
Window 0 Display Flag   (0=Off, 1=On)
Window 1 Display Flag   (0=Off, 1=On)
OBJ Window Display Flag (0=Off, 1=On)
*/
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)
{
    u16 newreg=video_createDispCnt(bgMode, frame, hBlank, objMapping, forceBlank, bg0, bg1, bg2, bg3, obj, win0, win1, winObj);
    if (newreg!=0)
        DISPCNT=newreg;



}
/**

choose the property to set between DISPCNT_XXX_PROPERTY

if bgmode, flag ignored
if other property, bgmode ignored

*/

void video_setDispCntProperties(u8 property, u8 bgMode, boolean flag)
{



    u16 newreg=0;
    u16 oldreg = DISPCNT;
    if (property!=DISPCNT_BGMODE_PROPERTY)
        newreg=flag<<property;
   // else if (!(bgMode>5)) newreg = bgMode;
    DISPCNT= (oldreg^newreg);





}

/**
    PRIVATE USE
*/
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)
{
    if (!(bgMode>5))
        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));

    else return 0;
}

T_COLOR video_alphaBlend(T_COLOR source, T_COLOR newcol, u8 coef)
{

/*
    float alpha=coef/255;
    {
        float ra = getR(source)/MAX_COLOR_VALUE;
        float ga = getG(source)/MAX_COLOR_VALUE;
        float ba = getB(source)/MAX_COLOR_VALUE;

        float rb = getR(newcol)/MAX_COLOR_VALUE;
        float gb = getG(newcol)/MAX_COLOR_VALUE;
        float bb = getB(newcol)/MAX_COLOR_VALUE;

        float rt= alpha * (rb - ra) + ra;
        float gt= alpha * (gb - ga) + ga;
        float bt= alpha * (bb - ba) + ba;

        int rd =(int)(rt*MAX_COLOR_VALUE);
        int gd=(int)(gt*MAX_COLOR_VALUE);
        int bd=(int)(bt*MAX_COLOR_VALUE);

        return RGB16(rd,gd,bd);
    }
    else<*/ return 0x8000; //colore invalido
}

void video_plotPixelM3(u8 x, u8 y, T_COLOR color, boolean transp)
{
    if (!((transp)&&(color>0x7fff )))
((u16*)0x06000000)[x+y*SCREEN_WIDTH] = color;
}



inline void video_plotPixelM3inline (int x, int y, T_COLOR clr)
{   (( u16*)0x06000000)[y*SCREEN_WIDTH+x]= clr;    }

int video_getR(T_COLOR c)
{   return (c&31);   }
int video_getG(T_COLOR c)
{   return ((c&992)>>5);    }
int video_getB(T_COLOR c)
{   return ((c&31744)>>10); }


grazie e buonasera

Ultima modifica effettuata da Bonnox 21/07/16 16:24
aaa