
//                                     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