EP: Groped chars v1.1

+ char calcs calls
This commit is contained in:
sShemet
2025-11-05 16:24:34 +05:00
parent 3513bcaed3
commit 49f11f6cc8
10 changed files with 1466 additions and 323 deletions

View File

@@ -0,0 +1,236 @@
// 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