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