Предлагаемый Вашему вниманию проигрыватель позволяет воспроизводить звуковой видеоряд непосредственно с ROM-Диска по схеме Апогея с поддержкой до 256 страниц.
формат видео
Ромдиск Апогея по схеме vinxru делится на страницы по 32 килобайт каждая - в одну такую страницу влезает 10 кадров 64x50 (3200) один за другим, со двигом к концу, чтобы освободить первые 768 байт страницы под плеер (0x0000...0x027F) и 2 спец.строки - статус (0x0280...0x02BF) и титул (0x02C0...0x02FF). Строки располагаются последовательно друг за другом, но каждая строка записана задом-наперёд т.к. копирование в экранную область происходит через указатель стека с помощью команды PUSH. Каждый четвёртый символ своим старшим битом задаёт значение сэмпла звука, который будет послан в магнитофонный выход. В пределах кадра получается 800 сэмплов звука или 8000 сэмплов на страницу плюс ещё 32 сэмпла записаны в строках титула и статуса - т.е. всего 8032 в странице или в среднем 803.2 сэмпла на кадр. Текущая версия плеера выдаёт порядка 7.5 FPS видео (и 6 кГц 1-битного звука), что позволяет записать в 8 мегабайтный ромдиск до 341 секунды (5 мин 41 сек).
Пример воспроизведения видео со звуком через эмулятор Emu80 v.4:
ВИДЕО BAD APPLE УБРАНО 3 ИЮЛЯ 2024 ГОДА ПО ТРЕБОВАНИЮ YOUTUBE - ВОТ ВАМ ВМЕСТО НЕГО A-HA:
Давайте сделаем нормальный видеоряд в 5-пиксельных символах
Это можно. Завтра займусь!
Shaos wrote:
Я могу нагенерить новый ромдиск, но надо плеер поправить, чтобы в режиме 78x61 символами 5 точек в высоту рисовал
А кадр - 64x50? Производительность не потянет. (Первый вариант позавчерашний типа так и работал. Но ПДП сильно тормозил всё и пришлось вообще режим не трогать.)
Shaos wrote:
И у тебя звук как закодирован? Сэмпл на строчку?
Версия выше - считывает самый первый символ строки и первые два бита использует под ШИМ на всю строку.
Сейчас подправил код:
Чётные символы проходят как есть - старшим битом можно атрибуты цвета ставить (в плеере режим видимых атрибутов)
Нечётные символы маскируют старший бит, используя его под звук - DI/EI (уже без ШИМ)
Вот архив, где звук как бы есть. Вернее, намёк на звук: Ускорив Emu80 клавишей End можно что-то типа звука услышать. (Производительность уже заметно упала.)
You do not have the required permissions to view the files attached to this post.
06 Apr 2024 14:51
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23200 Location: Silicon Valley
Я могу нагенерить новый ромдиск, но надо плеер поправить, чтобы в режиме 78x61 символами 5 точек в высоту рисовал
А кадр - 64x50? Производительность не потянет.
Да - картинка 64x50 получается, а у тебя реально было прямо 50 FPS? Можно попробовать закодировать RLE - там теоретически должно быть быстрее повторяющиеся поля заполнять, чем вычитывать попиксельно с квазидиска (как минимум ненадо инкрементировать и устанавливать адрес на каждый байт)
Да - картинка 64x50 получается, а у тебя реально было прямо 50 FPS?
Нет, конечно! Если файл проигрывается почти 4 минуты - 240 секунд, то 6,892,800 байтов ROM-Диска делим и получаем примерно 28,720 байтов в секунду. Один кадр 64x25 - 1600 байтов. Соответственно, получаем 17.95 fps.
Так как половина знакомест кодирует ещё и звук, получаем 800 сэмплов на кадр. Соответственно - 14,360 Гц должно быть.
DB 031H PUSH B PCHL LXI SP,00000H LXI SP,00600H LXI H,V78X30 CALL VIDEO LXI H,PWM@0 LXI D,AMP@0 MVI B,001H ;;;;;;;;;;;;;;;;; LOOP: MVI C,020H MOV A,M INX H STAX D INX D LOOP@1: PUSH H LOOP@2: MOV A,M INX H ORA A JNZ LOOP@5 MVI A,0DAH STAX D INX D MOV A,E ADI 004H STAX D INX D MOV A,D ACI 000H STAX D INX D JMP LOOP@2 LOOP@5: STAX D CPI 0C3H JZ LOOP@3 INX D JMP LOOP@2 LOOP@3: DCR C JZ LOOP@4 POP H JMP LOOP@1 LOOP@4: POP PSW INX D MOV A,M INX H STAX D INX D MOV A,M INX H STAX D INX D DCR B JNZ LOOP XCHG SHLD KILL+1 MVI M,0C3H INX H MVI M,000H INX H MVI M,0F8H
MVI A,090H STA 0A003H LXI H,00000H SHLD 0A001H MVI A,001H STA TEMPA LXI H,00000H SHLD 0A001H LXI H,0A002H MVI M,080H MVI M,000H MOVIE: PARTS: LXI SP,036CFH CALL PUTROM LXI B,0A000H LXI SP,03802H MVI A,019H FRAME: STA TEMPY LXI D,0A001H LXI H,AMP@0 LDAX B INR A JZ KILL ;;;;;;;;;;;;;;;;; SHOW: PCHL KILL: LXI SP,00600H LXI H,00001H MOV B,H MOV C,H PCHL ;;;;;;;;;;;;;;;;; L0: JNZ L1 LDA TEMPA MOV M,A INX H INR M JP L2 INR A STA TEMPA JZ KILL MVI M,000H L2: DCX H MVI M,000H L1: LXI H,0008EH DAD SP SPHL LDA TEMPY DCR A JNZ FRAME PAUSE: LDA 0C001H ANI 020H JZ PAUSE JMP PARTS
PUTROM: LXI B,03774H LHLD 0A001H LDA TEMPA CALL PUTHEX MOV A,H CALL PUTHEX MOV A,L PUTHEX: CALL PUTNBL PUTNBL: RRC RRC RRC RRC PUSH PSW ANI 00FH CPI 00AH SBI 02FH DAA STAX B INX B POP PSW RET
VIDEO: MOV A,M ; Читаем байт с ссылкой на порт УВВ. ANI 0F0H ; Маскируем старшие биты адреса. JP DVWAIT ; Если не указатель на УВВ, переходим к финалу. MOV D,A ; Иначе, сохраняем их в регистре D и MOV E,M ; вновь читаем байт с ссылкой на порт УВВ в регистр E. INX H ; Переходим к байту с параметром MOV A,M ; и читаем его. STAX D ; Записываем этот параметр в порт УВВ. INX H ; Переходим к следующему байту с ссылкой на УВВ JMP VIDEO ; и продолжаем копирование параметров устройств. DVWAIT: LDAX D ; Первое чтение сбрасывает все флаги. LDAX D ; Теперь читаем активный статус, ANA M ; маскируя лишние флаги. JZ DVWAIT+1; Если бит всё ещё не установлен, продолжаем ждать. INX H ; Переходим к финальным параметрам. MOV A,M ; Читаем байт с ссылкой на порт УВВ. ANI 0F0H ; Маскируем старшие биты адреса. MOV D,A ; Сохраняем в регистре D и MOV E,M ; читаем младшие биты адреса. INX H ; Переходим к параметру запуска ПДП. MOV A,M ; Читаем байт с командой запуска STAX D ; и передаём в УВВ. RET
V78X30: DB 0E8H,080H,0E4H,0D0H,0E4H,036H,0E5H,023H,0E5H,049H DB 0C1H,000H,0C0H,04DH,0C0H,01DH,0C0H,099H,0C0H,0D3H DB 0C1H,027H,020H,0E8H,0A4H
PWM@0: XCHG LDAX B ; 7 RAL ; 4 NOP ; 10 EI ; 4 DB 0FEH ; 7 DI ; 4 ORA A ; 4 RAR ; 4 MOV D,A ; 5 INR M ; 10 LDAX B ; 7 MOV E,A ; 5 INR M ; 10 PUSH D ; 11=82 : 9x32=288 JMP L0 ; 10 ;;;;;;;;;;;;;;;;;
AMP@0: DS 292
Как видите, сделать по 50 строк в кадре - правка трёх строчек.
Shaos wrote:
Можно попробовать закодировать RLE - там теоретически должно быть быстрее повторяющиеся поля заполнять, чем вычитывать попиксельно с квазидиска (как минимум ненадо инкрементировать и устанавливать адрес на каждый байт)
Не-е, это пусть другие этим занимаются. Я как-то, на базе .PIC-формата писал декомпрессор и на его базе разрабатывал оптимальный алгоритм, но компрессор - так и не написал.
Относительно формата сжатия для РК - могу предложить следующее: Так как коды "Стоп ПДП" (F0/F1/F2/F3) не должны попадаться в потоке, можно все коды C0-FF отдать под компрессию. То есть, закодировать до 64 команд PUSH махом. Что, однако, много, так как на всю строку в 64 знакоместа - 32 PUSH'а достаточно! Следовательно, можно использовать ШИМ: До 16 PUSH'ей и 4 уровня звука.
Правда, есть нюанс: Мой код сейчас переключает страницу только в конце каждой строки, если адрес достиг 8000. Соответственно, нельзя допускать переполнения!
В конечном итоге, всё взваливается на код генерации ROM-содержимого. (Сейчас у меня - это простой HTML/JS с тэгом video.)
Last edited by Alikberov on 07 Apr 2024 02:58, edited 2 times in total.
07 Apr 2024 02:32
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23200 Location: Silicon Valley
У меня по звуку такие мысли были - по идее не нужно каждый 1-битный отсчёт звука записывать т.к. очень часто оно будет несколько раз 1 или несколько раз 0, поэтому по идее надо иметь команды включения 1 и включения 0, которые будут перемежаться с потоком символов для показа на экране - можно конечно внедрять бит звука в каждый второй символ как старший бит, но можно воспользоваться тем свойством, что для представления большинства пар яркостей полупикселов могут быть использованы более чем одного символа:
Code:
00: 0x20 --> #20 03: 0x04 --> #04 05: ! --> #21 06: ' --> #27 0C: 0x02 --> #02 0F: 0x06 --> #06 13: / --> #2F 14: ) > --> #3E 15: 1 J --> #4A 16: I ] --> #5D 22: , : \ --> #5C 23: - ^ --> #5E 26: + ? --> #3F 27: T Т З --> #7A 28: 3 Э --> #7C 30: 0x10 --> #10 32: ( < --> #3C 33: 0x14 " --> #22 35: Y --> #59 36: 2 7 --> #37 37: * --> #2A 3C: 0x12 --> #12 3F: 0x16 --> #16 44: ; --> #3B 45: X Х У --> #75 46: & = S Д --> #64 47: Z Л --> #6C 48: 4 9 --> #39 4A: Я --> #71 50: L --> #4C 52: [ --> #5B 53: % C С --> #73 55: G U V Ц --> #63 56: 6 O О --> #6F 57: $ 5 8 A Q W А Ч --> #7E 59: Ж Ш --> #7B 5A: @ Щ --> #7D 63: Ь --> #78 64: K Г К --> #6B 66: D Ы --> #79 67: H N И Н П --> #70 68: 0 M Й М --> #6D 69: Ю --> #60 6B: Ф --> #66 75: E F Е --> #65 76: P Б Р --> #72 77: B R В --> #77 79: # --> #23 C0: 0x01 --> #01 C3: 0x05 --> #05 CC: 0x03 --> #03 CF: 0x07 --> #07 F0: 0x11 --> #11 F3: 0x15 --> #15 FC: 0x13 --> #13 FF: 0x17 --> #17
Соответственно можно для одних и тех же пар выбрать символы, которые будут устанавливать INTE, сбрасывать INTE или ничего не делать с INTE (можно наверное и со старшим битом это перемежать, не трогая символы 80h...9Fh, которые могут задавать цвет и инверсию)...
За плеер 64x50 - спасибо! Попробую завтра сгенерить видосик...
P.S. Чтобы было ближе к 50 Гц надо 61 строку делать, а сейчас в плеере 60 и похоже бит 1-пиксельного сдвига присутствует - у меня подразумевается, что сдвига нет:
Code:
lxi h, 0C000h ; для Апогея 0EF00h mvi m, 04Dh ; 78 символов mvi m, 60 ; 61 строка (50 Гц) mvi m, 4 ; Высота символа 5 mvi m, 03h ... lxi h,0E008h ; VT_57+8 mvi m,80h mvi l,4 ; VT_57+4 mvi m,00h mvi m,40h inr l ; адрес VT_57+5 mvi m,95h ; число байтов минус 1 mvi m,52h ; режим mvi l,8 ; VT_57+8 mvi m,0A4h
Если файл проигрывается почти 4 минуты - 240 секунд, то 6,892,800 байтов ROM-Диска делим и получаем примерно 28,720 байтов в секунду. Один кадр 64x25 - 1600 байтов. Соответственно, получаем 17.95 fps.
Так как половина знакомест кодирует ещё и звук, получаем 800 сэмплов на кадр. Соответственно - 14,360 Гц должно быть.
"Исходный код проигрывателя"...
Кстати, "исходный код проигрывателя" отличается от того, что я вижу в трёх бинарных VHS*RKR, что были приаттачены выше (первый был со шимом на строку, а второй и третий с битом звука в каждом втором символе) - что считать наиспоследнейшей версией?
Также BadApple, что есть у меня (mp4 и mp3) имеет длину 3 мин 39 сек (219 секунд) - это 6572 кадра при 30 FPS, что в нашем случае придётся прореживать (кстати можно интерполировать смешивая)
Вот, более-менее ускорил алгоритм сокращением циклов ПДП, вставив коды F1 в строки: Длина буфера стала 3720 байтов (по 74 байта на 50 строк и 20 байтов на верхний бордюр). Лично у меня звук пока никак не получается закодировать.
В файле ROM-образа первые 3200 байта должны быть пустыми, так как в перспективе там нужно разместить сам код плеера для директивы «R,13F».
Нюансы:
Так как производится заполнение экрана через стек - справа налево, следует отразить исходное изображение
Все байты, кратные восьми, в своём старшем бите могут нести информацию о звуке (DI/EI), замаскируется при записи в экран
Тем самым, алгоритмом звук вставляется при «address % 8 == 0» через старший бит «data |= 128». Так, при 50 строках и 64 символах, из которых каждый восьмой - звуковой, в строке имеем восемь флагов звука - 400 на 50 строк кадра. Соответственно, при 10 fps получим примерно 4 кГц.
07 Apr 2024 13:32
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23200 Location: Silicon Valley
Вот, более-менее ускорил алгоритм сокращением циклов ПДП, вставив коды F1 в строки: Длина буфера стала 3720 байтов (по 74 байта на 50 строк и 20 байтов на верхний бордюр).
Но сам кадр внутри ROM-файла 3200 байта? У меня конвертер выдаёт полноэкран 78x61 - т.е. я из него выкусываю полезное содержимое 64x50 и толкаю в образ диска один за другим (переворачивая строчки)? Кстати наверное 4 кГц для звука маловато - надо хотя бы 8 (т.е. каждыё четвёртый символ)...
Users browsing this forum: Claude AI [Bot] and 1 guest
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum