From b6df8a2348917b4b66395366e3bec54b359c6f02 Mon Sep 17 00:00:00 2001 From: XProger Date: Sat, 12 Feb 2022 06:14:47 +0300 Subject: [PATCH] #368 micro optimizations of rasterizer, remove per-pixel texturing (unused) --- src/platform/gba/asm/common_asm.inc | 23 +++- src/platform/gba/asm/faceAddMeshTriangles.s | 2 + src/platform/gba/asm/faceAddRoomTriangles.s | 2 + src/platform/gba/asm/flush.s | 5 + src/platform/gba/asm/rasterize.s | 21 ++- src/platform/gba/asm/rasterizeF.s | 14 +- src/platform/gba/asm/rasterizeFT.s | 105 ++++++--------- src/platform/gba/asm/rasterizeFTA.s | 108 +++++---------- src/platform/gba/asm/rasterizeGT.s | 135 +++++++------------ src/platform/gba/asm/rasterizeGTA.s | 137 +++++++------------- src/platform/gba/data/GYM.PKD | Bin 1463808 -> 1463808 bytes src/platform/gba/data/LEVEL1.PKD | Bin 2365360 -> 2365360 bytes src/platform/gba/data/LEVEL2.PKD | Bin 2624600 -> 2624600 bytes src/platform/gba/data/TITLE.PKD | Bin 313260 -> 313260 bytes src/platform/gba/rasterizer.h | 5 +- src/platform/gba/render.iwram.cpp | 12 +- 16 files changed, 221 insertions(+), 348 deletions(-) diff --git a/src/platform/gba/asm/common_asm.inc b/src/platform/gba/asm/common_asm.inc index 237f80e..512d7c6 100644 --- a/src/platform/gba/asm/common_asm.inc +++ b/src/platform/gba/asm/common_asm.inc @@ -1,8 +1,6 @@ .section .iwram .arm -#define TEX_2PX // lazy texturing, comment out for per-pixel - #define FRAME_WIDTH 240 #define FRAME_HEIGHT 160 @@ -45,9 +43,11 @@ .equ CLIP_MASK_VP, (CLIP_LEFT + CLIP_RIGHT + CLIP_TOP + CLIP_BOTTOM) .equ CLIP_MASK, (CLIP_MASK_VP + CLIP_FAR + CLIP_NEAR) -.equ FACE_TEXTURE_BITS, 13 -.equ FACE_TRIANGLE, (1 << FACE_TEXTURE_BITS) +.equ FACE_TEXTURE_BITS, 14 .equ FACE_TEXTURE, ((1 << FACE_TEXTURE_BITS) - 1) +.equ FACE_GOURAUD, (2 << FACE_TYPE_SHIFT) +.equ FACE_CLIPPED, (1 << 18) +.equ FACE_TRIANGLE, (1 << 19) .equ FACE_FLAGS, 0 .equ FACE_NEXT, 4 @@ -67,9 +67,6 @@ .equ FACE_TYPE_LINE_H, (8 << FACE_TYPE_SHIFT) .equ FACE_TYPE_LINE_V, (9 << FACE_TYPE_SHIFT) -.equ FACE_GOURAUD, (2 << FACE_TYPE_SHIFT) -.equ FACE_CLIPPED, (1 << 18) - .equ FIXED_SHIFT, 14 .equ PROJ_SHIFT, 4 .equ OT_SHIFT, 4 @@ -90,6 +87,7 @@ .equ MAX_CAUSTICS, 32 .equ MAX_RAND_TABLE, 32 +.equ MAX_ANIM_TEX, 128 .equ MIN_INT32, 0x80000000 .equ MAX_INT32, 0x7FFFFFFF @@ -110,6 +108,17 @@ ble \skip .endm +.macro scaleUV uv, u, v, f + asr \u, \uv, #16 + mul \u, \f // u = f * int16(uv >> 16) + lsl \v, \uv, #16 + asr \v, #16 + mul \v, \f // v = f * int16(uv) + lsr \u, #16 + lsl \u, #16 + orr \uv, \u, \v, lsr #16 // uv = (u & 0xFFFF0000) | (v >> 16) +.endm + .macro tex index, uv and \index, \uv, #0xFF00 orr \index, \uv, lsr #24 // index = v * 256 + u diff --git a/src/platform/gba/asm/faceAddMeshTriangles.s b/src/platform/gba/asm/faceAddMeshTriangles.s index e2fcc07..919ef41 100644 --- a/src/platform/gba/asm/faceAddMeshTriangles.s +++ b/src/platform/gba/asm/faceAddMeshTriangles.s @@ -89,6 +89,8 @@ faceAddMeshTriangles_asm: orr vp1, vp0, vp1, lsl #(16 - 3) mov vp2, vp2, lsr #3 + orr flags, #FACE_TRIANGLE + ldr ot, =gOT ldr next, [ot, depth, lsl #2] str face, [ot, depth, lsl #2] diff --git a/src/platform/gba/asm/faceAddRoomTriangles.s b/src/platform/gba/asm/faceAddRoomTriangles.s index 6567b55..dcb1cb8 100644 --- a/src/platform/gba/asm/faceAddRoomTriangles.s +++ b/src/platform/gba/asm/faceAddRoomTriangles.s @@ -96,6 +96,8 @@ faceAddRoomTriangles_asm: orr vp1, vp0, vp1, lsl #(16 - 3) mov vp2, vp2, lsr #3 + orr flags, #FACE_TRIANGLE + ldr ot, =gOT ldr next, [ot, depth, lsl #2] str face, [ot, depth, lsl #2] diff --git a/src/platform/gba/asm/flush.s b/src/platform/gba/asm/flush.s index a454602..91e46a4 100644 --- a/src/platform/gba/asm/flush.s +++ b/src/platform/gba/asm/flush.s @@ -25,6 +25,7 @@ verticesBase .req vZG facesBase .req vZG vertex .req vZG texture .req tmp +texAnim .req vXY texIndex .req tmp texTile .req tmp sprite .req tmp @@ -121,8 +122,12 @@ flush_asm: .set_texture: mov texIndex, flags, lsl #(32 - FACE_TEXTURE_BITS) + //cmp texIndex, #(MAX_ANIM_TEX << (32 - FACE_TEXTURE_BITS)) // TODO split to animated and static textures arrays add texIndex, texIndex, texIndex, lsl #1 add texture, TEXTURES, texIndex, lsr #(32 - FACE_TEXTURE_BITS - 2) + //addge texture, TEXTURES, texIndex, lsr #(32 - FACE_TEXTURE_BITS - 2) + //ldrlt texAnim, =gAnimTextures + //addlt texture, texAnim, texIndex, lsr #(32 - FACE_TEXTURE_BITS - 2) ldmia texture, {texTile, uv01, uv23} str texTile, [TILE] diff --git a/src/platform/gba/asm/rasterize.s b/src/platform/gba/asm/rasterize.s index 179ee49..db543e1 100644 --- a/src/platform/gba/asm/rasterize.s +++ b/src/platform/gba/asm/rasterize.s @@ -1,11 +1,11 @@ #include "common_asm.inc" flags .req r0 -top .req r1 -y .req r2 -width .req r3 -pixel .req flags +L .req r1 +R .req r2 +y .req r3 type .req r12 +pixel .req flags .extern rasterizeS_asm .extern rasterizeF_asm @@ -22,22 +22,19 @@ type .req r12 .global rasterize_asm rasterize_asm: and type, flags, #FACE_TYPE_MASK + cmp type, #FACE_TYPE_F - streqb flags, [top, #VERTEX_CLIP] + andeq R, flags, #0xFF // R = face color for FACE_TYPE_F + movne R, L // R = L otherwise ldr pixel, =fb ldr pixel, [pixel] - ldrsh y, [top, #VERTEX_Y] + ldrsh y, [L, #VERTEX_Y] -#if (FRAME_WIDTH == 240) // pixel += (y * 16 - y) * 16 + // pixel += y * 240 -> (y * 16 - y) * 16 rsb y, y, y, lsl #4 add pixel, pixel, y, lsl #4 -#else - mov width, #FRAME_WIDTH - mla pixel, y, width, pixel -#endif - mov r2, top add pc, type, lsr #(FACE_TYPE_SHIFT - 2) nop b rasterizeS_asm diff --git a/src/platform/gba/asm/rasterizeF.s b/src/platform/gba/asm/rasterizeF.s index 435b2ee..2839b1d 100644 --- a/src/platform/gba/asm/rasterizeF.s +++ b/src/platform/gba/asm/rasterizeF.s @@ -2,7 +2,7 @@ pixel .req r0 L .req r1 -R .req r2 +color .req r2 index .req r3 Lh .req r4 Rh .req r5 @@ -15,6 +15,7 @@ tmp .req r11 DIVLUT .req r12 width .req lr +R .req color h .req N Rxy .req tmp Ry2 .req Rh @@ -22,19 +23,16 @@ Lxy .req tmp Ly2 .req Lh LMAP .req Lx pair .req DIVLUT -blocks .req DIVLUT .global rasterizeF_asm rasterizeF_asm: stmfd sp!, {r4-r11, lr} - mov LMAP, #LMAP_ADDR - - // TODO use ldrh, swap g and clip + add LMAP, color, #LMAP_ADDR ldrb tmp, [L, #VERTEX_G] - ldrb index, [L, #VERTEX_CLIP] - orr tmp, index, tmp, lsl #8 // tmp = index | (L->v.g << 8) - ldrb index, [LMAP, tmp] // tmp = lightmap[tmp] + ldrb index, [LMAP, tmp, lsl #8] // index = lightmap[color + L->v.g * 256] + + mov R, L mov Lh, #0 // Lh = 0 mov Rh, #0 // Rh = 0 diff --git a/src/platform/gba/asm/rasterizeFT.s b/src/platform/gba/asm/rasterizeFT.s index e845e78..f6b6d54 100644 --- a/src/platform/gba/asm/rasterizeFT.s +++ b/src/platform/gba/asm/rasterizeFT.s @@ -17,6 +17,8 @@ Lt .req r11 Rt .req r12 h .req lr +ptr .req tmp + Ldx .req h Rdx .req h @@ -41,14 +43,14 @@ duv .req R du .req L dv .req R -Lduv .req h Ldu .req N Ldv .req h -Rduv .req h Rdu .req N Rdv .req h +Rti .req indexB + sLdx .req tmp sLdt .req N sRdx .req Lh @@ -58,32 +60,25 @@ SP_LDX = 0 SP_LDT = 4 SP_RDX = 8 SP_RDT = 12 +SP_L = 16 +SP_R = 20 +SP_LH = 24 +SP_RH = 28 +SP_SIZE = 32 .macro PUT_PIXELS tex indexA, t lit indexA -#ifndef TEX_2PX - add t, dtdx - - tex indexB, t - lit indexB - add t, dtdx - - orr indexA, indexB, lsl #8 - strh indexA, [tmp], #2 -#else add t, dtdx, lsl #1 - //orr indexA, indexA, lsl #8 - strb indexA, [tmp], #2 // writing a byte to GBA VRAM will write a half word for free -#endif + strb indexA, [ptr], #2 // writing a byte to GBA VRAM will write a half word for free .endm .global rasterizeFT_asm rasterizeFT_asm: stmfd sp!, {r4-r11, lr} - sub sp, #16 // reserve stack space for [Ldx, Ldt, Rdx, Rdt] + sub sp, #SP_SIZE // reserve stack space for [Ldx, Ldt, Rdx, Rdt] mov LMAP, #LMAP_ADDR ldrb tmp, [L, #VERTEX_G] @@ -125,16 +120,9 @@ rasterizeFT_asm: mul Ldx, tmp // Ldx = tmp * (N->v.x - Lx) str Ldx, [sp, #SP_LDX] // store Ldx to stack - ldr Lduv, [L, #VERTEX_T] - sub Lduv, Lt // Lduv = N->v.t - Lt - asr Ldu, Lduv, #16 - mul Ldu, tmp // Rdu = tmp * int16(Lduv >> 16) - lsl Ldv, Lduv, #16 - asr Ldv, #16 - mul Ldv, tmp // Rdv = tmp * int16(Lduv) - lsr Ldu, #16 - lsl Ldu, #16 - orr Ldt, Ldu, Ldv, lsr #16 // Ldt = (Rdu & 0xFFFF0000) | (Rdv >> 16) + ldr Ldt, [L, #VERTEX_T] + sub Ldt, Lt // Ldt = N->v.t - Lt + scaleUV Ldt, Ldu, Ldv, tmp str Ldt, [sp, #SP_LDT] // store Ldt to stack .calc_left_end: @@ -166,16 +154,9 @@ rasterizeFT_asm: mul Rdx, tmp // Rdx = tmp * (N->v.x - Rx) str Rdx, [sp, #SP_RDX] // store Rdx to stack - ldr Rduv, [R, #VERTEX_T] - sub Rduv, Rt // Rduv = N->v.t - Rt - asr Rdu, Rduv, #16 - mul Rdu, tmp // Rdu = tmp * int16(Rduv >> 16) - lsl Rdv, Rduv, #16 - asr Rdv, #16 - mul Rdv, tmp // Rdv = tmp * int16(Rduv) - lsr Rdu, #16 - lsl Rdu, #16 - orr Rdt, Rdu, Rdv, lsr #16 // Rdt = (Rdu & 0xFFFF0000) | (Rdv >> 16) + ldr Rdt, [R, #VERTEX_T] + sub Rdt, Rt // Rdt = N->v.t - Rt + scaleUV Rdt, Rdu, Rdv, tmp str Rdt, [sp, #SP_RDT] // store Rdt to stack .calc_right_end: @@ -185,44 +166,36 @@ rasterizeFT_asm: sub Lh, h // Lh -= h sub Rh, h // Rh -= h - stmfd sp!, {L,R,Lh,Rh} // sp-16 + add tmp, sp, #SP_L + stmia tmp, {L, R, Lh, Rh} .scanline_start: asr tmp, Lx, #16 // x1 = (Lx >> 16) rsbs width, tmp, Rx, asr #16 // width = (Rx >> 16) - x1 ble .scanline_end // if (width <= 0) go next scanline - add tmp, pixel, tmp // tmp = pixel + x1 + add ptr, pixel, tmp // ptr = pixel + x1 mov DIVLUTi, #DIVLUT_ADDR lsl inv, width, #1 ldrh inv, [DIVLUTi, inv] // inv = FixedInvU(width) - sub duv, Rt, Lt // duv = Rt - Lt - asr du, duv, #16 - mul du, inv // du = inv * int16(duv >> 16) - lsl dv, duv, #16 - asr dv, #16 - mul dv, inv // dv = inv * int16(duv) - lsr du, #16 - lsl du, #16 - orr dtdx, du, dv, lsr #16 // dtdx = (du & 0xFFFF0000) | (dv >> 16) + sub dtdx, Rt, Lt // duv = Rt - Lt + scaleUV dtdx, du, dv, inv mov t, Lt // t = Lt // 2 bytes alignment (VRAM write requirement) .align_left: - tst tmp, #1 // if (tmp & 1) + tst ptr, #1 // if (ptr & 1) beq .align_right - ldrb indexB, [tmp, #-1]! // read pal index from VRAM (byte) - and indexA, t, #0xFF00 - orr indexA, t, lsr #24 // res = (t & 0xFF00) | (t >> 24) - ldrb indexA, [TILE, indexA] - ldrb indexA, [LMAP, indexA] + tex indexA, t + lit indexA + ldrb indexB, [ptr, #-1]! // read pal index from VRAM (byte) orr indexB, indexA, lsl #8 - strh indexB, [tmp], #2 + strh indexB, [ptr], #2 add t, dtdx subs width, #1 // width-- @@ -231,19 +204,15 @@ rasterizeFT_asm: .align_right: tst width, #1 beq .align_block_4px - ldrb indexB, [tmp, width] + sub Rti, Rt, dtdx + tex indexA, Rti + lit indexA + + ldrb indexB, [ptr, width] subs width, #1 // width-- - - sub Rt, dtdx - and indexA, Rt, #0xFF00 - orr indexA, Rt, lsr #24 // res = (t & 0xFF00) | (t >> 24) - add Rt, dtdx - ldrb indexA, [TILE, indexA] - ldrb indexA, [LMAP, indexA] - orr indexB, indexA, indexB, lsl #8 - strh indexB, [tmp, width] + strh indexB, [ptr, width] beq .scanline_end // if (width == 0) @@ -276,8 +245,7 @@ rasterizeFT_asm: bne .scanline_block_8px .scanline_end: - add tmp, sp, #16 - ldmia tmp, {sLdx, sLdt, sRdx, sRdt} + ldmia sp, {sLdx, sLdt, sRdx, sRdt} add Lx, sLdx add Lt, sLdt add Rx, sRdx @@ -288,9 +256,10 @@ rasterizeFT_asm: subs h, #1 bne .scanline_start - ldmfd sp!, {L,R,Lh,Rh} // sp+16 + add tmp, sp, #SP_L + ldmia tmp, {L, R, Lh, Rh} b .loop .exit: - add sp, #16 // revert reserved space for [Ldx, Ldt, Rdx, Rdt] + add sp, #SP_SIZE // revert reserved space for [Ldx, Ldt, Rdx, Rdt] ldmfd sp!, {r4-r11, pc} \ No newline at end of file diff --git a/src/platform/gba/asm/rasterizeFTA.s b/src/platform/gba/asm/rasterizeFTA.s index e300f77..02028c5 100644 --- a/src/platform/gba/asm/rasterizeFTA.s +++ b/src/platform/gba/asm/rasterizeFTA.s @@ -17,6 +17,8 @@ Lt .req r11 Rt .req r12 h .req lr +ptr .req tmp + Ldx .req h Rdx .req h @@ -41,14 +43,14 @@ duv .req R du .req L dv .req R -Lduv .req h Ldu .req N Ldv .req h -Rduv .req h Rdu .req N Rdv .req h +Rti .req indexB + sLdx .req tmp sLdt .req N sRdx .req Lh @@ -58,38 +60,25 @@ SP_LDX = 0 SP_LDT = 4 SP_RDX = 8 SP_RDT = 12 +SP_L = 16 +SP_R = 20 +SP_LH = 24 +SP_RH = 28 +SP_SIZE = 32 .macro PUT_PIXELS -#ifndef TEX_2PX - tex indexA, t - add t, dtdx - - tex indexB, t - add t, dtdx - - // cheap non-accurate alpha test, skip pixels pair if one or both are transparent - ands indexA, #255 - andnes indexB, #255 - orrne indexB, indexA, indexB, lsl #8 // indexB = indexA | (indexB << 8) - ldrneb indexA, [LMAP, indexA] - ldrneb indexB, [LMAP, indexB, lsr #8] - orrne indexA, indexB, lsl #8 - strneh indexA, [tmp] - add tmp, #2 -#else tex indexA, t add t, dtdx, lsl #1 cmp indexA, #0 ldrneb indexA, [LMAP, indexA] - strneb indexA, [tmp] - add tmp, #2 -#endif + strneb indexA, [ptr] + add ptr, #2 .endm .global rasterizeFTA_asm rasterizeFTA_asm: stmfd sp!, {r4-r11, lr} - sub sp, #16 // reserve stack space for [Ldx, Ldt, Rdx, Rdt] + sub sp, #SP_SIZE // reserve stack space for [Ldx, Ldt, Rdx, Rdt] mov LMAP, #LMAP_ADDR ldrb tmp, [L, #VERTEX_G] @@ -131,16 +120,9 @@ rasterizeFTA_asm: mul Ldx, tmp // Ldx = tmp * (N->v.x - Lx) str Ldx, [sp, #SP_LDX] // store Ldx to stack - ldr Lduv, [L, #VERTEX_T] - sub Lduv, Lt // Lduv = N->v.t - Lt - asr Ldu, Lduv, #16 - mul Ldu, tmp // Rdu = tmp * int16(Lduv >> 16) - lsl Ldv, Lduv, #16 - asr Ldv, #16 - mul Ldv, tmp // Rdv = tmp * int16(Lduv) - lsr Ldu, #16 - lsl Ldu, #16 - orr Ldt, Ldu, Ldv, lsr #16 // Ldt = (Rdu & 0xFFFF0000) | (Rdv >> 16) + ldr Ldt, [L, #VERTEX_T] + sub Ldt, Lt // Ldt = N->v.t - Lt + scaleUV Ldt, Ldu, Ldv, tmp str Ldt, [sp, #SP_LDT] // store Ldt to stack .calc_left_end: @@ -172,16 +154,9 @@ rasterizeFTA_asm: mul Rdx, tmp // Rdx = tmp * (N->v.x - Rx) str Rdx, [sp, #SP_RDX] // store Rdx to stack - ldr Rduv, [R, #VERTEX_T] - sub Rduv, Rt // Rduv = N->v.t - Rt - asr Rdu, Rduv, #16 - mul Rdu, tmp // Rdu = tmp * int16(Rduv >> 16) - lsl Rdv, Rduv, #16 - asr Rdv, #16 - mul Rdv, tmp // Rdv = tmp * int16(Rduv) - lsr Rdu, #16 - lsl Rdu, #16 - orr Rdt, Rdu, Rdv, lsr #16 // Rdt = (Rdu & 0xFFFF0000) | (Rdv >> 16) + ldr Rdt, [R, #VERTEX_T] + sub Rdt, Rt // Rdt = N->v.t - Rt + scaleUV Rdt, Rdu, Rdv, tmp str Rdt, [sp, #SP_RDT] // store Rdt to stack .calc_right_end: @@ -191,46 +166,38 @@ rasterizeFTA_asm: sub Lh, h // Lh -= h sub Rh, h // Rh -= h - stmfd sp!, {L,R,Lh,Rh} // sp-16 + add tmp, sp, #SP_L + stmia tmp, {L, R, Lh, Rh} .scanline_start: asr tmp, Lx, #16 // x1 = (Lx >> 16) rsbs width, tmp, Rx, asr #16 // width = (Rx >> 16) - x1 ble .scanline_end // if (width <= 0) go next scanline - add tmp, pixel, tmp // tmp = pixel + x1 + add ptr, pixel, tmp // ptr = pixel + x1 mov DIVLUTi, #DIVLUT_ADDR lsl inv, width, #1 ldrh inv, [DIVLUTi, inv] // inv = FixedInvU(width) - sub duv, Rt, Lt // duv = Rt - Lt - asr du, duv, #16 - mul du, inv // du = inv * int16(duv >> 16) - lsl dv, duv, #16 - asr dv, #16 - mul dv, inv // dv = inv * int16(duv) - lsr du, #16 - lsl du, #16 - orr dtdx, du, dv, lsr #16 // dtdx = (du & 0xFFFF0000) | (dv >> 16) + sub dtdx, Rt, Lt // duv = Rt - Lt + scaleUV dtdx, du, dv, inv mov t, Lt // t = Lt // 2 bytes alignment (VRAM write requirement) .align_left: - tst tmp, #1 // if (tmp & 1) + tst ptr, #1 // if (ptr & 1) beq .align_right - and indexA, t, #0xFF00 - orr indexA, t, lsr #24 // res = (t & 0xFF00) | (t >> 24) - ldrb indexA, [TILE, indexA] + tex indexA, t cmp indexA, #0 - ldrneb indexB, [tmp, #-1]! // read pal index from VRAM (byte) + ldrneb indexB, [ptr, #-1]! // read pal index from VRAM (byte) ldrneb indexA, [LMAP, indexA] orrne indexB, indexA, lsl #8 - strneh indexB, [tmp], #2 - addeq tmp, #1 + strneh indexB, [ptr], #2 + addeq ptr, #1 add t, dtdx subs width, #1 // width-- @@ -240,17 +207,14 @@ rasterizeFTA_asm: tst width, #1 beq .align_block_4px - sub Rt, dtdx - and indexA, Rt, #0xFF00 - orr indexA, Rt, lsr #24 // res = (t & 0xFF00) | (t >> 24) - add Rt, dtdx - ldrb indexA, [TILE, indexA] + sub Rti, Rt, dtdx + tex indexA, Rti cmp indexA, #0 ldrneb indexA, [LMAP, indexA] - ldrneb indexB, [tmp, width] + ldrneb indexB, [ptr, width] orrne indexB, indexA, indexB, lsl #8 - addne indexA, tmp, width + addne indexA, ptr, width strneh indexB, [indexA, #-1] subs width, #1 // width-- @@ -285,8 +249,7 @@ rasterizeFTA_asm: bne .scanline_block_8px .scanline_end: - add tmp, sp, #16 - ldmia tmp, {sLdx, sLdt, sRdx, sRdt} + ldmia sp, {sLdx, sLdt, sRdx, sRdt} add Lx, sLdx add Lt, sLdt add Rx, sRdx @@ -297,9 +260,10 @@ rasterizeFTA_asm: subs h, #1 bne .scanline_start - ldmfd sp!, {L,R,Lh,Rh} // sp+16 + add tmp, sp, #SP_L + ldmia tmp, {L, R, Lh, Rh} b .loop .exit: - add sp, #16 // revert reserved space for [Ldx, Ldt, Rdx, Rdt] + add sp, #SP_SIZE // revert reserved space for [Ldx, Ldt, Rdx, Rdt] ldmfd sp!, {r4-r11, pc} \ No newline at end of file diff --git a/src/platform/gba/asm/rasterizeGT.s b/src/platform/gba/asm/rasterizeGT.s index 3c4a422..a1e4e3a 100644 --- a/src/platform/gba/asm/rasterizeGT.s +++ b/src/platform/gba/asm/rasterizeGT.s @@ -35,7 +35,7 @@ Ldt .req h Rdt .req h indexA .req Lh -indexB .req Rh +indexB .req tmp Rxy .req tmp Ry2 .req Rh @@ -47,23 +47,19 @@ DIVLUT .req N DIVLUTi .req tmp ptr .req Lx -width .req Rx +width .req Rh g .req Lg -dgdx .req Rg +dgdx .req L t .req Lt -dtdx .req Rt - -duv .req R +dtdx .req R du .req L dv .req R -Lduv .req N Ldu .req TILE Ldv .req N -Rduv .req N Rdu .req TILE Rdv .req N @@ -75,7 +71,7 @@ sLdg .req R sLdt .req Lh sRdx .req Rh sRdg .req tmp -sRdt .req N // not used in ldm due h collision +sRdt .req tmp // not enough regs for one ldmia SP_LDX = 0 SP_LDG = 4 @@ -83,6 +79,12 @@ SP_LDT = 8 SP_RDX = 12 SP_RDG = 16 SP_RDT = 20 +SP_L = 24 +SP_R = 28 +SP_LH = 32 +SP_RH = 36 +SP_SIZE = 40 +SP_TILE = SP_SIZE .macro PUT_PIXELS bic LMAP, g, #255 @@ -91,28 +93,18 @@ SP_RDT = 20 tex indexA, t lit indexA -#ifndef TEX_2PX - add t, dtdx - - tex indexB, t - lit indexB - - add t, dtdx - - orr indexA, indexB, lsl #8 - strh indexA, [ptr], #2 -#else add t, dtdx, lsl #1 - //orr indexA, indexA, lsl #8 strb indexA, [ptr], #2 // writing a byte to GBA VRAM will write a half word for free -#endif .endm .global rasterizeGT_asm rasterizeGT_asm: - stmfd sp!, {r4-r11, lr} - sub sp, #24 // reserve stack space for [Ldx, Ldg, Ldt, Rdx, Rdg, Rdt] + ldr r3, =gTile + ldr r3, [r3] + + stmfd sp!, {r3-r11, lr} + sub sp, #SP_SIZE // reserve stack space for [Ldx, Ldg, Ldt, Rdx, Rdg, Rdt] mov Lh, #0 // Lh = 0 mov Rh, #0 // Rh = 0 @@ -155,16 +147,9 @@ rasterizeGT_asm: asr Ldg, #8 // 8-bit for fractional part str Ldg, [sp, #SP_LDG] // store Ldg to stack - ldr Lduv, [L, #VERTEX_T] - sub Lduv, Lt // Lduv = N->v.t - Lt - asr Ldu, Lduv, #16 - mul Ldu, tmp // Rdu = tmp * int16(Lduv >> 16) - lsl Ldv, Lduv, #16 - asr Ldv, #16 - mul Ldv, tmp // Rdv = tmp * int16(Lduv) - lsr Ldu, #16 - lsl Ldu, #16 - orr Ldt, Ldu, Ldv, lsr #16 // Ldt = (Rdu & 0xFFFF0000) | (Rdv >> 16) + ldr Ldt, [L, #VERTEX_T] + sub Ldt, Lt // Ldt = N->v.t - Lt + scaleUV Ldt, Ldu, Ldv, tmp str Ldt, [sp, #SP_LDT] // store Ldt to stack .calc_left_end: @@ -204,16 +189,9 @@ rasterizeGT_asm: asr Rdg, #8 // 8-bit for fractional part str Rdg, [sp, #SP_RDG] // store Ldg to stack - ldr Rduv, [R, #VERTEX_T] - sub Rduv, Rt // Rduv = N->v.t - Rt - asr Rdu, Rduv, #16 - mul Rdu, tmp // Rdu = tmp * int16(Rduv >> 16) - lsl Rdv, Rduv, #16 - asr Rdv, #16 - mul Rdv, tmp // Rdv = tmp * int16(Rduv) - lsr Rdu, #16 - lsl Rdu, #16 - orr Rdt, Rdu, Rdv, lsr #16 // Rdt = (Rdu & 0xFFFF0000) | (Rdv >> 16) + ldr Rdt, [R, #VERTEX_T] + sub Rdt, Rt // Rdt = N->v.t - Rt + scaleUV Rdt, Rdu, Rdv, tmp str Rdt, [sp, #SP_RDT] // store Rdt to stack .calc_right_end: @@ -226,54 +204,44 @@ rasterizeGT_asm: sub Lh, h // Lh -= h sub Rh, h // Rh -= h - ldr TILE, =gTile - ldr TILE, [TILE] + ldr TILE, [sp, #SP_TILE] - stmfd sp!, {L,R,Lh,Rh} // sp-16 + add tmp, sp, #SP_L + stmia tmp, {L, R, Lh, Rh} .scanline_start: - stmfd sp!, {Lx,Rx,Lg,Rg,Lt,Rt} // sp-24 + stmfd sp!, {Lx, Lg, Lt} - asr tmp, Lx, #16 // x1 = (Lx >> 16) - rsbs width, tmp, Rx, asr #16 // width = (Rx >> 16) - x1 + asr Lx, Lx, #16 // x1 = (Lx >> 16) + rsbs width, Lx, Rx, asr #16 // width = (Rx >> 16) - x1 ble .scanline_end // if (width <= 0) go next scanline - add ptr, pixel, tmp // ptr = pixel + x1 + add ptr, pixel, Lx // ptr = pixel + x1 mov DIVLUTi, #DIVLUT_ADDR lsl inv, width, #1 ldrh inv, [DIVLUTi, inv] // inv = FixedInvU(width) + sub dtdx, Rt, Lt // dtdx = Rt - Lt + scaleUV dtdx, du, dv, inv + // t == Lt (alias) + sub dgdx, Rg, Lg // dgdx = Rg - Lg mul dgdx, inv // dgdx *= FixedInvU(width) asr dgdx, #15 // dgdx >>= 15 // g == Lg (alias) - sub duv, Rt, Lt // duv = Rt - Lt - asr du, duv, #16 - mul du, inv // du = inv * int16(duv >> 16) - lsl dv, duv, #16 - asr dv, #16 - mul dv, inv // dv = inv * int16(duv) - lsr du, #16 - lsl du, #16 - orr dtdx, du, dv, lsr #16 // dtdx = (du & 0xFFFF0000) | (dv >> 16) - // t == Lt (alias) - // 2 bytes alignment (VRAM write requirement) .align_left: tst ptr, #1 // if (ptr & 1) beq .align_right - ldrb indexB, [ptr, #-1]! // read pal index from VRAM (byte) bic LMAP, g, #255 add g, dgdx, asr #1 + tex indexA, t + lit indexA - and indexA, t, #0xFF00 - orr indexA, t, lsr #24 // res = (t & 0xFF00) | (t >> 24) - ldrb indexA, [TILE, indexA] - ldrb indexA, [LMAP, indexA] - + ldrb indexB, [ptr, #-1]! // read pal index from VRAM (byte) orr indexB, indexA, lsl #8 strh indexB, [ptr], #2 add t, dtdx @@ -284,21 +252,16 @@ rasterizeGT_asm: .align_right: tst width, #1 beq .align_block_4px - ldrb indexB, [ptr, width] - subs width, #1 // width-- + sub Rti, Rt, dtdx + tex indexA, Rti - mla Rti, width, dtdx, t // Rti = width * dtdx + t - and indexA, Rti, #0xFF00 - orr indexA, Rti, lsr #24 // res = (t & 0xFF00) | (t >> 24) - ldrb indexA, [TILE, indexA] - - asr Rgi, dgdx, #1 - mla Rgi, width, Rgi, g // Rgi = width * (dgdx / 2) + g + sub Rgi, Rg, dgdx, asr #1 bic LMAP, Rgi, #255 + lit indexA - ldrb indexA, [LMAP, indexA] - + ldrb indexB, [ptr, width] + subs width, #1 // width-- orr indexB, indexA, indexB, lsl #8 strh indexB, [ptr, width] @@ -333,10 +296,9 @@ rasterizeGT_asm: bne .scanline_block_8px .scanline_end: - ldmfd sp!, {Lx,Rx,Lg,Rg,Lt,Rt} // sp+24 + ldmfd sp!, {Lx, Lg, Lt} - add tmp, sp, #16 - ldmia tmp, {sLdx, sLdg, sLdt, sRdx, sRdg} + ldmia sp, {sLdx, sLdg, sLdt, sRdx, sRdg} add Lx, sLdx add Lg, sLdg @@ -344,17 +306,18 @@ rasterizeGT_asm: add Rx, sRdx add Rg, sRdg - ldr tmp, [sp, #(SP_RDT + 16)] - add Rt, tmp // Rt += Rdt from stack + ldr sRdt, [sp, #SP_RDT] + add Rt, sRdt add pixel, #FRAME_WIDTH // pixel += FRAME_WIDTH (240) subs h, #1 bne .scanline_start - ldmfd sp!, {L,R,Lh,Rh} // sp+16 + add tmp, sp, #SP_L + ldmia tmp, {L, R, Lh, Rh} b .loop .exit: - add sp, #24 // revert reserved space for [Ldx, Ldg, Ldt, Rdx, Rdg, Rdt] + add sp, #(SP_SIZE + 4) // revert reserved space for [Ldx, Ldg, Ldt, Rdx, Rdg, Rdt, TILE] ldmfd sp!, {r4-r11, pc} \ No newline at end of file diff --git a/src/platform/gba/asm/rasterizeGTA.s b/src/platform/gba/asm/rasterizeGTA.s index bc5e2f6..54d8fb3 100644 --- a/src/platform/gba/asm/rasterizeGTA.s +++ b/src/platform/gba/asm/rasterizeGTA.s @@ -35,7 +35,7 @@ Ldt .req h Rdt .req h indexA .req Lh -indexB .req Rh +indexB .req tmp Rxy .req tmp Ry2 .req Rh @@ -47,23 +47,21 @@ DIVLUT .req N DIVLUTi .req tmp ptr .req Lx -width .req Rx +width .req Rh g .req Lg -dgdx .req Rg +dgdx .req L t .req Lt -dtdx .req Rt +dtdx .req R duv .req R du .req L dv .req R -Lduv .req N Ldu .req TILE Ldv .req N -Rduv .req N Rdu .req TILE Rdv .req N @@ -75,7 +73,7 @@ sLdg .req R sLdt .req Lh sRdx .req Rh sRdg .req tmp -sRdt .req N // not used in ldm due h collision +sRdt .req tmp // not enough regs for one ldmia SP_LDX = 0 SP_LDG = 4 @@ -83,41 +81,32 @@ SP_LDT = 8 SP_RDX = 12 SP_RDG = 16 SP_RDT = 20 +SP_L = 24 +SP_R = 28 +SP_LH = 32 +SP_RH = 36 +SP_SIZE = 40 +SP_TILE = SP_SIZE .macro PUT_PIXELS bic LMAP, g, #255 add g, dgdx -#ifndef TEX_2PX - tex indexA, t - add t, dtdx - - tex indexB, t - add t, dtdx - - // cheap non-accurate alpha test, skip pixels pair if one or both are transparent - ands indexA, #255 - andnes indexB, #255 - orrne indexB, indexA, indexB, lsl #8 // indexB = indexA | (indexB << 8) - ldrneb indexA, [LMAP, indexA] - ldrneb indexB, [LMAP, indexB, lsr #8] - orrne indexA, indexB, lsl #8 - strneh indexA, [ptr] -#else tex indexA, t add t, dtdx, lsl #1 cmp indexA, #0 ldrneb indexA, [LMAP, indexA] strneb indexA, [ptr] -#endif - add ptr, #2 .endm .global rasterizeGTA_asm rasterizeGTA_asm: - stmfd sp!, {r4-r11, lr} - sub sp, #24 // reserve stack space for [Ldx, Ldg, Ldt, Rdx, Rdg, Rdt] + ldr r3, =gTile + ldr r3, [r3] + + stmfd sp!, {r3-r11, lr} + sub sp, #SP_SIZE // reserve stack space for [Ldx, Ldg, Ldt, Rdx, Rdg, Rdt] mov Lh, #0 // Lh = 0 mov Rh, #0 // Rh = 0 @@ -160,16 +149,9 @@ rasterizeGTA_asm: asr Ldg, #8 // 8-bit for fractional part str Ldg, [sp, #SP_LDG] // store Ldg to stack - ldr Lduv, [L, #VERTEX_T] - sub Lduv, Lt // Lduv = N->v.t - Lt - asr Ldu, Lduv, #16 - mul Ldu, tmp // Rdu = tmp * int16(Lduv >> 16) - lsl Ldv, Lduv, #16 - asr Ldv, #16 - mul Ldv, tmp // Rdv = tmp * int16(Lduv) - lsr Ldu, #16 - lsl Ldu, #16 - orr Ldt, Ldu, Ldv, lsr #16 // Ldt = (Rdu & 0xFFFF0000) | (Rdv >> 16) + ldr Ldt, [L, #VERTEX_T] + sub Ldt, Lt // Ldt = N->v.t - Lt + scaleUV Ldt, Ldu, Ldv, tmp str Ldt, [sp, #SP_LDT] // store Ldt to stack .calc_left_end: @@ -209,16 +191,9 @@ rasterizeGTA_asm: asr Rdg, #8 // 8-bit for fractional part str Rdg, [sp, #SP_RDG] // store Ldg to stack - ldr Rduv, [R, #VERTEX_T] - sub Rduv, Rt // Rduv = N->v.t - Rt - asr Rdu, Rduv, #16 - mul Rdu, tmp // Rdu = tmp * int16(Rduv >> 16) - lsl Rdv, Rduv, #16 - asr Rdv, #16 - mul Rdv, tmp // Rdv = tmp * int16(Rduv) - lsr Rdu, #16 - lsl Rdu, #16 - orr Rdt, Rdu, Rdv, lsr #16 // Rdt = (Rdu & 0xFFFF0000) | (Rdv >> 16) + ldr Rdt, [R, #VERTEX_T] + sub Rdt, Rt // Rdt = N->v.t - Rt + scaleUV Rdt, Rdu, Rdv, tmp str Rdt, [sp, #SP_RDT] // store Rdt to stack .calc_right_end: @@ -231,48 +206,39 @@ rasterizeGTA_asm: sub Lh, h // Lh -= h sub Rh, h // Rh -= h - ldr TILE, =gTile - ldr TILE, [TILE] + ldr TILE, [sp, #SP_TILE] - stmfd sp!, {L,R,Lh,Rh} // sp-16 + add tmp, sp, #SP_L + stmia tmp, {L, R, Lh, Rh} .scanline_start: - stmfd sp!, {Lx,Rx,Lg,Rg,Lt,Rt} // sp-24 + stmfd sp!, {Lx, Lg, Lt} - asr tmp, Lx, #16 // x1 = (Lx >> 16) - rsbs width, tmp, Rx, asr #16 // width = (Rx >> 16) - x1 + asr Lx, Lx, #16 // x1 = (Lx >> 16) + rsbs width, Lx, Rx, asr #16 // width = (Rx >> 16) - x1 ble .scanline_end // if (width <= 0) go next scanline - add ptr, pixel, tmp // ptr = pixel + x1 + add ptr, pixel, Lx // ptr = pixel + x1 mov DIVLUTi, #DIVLUT_ADDR lsl inv, width, #1 ldrh inv, [DIVLUTi, inv] // inv = FixedInvU(width) + sub dtdx, Rt, Lt // dtdx = Rt - Lt + scaleUV dtdx, du, dv, inv + // t == Lt (alias) + sub dgdx, Rg, Lg // dgdx = Rg - Lg mul dgdx, inv // dgdx *= FixedInvU(width) asr dgdx, #15 // dgdx >>= 15 // g == Lg (alias) - sub duv, Rt, Lt // duv = Rt - Lt - asr du, duv, #16 - mul du, inv // du = inv * int16(duv >> 16) - lsl dv, duv, #16 - asr dv, #16 - mul dv, inv // dv = inv * int16(duv) - lsr du, #16 - lsl du, #16 - orr dtdx, du, dv, lsr #16 // dtdx = (du & 0xFFFF0000) | (dv >> 16) - // t == Lt (alias) - // 2 bytes alignment (VRAM write requirement) .align_left: tst ptr, #1 // if (ptr & 1) beq .align_right - and indexA, t, #0xFF00 - orr indexA, t, lsr #24 // res = (t & 0xFF00) | (t >> 24) - ldrb indexA, [TILE, indexA] + tex indexA, t cmp indexA, #0 beq .skip_left @@ -296,29 +262,24 @@ rasterizeGTA_asm: tst width, #1 beq .align_block_4px - ldrb indexB, [ptr, width] - - sub width, #1 // width-- - - mla Rti, width, dtdx, t // Rti = width * dtdx + t - and indexA, Rti, #0xFF00 - orr indexA, Rti, lsr #24 // res = (t & 0xFF00) | (t >> 24) - ldrb indexA, [TILE, indexA] + sub Rti, Rt, dtdx + tex indexA, Rti cmp indexA, #0 + subeq width, #1 beq .skip_right - asr Rgi, dgdx, #1 - mla Rgi, width, Rgi, g // Rgi = width * (dgdx / 2) + g + sub Rgi, Rg, dgdx, asr #1 bic LMAP, Rgi, #255 + lit indexA - ldrb indexA, [LMAP, indexA] - + ldrb indexB, [ptr, width] + sub width, #1 // width-- orr indexB, indexA, indexB, lsl #8 strh indexB, [ptr, width] .skip_right: - cmp width, #0 // width-- + cmp width, #0 beq .scanline_end // if (width == 0) .align_block_4px: @@ -350,10 +311,9 @@ rasterizeGTA_asm: bne .scanline_block_8px .scanline_end: - ldmfd sp!, {Lx,Rx,Lg,Rg,Lt,Rt} // sp+24 + ldmfd sp!, {Lx, Lg, Lt} - add tmp, sp, #16 - ldmia tmp, {sLdx, sLdg, sLdt, sRdx, sRdg} + ldmia sp, {sLdx, sLdg, sLdt, sRdx, sRdg} add Lx, sLdx add Lg, sLdg @@ -361,17 +321,18 @@ rasterizeGTA_asm: add Rx, sRdx add Rg, sRdg - ldr tmp, [sp, #(SP_RDT + 16)] - add Rt, tmp // Rt += Rdt from stack + ldr sRdt, [sp, #SP_RDT] + add Rt, sRdt add pixel, #FRAME_WIDTH // pixel += FRAME_WIDTH (240) subs h, #1 bne .scanline_start - ldmfd sp!, {L,R,Lh,Rh} // sp+16 + add tmp, sp, #SP_L + ldmia tmp, {L, R, Lh, Rh} b .loop .exit: - add sp, #24 // revert reserved space for [Ldx, Ldg, Ldt, Rdx, Rdg, Rdt] + add sp, #(SP_SIZE + 4) // revert reserved space for [Ldx, Ldg, Ldt, Rdx, Rdg, Rdt, TILE] ldmfd sp!, {r4-r11, pc} \ No newline at end of file diff --git a/src/platform/gba/data/GYM.PKD b/src/platform/gba/data/GYM.PKD index 9d60a3734993997e348278357a05c2c8304c67b5..7f1aeb46019c5c607e95f1d250cfb2391390ee41 100644 GIT binary patch delta 5712 zcmcgwYmgmBbv`}s>3Q7u-MR0*yL<1hba$ndtsp;$HMYQI{J<8tQho{RVOf#|wgHDk z0eiRmF8GI)R6&utg&zd}!mk1+C2FXm3M}VWQZ5j$1W2I3P)@MH6@oFuJj8cqWo*YJ zRr>?BcE0K9>3jN|)7@WxJ*$shyNdrcv1Y89Yu1{*=B&AE-UIhRziBqfD{@wmm#a}&1pQq2EKGQe(XO|nR=hKkp@jRppX%p@j(=u)2_g{RU z|6KbmtM}7ow40t^y_X)Kf5zPre;k@u2uP_iudE|7xe9Mzoo>l2C2Bj&8vHTyc)53!$>-|K1N4b}7qrX<6BxL)(<^ zcyyMEOA(!|3dJ&QSCw*+yworWXj%d&$OOtL1O{;g%-;Ade_r%bVOtcZ2Dyx`10>k? zQeOrrPxQa}KfPX6;xb*JqH;`5N}|G8DFa27%SNpVtO|q6RA;Q$fK;x-MBuP#H)M0J z=`ngCkUMbF$*F($KQl@V$Hs%5o3LDye{3;2h6nVd12kR!LH78!bH6QHuqiTtj?0Lj z!EZ0`X!7EB*zX8_Uxak9-xWc?a)q%{6~JmO_gJv^br^EeTAi_8CYTGt+;4~d_K=b| z4LwHg0DiyeyX?2^tear(P1j9px>%54SocGU@5G?O}rc?P*+=*`A*uejtq&SUYAN9T$0b|MKLLj+ZU<`u-Fv>@%fGHEF7#HB=k?;F| zy<@|j1-YT@)*tvn9K!VB`NpFQv+HvYV;|>Z|N40dCox;uncQI+qbzgxWP!_tfZYr8 zK*EUKCWGh29^^qT8ZifdZ(JI73f{6f{<^`7x!%{tQ6^X6;=!MZdEOo z=shYf)abn`uC?h7HJeP+pR1`to!+OW>Nfp_nzC#3m#Pz4=-!hF+BD1@t$EbQW{-|3 zr(HwGqTPaX3v)yIE7e{RF&eM*`+ef|ZCip?W*F;UvmS{7bbb)?n z8Z|TRKG*jh)byJ(T+?dfSF_U{lpDz`>dgjcXnxQ@IhbeXhVubz8gng_7g{TGcxWvM zG#UmA^Z_+D8q%F=X*i<0)L^(sD{5(RNULhIIUuDr4;D$QO>+i~)uz!LMQK1~MyrG& zjYSz)imHrO#Pua&Ec29MjwAZ{>8t65)93bxW(e)FozME0iYqrfha9&Cldf3@BguS@ zuFuPc!}ZxWp7Zy>>PDAsE$8QY&d*`KVAmIB&1taJwIBN>tM@7<`FPGGf0r}KCvqlv zP-Q26;{TJeqJl<952>)`(Zj0l)qu5-t!#9Cz7nbXdm^p5b@GW*dJM^(!C-KbiLzh4 z05&|N0`&Qa3eo?gst#WsRW9bEWsgTDu^WgC|7+y&Q;&@dB&@` z-m9jQ+iiJrMe!o|sWPE$UQiCU+@C3eNO)0MPMLnL$a3iy%7<+EALOe{FDYqz^h+f? zn|`HAWruzZqmpV^QYEUSMrbmE&MIl>aJk@D_-)BSxrmLdl2&99Qu1p0;puB>^0*^E zJklogilr^#07JtCI%Y_=wxEF=Eun`@y>5E)PFGG2=_rgT)P*>tNW1Vi)+`qaI*J7q zwSmzuX(KkNtP5sL6>S!XsyZaz{sn|rlnW&Yg>?<&F&(gYgr@UZc6i7yB*HD8{Kpk7 zker4#k*Fs8vZ$4J*47rn?`T4Dy4pvgdfG-Rrs1zmeJzlv8C^meXLSXstEHtpEoNwN zaso!v;Y3yZ0^T~Myj&=vrYI}p^dxt`Y+lCz*$ESh@V z^yILVlNF>Qq(xmoqL#FaM6-HX?i>jcX6((Fe?d7)U*zBK3>Om9io>d+48I&B3uU9Y8Iq8oIvzL(I(DPN3=&49o6KSD6?Nj^kjcU zDiaUn`b5GdR%SP;gn@;|r&Zbb$59dw2Vv4EyWrLH)r(O>5 z=$Qb?@^TNk(U}0ROV||Z+0@g?{}JFd4f((b=7RHhhU1i5%Xjt*Q+Ss}|d^*-~Uzxu(Kc ztwnT~E*27CVT#ekaTG+^Bw9t!O;Xy#5lADMO|-97>u6JMaLY@qmPupXYBDz4F0JVn zcG?f>E;i*4>1MZ0ck7vUmxk&5+<R6Lt8KYYtZ0i$bR13!AQR1T zUBuWP*L?atp3}{7UBWmX*P`SBOJJzu+AifSy%H?>IL!@H30528I|5@Nj2NSs5j=W+ z>J>4H__Jvj5W7&;rs${)8+wucs}*ZIIdk$6gz6g^7J6&CZ(RwU3WJ2~3HEyEbqGCLD-qaM?^a91EvFAP%!t zSmLssaA=OrWhdbPU5CqV!eM$Ym%W68^*t{835P6wF3W@i4{*M$ViQa_ehT;@`^`Xp z(ypY*Y>}F2W2O(>zHwo4a&#afUvn-;i=XsKIWE20Lgp*fq#9U@fTv>q!kb zmDGXNWC}a#XlWLhUA|Sm*AP!;Pi&KW#7MKc%k)gY1#IA4n(1z@0qnH;!2WCpm^7z> z*(GOh^cSbL%X`d`W-p%7NrSP|ZUWma#wPlBO82L^JXP-kCm%XTE{QZdagO|3!%fdU zX9qstWLKRp@B7`;YdE7<{fmpx5W`hwS zERVBm-X?c>D`PjP&<*2C$p!jmk@k#>W$YT`0D5oFxE%TPj&Y~ar5nf1ZiDuYdpP9p z8z=aRuz%d1?$LqqY;T%w8h2+pba347%+Sr_{(OfHjR&21l-qODC=aLS&MZ2<9W7i; z=jYE^^Llxk-5ZDaaB^(yLu4Hr2a?gpr?O+?LR1815ABuTvqoe7uJy68^kcerT)=m_ z`^FxAasN23N??GmC=ZMqoi6b169*-(09S}B!WH8x;40!O;VR>*;HqXP4%ROJuipY{ C#ij-T delta 5712 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 DFai_x diff --git a/src/platform/gba/data/LEVEL1.PKD b/src/platform/gba/data/LEVEL1.PKD index 8d83a919fa17e1c498763bb86cfedc79ee27d9b3..c5969a3573f34853df74e09be1f9b7af580a1738 100644 GIT binary patch delta 10043 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 diff --git a/src/platform/gba/data/LEVEL2.PKD b/src/platform/gba/data/LEVEL2.PKD index fc1c50a513c3db55930fffb582673535a3ebcfc1..3074ca96ab1c78cbf106c512eecd1bc431faf564 100644 GIT binary patch delta 9314 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 delta 9314 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 diff --git a/src/platform/gba/data/TITLE.PKD b/src/platform/gba/data/TITLE.PKD index 5291ef64cd006c93e5b42f28bb965cd18634a063..5bf0464cd3122a31129c2a450538ec0322dd1699 100644 GIT binary patch delta 119 zcmZ3}FTAE-xS@ryg=q_OsJ5_!gt7pGl!K&_B9Jt(*8!5-GqjllnVlP?bd(qb8_XQ^ z7(^TxBpHDuqa+iMWRheClFX6}KvGmf1W1ZWhyqD*2{9lkA|cKo?4Yfy3?$qC=rM2q JqsOvg1^{HE79{`x delta 119 zcmZ3}FTAE-xS@ryg=q_OsJ3u|gt7pGRDz_EB9Jt(*8!5-GqjllnVlC%=_oM>E--V@ zV-QJTkYogsjFL=1l1Y*oNHR+@07+2^5g;ihAqphLCB%TFh=e$UaDuk3GLUTlqsP4c Jj~>g0835Iz7$pDz diff --git a/src/platform/gba/rasterizer.h b/src/platform/gba/rasterizer.h index 51b4824..53ab6ac 100644 --- a/src/platform/gba/rasterizer.h +++ b/src/platform/gba/rasterizer.h @@ -153,7 +153,8 @@ void rasterizeS_c(uint16* pixel, const VertexLink* L, const VertexLink* R) void rasterizeF_c(uint16* pixel, const VertexLink* L, const VertexLink* R) { - uint16 color = gLightmap[(L->v.g << 8) | L->v.clip]; + uint32 color = (uint32)R; + color = gLightmap[(L->v.g << 8) | color]; color |= (color << 8); int32 Lh = 0; @@ -163,6 +164,8 @@ void rasterizeF_c(uint16* pixel, const VertexLink* L, const VertexLink* R) int32 Rx; int32 Lx; + R = L; + while (1) { while (!Lh) diff --git a/src/platform/gba/render.iwram.cpp b/src/platform/gba/render.iwram.cpp index e354e21..811bbf9 100644 --- a/src/platform/gba/render.iwram.cpp +++ b/src/platform/gba/render.iwram.cpp @@ -49,12 +49,12 @@ enum FaceType { FACE_TYPE_MAX }; -#define FACE_TRIANGLE (1 << 13) +#define FACE_TRIANGLE (1 << 19) #define FACE_CLIPPED (1 << 18) #define FACE_TYPE_SHIFT 14 #define FACE_TYPE_MASK 15 #define FACE_GOURAUD (2 << FACE_TYPE_SHIFT) -#define FACE_TEXTURE 0x1FFF +#define FACE_TEXTURE 0x3FFF #include "rasterizer.h" @@ -411,6 +411,7 @@ void faceAddRoomTriangles_c(const RoomTriangle* polys, int32 count) if (g0 != g1 || g0 != g2) { flags += FACE_GOURAUD; } + flags |= FACE_TRIANGLE; if (checkBackface(v0, v1, v2)) continue; @@ -487,6 +488,7 @@ void faceAddMeshTriangles_c(const MeshTriangle* polys, int32 count) if ((c0 | c1 | c2) & CLIP_MASK_VP) { flags |= FACE_CLIPPED; } + flags |= FACE_TRIANGLE; int32 depth = (v0->z + v1->z + v2->z + v2->z) >> (2 + OT_SHIFT); @@ -634,11 +636,9 @@ X_NOINLINE void rasterize_c(uint32 flags, VertexLink* top) uint32 type = (flags >> FACE_TYPE_SHIFT) & FACE_TYPE_MASK; - if (type == FACE_TYPE_F) { - top->v.clip = flags; // use tex coord as color index for untextured polys - } + VertexLink* R = (type == FACE_TYPE_F) ? (VertexLink*)(flags & 0xFF) : top; - gRasterProc[type]((uint16*)pixel, top, top); + gRasterProc[type]((uint16*)pixel, top, R); } void flush_c()