236 lines
11 KiB
NASM
236 lines
11 KiB
NASM
|
||
// 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 |