Files
Persona2-PSX-asm-sources/2_EP/EP_charload_grouped.asm
sShemet 49f11f6cc8 EP: Groped chars v1.1
+ char calcs calls
2025-11-05 16:24:34 +05:00

236 lines
11 KiB
NASM
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// LOADING CHAR FROM CUSTOM FONT FOR ALL LINE
make_char_line_in_scratch:
addiu sp, sp,-0x18
sw ra, 0x10(sp)
sw t5, 0x14(sp)
move t5, a0 //char num
sll s3, a1, 0x2 //width in bytes (sprite count * 4)
lui t7, MyAddr
addiu t7, -0x0c //Text buffer pointer
char_data_clear:
move a1, t3 //dest address
addiu a0, a1, 0x184
li v0, 0
char_data_loop:
sw v0, 0x0(a1)
addiu a1, 0x4
bne a1, a0, char_data_loop
nop
move s1, t3 // destination address reset
li a2, 0 // char index counter
lbu v0, 0x0(t7)
lbu t2, 0xa4(gp) //load color
addiu t7, t7, 0x01
lui a3, 0x1f80
ori a3, a3,0x390 // set scratch convert addr r7 = 1f8002e0
chars_font_loop:
addiu v0, -0x20 //shift unprintable
beq v0, zero, spaceJump //If space (0x20 ASCII) -- bypass char
nop
lui v1, 0x801f // //load font addr to r3 (801ef000 + BA00)
ori v1, v1, 0xaa00 // ==== 801faa00
sll t0, v0, 2 // t0 = v0 * 4
sll v0, v0, 3 // v0 = v0 * 8
addu v0, v0, t0 // v0 = (v0*8) + (v0*4) = v0*12
addu t1, v0, v1 //t1 = char addr // t1 = r2(offs) + r3 (start)
clear t3 //new lines counter
char_lines_loop:
lbu v1, 0x0(t1) //load byte of char font to r3
nop
beq v1, zero, zero_jump
nop
its_not_empty:
//right
andi a0, v1, 0xf // a0 = r3 & 0f - cutting left semibyte
sll a0, a0, 0x1 // a0 << 1
addu a0, a0, a3 // a0 += bit table
lhu a0, 0x0(a0) // в a0 - правый полусимвол в 4 бит
//left
srl a1, v1, 0x4 // r3 >> 4
andi a1, a1, 0xf // r2 = r3 & 0f
sll a1, a1, 0x1 // r2 << 1
addu a1, a1, a3 // r2 = r2 + to4bitConvertTableAddr (r7)
lhu a1, 0x0(a1)//>DAT_1f8002e0 в a1 - левый полусимвол в 4 бит
nop
//combine & color
sll a1, 0x10
or a0, a1
mult a0, t2 //set color - сохраняем в регистре умножения готовые 4 байта
//line dest addr calc -
// s1(dest addr) + ((current line * (charcount * 4) + charIndex * 3))
//calc char index * 3
sll a1, a2, 1
addu a1, a1, a2
//getting final char line word...
nop
mflo t4 // t4 = final char
//multiplying current line * width
mult t3, s3
nop
nop
nop
mflo a0
//getting final address
addu a0, a0, a1 // a0 = current_line * width_in_bytes + charindex * 3
addu a0, a0, s1 // s1 = destination write address
andi v0, t4, 0xFF //
sb v0, 0x00(a0) //
sra v0, t4, 0x08 //
andi v0, v0, 0xFF //
sb v0, 0x01(a0) // Byte by byte char data save in LITTLE ENDIAN
sra v0, t4, 0x10 // cause we are not fitting to memory words
andi v0, v0, 0xFF //
sb v0, 0x02(a0) //
addiu v0, t5, -0x1
bne a2, v0, not_last
andi v1, t5, 0x3
beq v1, zero, divideby4
not_last:
sra v0, t4, 0x18 // Байт рисуется только если длина не кратна 4
andi v0, v0, 0xFF // и это не последний байт
sb v0, 0x03(a0) // (иначе происходит наложение байта на следующую строку)
divideby4:
zero_jump:
addiu t3, t3, 0x01 //inc line counter
li v0, 0x0C //line max count
bne t3, v0, char_lines_loop //comparing...
addiu t1, t1, 0x01 //shift char font line address
spaceJump:
addiu a2, a2, 0x1 // inc char index
lbu v0, 0x0(t7)
addiu t7, t7, 0x01
beq v0, zero, sprite_end //if we read 0 - end
nop
bne a2, t5, chars_font_loop // if r3 counter<>0 goto loop
nop
sprite_end:
lbu v1, 0xa5(gp) // >DAT_8007b23d_textMode load curText Shadow?
li v0, 0x1
bne v1, v0, NotShadow //Shadow character check
nop
move a0, s1
nop
make_shadow: //s3 - line width in bytes, a0 - data start
move a1, s3 // a1 = ширина
sll a1, 0x1 //a1 = смещение на 3 строку (ширина * 2)
sll v0, s3, 3 //v0 = ширина строки * 8
addu v0, a1 //v0 = ширина строки * 10
addu a3, a0, v0 // a3 = указатель на 10 строку
addu a0, a1 // a0 = Указатель на 3 строку
lbu t1, 0xa4(gp) // v0 = базовый цвет символа
li t2, 0xf // t2 = маска 0xF для работы с 4 битами пикселя
addiu t1, 0x1 // t1 = цвет тени (базовый цвет + 1)
// Основной цикл по строкам (снизу вверх)
shadow_row_loop:
clear t5 //clear sprite shift counter
//Цикл спрайтов в строке
shadow_sprites_loop:
addu t7, a3, t5 //Текущий адрес спрайта = Адрес текущей строки + смещение спрайта
lw t0, 0x0(t7) // t0 = текущая полоса спрайта
clear a2 // a2 = счётчик пикселей в строке (X координата)
li a1, 0x4 // a1 = сдвиг 1 пиксель вправо (4 бита)
// Внутренний цикл по пикселям в строке
shadow_pixel_loop:
move a1, a2 // a1 = текущий X пиксель
addiu a1, a1, 0x1 // +1 пиксель вправо
sll a1, a1, 0x2 // ×4 (перевод в биты)
sll v0, a2, 0x2 // v0 = смещение исходного пикселя (X * 4)
sllv v0, t2, v0 // v0 = маска для исходного пикселя
and v0, t0, v0 // проверяем есть ли исходный пиксель
beq v0, zero, no_s // если пикселя нет, пропускаем
nop
//Проверяем граничный случай (8-й пиксель)
li v0, 0x7 // последний пиксель (X = 7)
bne a2, v0, normal_case // если не 8-й пиксель - обычная обработка
nop
// Граничный случай: 8-й пиксель исходного спрайта
// Тень будет в позиции a1 = 32 (8 × 4) - это следующий word!
addu t8, t7, s3 // адрес следующей строки
addiu t8, t8, 0x4 // переходим к следующему word
lw v1, 0x0(t8) // загружаем следующий word
li v0, 0xF // маска для ПЕРВОГО пикселя в новом word
and v0, v1, v0 // проверяем занятость (биты 0-3 нового word)
bne v0, zero, no_s // если занято - пропускаем
nop
move v0, t1 // цвет тени (в биты 0-3 нового word)
or v0, v1, v0 // добавляем тень
sw v0, 0x0(t8) // сохраняем
b no_s
nop
normal_case:
addu t8, t7, s3 // этот же word в следующей строке
lw v1, 0x0(t8) // следующая строка
sllv v0, t2, a1 // маска для пикселя тени
and v0, v1, v0 // проверяем занятость
bne v0, zero, no_s // если занято - пропускаем
nop
sllv v0, t1, a1 // цвет тени
or v0, v1, v0 // добавляем тень
sw v0, 0x0(t8) // сохраняем
no_s:
addiu a2, a2, 0x1 // следующий пиксель
sltiu v0, a2, 0x8 // X < 8 (все 8 пикселей!)
bne v0, zero, shadow_pixel_loop
nop
addiu t5, t5, 0x04
bne t5, s3, shadow_sprites_loop
nop
// next line
subu a3, s3 //Двигаемся назад на ширину строки
sltu v0, a3, a0 // проверяем вышли ли за верхнюю границу
beq v0, zero, shadow_row_loop // продолжаем цикл по строкам
nop
NotShadow:
lw t5,0x14(sp)
lw ra,0x10(sp) //Restore stack and exit
move v0, s1
jr ra
addiu sp, sp, 0x18