m3




Еще одна работа, какую можно рассмотреть как некий вызов к самому себе: 1)изучить Yamaha MSX. 2)Изучить работу с видеопамятью.

с MSX в реале я не сталкивался, поэтому запись представляет не руководство к использованию, а просто заметки.

Эмуляторов было испробовано немало, выбор пал на BlueMSX/ Удобнее просто скачать дистрибутив, установить, настроить и запустить готовую систему. Для удобства можно поискать статью на сайте и подключить HDD к эмулируемому компьютеру.

Система запустилась, остались инструменты. Я поставил MSX Commander, установил ассемблер и текстовый редактор, помучался с готовым набором и забросил их в ужасе. BlueMSX позволяет монтировать папку на жестком диске как диск, поэтому остался только sjasm и привычный EmEditor.

Графика
Описание нашлось здесь


Выбор пал на режиме 3 так как есть несколько работ 512байт, по которым можно судить о возможностях. К тому же есть несколько толковых примеров:

Включение режима 3

;
; How to set up screen mode with BIOS?
; Featuring also VDP writing and keyboard reading.
; Note that TASM doesn't know about precedence in arithmetic.
;
; - Marq/L!T

PIXELS  .equ    0 ; Address of pixels in VRAM

.org	100h

	ld	a,3	; SCREEN 3 (64x48 gfxmode)
	ld      (0fcafh),a
	ld	ix,05fh
	ld	iy,(0fcc0h)
	call	01ch	; Inter-slot call

	ld	d,0

mainloop:
	halt		; Wait for vertical blank

	ld	a,PIXELS & 0ffh ; Set write address to VDP
	out	(099h),a
	ld	a,PIXELS >> 8
	or	040h
	out	(099h),a

	ld	bc,32*48 ; We'll write 64*48 pixels (1 byte=2 pixels)

filloop:
	ld	a,d	
	out	(98h),a	; Write fill byte to VRAM. VDP increases the address
	dec	bc	; automatically
	ld	a,b
	or	c
	jp	nz,filloop ; Over and over

	inc	d	; Increase fill byte

	in	a,(0aah) ; Check whether space is pressed
	and	0f0h
	or	8
	out	(0aah),a
	in	a,(0a9h)
	and	1
	jp	nz,mainloop ; Not pressed, keep on keeping on
	
	xor	a	; SCREEN 0 (40x24 textmode)
	ld	(0fcafh),a
	ld	ix,05fh
	ld	iy,(0fcc0h)
	call	01ch	; Inter-slot call

	ret	; Back to DOS

.end


и VDP programming tutorial

Из прочтения мало что понятно, ясно, что доступ к видеопамяти реализован вычурно. Некоторые попытки разобраться с видеопамятью и чтение доступных русских руководств ничего не дали. Я взял работу Iworld, дизассемблировал и стал разбираться.


Первое открытие:

RAM:0100                 segment RAM
RAM:0100                 org 100h
RAM:0100                 ld      hl, 0
RAM:0103                 ld      (0F3EAh), hl    ; FORCLR  #F3E9   1       Foreground color
RAM:0103                                         ; BAKCLR  #F3EA   1       Background color
RAM:0103                                         ; BDRCLR  #F3EB   1       Border color
RAM:0103                                         ;
RAM:0103                                         ;
RAM:0106                 ld      a, 3            ; CHGMOD
RAM:0106                                         ;
RAM:0106                                         ;
RAM:0106                                         ; Address  : #005F
RAM:0106                                         ; Function : Switches to given screenmode
RAM:0106                                         ; Input    : A  - screen mode
RAM:0108                 rst     30h
RAM:0108 ; ---------------------------------------------------------------------------
RAM:0109                 db  80h ; À
RAM:010A                 dw 5Fh

Очевидно, что включение графического режима реализовано проще — для меня это новость.

Дальнейший код мало понятен, глаз пал на процедуру:


RAM:02AB ; =============== S U B R O U T I N E =======================================
RAM:02AB
RAM:02AB
RAM:02AB sub_2AB:                                ; CODE XREF: RAM:012Ep
RAM:02AB                 di
RAM:02AC                 xor     a
RAM:02AD                 out     (99h), a
RAM:02AF                 ld      a, 8Eh ; 'Î'
RAM:02B1                 out     (99h), a
RAM:02B3                 xor     a
RAM:02B4                 out     (99h), a
RAM:02B6                 ld      a, 40h ; '@'
RAM:02B8                 out     (99h), a
RAM:02BA                 ld      hl, 0F00h
RAM:02BD                 ld      bc, 98h ; 'Ø'   ; port #98
RAM:02C0                 ld      e, 6
RAM:02C2
RAM:02C2 loc_2C2:                                ; CODE XREF: sub_2AB+1Aj
RAM:02C2                 otir
RAM:02C4                 dec     e
RAM:02C5                 jr      nz, loc_2C2
RAM:02C7                 ret
RAM:02C7 ; End of function sub_2AB


Похожие действия описаны в VDP tutorial, я взял процедуру записи в видеопамять и продолжил исследования. Несколько мучений прошло, пока меня не осенило, как размещать данные, чтобы разобраться с форматом видеопамяти. Вышло вот что:


;+0
;
;00 08 16
;01 09 ..
;02 ..
;03
;04
;05
;06
;07 15 .. .. 255
;+256
;same, 6 pages

