Fermer2
yaouankLe 02/08/2004 à 23:49
NOTE: les sources sont telechargeable en ./3 (je maitrise pas trop yaro, on va faire comme ca)

Ca a l'air de marcher. J'ai le pressentiment qu'il reste un truc qui cloche avec les histoires d'images qui ont des lignes noires en haut
pour faire un multiple de 4 lignes (norme du SDK Gp32 et de GP32Converter.exe)

Alors moi, pour compiler de l'assembleur ARM avec minigp32, je fais comme ca:
- dans le makefile (genere par Visual MinGW), je rajoute mon asm.o a la suite de tous les .o
- je fais un fichier sprite.h contenant la definition de ma fonction
#ifndef SPRITE_H
#define SPRITE_H
extern void GpBitBltASM(GPDRAWSURFACE* screen, int startX, int startY, unsigned char* sprite, int sprite_width, int sprite_height);
#endif

- je fais un fichier asm.s avec le code de ma fonction (Pensez a commenter chaque ligne)
@***void GpBitBltASM(GPDRAWSURFACE * screen, int startX, int startY, unsigned char* sprite, int sprite_width, int sprite_height); ***
.ALIGN
.GLOBAL GpBitBltASM
.TYPE GpBitBltASM, function
.CODE 32

@r0 = screen (structure first then replaced by direct pointer)
@r1 = startX
@r2 = startY
@r3 = sprite

@r4 = sprite_width
@r5 = sprite_height (user value then ASM value being a multiple of 4)

@r6 = screen_width
@r7 = screen_height

@r8 = width copy
@r9 = height copy

@r10 = number of sprite lines after the multiple of 4 before. (if height of sprite is 9 then r10 = 1 because 9%4 = 1)

GpBitBltASM:
	SUB sp,sp,#8			@protect the memory where the params are
	STMFD r13!,{r4-r10}		@save used registers
	LDR r4,[r13,#36]		@then load the 5th and 6th params using ldrs
	LDR r5,[r13,#40]		@2 params + 7 saved registers (4 bytes each)
        				@=> 9 x 4 = 36 bytes from sp (r4), and then 40 for r5

	LDR r6, [r0, #8]		@read screen_width
	LDR r7, [r0, #12]		@read screen_height
	LDR r0, [r0]			@read screen pointer

	ADD r2, r2, r5			@Convert user coordinates to gp32 coordinates (y becomes screen height - (y+sprite_height) )
	SUB r2, r7, r2			@.

					@GP32 height of sprite must be a multiple of 4. If user given height is not a multiple of 4, some pixels are added.
	ANDS r10, r5, #0x0003		@r5%4 -> r10 (check if height is a multiple of 4)
	SUBNE r5, r5, r10		@if modulo if not zero clear last bits (if not ...)
	ADDNE r5, r5, #4		@and add #4  (... replace height by next multiple of 4)

	MOV r8, r4			@first value of Lcopy
	MOV r9, r5			@first value of Hcopy
	
					@those 3 lines were added in order to adapt the function to sprites with lines non multiple of 4.
	CMP r10, #0			@if r10 is not zero (r10 is the number of lines after multiple of 4)
	RSBNE r10, r10, #4		@then number of lines to remove is #4-r10
	SUBNE r9, r9, r10		@and zap last lines of dead pixels by reducing height copy (here because columns have to have a multiple of 4 pixels)
	
					@vertical update of screen and sprite pointers and of copy zone height.
	CMP r2, #0			@if startY is positive
	ADDGT r0, r0, r2		@then add startY to screenPointer
	SUBLT r3, r3, r2		@else remove startY from sprite pointer (=add absolute value of startY to pointer)
	ADDLT r9, r9, r2		@and reduce height of copy zone to correct value.
	
	ADD r2, r2, r5			@precalc (r2+r5+1) = startY + heightSprite-1
	SUB r2, r2, #1			@which is max Y value of sprite
	SUBS r2, r7, r2			@test screenheight - (starty+heightSprite-1). If this is negative, the sprite goes outside the screen (up)
	ADDLT r9, r9, r2		@reduce height of copy and then copy zone stay in the screen.

					@r2 is now free to be used.

					@horizontal update of screen and sprite pointers and of copy zone width
	CMP r1, #0			@if startX is positive
	MULGT r2, r1, r7		@precalc startX*screenHeight and put it in r2
	ADDGT r0, r0, r2		@add startX*screenHeight to screen pointer
	MULLT r2, r1, r5		@else precalc startX*spriteheight and put it in r2
	SUBLT r3, r3, r2		@and remove this value to sprite pointer (=add absolute value)
	ADDLT r8, r8, r1		@and reduce width of copy zone.

	ADD r2, r1, r4			@precalc (r1+r4) = startX + widthSprite
	SUBS r2, r6, r2			@screenwidth - (startX + widthSprite). If this is negative sprite goes outside the screen (right)
	ADDLT r8, r8, r2		@Then reduce width of copy zone to correct value.

					@r1 is now free to be used

	CMP r8, #0			@if width copy <=0
	BLE endGpBitBltASM		@jump to the end of the function
	CMP r9, #0			@if height copy <=0
	BLE endGpBitBltASM		@jump to the end of the function



bigLoop:
	STMFD sp!, {r0, r3}		@Push pointer to screen and to sprite
	STMFD sp!, {r9}			@Save height copy value (r9)
smallLoop:
	LDRB	r1, [r3], #1		@read pixel P2[0] and P2++
	STRB r1, [r0], #1		@write pixel P1[0] and P1++
	SUBS r9, r9, #1			@r9 --
	BNE smallLoop			@loop while r9 != 0 (do every pixels of the column)

	LDMFD sp!, {r9}			@Restore Lcopy value
	LDMFD sp!, {r0, r3}		@Pop pointer to screen and to sprite
	ADD r0, r0, r7			@Next screen column
	ADD r3, r3, r5			@Next sprite line (r5 is corrected height. The one that is a multiple of 4)
	SUBS r8, r8, #1			@Do it widthCopy times
	BNE bigLoop		
	
endGpBitBltASM:
	LDMFD r13!,{r4-r10}		@end of function. Restore register
	ADD sp,sp,#8			@restore stack pointer
	BX lr				@and back to C


4- et je compile comme d'hab