Login

Subversion Repositories NedoOS

Rev

Rev 595 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

todo вернуть OSCALLS для перехвата клавиш, для этого в оси сделать хук для юзерского обработчика прерываний?
перехват надо уже в юзерспейсе, а в системспейсе надо вызывать заданный обработчик (возможно, другой)
щедулинга при этом нет, но есть выставление палитры


bugs:
графика портится после raytrace
на 8-2 прохождение обламывается при MULTITASKING=1 (даже с MUSICONINT=0)

если подбежать к грибу справа, когда он на левом краю экрана, то счёт показывается наполовину справа (так и было? в версии без оптимизированного клипирования так уже было)

ни одна дема не проходит 1-2:

;фиксы CY не помогли (проверил 0..5)
;возможные причины:
;- субпиксели - не нашёл, есть только friction - как он работает?
;- история запуска (вроде всё чистится!)
;- игрок возник не там (но тогда бы не смог так точно прыгать?)
;- игрок возник не когда надо
;- враг возник не там
;- враг возник не когда надо
;- неправильный bounding box врага
;- неправильный критерий столкновения с врагом (на 1-2 этого врага мы должны перепрыгнуть в последний момент перед ним)
;- неправильно определяется столкновение с трубой
;- неправильно реагирует на столкновение с трубой


в 177... убрал после 1-1 3 фрейма - проходит дальше (умирает на третьей трубе), 4 фрейма - не допрыгивает до третьей трубы, 5-20 всё плохо
сделал NOPIRANHAPLANT=1, убрал 3 фрейма после 1-1, 2 фрейма после 1-2 (с 1 доходит далеко)
1-4 (с ошибкой в Z80OPT3hy): 1 убранный фрейм не помогает, 0..14 добавленных фреймов не помогает, 0..14+сразу B не помогает, 15+-сразу B лучше, 16+-сразу B ещё лучше, 17..18 то же, 19 доходит до дракона, 20 его убивает (пробовал только без сразу B - как в оригинале)
2-1 (7900): убрать 0..3 плохо, 4 лучше, 5 не так хорошо, 6 застревает, добавить 1..27 ничего не даёт; поэтому сделал изменения в двух местах (замедление в середине и три лишних фрейма бега в конце, 4 тоже можно, 2 мало)
2-2 (9710): вставка 7..11 нормально ест 3 первых монетки, дальше плохо, 12..14 вообще тонет в яме, 15..17 плохо, 18 тонет в яме, 19..20 лучше, 21 плохо
в итоге очень много изменений
2-3 (13600): сразу работает
2-4 (16300): 0..5 плохо, +6..21 умер сразу
в итоге много исправлений
3-1 (18200): нет хорошей фазы, взял лучшую (вставка 5) и сильно переделал
3-2 (20600): поскольку флаг в прошлом уровне снят не сверху, а снизу, то потеряно много времени, сделана большая вставка, а ложные нажатия в начале вырезаны
в итоге пришлось всё переписать
3-3 (22800): записан с клавиатуры
3-4 (26077): записан с клавиатуры
4-1 (29750): записан с клавиатуры
4-2 (33050): записан с клавиатуры и т.д.

4-2 лоза растёт (и звук есть), но при скролле исчезает (реально по ней при этом можно залезть) - это не KillVine, но при этом не вызывается DrawVine, вызывается только VineObjectHandler
вылетает сразу:
           cpxn ++$05                  ;check enemy offset for special use slot ;реально там 4
           bne ExitVH                ;if not in last slot, branch to leave
исчезает на 1 метатайл раньше, чем в оригинале? или в оригинале не видим левый край экрана?


