Исследование интро Motion(Atari 65XE)

Эта работа(http://a8.fandal.cz/detail.php?files_id=4900) попалась мне на
глаза совершенно случайно. Поскольку в демо используется походая техника, я
решил посмотреть внутрь.
Какой инструмент понадобится? С одной стороны
Dis6502(http://www.atarimax.com/dis6502/) удобнее, потому что в нем включена
поддержка символьных мнемоник и можно помечать часть фрагментов в слова или
в байты, тогда нечитаемая каша превратится в осмысленный код. С другой
стороны, самомодифицирущийся код в дизассемблере останется непонятным. Тогда
IDA вам в помощь.

Хорошо, скормил программу дизассемблеру, и после нескольких просмотров
получилось вот что(комментарии мои)
*= $B000
;
LB000 ldx #$1B
lda #$02
LB004 sta LB0EF,X
dex
bpl LB004
немного неясный участок, разберемся попозже lda #$EC
sta LB10C
sta SDLSTL
lda #$B0
sta LB10D
sta SDLSTH
lda #$80
sta CHBAS
lsr A
sta GPRIOR
lda #$41
sta LB10B
Часть становится яснее, например в CHBAS вносится значение $80.Загляну в руководство Mapping the Atari: CHBAS(756) это адрес данных знакогенератора, умноженный на 256, получается данные шрифта хранятся в $8000. в GPRIOR заносится значение $40(LSR A - деление на 2) получается GRAPHICS 9 (GTIA mode)
Осталось разобраться с непонятным кодом. SDLSTL/SDLSTH(560 и 561) это адрес инструкции Display List.
Запущу интро в Atari800Plus, жму F8 и ввожу следующее:
TIP: Type '?' for help, 'CONT' to exit
312 0 B0A7 INC $B098 (003B) A=0f S=fb X=1c Y=0c P=--*B---C
> m 230
0230 : EC B0 03 00 00 00 92 C0 6E C9 00 00 00 00 00 00 ........n.......
0240 : 00 00 00 07 00 00 01 00 00 00 00 00 00 00 00 00 ................
0250 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0260 : 00 00 00 00 00 00 00 00 00 00 00 CC 00 00 00 40 ...............@
0270 : E4 E4 E4 E4 E4 E4 E4 E4 0F 0F 0F 0F 01 01 01 01 ................
0280 : 01 01 01 01 01 01 01 01 00 00 00 00 00 00 00 00 ................
0290 : 00 02 00 00 60 BF 00 00 00 00 00 00 00 00 01 00 ................
02A0 : FF 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
02B0 : 01 01 FF FF FF FF 00 00 00 00 00 00 00 00 40 18 ..............@.
02C0 : 00 00 00 00 28 CA 94 46 00 00 00 00 00 00 00 00 ....(..F........
02D0 : 00 00 00 00 00 80 00 00 00 28 05 00 00 00 00 00 .........(......
02E0 : 00 B0 00 D7 C0 1F BC 00 07 00 18 FF 01 00 CC 05 ................
02F0 : 00 00 00 02 80 00 00 00 00 00 80 00 FF 00 00 00 ................
0300 : 31 01 52 01 00 04 07 00 80 00 01 00 00 00 00 00 1.R.............
0310 : 00 00 00 00 1E 00 00 00 00 00 50 30 E4 43 40 E4 ..........P0.C@.
0320 : 45 00 E4 53 10 E4 4B 20 E4 00 00 00 00 00 00 00 E..S..K ........
> dlist b0ec
B0EC: LMS 9000 MODE 2
B0EF: MODE 2
B0F0: MODE 2
B0F1: MODE 2
B0F2: MODE 2
B0F3: MODE 2
B0F4: MODE 2
B0F5: MODE 2
B0F6: MODE 2
B0F7: MODE 2
B0F8: MODE 2
B0F9: MODE 2
B0FA: MODE 2
B0FB: MODE 2
B0FC: MODE 2
Press return to continue ('q' to quit):
B0FD: MODE 2
B0FE: MODE 2
B0FF: MODE 2
B100: MODE 2
B101: MODE 2
B102: MODE 2
B103: MODE 2
B104: MODE 2
B105: MODE 2
B106: MODE 2
B107: MODE 2
B108: MODE 2
B109: MODE 2
B10A: MODE 2
B10B: JVB b0ec
первая инструкция B0EC: LMS 9000 MODE 2 - текстовый режим(аналог GR.0 в Бейсике), адрес берется с $9000(бит LMS), следующие 28 строк - тот же текстовый режим, а последняя JVB b0ec - дождаться прерывания и перейти по адресу,стандартное завершение Display List, как раз переход по начальному адресу инструкций.
Теперь о текстовом режиме. Существует 256 символов - 128 стандартные и 128 инверсные.Символы задаются 8 байтами, например А задается так:

Подробнее можно узнать о знакогенераторе, прочитав статью: http://www.atariarchives.org/creativeatari/The_Beginners_Guide_to_Character_Sets.php ,но я ее пересказывать не буду.
Еще одно интересное значение в GPRIOR изменяет режим отображения символов. Каждый байт разбивается на 2 половинки АААА.ВВВВ. Ясно, что половинка может состоять из значений 0-15, а это и есть цвет или оттенок цвета.
ldy #$1F
inx
LB02B lda LB0CC,X
sta L8600,X
sta L8640,X
sta L8680,X
sta L86C0,X
sta L8700,X
sta L8620,Y
sta L8660,Y
sta L86A0,Y
sta L86E0,Y
sta L8720,Y
dey
inx
cpx #$20
bne LB02B
Не совсем ясно, что творится здесь, разбор оставлю на потом(это оказалась генерация таблицы синуса).
iny
lda #$FF
LB055 ldx #$07
LB057 sta L8000,Y
iny
dex
bpl LB057
sec
sbc #$11
cpy #$80
bne LB055
Данные знакогенератора готовятся очень интересно - 8 байт $FF, затем $EE и до $11, таким образом получаются 15 символов, каждый из которых отображается как квадратик разного цвета, по сути почти атрибуты на ZX Spectrum.
Теперь, после подготовки данных, интро начинает работать. данные для экрана хранятся в $9000, таблица синуса в $8600
LB065 lda #$00
sta LB0A5
lda #$90
sta LB0A6
Непонятны эти инструкции, результат работы дизассемблера. Нахожу похожий адрес LB0A4 sta L9000,Y инструкция представляет собой $99,$00,$90, значит LB0A5 это LB0A4+1, LB0A6 это LB0A4+2, получается, что в инструкцию вносятся байты $00 и $90,
Lb06F lda #$00
sta LB09C; LB09B+1
Еще интереснее, B09C это адрес adc L8614,Y. Дальше я плюнул на копание адресов и дописал правильные значения в комментариях.
eor #$FF
sta LB07F;LB07E+1
inc LB070 ; Lb06F+1
ldx #$1C
LB07E lda L8600
lsr A
sta LB08C;LB08B+1
inc LB07F;LB07E+1
inc LB07F;LB07E+1
LB08B lda #$14
sta LB098;LB097+1
lda #$86
sta LB099;LB097+2
ldy #$27
LB097 lda L860A,Y
asl A
LB09B
adc L8614,Y
cmp #$10
bcc LB0A4
lda #$0F
LB0A4 sta L9000,Y
inc LB098;LB097+1
inc LB098;LB097+1
dey
bpl LB097
inc LB09C;LB09B+1
inc LB09C;LB09B+1
inc LB09C;LB09B
дальше идет переход на 40 байт,столько необходимо для текстового режима GR.0
clc
lda #$28
adc LB0A5;LB0A4+1
sta LB0A5;LB0A4+1
bcc LB0C7
inc LB0A6;LB0A4+2
LB0C7 dex
bpl LB07E
Весьма логичное завершение цикла по строкам - bpl сработает тогда, когда результат операции положительной, регистр X работает от $1C до $FF,29 линий
bmi LB065
Это элегантно и красиво: результат вышел отрицательный и переход bmi выполнится - 2 байта вместо jmp адрес(3 байта)
LB0CC .byte $00,$00,$00,$01,$01,$01,$02,$02
.byte $03,$03,$04,$04,$05,$05,$06,$07
.byte $08,$09,$0A,$0A,$0B,$0B,$0C,$0C
.byte $0D,$0D,$0E,$0E,$0E,$0F,$0F,$0F
Это и есть начало инструкции Display List
.byte $42,$00,$90
"Хвостик" .com-файла: адрес запуска.
*= $02E0
.word LB000
Наверное, читатели запутаются в исходном тексте и в моем описании. Для простоты понимания я написал программу на PureBasic:
Dim s.a(256)
Restore L8600
For i=0 To 255
Read.A s(i)
Next i
LB06F.a=0
LB07F.a=0
If InitSprite() And OpenWindow(0,0,0,640,480,"Motion",#PB_Window_SystemMenu) And OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0)
Repeat
StartDrawing(ScreenOutput())
Box(0,0,640,480,0)
LB09C.a=LB06F
LB07F=LB06F|255
LB06F+1
For y=0 To $1C; To -1 Step -1
a.a=s(LB07F)
LB08C.a=a>>1
LB07F+2
For x.a=$27 To 0 Step -1
t.a=x+LB08C
u.a=x+LB09C
a.a=s(t)>>1+s(u)
If a>16:a=15:EndIf
;a=(a|255)&15
Box(x*8,y*8,8,8,RGB(a*8,a*8,a*8))
LB08C+2
Next x
LB09C+3
Next y
StopDrawing()
FlipBuffers()
Until WindowEvent()=#PB_Event_CloseWindow
EndIf
DataSection
;generated file:D:\00\bluegriffon\.nntro\model\l8600.bin
L8600:
Data.b $00,$00,$00,$01,$01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$07
Data.b $08,$09,$0A,$0A,$0B,$0B,$0C,$0C,$0D,$0D,$0E,$0E,$0E,$0F,$0F,$0F
Data.b $0F,$0F,$0F,$0E,$0E,$0E,$0D,$0D,$0C,$0C,$0B,$0B,$0A,$0A,$09,$08
Data.b $07,$06,$05,$05,$04,$04,$03,$03,$02,$02,$01,$01,$01,$00,$00,$00
Data.b $00,$00,$00,$01,$01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$07
Data.b $08,$09,$0A,$0A,$0B,$0B,$0C,$0C,$0D,$0D,$0E,$0E,$0E,$0F,$0F,$0F
Data.b $0F,$0F,$0F,$0E,$0E,$0E,$0D,$0D,$0C,$0C,$0B,$0B,$0A,$0A,$09,$08
Data.b $07,$06,$05,$05,$04,$04,$03,$03,$02,$02,$01,$01,$01,$00,$00,$00
Data.b $00,$00,$00,$01,$01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$07
Data.b $08,$09,$0A,$0A,$0B,$0B,$0C,$0C,$0D,$0D,$0E,$0E,$0E,$0F,$0F,$0F
Data.b $0F,$0F,$0F,$0E,$0E,$0E,$0D,$0D,$0C,$0C,$0B,$0B,$0A,$0A,$09,$08
Data.b $07,$06,$05,$05,$04,$04,$03,$03,$02,$02,$01,$01,$01,$00,$00,$00
Data.b $00,$00,$00,$01,$01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$07
Data.b $08,$09,$0A,$0A,$0B,$0B,$0C,$0C,$0D,$0D,$0E,$0E,$0E,$0F,$0F,$0F
Data.b $0F,$0F,$0F,$0E,$0E,$0E,$0D,$0D,$0C,$0C,$0B,$0B,$0A,$0A,$09,$08
Data.b $07,$06,$05,$05,$04,$04,$03,$03,$02,$02,$01,$01,$01,$00,$00,$00
EndDataSection
И на основе алгоритма я написал маленькое интро
http://www.pouet.net/prod.php?which=63739
В интро создана другая генерация чанок 8х8 и добавлен звук.
Да, воровать код нехорошо, но мне изучение этой работы помогло многим вопросам(не второму месту в компо)
Интро Атари, которые используют похожую описанную технику:
Swamp/g0blinish
http://www.pouet.net/prod.php?which=63639
Dragons:
http://a8.fandal.cz/detail.php?files_id=244
Point 256b:
http://256bytes.untergrund.net/demo/1279
Ye Olde Plasma/g0blinish
http://256bytes.untergrund.net/demo/1135
И да пребудет с вами легкий код!