| Разработка и ромхакинг > Программирование |
| [NES] Изучаем Ассемблер 6502 |
| << < (2/2) |
| Ti_:
--- Цитата: Arigato от 03 Июнь 2023, 17:09:38 ---В общем, как такое решение? Можно ли что-то улучшить или оптимизировать? --- Конец цитаты --- Не совсем понял, но отдельный код для вывода каждой строки нигде не делают, обычно везде одна функция печати строки, и для нее параметры передаются. Это может быть даже просто её номер, а всё остальное в массиве данных быть. Вычисления как раз можно через макрос сделать. LDA PPU_STATUS тоже нет никакого смысла каждый раз перед установкой адреса делать, это нужно только в 1 случае - если ты где-то записал только 1 раз в $2006 или $2005. Сам по себе регистр на 'нечетный' никак не слетит. Вот под твой случай: --- Код: ---; 2 переменные обязательно в zeropage! tmp_ptr_l equ $20 tmp_ptr_h equ $21 ; макрос для печати строки (не знаю подойдёт ли под твой asm) MACRO print_str str_x,str_y,str_ptr,nt LDX #>((str_y*32)+$2000 + nt*$400) LDY #<(str_y*32 + str_x) LDA #<str_ptr STA tmp_ptr_l LDA #>str_ptr JSR print_str_ ENDM ; функция печати print_str_: STA tmp_ptr_h STX PPU_ADDRESS STY PPU_ADDRESS LDY #0 LDA (tmp_ptr_l),Y @print_l INY STA PPU_DATA LDA (tmp_ptr_l),Y BNE @print_l RTS stroka1: .BYTE 'TEST STROKA 1 ',0 stroka2: .BYTE ' STROKA 2 TEST ',0 ; пример использования в коде: print_str 4,5,stroka1,0 ; печать строки str0 по x=4,y=5, экран0 print_str 10,15,stroka2,0 ; печать строки str1 по x=10,y=15, экран0 --- Конец кода --- |
| Arigato:
--- Цитата: Ti_ от 03 Июнь 2023, 21:59:12 ---LDA PPU_STATUS тоже нет никакого смысла каждый раз перед установкой адреса делать, это нужно только в 1 случае - если ты где-то записал только 1 раз в $2006 или $2005. --- Конец цитаты --- Ну по идеи чисто в теории такая ситуация может возникнуть, если между парой записей произойдет вызов nmi. Хотя это весьма странно, так как к этому моменту работу с PPU уже надо бы завершить. Но читал рекомендацию делать LDA PPU_STATUS, видимо, как раз на такой случай (вариант что просто в коде где-то забыли второй раз записать маловероятен, да и в принципе ошибочен). В общем убрал. По поводу печати, то у меня две отдельные подпрограммы: одна устанавливает "курсор" в нужную клетку экрана, а другая выводит текст, перемещая курсор в конец строки (ну это автоматически происходит при обращении к PPUDATA). Это позволяет вызывать подпрограмму печати одну за другой, тогда текст будет выводиться дальше, за предыдущим. По логике это как в обычном BASIC командой PRINT происходит. Например: --- Код: --- _GOTOXY #1, #11 ; это координаты курсора _PRINT str_hello4 ; это вывод строки на экран _PRINT16 game_hst ; тут вывод 16-битного числа _PRINT_CHAR #'.' ; и символ "." в конце предложения --- Конец кода --- На экране это выглядит так: При этом в _GOTOXY можно передавать не только числа (константы), но и регистры или переменные. Скажем: _GOTOXY #10, Y - установить курсор в строку с номером Y (регистр) в позицию 10. Выбор экранов пока не сделал, в данный момент мне это не нужно. Может позже добавлю. |
| Ti_:
--- Цитата: Arigato от 03 Июнь 2023, 23:04:00 ---Ну по идеи чисто в теории такая ситуация может возникнуть, если между парой записей произойдет вызов nmi. Хотя это весьма странно, так как к этому моменту работу с PPU уже надо бы завершить. --- Конец цитаты --- Само по себе NMI не сбрасывает адрес тоже. Просто там может быть, код который тоже делает запись в vram, или даже просто строчка BIT PPU_STATUS. Только чтение PPU_STATUS в основном цикле в этом случае не поможет, код всё равно 'посыпется'. Потому что тогда nmi может проскочить и 'между строк' установки адреса, или просто в цикле записи в PPU_DATA. Поэтому, если у тебя много данных для записи (более 1 фрейма по времени) то NMI отключают вместе с дисплеем (или можно в самом nmi вначале добавить 'флаг'), а если у тебя записи в пределах vblank или даже экрана, то случайно/повторно в текущем кадре nmi сработать не может. Добавлено позже: --- Цитата: Arigato от 03 Июнь 2023, 23:04:00 ---При этом в _GOTOXY можно передавать не только числа (константы), но и регистры или переменные. Скажем: _GOTOXY #10, Y - установить курсор в строку с номером Y (регистр) в позицию 10. --- Конец цитаты --- Понятно, ну минимально можно сделать функцию вместо макроса .macro _PRINT , чтобы не забивать ром однотипным кодом (передавать адрес строки). Если скорость не важна, можно даже сделать и отдельную функцию для установки адреса сделать вместо макроса, а в макросе оставить только вычисление A и Y. --- Код: ---proc_set_ppu_addr: STA PPU_ADDRESS STY PPU_ADDRESS RTS --- Конец кода --- Если наоборот нужна скорость , можно и в столбик строчки писать (такое тоже встречается): --- Код: ---; 'PRESS START' LDX #'P' STX PPU_DATA INX ; R' STX PPU_DATA LDA #'E' STA PPU_DATA LDY #'S' STY PPU_DATA STY PPU_DATA LDA #' ' STA PPU_DATA STY PPU_DATA ; 'S' INY ; 'T' STY PPU_DATA ; 'T' LDA #'A' STA PPU_DATA ; 'A' STX PPU_DATA ; 'R' STY PPU_DATA ; 'T' --- Конец кода --- Касаемо вычислений, можно так попробовать: --- Код: ---offset: LDA #>SCR_BASE ; SCR_BASE = $2000 ORA sreg + 1 STA PPU_ADDRESS TXA ORA sreg STA PPU_ADDRESS RTS --- Конец кода --- |
| Arigato:
--- Цитата: Ti_ от 04 Июнь 2023, 08:00:20 ---Поэтому, если у тебя много данных для записи (более 1 фрейма по времени) то NMI отключают вместе с дисплеем (или можно в самом nmi вначале добавить 'флаг'), --- Конец цитаты --- Или можно разбить вывод на несколько кадров, если скорость неважна. Я так делаю, разбиваю информацию на части и вывожу порциями в разных кадрах. |
| Навигация |
| Главная страница сообщений |
| Предыдущая страница |