fixed:
спуск в трубу уже работает, враги в трубах в 1-2 есть, черепахи работают, лифты работают, блоки разбиваются головой большого Марио
фейерверки в конце 1-1 работают
после спуска флага вверху остаются цифры (так и надо)
1-4 вода не шевелится (так и надо)
после некоторых смертей не показывал x2 (т.е. число жизней), а только фигуру Марио - выводится всегда на 0 экране тайлов (нет сплитскрина по монетке) - исправлено в main
убийство первого монстра может приводить к зависанию? - вроде исправилось после SCRATCHPAD2
в деме была всегда смерть на первом монстре (в оригинале это редко) - исправилось
world 1-2 неправильно показан вход в трубу - исправлен флаг
были тормоза из-за выключенных прерываний
world 2-4 используется переворот спрайтов огня по вертикали (мёртвые монстры в 1-1 тоже)
перекрасил тайлы фона в соответствии с их палитрами (взять из метатайлов). если на один тайл много палитр, то размножить тайл и поменять номера в исходнике метатайлов
world 1-3 в конце флажок поднимается в середине здания (от должен быть позади тайлов - реализовал такое поведение спрайтов, заодно для монетки в спрайте 0)
были неправильно окрашены монетки в воде 2-2 и следы от них (красный фон), водоросли (зелёный фон), нижняя часть гориз. трубы в 2-2 (x91,x92)
при движении платформ на верёвочках новые верёвочки были зелёные
были подёргивания экрана из-за рисования на отображаемом экране иногда
;[почему-то огненные палки и плевки дракона голубые]
;[и рамка их центра голубая]
;[и лава голубая]
;[фаербол Марио почему-то с чёрной окантовкой (надо оранжевый с красной окантовкой, взрыв внутри белый)]
;[очки надо белым (сейчас розовым)]
;[гриб надо c белой ножкой, оранжевый с красными пятнами]
;[плевок лавы наполовину зелёный почему-то, а наполовину голубой]
;[ёжик падает зелёный, а приземляется красный - а надо всегда красный с белыми блестючками]
;[лоза в подземелье ок, но наверху она почему-то чёрная]

TODO в будущем использовать только метатайлы 16х16 и не строить карту тайлов 8х8? (кроме верха экрана и сообщений о смерти)
для некоторых метатайлов (которые не бывают внизу экрана) можно уже делать 16x8 (вертикально), но без выигрыша в скорости, т.к. во втором ряду надо пропускать

TODO спрайты надо сгенерить со всеми существующими палитрами в отдельные страницы, переворот по вертикали можно программно?

TODO ускорить логику, сейчас она 47000 тактов (было 80000)

палитры: WaterPaletteData и др. (много), мигание вопросиков



вывод тайлов фона:

пусть тайл - это процедура
>2..3 байта на байт
то есть все тайлы одного набора не поместятся в странице?
нам нужно только 256-19 тайлов, из которых 4 полностью залитые, а 1 (№255) может не использоваться
в среднем надо 69 байт на тайл (2,17 байта на байт)
можно для цифробукв сделать call:db data,data...

если бы не было скроллинга, то прокатило бы так:
ld (hl),n
set 7,h
ld (hl),n
set 6,h
ld (hl),n
res 7,h
ld (hl),n
add hl,bc
... и наоборот
но реально все 4 адреса столбцов независимые! вплоть до невидимых


один столбец тайла = 0..+40*7 = +280
-128
-88
-48
-8
+32
+72
+112
(+142)

ld (ix+-d),n
...
ld (iy+-d),n ;19t
...
ld (hl),n
add hl,bc ;21t, т.е. проигрыш (21-19)*8-11 = 5t, реально проигрыша нет
...
ex de,hl
ld (hl),n
add hl,bc
...

потом надо обновить экранные адреса


мы можем читать из стека экранные адреса, но не все (а то слишком большие таблицы надо разместить в нижней памяти, и стек нельзя ниже 3b00)
но если переход на тайлопроцедуру быстрый, то можно выводить экран по 2 слоя (не 4) за раз, заодно нет проблем с ужиманием всех тайлов в страницу, такие страницы:
0000 kernel
4000 screenaddrstack
8000 screen
c000 tileprocleft/tileprocright
тогда можно хранить в стеке все экранные адреса


минимальный переход на тайлопроцедуру:
[а)
ld a,(de)
inc e
ld hx,a ;64 tiles!!
jp (ix)
...
jp
;37t]
[б)
ex de,hl
ld d,(hl)
inc l
ex de,hl
ld a,1
srl h
rra
rr h
rra
ld l,a ;hl=%10tttttt tt000000
jp (hl)
;58t]
[в)
ld a,(de)
inc e
ld l,1
srl a ;rra (если гарантированно NC)
rr l
rra
rr l ;NC
ld h,a ;hl=%10tttttt tt000000
jp (hl)
;54(50)t]
г)
процедуры расположены лесенкой: 0xc000,0xc101...
ld a,(de)
inc e
ld l,a
or 0xc0
ld h,a
jp (hl)
;30t, 7b
выход из строки по одному из незанятых номеров тайлов (надо патчить тайловую карту перед входом, а потом распатчить обратно)

