Making of "Shiny"



Страница:http://www.pouet.net/prod.php?which=76026

Три года назад я предпринял попытку ознакомиться с Sinclair QL и, заодно, изучить процессор Motorola 68000. Эта попытка завершилась провалом, поскольку я получил массу противоречивых сведений, мне не удалось запускать нужные программы.
Пересказывать историю создания компьютера не имеет смысла, похожие материалы найдутся в интернетах. Поэтому статья выглядит как простое описание процесса создания программы.

Эмулятор.

На форуме посоветовали Q-Emulator (http://www.terdina.net/ql/winql.html)

внешний вид эмулятора


Однако, эмулятор платный, многие функции блокированы, поэтому использовать его не удастся - запись файлов на носители заблокирована. По опыту платные программы являются убогими и не выполняют тех функций, за которые нужно платить, поэтому эмулятор был удален.Из плюсов - отладчик и эмуляция звука.

Выбор пал на QL2K(http://www.jadiam.org/QL/), достаточно взять версию 0.96а


В одном паблике на Facebook я услышал негативный отзыв, что QL-убогий компьютер без дополнительных ROM, что так и оказалось - без Toolkit2(TK2.ROM) с компьютером делать нечего.
При запуске эмулятор предлагает настройки, с которыми не нужно морочиться, работает с уже готовыми. Единственное, на что нужно обратить внимание - кнопка MDV WIN, которая позволяет задать пути к виртуальным устройствам.

настройки программы


Устройства называются следующим образом: MDV1_ - микродрайв(у оригинала 2, а у эмулятора 5), утилит работы с образом просто не нашлось, WIN1_ - WIN5_ -дискеты.

Софт

Ясно, что лучше всего использовать ассемблер и текстовый редактор. На вечнео падающем сайте(http://www.dilwyn.me.uk) после нескольких проб я нашел Qmac и Qed с описаниями функций. Но перед началом работы нужно подготовить файлы для запуска. Следует заметить, что большая часть программ доступна в странном виде - .ZIP-архив с метаданными в хвосте, которые скачиваюся браузерами по разному. Также эмуляторы не читают тпкие архивы. Поэтому решение было другим:

Использовать встроенную утилиту qlayt(не помешает почитать документацию):
del qlay.lst
del qlay.dir
dir/b > qlay.lst
qlayt -c qlay.lst

Запускаю эмулятор, жму F4, ввожу dir win3_, вижу файлы. Как их запустить? exec win3_qmac - ошибка!
Оказывается, что ось не различает текстовые и бинарные файлы, или эмулятор их криво перенес.
Сработало так:

10 a=ALCHP(34542)
20 LBYTES win3_qmac,a
30 SEXEC win3_qmac,a,34542,4096
40 RECHP a


10 отводится память размером 34542 байта - размер файла Qmac
20 загрузка файла по зарезервированному адресу в переменной А.
30 сохранение бинарного файла из памяти, можно заменить на SEXEC_O, чтобы не задавался вопрос о перезаписи.
40 освобождается зарезервированная память.


Заметно, что при обращении к устройству добавляется WIN3_, я работал с этим носителем(по умолчанию с папкой WIN3_). На будущее удобнее всего сохранить Бейсик программы на диске, чтобы не пришлось набирать текст снова.
Формат строк немного непривычный - Linux-style с концом строки chr($0A). Мой исправленный вариант выглядел так(runk_bas):

100 fnm$='win3_kl_bin'
110 fl=FLEN(\ fnm$)
120 adr=ALCHP(fl)
130 LBYTES fnm$,adr
140 CALL adr
150 RECHP adr

все типы файлов отделяются от имени подчеркиванием - _bin,_bas, .bin и .bas не воспринимались.

Кстати, изучение команд Бейсика тоже не помешвет. Для редактирования строк используется команда EDIT номер
Теперь, когда инструментарий готов, можно приступить к написанию программы. Но для начала я решил испытать простой пример исходного текста, чтобы собирать готовую программу.
Больше всего времени ущло на запуск Qed и на изучение функций.

подготовка к запуску:

10 a=ALCHP(7900)
20 LBYTES win3_QED,a
30 SEXEC win3_QED,a,7900,4096
40 RECHP a

Запуск:  EXEC win3_QED



Редактор запрашивает имя файла, если текстовый файл не найден, то будет создан. Ввожу win3_a_s - мой исходный текст, набираю пример

        filetype 0
       
        section code

     move.l #0,a0
     lea.l  mess,a1
     move.w $d0,a2
     jsr    (a2)
     rts
mess dc.w   12
     dc.b   'Hello World!',10
     end

Теперь нужно сохранить текст  и выйти из редактора:
F3,SA путь к файлу - сохранение
F3,Q - выход

Или другой пример - определение версии QDOS:

        filetype 0
       
        section code

UT_MTEXT equ $d0

         clr.l d0               sms.info
         trap #1                you forgot this!

         lea M9,a1
         move.l d2,(a1)         version

         lea M8,a1
         sub.l a0,a0
         move.w UT_MTEXT,a2
         jsr (a2)
         rts

M8
         dc.w M2-M1
M1       dc.b 'QDOS Version -  '
M9       ds.l 1
M2
*
        end

Заморачиваться с нюансами исходных текстов я не стал, целью было получение рабочих бинарных файлов. Осталась компиляция исходного текста, которая описана в документации.

10 DELETE win3_hl_bin
11 DELETE win3_HL_rel
30 EXEC win3_qmac;'win3_a_asm -BIN win3_hl_rel'
31 VIEW win3_a_list
40 EXEC win3_qlink;'win3_hl_rel'

Единственное, что не удалось - это отключить генерацию листинга.

Запуск готового файла:
100 fnm$='win3_hl_bin'
110 fl=FLEN(\ fnm$)
120 adr=ALCHP(fl)
130 LBYTES fnm$,adr
131 CALL adr

Теперь, когда имеется готовый набор, можно приступить к созданию программы и к изучению ассемблера. Первая книга, что мне попалась - Assembly Language Programming on the Sinclair QL.


 В книге описаны типы алресации и опкоды процессора, вторая часть касается графики. Изложение материала мне показалось несистемным, поэтому пришлось сделать усилия, чтобы прочитать материал.

Достаточно  было принять тот факт, что формат хранения 16бит и 32бит отличается от принятого формата Intel.

Процессор содержит 8 адресных 32-битных регистров A0-A7, которые используются для обращения к памяти. A7 называют стеком, который применен для сохранения регистров.Есть 8 32битных регистра данных D0-D7,
причем инструкция указывает, с каким типом данных(байт, слово, длинное слово) будет выполнена операция.
Важно! запомнить, что к опкодам относится source,destination.
Например, MOVE.L #0,D0 поместит 0 в регистр D0(.L - длинное слово).

Согласно карте памяти, которая есть в книге, экранная память расположена по адресам $20000 и второй экран $28000. Непонятно, разберемся дальше.

Какой видео режим выбрать? 512х256 4 цвета или 256х256 8 цветов? Для задуманного эффекта я выбрал 8 цветов:

Чтение материала еще более запутало, автор рисует некие схемы

И, наверное, отчаявшись объяснить, приводит образец построения точки. Выходит, что адрес определяется как $20000+Y/128+X/4. Это меня совсем запутало, я решил подготовить графику.

Создание логотипа - это отдельная песня. Шрифт уже был выбран:

Но раскраска мне не понравилась:

Камрад AER сделал набросок по моей просьбе:

И я начал рисовать слово Shiny с помошью Graphics Gale стандартной палитрой. После нескольких проб и ошибок лого было получено.На PureBasic код конверсии выглядел так:


*m=AllocateMemory(32*256)
LoadImage(0,"lg5.bmp")
StartDrawing(ImageOutput(0))
For y.l=0 To 31; Step 2
  For x.l=0 To 511 Step 2
    d=(x>>2)&$7E+y*128
    d1=x&6
    co=Point(x/2,y)
    cc=0
    If Blue(co):cc|1:EndIf
    If Red(co):cc|2:EndIf
    If Green(co):cc|4:EndIf
    co=cc
    ;Debug cc
   
    d3.u=co<<6
    d4.u=d3<<7
    d4=d4&$8000
    d3=d3&$C0
    d3=d4|d3
   
    If d1<>0
     For i=1 To d1
       d3=(d3>>1)|($8000*(d1&1))
     Next i
  EndIf
 
  d3=((d3&255)<<8)|(d3>>8)
  PokeW(*m+d,PeekW(*m+d)|d3)
 
  Next x
Next y

StopDrawing()
CreateFile(0,"pic_bin")
WriteData(0,*m,32*256)
CloseFile(0)
FreeMemory(*m)


Хорошо, картинка загружается, остальная часть экрана отведена под эффект. Мне нужна таблица синуса, которую я хочу попробовать с помощью замысловатого алгоритма. Как тут быть? Отладчика я не нашел. Ответ приходит сам: Easy68K(http://www.easy68k.com) - ассемблер и симулятор. Он позволяет рисовать и выводить текст на виртуальных устройствах.

Запускаю EDIT68K, после возни с алгоритмом и чтения документации, жму F9, Execute:


    ORG    $1000
START:                  ; first instruction of program

    move.b    #33,d0                    ; set window size
    move.l    #(1024<<16+768),d1        ; 1024 x 768
    trap    #15

* sin generation

    lea sint,a0
    clr.l d0 ; hl
    clr.l d1 ; de
    clr.l d3 ; counter
    move.w #$08,d2 ; bc
glp:
    move d0,d4
    lsr.w #8,d4
    cmp.b #$40,d4
    bcs bra1
    sub d2,d1
    bra bra2
bra1:
    add d2,d1
bra2:
    add d1,d0
    move d0,d4
    lsr.w #8,d4

    move.b d4,(a0)+
    add #1,d3
    cmp.w #256,d3
    bne glp

*now draw
    move.l  #$0000FFFF,D1   ; Pen color yellow
    move.b  #80,d0          ; set pen color trap task
    trap    #15             ; do task

    lea sint,a0
    clr.l d1
pllp:
    move.b (a0)+,d2
*    asl.b #1,d2
    move.b  #82,D0  ; draw pixel at X = D1, Y = D2
    trap    #15     ; do task   
    add #1,d1
    cmp.w #256,d1
    bne pllp
   
    SIMHALT             ; halt simulator

sint:
* Put variables and constants here

    END    START        ; last line of source



Ого, уже интереснее. Несколько часов ушло на подготовку данных, потом, после поисков ошибок алгоритм заработал. Описывать его нет смысла, любой школьник знает.
Причем эффект на экране работает достаточно шустро, нет побочного эффекта как "сечение с лучом". Надо бы замедлить вывод на экран, или синхронизировать.
Задаю на форуме вопрос о таймере, получаю массу примеров и ссылок на исходные тексты. Не работает.

Открываю QL technical guide(http://www.dilwyn.me.uk/docs/manuals/qltm.pdf) и начинаю читать. Получаеся:

*setup interrupt
         lea hook(pc),a0
         lea routine(pc),a1
         move.l a1,4(a0)
         moveq #$1c,d0
         trap #1 *системный вызов с определенными параметрами

ниже в программе:

*interrupt
hook: ds.l 2

routine:*идея проста - на каждое прерывание tik увеличивается на 1
         move.l a0,-(a7)
         lea tik(pc),a0
         add.b #1,(a0)
         move.l (a7)+,a0
         rts
tik:     dc.b 0

А синхронизация сделана так:
zz:
         lea tik(pc),a0
         move.l #3,d2
wa3:
         move.b (a0),d0 *получить tik
wa:
         move.b (a0),d1
         cmp.b d0,d1 *если tik отличается от предыдущего, то произошло прерывание
         beq wa
         dbra d2,wa3 * повторить три раза


Осталось две задачи - звук и видеорежим. Звук не эмулируется, возвращаюсь к видео.
Из документации находится важная ячейка:
mc_stat  equ      $18063
*b1 screen off
*b3 lores(1),hires(0)
*b6 (0)PAL, (1)NTSC
*b7 (0)VRAM from $20000,(1) $28000

*setup video
         move.b mc_stat,d0
         and.b #%01110111,d0
         or.b  #%00001000,d0
         move.b d0,mc_stat

Ага, теперь ясно, что можно использовать два экрана по разным адресам. Но мне трюк с буфферами не понадобился, я использовал память $28000 для данных.


Я смотрю на экран и испытываю чувство усталости от проделанных шагов и сделанных открытий и чувство удовлетвориния от того, что поставленная цель выполнена.
Каждый может описать свои чувства, когда первая написанная программа заработала - "Я всемогущ!".

У меня есть готовые наработки, я теперь могу вернуться к творчеству - написать несколько программ. К тому, же шаг к знакомству с MC68000 сделан, что позволит изучать другие, незнакомые компьютеры, делать открытия и некие важные для себя победы - не это ли радость?