Один байт описывает два цвета (ниббл) точка ниже +1 байт и так до +7 байт. +8 байт — это еще две точки справа. Всего вышло 6х256 байт на видеопамять.

Теперь взгляд на Iworld проясняет картину:

RAM:0266 ; =============== S U B R O U T I N E =======================================
RAM:0266
RAM:0266
RAM:0266 sub_266:                                ; CODE XREF: RAM:012Bp
RAM:0266                                         ; DATA XREF: sub_19B+12o
RAM:0266                 ld      ix, 300h
RAM:026A                 ld      iy, 0F00h
RAM:026E                 ld      b, 6
RAM:0270
RAM:0270 loc_270:                                ; CODE XREF: sub_266+42j
RAM:0270                 push    bc
RAM:0271                 push    ix
RAM:0273                 ld      b, 20h ; ' '
RAM:0275
RAM:0275 loc_275:                                ; CODE XREF: sub_266+39j
RAM:0275                 push    bc
RAM:0276                 push    ix
RAM:0278                 ld      b, 8
RAM:027A
RAM:027A loc_27A:                                ; CODE XREF: sub_266+30j
RAM:027A                 ld      a, (ix+0)
RAM:027D                 inc     ix
RAM:027F                 sla     a
RAM:0281                 sla     a
RAM:0283                 sla     a
RAM:0285                 sla     a
RAM:0287                 ld      c, a
RAM:0288                 ld      a, (ix+0)
RAM:028B                 or      c
RAM:028C                 ld      (iy+0), a
RAM:028F                 inc     iy
RAM:0291                 ld      de, 3Fh ; '?'
RAM:0294                 add     ix, de
RAM:0296                 djnz    loc_27A
RAM:0298                 pop     ix
RAM:029A                 inc     ix
RAM:029C                 inc     ix
RAM:029E                 pop     bc
RAM:029F                 djnz    loc_275
RAM:02A1                 pop     ix
RAM:02A3                 inc     xh
RAM:02A5                 inc     xh
RAM:02A7                 pop     bc
RAM:02A8                 djnz    loc_270
RAM:02AA                 ret
RAM:02AA ; End of function sub_266

Суть действий такая: интро хранит по адресу $300 участок памяти, где один байт отводится на 1 цвет, байты хранятся линейно.
Приведенная процедура преобразует участок памяти в описанный формат по адресу $F00.

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

Наверняка решение было не блестящим, генерация lut для построения точек выглядела так:


;generate LUT table for plot
lut_tab equ $2000
pixa	equ $0F00
	ld de,pixa;$F00
	ld l,e
;B=0
lut_lp:
	ld h,lut_tab/256
	ld (hl),d
	inc h
	ld (hl),e
	inc h
	ld (hl),b;X
	inc l
	inc de
	ld a,l
	and 7
	jr nz,no_disp_x
	inc d
	ld e,a;A=0
no_disp_x:
;	and 1
;	jr nz,next_x
	rra
	jr c,next_x

	ld a,b
	add a,8
	ld b,a
next_x:
	bit 6,l
	jr z,lut_lp


А процедура построения точек так:

plot: ; D.E=y.x
	ld h,lut_tab/256
	ld l,d
	
	ld d,(hl)
	inc h
	ld a,(hl)
	inc h ;Y done
	ld l,e
	add a,(hl)
;	ld l,e
	ld e,a
	ld a,$F0
	bit 0,l
	jr z,no_inv
	cpl
no_inv:
	ex de,hl
	or (hl)
	ld (hl),a
	pop de
	ret

Немного мучений, тестов, и я получил желаемый результат. Осталось применить готовые наработки и создать интрошку.
Первоначальная идея просто отпала, я решил пустить точки, скачущие ping-pong style и оставляющие хвост.
Как сделать хвост? да очень просто!

Процедура вышла немного тормозная, но в угоду поставленной цели «создать 256 байт» сойдет и так:


;;;;;;;; reset data ;;;;;;;;;;;;;
	pop hl
	push hl
res_lp:
	ld a,(hl)
	ld c,a
	and $0F
	jr z,no_dec_r
	dec c
no_dec_r:
	ld a,c
	and $F0
	jr z,no_dec_l
	ld a,c
	sub $10
	ld c,a
no_dec_l:
	ld (hl),c
	inc hl
	ld a,h
	cp 6+pixa/256
	jr nz,res_lp

	pop hl


Сложного тут нет, каждый байт описывает цвет из 16-ти значений — старший и младший ниббл. 16 цветов хватит для «хвостов», которые оставляют за собой точки.

Остался еще один вопрос — цвета. Поиск в Гугле и чтение документации вывело на описание цвета:


;;generate pal
	ld      hl, $300
	push hl
	xor a
gen_pal:
	push af
	rra
;0rrr.0bbb,0000.0ggg
	ld (hl),0;a
	inc hl
	ld (hl),a;c
	inc hl
	pop af
	inc a
	cp 16
	jr nz, gen_pal


Вышла симпатичная зеленая гамма.

Вот, наверное и все, история заканчивается.
Файл с исходным текстом и с загрузочным диском, где размещен рабочий файл M3.COM

А для ленивых видео:


Я думаю, что некое исследование просто поверхностное, есть еще немало интересных пунктов. Например, спрайты.

0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.