[Из песочницы] Эмуляция Sinclair zx80/zx81
Многие согласятся, что возникшая пандемия COVID-19 изрядно попортила жизнь IT-сообществу. Но речь пойдет не о темной полосе, а о другом эпизоде.
Уже в марте была отменена известная demoparty Forever 2020, а позже мероприятие перенесено на осень. Задолго до отмены, я общался с организаторами. Они отказались принять одну мою работу, мотивируя тем, что нет Apple II, попросили взамен видео работы с реального компьютера.
Что же, получить запись мне не удалось, поэтому я обратил внимание на список платформ:
Amstrad CPC, Thomson, PMD-85, MSX, ZX81, Sam Coupe, all non-C=64 8-bit Commodores or any other 8-bit system
Меня привлек ZX81, так как я уже пытался изучить компьютер, но потерпел крах.
Исследования пошли по привычной для меня схеме:
Эмулятор
Я выбрал EightyOne
взял версию 1.6.1. У версии удобный отладчик, но программа не эмулирует другую модель — ZX80, позже я нашел другой билд 3.7.
Кросс-средства
Поиск вывел на FASM (топик на форуме, адаптированный для платформы. Однако, скомпилированные примеры не запускались. Я попробовал и другие варианты ассемблера — Pasmo и другие, но так и не собрал рабочую программу.
Долгие поиски вывели на пример печати Hello, world!
О, чудо! получилось! Теперь пришел черед к третьему эпизоду.
Документация
Часть информации нашлась тут
Дизассемблер ПЗУ здесь
Карта памяти:
0000-1FFF - ROM
2000-3FFF - Shadow ROM. Назначение не описано, иногда упоминается Interface 1
4000-7FFF - память 16К
Часть памяти отведена для системных переменных.
Далее по адресу 16509 хранится программа на Бейсике и её переменные.
Программа на Бейсике содержит формат:
2 байта номер строки в формате big endian
2 байта длина строки
... сама программа
1 байт ($76) - новая строка
Для кассеты возможны только программы на Бейсике, был предложен такой способ:
1 REM (бинарные данные или машинный код)
2 RANDOMIZE USR(16514) - тот самый адрес программы, хранящейся после REM
Следует обратить внимание на системную переменную D_FILE, которая указывает на видеопамять.
В указанном примере это реализовано так:
D_FILE: defw display_file
display_file: defb _NL
defs 32
...
defs 32
defb _NL
Первый байт — признак начала строки, затем 32 байта пробелы.
Так получилось 24 строки, что выглядело громоздко.
Первая программа, которую я написал:
;compile with sjasmplus
device zxspectrum128
p_start: org 0x4009
begin
VERSN: defb 0
E_PPC: defw 20 ; BASIC line number of line with cursor.
D_FILE: defw display_file2
DF_CC: defw display_file2+1
VARS: defw variables
DEST: defw 0
E_LINE: defw edit_line
CH_ADD: defw p_end-1
X_PTR: defw 0
STKBOT: defw p_end
STKEND: defw p_end
BERG: defb 0
MEM: defw MEMBOT
SPARE1: defb 0
DF_SZ: defb 2 ; Number of lines in lower part of screen.
S_TOP: defw 10 ; BASIC line number of line at top of screen.
LAST_K: defw 0xffff
DB_ST: defb 0
MARGIN: defb 55 ; Blank lines above/below TV picture: US = 31, UK = 55.
NXTLIN: defw display_file ; Memory address of next program line to be executed.
OLDPPC: defw 0
FLAGX: defb 0
STRLEN: defw 0
T_ADDR: defw 0x0c8d
SEED: defw 0
FRAMES: defw 0 ; Updated once for every TV frame displayed.
COORDS: defw 0
PR_CC: defb 0xbc
S_POSN: defb 0x21,0x18
CDFLAG: defb 0x40
PRBUF: defs 0x20
defb _NL
MEMBOT: defs 0x1e
SPARE2: defw 0
; Start of the BASIC area for user programs.
basic_0001: defb 0,1 ; 1 REM
defw basic_0010-basic_0001-4
defb _REM
; Start of user machine code program
mem_16514:
ld hl,p_end;display_file2
push hl
;cls
ld c,25
c1:
ld b,32
ld (hl),$76:inc hl
c2:
ld (hl),0:inc hl
djnz c2
dec c
jr nz,c1
pop hl
push hl
ld c,$0
ylp:
ld (hl),$76
inc hl
ld b,32
xlp:
ld (hl),c
inc hl
inc c
bit 6,c
jr nz,endp;ret nz
djnz xlp
jr ylp
endp:
pop hl
ld (D_FILE),hl
jr $
display_file2:
dup 25
defb _NL
edup
end
display /d,end-begin
savebin "prb.p",begin,end-begin
Укороченный вариант подсказал этот топик.
Один недостаток: после загрузки программа не отображается нижняя строка. Это неудивительно, ведь строки пустые.Чтение руководств подсказало на еще одно изменение:
NXTLIN: defw basic_0010 ; адрес памяти выполняемой строки
Получился такой простой трюк: после загрузки не нужно набирать RUN, программа запустится сама.
Если коротко, то я опишу суть программы: сначала заполнение видеопамяти по образцу, как было в программе печати «Hello, world», затем заполнение строк символами с кодами 00–63.
При первой разработке я ошибся и написал заполнение символов с кодами 00–255, но программа не заработала, так как часть кодов не используется
Результатом исследований стала работа kerr, которая покажется неинтересной, но для меня сама программа — большое достижение.
А до проведения demoparty есть масса времени, которое будет потрачено на разработку программу в номинацию 1k.
Остался ZX80.
Для него есть другой порядок системных переменных.
Софт хранится здесь.
Поэтому я набрал программу и посмотрел в отладчике:
Здесь есть небольшое ограничение — память 1к, поэтому нужно подумать, какую программу написать.
Может быть, я напишу когда-нибудь.