245 lines
13 KiB
NASM
245 lines
13 KiB
NASM
; ===== ОСНОВНАЯ ФУНКЦИЯ ПЕЧАТИ =====
|
||
.org 0x80090000
|
||
ExternalPrint:
|
||
lhu v0,0x0(a0) ; Читаем 2 байта текста
|
||
nop
|
||
srl v1,v0,0xD ; Проверяем 13-й бит (система 1-байтовых символов)
|
||
bne v1,zero,MyPrintLineRoutine ; Если установлен - используем кастомную систему
|
||
clear v1
|
||
j PrintBigDMAText ; Иначе - оригинальная система печати
|
||
nop
|
||
|
||
; ===== КАСТОМНАЯ СИСТЕМА ПЕЧАТИ =====
|
||
MyPrintLineRoutine:
|
||
addiu sp,sp,-0x50 ; Сохраняем контекст
|
||
sw s4,0x38(sp)
|
||
move s4,r4 ; s4 = адрес текста для чтения
|
||
sw s0,0x28(sp)
|
||
move s0,r5 ; s0 = параметр X
|
||
sw s1,0x2c(sp)
|
||
move s1,r6 ; s1 = параметр Y
|
||
sw s3,0x34(sp)
|
||
|
||
; ===== ИНИЦИАЛИЗАЦИЯ ПАРАМЕТРОВ ТЕКСТА =====
|
||
andi v0,v0,0xff
|
||
addiu s4,s4,0x2 ; Сдвигаем указатель текста на +2 байта
|
||
|
||
lui s3,MyAddr
|
||
sw v0,-0x10(s3) ; Сохраняем счётчик байтов @ 8008fff0
|
||
sh zero,-0xE(s3) ; Очищаем счётчик символов @ 8008fff2
|
||
|
||
; ===== ИНИЦИАЛИЗАЦИЯ DMA ЦЕПОЧЕК =====
|
||
lui s3,0x1f80
|
||
ori s3,s3,0x3d0 ; s3 = 1f8003d0 - команда копирования спрайта в scratch
|
||
|
||
lui t0,0xff
|
||
ori t0,t0,0xffff ; t0 = 00FFFFFF (маска)
|
||
|
||
andi r4,r7,0xff ; Режим текста (цвет и тень)
|
||
lui r7, 0x8008 ; r7 = 80080000
|
||
lui r6, 0xff00 ; r6 = FF000000 (маска)
|
||
|
||
; ЗАГРУЗКА ЦЕПОЧКИ ФОРМИРОВАНИЯ СИМВОЛОВ
|
||
addiu t1,r7,-0x31a8 ; t1 = адрес цепочки формирования (8007ce58)
|
||
lw v1, -0x31a8(r7) ; v1 = текущая свободная цепочка формирования
|
||
lbu r5,0x60(sp) ; Флаг тени из стека
|
||
|
||
and r6,v1,r6 ; r6 = старшие байты цепочки (FFxxxxxx)
|
||
andi r5,r5,0xff ; Очищаем режим текста
|
||
and v1,v1,t0 ; v1 = младшие байты цепочки (00xxxxxx)
|
||
or s5,v1,v0 ; s5 = адрес текущей цепочки формирования (80xxxxxx)
|
||
|
||
; ОБНОВЛЕНИЕ СЧЁТЧИКА И ЦЕПОЧКИ
|
||
lw v0,0x4(t1) ; Счётчик команд DMA
|
||
lw v1,0x0(s5) ; Следующая свободная цепочка
|
||
addiu v0,v0,-0x1 ; Уменьшаем счётчик
|
||
and v1,v1,t0 ; Обрезаем старший байт
|
||
or r6,r6,v1 ; Объединяем с старшими байтами
|
||
sw v0,0x4(t1) ; Сохраняем счётчик
|
||
jal storeColor
|
||
sw r6,-0x31a8(r7) ; Сохраняем обновлённую цепочку
|
||
|
||
; ===== ИНИЦИАЛИЗАЦИЯ ЦЕПОЧКИ КОПИРОВАНИЯ =====
|
||
move r4,s5 ; Адрес текущей цепочки
|
||
sll r5,s0,0x10 ; Координата X
|
||
sra r5,r5,0x10
|
||
sll r6,s1,0x10 ; Координата Y
|
||
jal initCopyCharChain ; Инициализация цепочки копирования
|
||
sra r6,r6,0x10
|
||
|
||
; ===== НАСТРОЙКА SCRATCH PAD ДЛЯ DMA =====
|
||
lui r6,0x1f80
|
||
ori r6,r6,0x348 ; r6 = 1f800348 - начало данных символа в scratch
|
||
|
||
; ... (паттерны 4-bit и инициализация пропущены для краткости)
|
||
|
||
; ===== ОСНОВНОЙ ЦИКЛ ОБРАБОТКИ СИМВОЛОВ =====
|
||
NextChar:
|
||
addiu r4,r4,-0x20 ; Сдвигаем непечатаемые символы
|
||
|
||
; ОБРАБОТКА ПРОБЕЛОВ
|
||
bne r4,zero,SpaceCheckBranch
|
||
nop
|
||
|
||
lui t2,MyAddr
|
||
lh v0,-0xE(t2) ; Текущий счётчик символов
|
||
nop
|
||
lh t3,-0x10(t2) ; Общий счётчик символов
|
||
addiu v0,v0,1
|
||
beq v0,t3,SpaceCheckBranch ; Если последний символ - не обрабатываем пробел
|
||
nop
|
||
|
||
; ПРОБЕЛ - только сдвигаем позицию
|
||
sh v0,-0xE(t2) ; Обновляем счётчик
|
||
nop
|
||
lbu r4,0x0(s4) ; Следующий символ
|
||
|
||
; СДВИГ ПОЗИЦИИ X
|
||
lhu v0,0xa8(gp) ; Начальный X
|
||
lhu v1,0x8(s3) ; Текущий X в scratch
|
||
addiu v0,v0,0x6 ; Сдвиг на 6 пикселей
|
||
addu v1,v1,v0 ; Новый X
|
||
sh v1,0x8(s3) ; Обновляем в scratch DMA
|
||
|
||
j NextChar
|
||
addiu s4,s4,0x1 ; Следующий байт текста
|
||
|
||
; ===== ОБРАБОТКА НЕ-ПРОБЕЛЬНЫХ СИМВОЛОВ =====
|
||
SpaceCheckBranch:
|
||
jal makeCharPixelsCustom ; СОЗДАЁМ ПИКСЕЛИ СИМВОЛА В SCRATCH
|
||
clear s2
|
||
|
||
; ===== ФОРМИРОВАНИЕ КОМАНДЫ КОПИРОВАНИЯ SPRITE =====
|
||
PageLoop:
|
||
; ЗАГРУЗКА ЦЕПОЧКИ КОПИРОВАНИЯ SPRITE
|
||
lw v0,-0x3198(s6) ; Адрес свободной цепочки копирования (8007ce68)
|
||
nop
|
||
and r4,v0,t2 ; Старшие байты
|
||
and v0,v0,s0 ; Младшие байты
|
||
or r5,v0,s1 ; r5 = полный адрес цепочки (80xxxxxx)
|
||
|
||
; ОБНОВЛЕНИЕ СЧЁТЧИКА КОПИРОВАНИЯ
|
||
lw v0,0x4(s7) ; Счётчик команд копирования
|
||
lw v1,0x0(r5) ; Следующая свободная цепочка
|
||
addiu v0,v0,-0x1 ; Уменьшаем счётчик
|
||
and v1,v1,s0 ; Обрезаем старший байт
|
||
or r4,r4,v1 ; Объединяем
|
||
sw v0,0x4(s7) ; Сохраняем счётчик
|
||
sw r4,-0x3198(s6) ; Сохраняем обновлённую цепочку
|
||
|
||
; ===== КОПИРОВАНИЕ ИЗ SCRATCH В ЦЕПОЧКУ =====
|
||
CopyCmdFromScratch:
|
||
; Копируем команду DMA из scratch в цепочку
|
||
lw t9,0x0(s3) ; Количество команд (04000000)
|
||
lw t7,0x4(s3) ; Команда копирования спрайта (64808080)
|
||
lw t8,0x8(s3) ; Координаты XY на экране
|
||
lw t5,0xc(s3) ; CLUT и координаты текстуры
|
||
|
||
; СОХРАНЯЕМ В ЦЕПОЧКУ КОПИРОВАНИЯ
|
||
sw t9,0x0(r5) ;
|
||
sw t7,0x4(r5)
|
||
sw t8,0x8(r5)
|
||
sw t5,0xc(r5)
|
||
lw t9,0x10(s3) ; Размер спрайта после копирования
|
||
nop
|
||
sw t9,0x10(r5) ; Последняя команда
|
||
|
||
; ===== СВЯЗЫВАНИЕ ЦЕПОЧЕК =====
|
||
; СВЯЗЬ: ЦЕПОЧКА ФОРМИРОВАНИЯ → ЦЕПОЧКА КОПИРОВАНИЯ
|
||
lw v1,0x18(t1) ; Текущая цепочка формирования
|
||
lw v0,0x0(r5) ; Текущая команда копирования
|
||
lw v1,0x0(v1) ; Следующая цепочка формирования
|
||
and v0,v0,t2 ; Маска старших байтов
|
||
and v1,v1,s0 ; Маска младших байтов
|
||
or v0,v0,v1 ; Объединяем
|
||
sw v0,0x0(r5) ; Обновляем команду
|
||
|
||
; ОБНОВЛЯЕМ ССЫЛКУ В ЦЕПОЧКЕ ФОРМИРОВАНИЯ
|
||
lw r4,0x18(t1) ; Адрес цепочки формирования
|
||
nop
|
||
lw v0,0x0(r4) ; Текущая команда формирования
|
||
and v1,r5,s0 ; Адрес цепочки копирования
|
||
and v0,v0,t2 ; Маска старших байтов
|
||
or v0,v0,v1 ; Объединяем
|
||
sw v0,0x0(r4) ; Сохраняем обновлённую ссылку
|
||
|
||
sw r5,0x18(t1) ; Сохраняем текущую цепочку копирования
|
||
|
||
; ===== ПРОВЕРКА ПЕРВОГО СИМВОЛА =====
|
||
lhu v0,0x4(t6) ; Счётчик символов
|
||
nop
|
||
bne v0,zero,NotFirstChar ; Если не первый символ - пропускаем
|
||
nop
|
||
|
||
; ИНИЦИАЛИЗАЦИЯ ДЛЯ ПЕРВОГО СИМВОЛА
|
||
sw r5,0x28(t1) ; Устанавливаем первую цепочку символа
|
||
sw t8,0xc(t6) ; Сохраняем координаты в параметрах
|
||
|
||
NotFirstChar:
|
||
|
||
; ===== КОПИРОВАНИЕ ДАННЫХ СИМВОЛА ИЗ SCRATCH =====
|
||
lui r5,0x1f80
|
||
ori r5,r5,0x348 ; r5 = данные символа в scratch
|
||
|
||
lw v0,-0x31a8(t3) ; Следующая свободная цепочка формирования
|
||
and r4,v0,t2 ; Старшие байты
|
||
and v0,v0,s0 ; Младшие байты
|
||
or r7,v0,s1 ; r7 = адрес цепочки (80xxxxxx)
|
||
move r6,r7 ; r6 = адрес назначения
|
||
|
||
; ... (копирование данных пропущено для краткости)
|
||
|
||
; ===== СВЯЗЫВАНИЕ: ДАННЫЕ СИМВОЛА → КОМАНДА КОПИРОВАНИЯ =====
|
||
lw v1,0x18(t1) ; Текущая команда копирования
|
||
lw v0,0x0(r7) ; Текущие данные символа
|
||
lw v1,0x0(v1) ; Следующая команда копирования
|
||
and v0,v0,t2 ; Маска старших байтов
|
||
and v1,v1,s0 ; Маска младших байтов
|
||
or v0,v0,v1 ; Объединяем
|
||
sw v0,0x0(r7) ; Обновляем данные символа
|
||
|
||
; ОБНОВЛЯЕМ ССЫЛКУ В КОМАНДЕ КОПИРОВАНИЯ
|
||
lw r4,0x18(t1) ; Адрес команды копирования
|
||
nop
|
||
lw v0,0x0(r4) ; Текущая команда
|
||
and v1,r7,s0 ; Адрес данных символа
|
||
and v0,v0,t2 ; Маска старших байтов
|
||
or v0,v0,v1 ; Объединяем
|
||
sw v0,0x0(r4) ; Сохраняем обновлённую ссылку
|
||
|
||
sw r7,0x18(t1) ; Сохраняем текущие данные символа
|
||
|
||
; ===== СДВИГ ПОЗИЦИИ ДЛЯ СЛЕДУЮЩЕГО СИМВОЛА =====
|
||
lhu v0,0xa8(gp) ; Начальный X
|
||
lhu v1,0x8(s3) ; Текущий X
|
||
addiu v0,v0,0x6 ; Сдвиг на 6 пикселей
|
||
addu v1,v1,v0 ; Новый X
|
||
sh v1,0x8(s3) ; Обновляем
|
||
|
||
; ===== ПРОВЕРКА ЗАВЕРШЕНИЯ ТЕКСТА =====
|
||
lhu v0,0x4(s5) ; Счётчик символов DMA
|
||
lui t9,MyAddr
|
||
addiu v0,v0,0x1
|
||
sh v0,0x4(s5) ; Сохраняем
|
||
|
||
; ПРОВЕРКА ПЕРЕПОЛНЕНИЯ DMA
|
||
lw v0,0x4(s7) ; Текущий счётчик
|
||
move v1,5 ; Минимальный лимит
|
||
sltu v0,v0,v1 ; Проверяем переполнение
|
||
bne v0,zero,TextEnd ; Если переполнение - завершаем
|
||
|
||
; ПРОВЕРКА КОНЦА СТРОКИ
|
||
lui t3,MyAddr
|
||
lhu v0,-0xE(t3) ; Текущий символ
|
||
lhu v1,-0x10(t3) ; Общее количество символов
|
||
addiu v0,v0,0x1
|
||
lbu r4,0x0(s4) ; Следующий символ
|
||
sh v0,-0xE(t3) ; Сохраняем счётчик
|
||
addiu s4,s4,0x1 ; Сдвигаем указатель
|
||
|
||
bne v0,v1,NextChar ; Если не конец - продолжаем
|
||
nop
|
||
|
||
; ===== ЗАВЕРШЕНИЕ ОБРАБОТКИ ТЕКСТА =====
|
||
TextEnd:
|
||
; ... (восстановление контекста и завершение) |