Цвета можно и без слоев уменьшить, хотя и не очень удобно. Один поток - двухбитный (4 точки в байте), второй - однобитный (8 точек в байте).
Цвета можно и без слоев уменьшить, хотя и не очень удобно. Один поток - двухбитный (4 точки в байте), второй - однобитный (8 точек в байте).
Что нужно спрямить в dzx0? Ты писал про поточный, но я не совсем понял, ты же уже сделал поточный и я там какие-то мелочи дошлифовывал.
Сейчас dzx0 -- это от начала до конца один цикл. Если я хочу что-то делать с данными по частям, то есть пока этот цикл не завершился, мне приходится встревать в него разными зверскими способами.
Было бы удобно, если бы дополнительно существовал вариант dzx0, который устроен так, что можно вызывать из основной программы типа "call dzx0_stream_getbyte" когда надо. А он бы внутри себя декодировал очередную порцию по мере надобности. В картинках у меня сейчас именно так и сделано, но методом выворачивания цикла наизнанку. Почти так же, как в гигачаде, но попроще, потому что один поток. У этого есть недостатки -- плохая читаемость, необходимость запрещать прерывания пока стеки подменяются, оверхед на все это тоже может быть больше, чем если бы был прямой вызов.
Предполагаемый API такой:
dzx0_stream_init: -- инициализация: d=адрес откуда читаем, b=адрес буфера
dzx0_stream_getbyte: -- очередной байт (допустим Carry=1, если конец потока)
dzx0_stream_getbyte внутри себя вызывает dzx0_decode_chunk, когда исчерпываются данные в буфере
Все это разумеется применимо только к варианту с ограниченным размером буфера. 256 показал себя хорошо.
Больше игр нет
de, bc (хотя bc будет выровнен по 256)
Алгоритм внутри себя будет декодировать порциями в любом случае. Можно сделать фиксированный размер порции 256 байт. getbyte в обычном случае будет просто брать очередной байт из циклического буфера, если данные уже декодированы, и обращаться к алгоритму за очередной порцией когда буфер истощен.
Для смелых пользователей, кому важна эффективность и не хочется вызывать getbyte для каждого байта, останется возможность вызывать dzx0_decode_chunk напрямую.
256 байт хороший размер с точки зрения эффективности. Но чтобы не блокировать исполнение юзерского когда слишком на долго, хорошо иметь возможность рулить размером порции. Можно условной компиляцией 16/256, например. Или вообще по размеру порции в LDIR-е, правда это усложнит getbyte.
Больше игр нет
Пока для пробы сделал распаковщик чанками по 256 байт. GetByte можно сделать внешним, как с файловыми буферами: берем байт из буфера, если буфер пуст - распаковываем следующий чанк.
Пример почанковой распаковки всего файла
Код:lxi b,dzx0_Buffer ;DE - откуда ;HL - куда ;BC - буфер MovLoop2: push h call dzx0 pop h jnc LastMov MovLoop1: ldax b mov m,a inr c inx h jnz MovLoop1 jmp MovLoop2 LastMov: inr c dcr c jz Start mov e,c mvi c,0 LastMov1: ldax b mov m,a inr c inx h dcr e jnz LastMov1 jz Start[свернуть]
Забыл в файле написать - на выходе из dzx0
CY=0 - закончили распаковку
CY=1 - еще не закончили
- - - Добавлено - - -
Отмечу, что учитывая самомодификацию распаковщик однопоточный.
- - - Добавлено - - -
Один чанк распаковывается в среднем за 35000-45000 тактов. Крайние значения, которые видел - от 20000 до 50000 тактов.
Upd 18.09.2022: Примерно на 3% быстрее, сохраняет BC между распаковкой чанков (если убрать сохранение BC, то будет на 7 байт короче).
Последний раз редактировалось ivagor; 18.09.2022 в 07:34.
svofski(14.09.2022)
ivagor, спасибо! Попробовал, работает. Для моего случая годно. По-моему backwards тут не имеет смысла, под себя заменил макросы, потому что prettyasm в них не умеет. Ко всем меткам приставил stream_, чтобы не было конфликтов. А зачем нужна часть, которая подменяет точку входа, почему не просто отдельно инициализация и отдельно распаковка?
Больше игр нет
Ну что, на этом можно и успокоиться, правда 144 байта еще осталось http://sensi.org/~svo/b/mandrill/progdemo.rom
Больше игр нет
Ты опять сумел удивить, три картинки (пусть и не полноэкранных)! И музычка хорошо подобрана.
Личное предпочтение, чтобы упростить вызов. Понятно, что это можно вынести наружу, возможно для гитхаба я так и сделаю, надо еще подумать.
Насчет размера чанков. Степени двойки (2-128) можно получить добавив по паре команд перед jnz dzx0_ldir1_3 и jnz dzx0_ldir2_3
mvi a,Mask
ana c
Mask=(16-1) для 16 и т.д.
- - - Добавлено - - -
Ну и для простоты лучше сжимать файлы с размером кратным чанку, тогда хвосты не надо отдельно обрабатывать.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)