Жизнь как зебра

И я думаю, что продолжение афоризма легко прочитать. А пока я расскажу о создании 1К. Идея возникла совершенно случайно, когда я готовил работу Stripes к Di:Halt 2015 года. Кроме готовой работы остался один исходник с необычным эффектом, возможно, что в алгоритм вкралась ошибка. Вот эту ошибку я решил развить в тот момент, когда увидел, что работ категории 1К не было.

Хорошо, у меня был простой музончик, который когда-то написал splin7er(спасибо, Роман!) и я решил пойти ва-банк и втиснуть музыку. Что? Большой размер мелодии и код проигрывателя? Не страшно, у меня есть выигрыватель!

Довольно петросянства, взглянем на код:


    

    device zxspectrum128
        ORG #6000
runi:
 ld hl,$8000
 ld de,$00FF
 ld bc,$00FF;FF00
tt2:
 push hl
tt1:
 ld (hl),d:inc l
 ld (hl),e:inc l
 bit 4,l
 jr z,tt1
 ex de,hl
 add hl,hl
 jr nc,no_rot
 set 0,l
no_rot:
 ex de,hl
tt3:
 ld (hl),c:inc l
 ld (hl),b:inc l
 bit 5,l
 jr z,tt3
 or a
 rr b
 rr c
 jr nc,no_7b
 set 7,b
no_7b:
 pop hl
 inc h:jr nz,tt2

Этот замысловатый код генерирует спрайт из полос, причем полоски отображаются зеркальными

       ld hl,$800F
 ld bc,$0201
rrlp2:
 push hl,bc
rrlp1:
 ld a,(hl):or c:ld (hl),a;добавить
 rrc c
 jr nc,noinchl1
 inc hl
noinchl1:
 djnz rrlp1
 pop bc,hl
 inc h
 rlc c
 jr nc,noinchl2
 dec hl
noinchl2:
 inc b,b
 jr nz,rrlp2
А вторая часть заполняет полосы, таким образом вышло от что:


Теперь нужно подготовить табличку синуса, похожую процедуру я нашел у Baze, спросите у introspec'a, он внятно объяснит, как это работает:
      ;-----------------------sine precalc
        ld    hl, unk_63A6
        ld    de, #7c00
        ld    c, e
        ld    xl, 10h
loc_600F:
        ld    b, 4
loc_6011:
        xor    a
        rl    (hl)
        rla
        rl    (hl)
        rla
        add    a, c
        ld    c, a
        ld    (de), a
        inc    e
        djnz    loc_6011
        inc    hl
        dec    xl
        jr    nz, loc_600F
        ld    h, d
        ld    l, e
loc_6027:
        ld    (de), a
        inc    e
        dec    l
        ld    a, (hl)
        jr    nz, loc_6027
loc_602D:
        ld    a, (hl)
;        neg
        ld    (de), a
        inc    de
        inc    l
        jr    nz, loc_602D
;----------------------------
Наверное. одним решением будет использование калькулятора для вычисления синуса, но я противник долгих ожиданий depacking/decrunching..

Последний шаг перед запуском интро, это формирование просто процедурки 32 раза ldi подряд
       ld hl,unk_63A6
 ld b,32
frmlp:
 ld (hl),$ED:inc hl
 ld (hl),$A0:inc hl
 djnz frmlp
 ld (hl),$C9:inc hl
; jr $
;----------------------------
Теперь инициализация прерывания для воспроизведения музончика и работа интро.
А работает оно так: таблица синусов расположена с $7C00, для каждой линии получается значения sin(d)+sin(e). Это значение обрезается до диапазона 0..127, к нему добавляется 128 и так получается адрес линии спрайта. Такой вот вышел размах - спрайт занимает 32 килобайта.

       di
 ld a,$5B,i,a
 im 2
 ld hl,INTVEC,($5BFF),hl

doi:ei:halt
 ld hl,#4020
rv: ld de,0000
 inc e,e
 dec d,d,d
 ld (rv+1),de
  ld ixl,$B0