минимальный вывод тайла (pop hl не будет быстрее add hl,bc):
pop hl ;пиксели 0..1
dup 7
ld (hl),n
add hl,bc
edup
ld (hl),n
pop hl ;пиксели 4..5 в той же странице (другой bit 5 и возможно +1)
dup 7
ld (hl),n
add hl,bc
edup
ld (hl),n
;336t (*2 для второй страницы), 48b
;+7b, итого меньше 64b
;проблема только с тайлом 0xff, у которого адрес процедуры 0xffff (но, возможно, он не используется)
;весь экран = 366*2*33*25 = 603900t
можно пропускать ld (hl),0, если экран очищен

обработчик прерывания надо свой, чтобы восстанавливать данные в стеке, если стек в 0x4000+ - из копии в другой странице?
что выгоднее - пустой тайл выводить так же (только через ld (hl),b - 288t) или заранее затереть весь экран через push, а вместо вывода пустого только pop:pop (20t)?
5.5*32*200*4 = 35200*4t = 176t/tile
если пустых тайлов 50%, то весь экран будет:
при обычной процедуре: (318+366)*33*25 = 564300t
через push: 140800 + 366*33*25 = 442750t
при push ещё можно немного оптимизировать тайлы с прозрачными пикселями, просто пропускать эти байты

как лежит стек экранных адресов:
в каждой строке 33 пары адресов
всего 25 строк
4 фазы скролла
итого 33*2*2*25*4 = 13200, но класть влоб 33 пары неудобно
ширину строки лучше не сокращать
поэтому надо таблицу адреса входа в каждую строку для фазы 0, а для остальных фаз прибавлять константы
или всегда выводить все строки, тогда достаточно прибавлять константу на каждой строке

;для scroll phase 0 стек такой:
;(scrL) 0x8004, 0xa004, 0x8005, ... 0xa023, noaddr x 2
;(scrR) 0x8004, 0xa004, 0x8005, ... 0xa023, noaddr x 2
;для scroll phase 1 стек такой:
;(scrR) noaddr, 0x8004, 0xa004, 0x8005, ... 0xa023, noaddr x 1
;(scrL) 0x8004, 0xa004, 0x8005, ... 0xa023, noaddr x 2
;для scroll phase 2 стек такой:
;(scrL) noaddr, 0x8004, 0xa004, 0x8005, ... 0xa023, noaddr x 1
;(scrR) noaddr, 0x8004, 0xa004, 0x8005, ... 0xa023, noaddr x 1
;для scroll phase 3 стек такой:
;(scrR) noaddr, noaddr, 0x8004, 0xa004, 0x8005, ... 0xa023
;(scrL) noaddr, 0x8004, 0xa004, 0x8005, ... 0xa023, noaddr x 1
реально достаточно сгенерировать стек для одной фазы скролла с запасами на пустышки слева

СПРАЙТЫ

если все экранные адреса лежат в стеке, то надо несколько страниц стека (постолбцово).
код
стек
экран
спрайтокод
- когда переключать экранные страницы? вывести сначала чётные столбцы спрайта, потом нечётные?
у нас активный экран (256+7) * (200+7+7), при спрайтах 8х8
тогда стек (точнее, стек для одной страницы экрана) займёт 2 * (64+2) * (200+7+7) = 28248
реально надо 3 страницы стека (столбцы левой половины экрана, столбцы правой половины экрана, центр)

как переходить между столбцами стека? inc h? в любом случае 3 страницы стека
ld sp,hl
pop de
ld a,(de)
and...
or...
ld (de),a
...
inc h
...

как выходить из спрайта? jp (ix)?