drlp:
push hl
 ld h,$7C
 ld l,e
 ld a,(hl)
 ld l,d
 add a,(hl)
pop hl
 push de
 push hl
 sra a
 or $80
ld d,a,e,0
 ex de,hl

  call unk_63A6

 pop hl
 pop de

 INC h:LD A,h
 AND 7:jr nz,$+12
 LD A,L:ADD A,#20:LD L,A:jr c,$+6
 LD A,H:SUB 8:LD H,A

 inc e,e,e
 dec d,d
 dec ixl
 jp nz,drlp
 jp doi
;----------------------------
INTVEC
   PUSH AF,BC,DE,HL
        call play
        POP HL,DE,BC,AF
        EI:RETI
Это таблица для генерации синуса
      unk_63A6:
        db    026h
        db    066h
        db    066h
        db    066h
        db    065h
        db    096h
        db    059h
        db    055h
        db    095h
        db    055h
        db    015h
        db    045h
        db    011h
        db    010h
        db    041h
        db    0
end
    display /d,runi
    display /d,end-begin
    savesna "!void.sna",runi
    savebin "z0rb.bin",begin,end-begin
А где музон спросите вы, если не уснули после чтения исходника? А музон где-то там, наверное легко догадаться об этой таинственной технологии.

Максимум, на что я пошел - это добавил вывод текста в Бейсике. Впрочем, без него вышло и неплохо, гораздо смешнее выглядел бы вывод афоризма по фразам. Но такой замысел изменил бы размер до 2К, наверное.

     И Уг-Глук воскликнул:
     - О!
     И Клош-Кван сказал:
     - А!
     И каждый сказал по-своему, и все поняли.
        Джек Лондон, "Сказание о Кише"


нет, не "О! А!". Остался еще один эпизод: воспроизведение музыки. Чтобы утереть нос крикунам "Код без музыки! Трата времени!", я добавлю воспроизведение музыки.
трек 482 байта, на плейер уйдет примерно 2 килобайта... грр, засада! Я сконвертировал .pt3 в формат .psg, получилось 1452 байт плюс мизерная процедурка воспроизведения.
Разобрать формат .psg несложно:
10 байт - заголовок
значение $FF - маркер прерывания, вслед за ним указывается номер регистра и значение, которое должно записано, заканчивается такая последовательность байтом $FF или $FE.
вслед за байтом $FE идет значение, умножаю его на 4 это даст паузу.
Признак концовки трека - это байт $FD.

Поэтому в код добавлено:
song:incbin "tune.psg"
 db $FD

и сама процедурка:
;---------------play PSG dump-----------
play:
psgplay:ld a,1:or a:jr z,psga
 dec a:ld (psgplay+1),a:ret
psga: ld hl,song;+16

dumpreg:
     ld e,(hl):inc hl
     ld a,e
     cp #FF:jr z,stoplay
     cp #FE:jr nz,nogetwait
    ld e,(hl):inc hl;(hl)*4
 ld a,e
 add a,a
 add a,a
 ld (psgplay+1),a:jr stoplay

nogetwait:
    cp #FD:jr z,stoplay2
    ld bc,0xfffd
    out (c),e
    ld e,(hl):inc hl
    ld b,0xbf
    out (c),e
    jr dumpreg
stoplay2:
  ld hl,song;+16
stoplay:
 ld (psga+1),hl
 ret
+16 из процедуры(смещение в .psg) я убрал, обрезал 16 байт заголовка для того, чтобу втиснуть код при упаковке  zx7. Нет, пакер не выход, конечно, но расчет на сжатие был имеенно таким. Было бы здорово, если нашелся умелец и написал простейший 1K tracker, но об этом приходится мечтать.

Все, код собирается, пакуется, собирается .scl/.tap, работа отправляется, джип наш! Нет, целью было не набрать диплом а поддержка пати, как принято говорить.
Тут и сказочке конец, а кто понял - молодец!