более универсально выводить столбцы подряд, в две страницы экрана
тогда надо переключать все 4 окна
такой процедуры в недоос нет, надо её генерировать из существующих (а если керналь изменится - придётся переделывать)
удобнее всего стек в 0xc000, тогда в 3D можно inc h:jr nz
в 3D переключаются не страницы спрайтокода, а страницы с текстурой, их нельзя в 0000 (или уменьшить текстуру)
экран тоже нельзя в 0000
получается, стек надо в 0x100..0x3fff: dec h:jr nz

если стек горизонтальный и без клипирования по вертикали, то:
pop hl
add hl,de ;смещение по Y относительно того, что в стеке
...
[ld a,(hl)]
[and...]
[or...]
ld (hl),a ;/ld (hl),n
add hl,bc
;max 39t, 7b/b

тут достаточно стека на 2*160 байт (ширина экрана), его можно в 0x3b00

наложение спрайта под фон:
надо накладывать только на пустые пиксели
ld a,(hl):and:or:ld (hl),a не получается
можно целыми байтами:

pop hl
add hl,de ;смещение по Y относительно того, что в стеке
...
cp (hl) ;a=0
jr nz,$+4
ld (hl),n
add hl,bc
;32.5t, 6b/b

неудобно через de

при 6..7 b/b нужно под 256 спрайтов (32-байтных) 4 страницы - только под один вид поворота-подкладывания!
спрайт 0xff - низ монетки, его можно не использовать
если 2 страницы экрана включено одновременно, то размещать спрайты надо с шагом 256 и пересчётом номера страницы
если включена только 1 страница экрана, то надо с шагом 128 (неудобно) или с переходом по таблице (пересчёт номера страницы тоже нужен, иначе надо включить сразу 2 страницы спрайтов)

вызов спрайта:

        ld a,(ix) ;y
         sub 8*YSKIPFROMTOP
        cp 200-8
        jp nc,prsprites_skip ;большинство спрайтовых записей пустые, можно даже проверять на ==0xf8
        ld l,a ;y
;CY=1
        ld d,(ix+1) ;tile
        ld a,(ix+2) ;attributes (d7=flip vertically, d6=flip horizontally, d5=behind background, d1..d0=palette)
         rr d
        rra
         srl d ;%01tttttt
        rra
        ld c,a ;%tTVHB??? ;TODO palette (128 pages???)
        ld b,tsprpages/256
        ld a,(bc)        
        SETPG16K        

       if 1==1
        ld h,tlineaddr/256
        ld e,(hl)
        inc h
        ld d,(hl) ;de=y*40
        inc h ;ld h,sprscrstack/256
       else
        ld h,0
        ld b,h;0
        ld c,l
        add hl,hl
        add hl,hl
        add hl,bc ;*5
        add hl,hl
        add hl,hl
        add hl,hl ;*40
        ex de,hl ;de=y*40
        ld h,sprscrstack/256
       endif

        ld l,(ix+3) ;x
        res 0,l
        ld sp,hl ;sp=sprscrstack+2*(x/2)

;de=y*40
         ld bc,40
        ld l,b
        jp (hl)
...
xor a
pop hl
add hl,de ;смещение по Y относительно того, что в стеке
...
cp (hl) ;a=0
jr nz,$+4
ld (hl),n
add hl,bc
...
jp (iy)

можно переворот спрайта сделать выводом снизу вверх: надо по-другому проверить границу, прибавить 40*7, заменить константу 40 на -40

сейчас скорость без процедурных спрайтов на сцене 2.5 Goomba + маленький Марио + 2 трубы:
173156 cls
189924 фон (после ускорения пустых примерно 143700)
65667 спрайты (14 шт, 4 персонажа, т.е. 16416/персонаж) - при этом настройка спрайтов персонажей EnemyGfxHandler заняла 3280 на каждый из 4 персонажей (на каждом фрейме, включая 2(?) пропущенных!), то есть 10000 тактов/персонаж, что сравнимо с отрисовкой! <--- сделал EnemyGfxHandler только на последнем фрейме, но с PlayerGfxHandler проблемы
(после ускорения пустых спрайтов 50190 спрайты (большой Марио + 2 Goomba) = 16 шт)

можно сэкономить 29000 на обновлении верхних 2 строк, если там нет спрайтов и ничего не менялось? TODO найти все места, где меняют строки статуса!