;*******************************
; mandel : mandelbrot figure
;        for FM-TOWNS
;    (C)1990.3.20 by Fumi
; #1 1990.4.3   Ver0.1 for SOFT BANK
; #2 1990.4.10  Ver1.0 first edition
;*******************************
	.386p
TRUE	equ	1
FALSE	equ	0
;
EGBSIZ	equ	2000	; EGB work area byte size
VRAMW	equ	1024	; VRAM byte width
VRAMDW	equ	640	; VRAM display width
VRAMDH	equ	480	; VRAM display hight
;
BGBW	equ	10	; background block width
BGBH	equ	10	; background block hight
BGBSIZ	equ	BGBW*BGBH	; background block size
BGBCN	equ	64	; background block column number
BGBLN	equ	48	; background block line number
;
SCRX	equ	40	; display screen x position
SCRY	equ	60	; display screen y position
SCRW	equ	400	; display screen width
SCRH	equ	400	; display screen hight
SCRADR	equ	SCRY*VRAMW+SCRX	; display screen VRAM address
;
TITX	equ	SCRX+(SCRW-TITW)/2	; title box x position
TITY	equ	20	; title box y position
TITW	equ	260	; title box width
TITH	equ	25	; title box hight
TITADR	equ	TITY*VRAMW+TITX	; title box VRAM address
;
PARX	equ	470	; parameter box display x positon
PARY	equ	60	; parameter box display y position
PARW	equ	140	; paremeter box display width
PARH	equ	75	; parameter box display hight
PARADR	equ	PARY*VRAMW+PARX	; parameter box VRAM address
;
PTX	equ	470	; pallet table x position
PTY	equ	145	; pallet table y position
PTW	equ	PTBCN*PTBW+40	; pallet table boxwidth
PTH	equ	PTBLN*PTBH+20	; pallet table box hight
PTADR	equ	PTY*VRAMW+PTX	; pallet table start VRAM address
PTBW	equ	4	; pallet table block width
PTBH	equ	10	; pallet table block hight
PTBCN	equ	25	; pallet table block column number
PTBLN	equ	10	; pallet table block line number
PTBADR	equ	(PTY+17)*VRAMW+(PTX+35)	; pallet table block address
;
MENUX	equ	470	; menu display x position
MENUY	equ	275	; menu display y position
MENUW	equ	140	; menu display width
MENUH	equ	185	; menu display hight
MENUADR	equ	MENUY*VRAMW+MENUX	; menu start VRAM address
;
LPOSX	equ	PARX+PARW-10*8-3+(PARY+18)*VRAMW	; position x
LPOSY	equ	PARX+PARW-10*8-3+(PARY+36)*VRAMW	; position y
LRESO	equ	PARX+PARW-10*8-3+(PARY+54)*VRAMW	; resolution
LLIMIT	equ	PARX+PARW-5*8-12+(PARY+72)*VRAMW	; limit parameter
LDSTEP	equ	MENUX+(MENUW-9*8)/2+(MENUY+110)*VRAMW	; drawing step
LZPOSX	equ	MENUX+MENUW-10*8-10+(MENUY+48)*VRAMW	; zoom in position x
LZPOSY	equ	MENUX+MENUW-10*8-10+(MENUY+66)*VRAMW	; zoom in position y
LCL1	equ	MENUX+70+(MENUY+46)*VRAMW	; old limit
LCL2	equ	MENUX+70+(MENUY+66)*VRAMW	; new limit
LAUP	equ	MENUX+(MENUW-5*8)/2+(MENUY+110)*VRAMW	; auto up limit
LCSTEP1	equ	MENUX+72+(MENUY+46)*VRAMW	; color step change unit
LCSTEP2	equ	MENUX+72+(MENUY+66)*VRAMW	; color step
;
EXTALL	equ	"LDM."	; extension all
EXTCOL	equ	"CDM."	; extension col
;
USRCN	equ	250	; numbers of color
PALSBS	equ	42	; pallet set block size (not factor 1+USRCN)
PALSBN	equ	(1+USRCN)/PALSBS+1	; number of pallet block
PALSBR	equ	(1+USRCN) mod PALSBS	; number of rest pallet (inhibit 0)
;
PADREP	equ	10	; pad repeat count (unit VSYNC)
INIREP	equ	-1	; initial repeat counter code
;
P$FWD	equ	1	; TOWNS pad button
P$BACK	equ	2
P$LEFT	equ	3
P$RIGHT	equ	4
P$RUN	equ	5
P$SEL	equ	6
P$TRIG1	equ	01b
P$TRIG2	equ	10b
;
C$NULL	equ	0	; system pallet code
C$BLOCK	equ	251
C$LIGHT	equ	252
C$DARK	equ	253
C$PANEL	equ	254
C$INT	equ	255
;
DS$NONE	equ	0	; no first figure
DS$ON	equ	1	; on the way
DS$FULL	equ	2	; full display
;
MINFR	equ	16	; zoom up frame minimum size
IPOSX	equ	-2 shl 24	; initial position x
IPOSY	equ	-2 shl 24	; initial position y
IRESO	equ	(4 shl 24)/SCRW	; initial resolution
ILIMIT	equ	250		; initial limit
;
boxstr	struc		; down box structure
boxadr	dd	?	; box start VRAM address
boxw	dw	?	; box pixcel width
boxh	dw	?	; box pixcel hight
boxstr	ends
menuitm	struc		; menu items index structre
butptr	dw	?	; buttons  pointer
butnum	dw	?	; number of button
strptr	dw	?	; strings pointer
menuitm	ends
butstr	struc		; button data structure
butadr	dd	?	; button start VRAM address
butw	dw	?	; button pixcel width
buth	dw	?	; button pixcel hight
butstr	ends
locdat	struc		; location data structure
locdatx	dd	?	; position x
locdaty	dd	?	; position y
locdatr	dd	?	; resolution
locdatl	dw	?	; limit
locdat	ends

data	segment	use32 rw
;*******************************
; variables
;*******************************
buffer	dd	?	; calculate data buffer pointer
bufsiz	dd	?	; buffer byte size (400*400*8 bytes)
;
posx	dd	IPOSX	; display position x
posy	dd	IPOSY	; display position y
reso	dd	IRESO	; resolution
limit	dw	ILIMIT	; upper limit of repeat number
curstat	dw	DS$FULL	; current display state
step	dw	4	; display step for dsp3q
islin	dw	0	; initial screen calculated line
;
cura	dd	?	; current real part
curb	dd	?	; current imaginary part
pstep	dd	?	; position step (reso*step) for dsp3q
bstep	dd	?	; block line VRAM step for ds3q
hbnum	dw	?	; horizon block number for ds3q
count1	dw	?	; public counter 1
count2	dw	?	; public counter 2
;
repcnt	dw	?	; pad repaet counter
frame	dw	SCRX+SCRW*3/8,SCRY+SCRH*3/8,SCRW/4,SCRH/4	; zoom up frame
;
numwid	db	5	; dispaly width of integer for putdec
palpkt	label	byte	; pallet data packet address
palnum	db	1	; pallet number
bpal	db	0	; blue pallet data
rpal	db	0	; red pallet data
gpal	db	255	; green pallet data
	db	?	; dummy
colnum	db	1	; color number
spflg	db	FALSE	; saving pallet plag
currgb	db	0	; current B|R|G (B=0,R=1,G=2)
exts	dd	?	; extension for open
;*******************************
; constants
;*******************************
syspal	db	251,0,192,62	; block
	db	252,200,200,200	; light shadow
	db	253,10,10,10	; dark shadow
	db	254,120,120,120	; panel
	db	255,10,10,200	; string
syspalN	equ	5
;
bgblock	db	0FCh,0FCh,0FCh,0FCh,0FCh,0FCh,0FCh,0FCh,0FCh,0FDh
	db	0FCh,0FBh,0FBh,0FBh,0FBh,0FBh,0FBh,0FBh,0FBh,0FDh
	db	0FCh,0FBh,0FBh,0FBh,0FBh,0FBh,0FBh,0FBh,0FBh,0FDh
	db	0FCh,0FBh,0FBh,0FBh,0FBh,0FBh,0FBh,0FBh,0FBh,0FDh
	db	0FDh,0FDh,0FDh,0FDh,0FDh,0FDh,0FDh,0FDh,0FDh,0FDh
	db	0FCh,0FCh,0FCh,0FCh,0FDh,0FCh,0FCh,0FCh,0FCh,0FCh
	db	0FBh,0FBh,0FBh,0FBh,0FDh,0FCh,0FBh,0FBh,0FBh,0FBh
	db	0FBh,0FBh,0FBh,0FBh,0FDh,0FCh,0FBh,0FBh,0FBh,0FBh
	db	0FBh,0FBh,0FBh,0FBh,0FDh,0FCh,0FBh,0FBh,0FBh,0FBh
	db	0FDh,0FDh,0FDh,0FDh,0FDh,0FDh,0FDh,0FDh,0FDh,0FDh
;
cmdtbl1	dd	zoomin,zoomout,whole,chgcol,chglim	; menu1 dispatch
	dd	load,save,main10,main99
cmdtbl2	dd	indcol,setcs,grad,cload,csave,crest	; change color dispatch
;
mdrawon	menuitm	<butd,butdN,str3>	; on drawing message items
mzoin	menuitm	<but1,but1N,str6>	; zoom in menu
mcgl	menuitm	<but2,but2N,str7>	; change limit menu
mautad	menuitm	<butA,butAN,str8>	; automatically limit addition menu
mautup	menuitm	<butU,butUN,strU>	; automatically limit up menu
mcgc	menuitm	<but3,but3N,str9>	; change color menu
mindc	menuitm	<but4,but4N,strA>	; change individual color menu
mced	menuitm	<but5,but5N,strB>	; color edit menu
mexp	menuitm	<but6,but6N,strC>	; extract pallet number from pixcel
msave	menuitm	<but7,but7N,strD>	; save menu
mload	menuitm	<but8,but8N,strE>	; load menu
msetcs	menuitm	<but9,but9N,strF>	; set color step menu
mgrad	menuitm	<butG,butGN,strG>	; gradation menu
;
titbox	boxstr	<TITADR,TITW,TITH>	; title box data
scrbox	boxstr	<SCRADR,SCRW,SCRH>	; screen box data
parbox	boxstr	<PARADR,PARW,PARH>	; parameter box data
palbox	boxstr	<PTADR,PTW,PTH>		; pallet box data
menubox	boxstr	<MENUADR,MENUW,MENUH>	; menu box data
;
str1	dw	1,str11				; title string index
str2	dw	9,str21,str22,str23,str24	; starting message
	dw	str25,str26,str27,str28,str29
str3	dw	3,str31,str32,str33		; on drawing message index
str4	dw	11,str411,str412,str413,str414	; parameter box and
	dw	str421,str422			; pallet table scale strings
	dw	str431,str432,str433,str434,str435
str5	dw	6,str51,str52,str53,str54	; scroll mode message
	dw	str55,str56
str6	dw	7,str61,str62,str63,str64	; zoom in mode messag
	dw	str65,str66,str67
str7	dw	8,str71,str72,str73,str74	; limit change
	dw	str75,str76,str77,str78
str8	dw	4,str81,str82,str83,str84	; automatically limit addition
strU	dw	4,strU1,strU2,strU3,strU4	; automatically limit up
str9	dw	2,str91,str92		; change color menu
strA	dw	10,strA1,strA2,strA3	; change individual color menu
	dw	strA4,strA5,strA6,strA7
	dw	strA8,strA9,strA10
strB	dw	7,strB1,strB2,strB3	; edit color code
	dw	strB4,strB5,strB6,strB7
strC	dw	6,strC1,strC2,strC3	; extract pallet number from pixcel
	dw	strC4,strC5,strC6
strD	dw	4,strD1,strD2,strD3,strD4	; save
strE	dw	5,strE1,strE2,strE3,strE4,strE5	; load
strF	dw	9,strF1,strF2,strF3,strF4,strF5	; set color step
	dw	strF6,strF7,strF8,strF9
strG	dw	4,strG1,strG2,strG3,strG4	; gradation menu
;
str11	dw	TITX+(TITW-30*8)/2,TITY+19,30
	db	"マンデルブロ図形描画プログラム"
str20	dw	SCRX+(SCRW-28*8)/2,SCRY+(SCRH-16)/2+16,28
	db	"ＲＵＮボタンを押してください"
str29	dw	SCRX+(SCRW-10*8)/2,SCRY+30,10
	db	"Volume One"
str21	dw	SCRX+(SCRW-19*8)/2,SCRY+58,19
	db	"ＭＡＮＤＥＬ.ＥＸＰ"
str22	dw	SCRX+(SCRW-11*8)/2,SCRY+82,11
	db	"Version 1.0"
str23	dw	SCRX+(SCRW-16*8)/2,SCRY+124,16
	db	"このプログラムは"
str24	dw	SCRX+(SCRW-28*8)/2,SCRY+148,28
	db	"ＴＯＷＮＳパッドで操作します"
str25	dw	SCRX+(SCRW-40*8)/2,SCRY+270,40
	db	"本プログラムの無断複製・譲渡を許可します"
str26	dw	SCRX+(SCRW-38*8)/2,SCRY+294,38
	db	"但し著作権を放棄するものではありません"
str27	dw	SCRX+(SCRW-26*8)/2,SCRY+346,26
	db	"Copyright (C) 1990 by Fumi"
str28	dw	SCRX+(SCRW-35*8)/2,SCRY+370,35
	db	"Special Thanks to Oh!FM and FUJITSU"
str31	dw	MENUX+(MENUW-6*8)/2,MENUY+20,6
	db	"描画中"		; on drawing title
str32	dw	MENUX+(MENUW-8*8)/2,MENUY+80,8
	db	"描画間隔"
str411	dw	PARX+3,PARY+18,6
	db	"左上Ｘ"
str412	dw	PARX+3,PARY+36,6
	db	"左上Ｙ"
str413	dw	PARX+3,PARY+54,6
	db	"分解能"
str414	dw	PARX+3,PARY+72,8
	db	"上限回数"
str421	dw	PTX+25,PTY+15,2
	db	"+1"
str422	dw	PTX+112,PTY+15,3
	db	"+25"
str431	dw	PTX+10,PTY+30,1
	db	"0"
str432	dw	PTX+7,PTY+50,2
	db	"50"
str433	dw	PTX+3,PTY+70,3
	db	"100"
str434	dw	PTX+3,PTY+90,3
	db	"150"
str435	dw	PTX+3,PTY+110,3
	db	"200"
str51	dw	MENUX+(MENUW-14*8)/2,MENUY+30,14
	db	"SELECTボタンで"
str52	dw	MENUX+(MENUW-10*8)/2,MENUY+50,10
	db	"メニューへ"
str53	dw	MENUX+(MENUW-12*8)/2,MENUY+80,12
	db	"移動ボタンで"
str54	dw	MENUX+(MENUW-10*8)/2,MENUY+100,10
	db	"スクロール"
str55	dw	MENUX+(MENUW-10*8)/2,MENUY+130,10
	db	"Ａボタンで"
str56	dw	MENUX+(MENUW-8*8)/2,MENUY+150,8
	db	"描画続行"
str61	dw	MENUX+(MENUW-5*8)/2,MENUY+20,5
	db	"拡 大"
str62	dw	MENUX+10,MENUY+48,4
	db	"枠Ｘ"
str63	dw	MENUX+10,MENUY+66,4
	db	"枠Ｙ"
str64	dw	MENUX+(MENUW-10*8)/2,MENUY+94,10
	db	"RUN 枠拡大"
str65	dw	MENUX+(MENUW-10*8)/2,MENUY+116,10
	db	"SEL 枠縮小"
str71	dw	MENUX+(MENUW-8*8)/2,MENUY+20,8
	db	"上限回数"		; change limit menu title
str72	dw	MENUX+20,MENUY+46,6
	db	"現在値"
str73	dw	MENUX+20,MENUY+66,6
	db	"変更値"
strF4	label	word
str74	dw	MENUX+(MENUW-10*8)/2,MENUY+89,10
	db	"↑ ↓ 増減"
str77	dw	MENUX+(MENUW-12*8)/2,MENUY+112,12
	db	"RUN 自動追加"
str78	dw	MENUX+(MENUW-12*8)/2,MENUY+134,12
	db	"SEL 自動増加"
str81	dw	MENUX+(MENUW-8*8)/2,MENUY+20,8
	db	"自動追加"
strU2	label	word
str82	dw	MENUX+(MENUW-8*8)/2,MENUY+80,8
	db	"上限回数"
strU1	dw	MENUX+(MENUW-8*8)/2,MENUY+20,8
	db	"自動増加"
str91	dw	MENUX+(MENUW-6*8)/2,MENUY+20,6
	db	"色設定"		; change color menu title
str92	dw	MENUX+(MENUW-11*8)/2,MENUY+175,11
	db	"↑ ↓ Ａ Ｂ"		; cahnge color menu button
strA1	dw	MENUX+(MENUW-10*8)/2,MENUY+20,10
	db	"色番号選択"		; change individual color menu title
strA2	dw	MENUX+10,MENUY+63,2
	db	"←"
strA3	dw	MENUX+MENUW-26,MENUY+63,2
	db	"→"
strRGB	label	word		; for indc
strRGBL	equ	8		; for indc
strC2	label	word
strB2	label	word
strA4	dw	MENUX+12,MENUY+92,2
	db	"Ｂ"
strC3	label	word
strB3	label	word
strA5	dw	MENUX+12,MENUY+108,2
	db	"Ｒ"
strC4	label	word
strB4	label	word
strA6	dw	MENUX+12,MENUY+124,2
	db	"Ｇ"
strA7	dw	MENUX+18,MENUY+156,3
	db	"SEL"
strA8	dw	MENUX+14,MENUY+178,4
	db	"抽出"
strU3	label	word
str83	label	word
strG3	label	word
str66	label	word
str75	label	word
strF8	label	word
strC5	label	word
strA9	dw	MENUX+MENUW/2+8,MENUY+156,7
	db	"Ａ 決定"
strU4	label	word
str84	label	word
str33	label	word
strG4	label	word
str67	label	word
str76	label	word
strF9	label	word
strB7	label	word
strC6	label	word
strA10	dw	MENUX+MENUW/2+8,MENUY+178,7
	db	"Ｂ 中止"
strB1	dw	MENUX+(MENUW-6*8)/2,MENUY+20,6
	db	"色編集"	; edit color menu title
strB5	dw	MENUX+10,MENUY+146,10
	db	"SEL  ← →"
strB6	dw	MENUX+10,MENUY+178,7
	db	"Ａ 決定"
strC1	dw	MENUX+(MENUW-6*8)/2,MENUY+20,6
	db	"色抽出"	; extract pallet number menu title
strD1	dw	MENUX+(MENUW-5*8)/2,MENUY+20,5
	db	"保 存"		; save menu title
strD2	dw	MENUX+(MENUW-10*8)/2,MENUY+50,10
	db	"ファイル名"
strD3	dw	MENUX+(MENUW-11*8)/2+8,MENUY+120,10
	db	"CR Ａ 決定"
strD4	dw	MENUX+(MENUW-11*8)/2,MENUY+146,11
	db	"ESC Ｂ 中止"
strE1	dw	MENUX+(MENUW-8*8)/2,MENUY+20,8
	db	"読み込み"	; load menu title
strE2	dw	MENUX+106,MENUY+67,2
	db	"↑"
strE3	dw	MENUX+106,MENUY+89,2
	db	"↓"
strE4	dw	MENUX+106,MENUY+138,2
	db	"Ａ"
strE5	dw	MENUX+106,MENUY+160,2
	db	"Ｂ"
strF1	dw	MENUX+(MENUW-6*8)/2,MENUY+20,6
	db	"色間隔"	; set color step menu title
strF2	dw	MENUX+20,MENUY+46,6
	db	"増単位"
strF3	dw	MENUX+20,MENUY+66,6
	db	"色間隔"
strF5	dw	MENUX+(MENUW-10*8)/2,MENUY+114,10
	db	"← → 単位"
strF6	dw	MENUX+18,MENUY+156,3
	db	"RUN"
strF7	dw	MENUX+14,MENUY+178,4
	db	"自動"
strG1	dw	MENUX+(MENUW-14*8)/2,MENUY+20,14
	db	"グラデーション"	; gradation menu title
strG2	dw	MENUX+66-24,MENUY+90,9
	db	"← SEL →"
;
but1N	equ	5		; zoom up command button data
but1	butstr	<(MENUY+3)*VRAMW+MENUX+3,MENUW-6,20>	; 拡大
	butstr	<(MENUY+94-18)*VRAMW+MENUX+(MENUW-10*8)/2-2,28,20>	; RUN
	butstr	<(MENUY+116-18)*VRAMW+MENUX+(MENUW-10*8)/2-2,28,20>	; SEL
	butstr	<(MENUY+138)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ａ
	butstr	<(MENUY+160)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ｂ
but2N	equ	7		; change limit command button
but2	butstr	<(MENUY+3)*VRAMW+MENUX+3,MENUW-6,20>	; 上限回数
	butstr	<(MENUY+72)*VRAMW+MENUX+(MENUW-10*8)/2-2,20,20>		; ↑
	butstr	<(MENUY+72)*VRAMW+MENUX+(MENUW-10*8)/2+3*8-2,20,20>	; ↓
	butstr	<(MENUY+94)*VRAMW+MENUX+(MENUW-12*8)/2-2,28,20>		; RUN
	butstr	<(MENUY+116)*VRAMW+MENUX+(MENUW-12*8)/2-2,28,20>	; SEL
	butstr	<(MENUY+138)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ａ
	butstr	<(MENUY+160)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ｂ
butdN	equ	2		; on drawing message button
butUN	equ	3		; automatically limit up
butAN	equ	3		; automatically limit addition
butd	label	byte
butU	label	byte
butA	butstr	<(MENUY+3)*VRAMW+MENUX+3,MENUW-6,20>; 自動追加/自動増加/描画中
	butstr	<(MENUY+160)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ｂ
	butstr	<(MENUY+138)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ａ
but3N	equ	4		; change color menu button
but3	butstr	<(MENUY+175-17)*VRAMW+MENUX+(MENUW-11*8)/2-2,20,20>	; ↑
	butstr	<(MENUY+175-17)*VRAMW+MENUX+(MENUW-11*8)/2+3*8-2,20,20>	; ↓
	butstr	<(MENUY+175-17)*VRAMW+MENUX+(MENUW-11*8)/2+6*8-2,20,20>	; Ａ
	butstr	<(MENUY+175-17)*VRAMW+MENUX+(MENUW-11*8)/2+9*8-2,20,20>	; Ｂ
but4N	equ	8		; change color command button
but4	butstr	<(MENUY+3)*VRAMW+MENUX+3,MENUW-6,20>	; 色番号選択
	butstr	<(MENUY+45)*VRAMW+MENUX+(MENUW-78)/2,78,20>	; color box
	butstr	<(MENUY+45)*VRAMW+MENUX+10-2,20,20>		; ←
	butstr	<(MENUY+45)*VRAMW+MENUX+MENUW-26-2,20,20>	; →
	butstr	<(MENUY+74)*VRAMW+MENUX+(MENUW-70)/2,70,52>	; bar frame
	butstr	<(MENUY+138)*VRAMW+MENUX+18-2,28,20>		; SEL
	butstr	<(MENUY+138)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ａ
	butstr	<(MENUY+160)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ｂ
but5N	equ	8		; edit color button
but5	butstr	<(MENUY+3)*VRAMW+MENUX+3,MENUW-6,20>	; 色編集
	butstr	<(MENUY+45)*VRAMW+MENUX+(MENUW-78)/2,78,20>	; color box
	butstr	<(MENUY+74)*VRAMW+MENUX+(MENUW-70)/2,70,52>	; bar frame
	butstr	<(MENUY+146-18)*VRAMW+MENUX+10-2,28,20>		; SEL
	butstr	<(MENUY+146-18)*VRAMW+MENUX+10+5*8-2,20,20>	; ←
	butstr	<(MENUY+146-18)*VRAMW+MENUX+10+8*8-2,20,20>	; →
	butstr	<(MENUY+160)*VRAMW+MENUX+10-2,20,20>		; Ａ
	butstr	<(MENUY+160)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ｂ
but6N	equ	5		; extract pallet number button
but6	butstr	<(MENUY+3)*VRAMW+MENUX+3,MENUW-6,20>	; 色抽出
	butstr	<(MENUY+45)*VRAMW+MENUX+(MENUW-78)/2,78,20>	; color box
	butstr	<(MENUY+74)*VRAMW+MENUX+(MENUW-70)/2,70,52>	; bar frame
	butstr	<(MENUY+138)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ａ
	butstr	<(MENUY+160)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ｂ
but7N	equ	6		; save menu button
but7	butstr	<(MENUY+3)*VRAMW+MENUX+3,MENUW-6,20>	; 保 存
	butstr	<(MENUY+80-18)*VRAMW+MENUX+(MENUW-80)/2,80,20>	; for file name
	butstr	<(MENUY+120-18)*VRAMW+MENUX+(MENUW-11*8)/2+8-2,2*8+4,20>; CR
	butstr	<(MENUY+120-18)*VRAMW+MENUX+(MENUW-11*8)/2+4*8-2,2*8+4,20>; Ａ
	butstr	<(MENUY+146-18)*VRAMW+MENUX+(MENUW-11*8)/2-2,3*8+4,20>	; ESC
	butstr	<(MENUY+146-18)*VRAMW+MENUX+(MENUW-11*8)/2+4*8-2,2*8+4,20>; Ｂ
but8N	equ	6		; load menu button
but8	butstr	<(MENUY+3)*VRAMW+MENUX+3,MENUW-6,20>	; 読み込み
	butstr	<(MENUY+33)*VRAMW+MENUX+20,10*8,8*18+2>; file name
	butstr	<(MENUY+67-17)*VRAMW+MENUX+104,20,20>	; ↑
	butstr	<(MENUY+89-17)*VRAMW+MENUX+104,20,20>	; ↓
	butstr	<(MENUY+138-18)*VRAMW+MENUX+104,20,20>	; Ａ
	butstr	<(MENUY+160-18)*VRAMW+MENUX+104,20,20>	; Ｂ
but9N	equ	8		; set color step menu button
but9	butstr	<(MENUY+3)*VRAMW+MENUX+3,MENUW-6,20>	; 色間隔
	butstr	<(MENUY+72)*VRAMW+MENUX+(MENUW-10*8)/2-2,20,20>		; ↑
	butstr	<(MENUY+72)*VRAMW+MENUX+(MENUW-10*8)/2+3*8-2,20,20>	; ↓
	butstr	<(MENUY+96)*VRAMW+MENUX+(MENUW-10*8)/2-2,20,20>		; ←
	butstr	<(MENUY+96)*VRAMW+MENUX+(MENUW-10*8)/2+3*8-2,20,20>	; →
	butstr	<(MENUY+138)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ａ
	butstr	<(MENUY+160)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ｂ
	butstr	<(MENUY+138)*VRAMW+MENUX+18-2,28,20>		; RUN
butGN	equ	8		; gradation menu button
butG	butstr	<(MENUY+3)*VRAMW+MENUX+3,MENUW-6,20>	; グラデーション"
	butstr	<(MENUY+60-17)*VRAMW+MENUX+40-2,80,20>		; 1 color
	butstr	<(MENUY+120-17)*VRAMW+MENUX+40-2,80,20>		; 250 color
	butstr	<(MENUY+90-17)*VRAMW+MENUX+66-24-2,20,20>	; ←
	butstr	<(MENUY+90-17)*VRAMW+MENUX+66-2,28,20>		; SEL
	butstr	<(MENUY+90-17)*VRAMW+MENUX+66+32-2,20,20>	; →
	butstr	<(MENUY+138)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ａ
	butstr	<(MENUY+160)*VRAMW+MENUX+MENUW/2+8-2,20,20>	; Ｂ
;
simain	dw	0,9		; selector item in main menu
	dw	simain0,simain1,simain2,simain3,simain4
	dw	simain5,simain6,simain7,simain8
sicol	dw	0,6		; selector item in color menu
	dw	sicol0,sicol1,sicol2,sicol3,sicol4,sicol5
;
simain0	dw	MENUX+(MENUW-5*8)/2,MENUY+19,5
	db	"拡 大"
simain1	dw	MENUX+(MENUW-5*8)/2,MENUY+39,5
	db	"縮 小"
simain2	dw	MENUX+(MENUW-6*8)/2,MENUY+59,6
	db	"全体図"
simain3	dw	MENUX+(MENUW-6*8)/2,MENUY+79,6
	db	"色設定"
simain4	dw	MENUX+(MENUW-8*8)/2,MENUY+99,8
	db	"上限回数"
simain5	dw	MENUX+(MENUW-8*8)/2,MENUY+119,8
	db	"読み込み"
simain6	dw	MENUX+(MENUW-5*8)/2,MENUY+139,5
	db	"保 存"
simain7	dw	MENUX+(MENUW-8*8)/2,MENUY+159,8
	db	"描画続行"
simain9	dw	MENUX+(MENUW-10*8)/2,MENUY+159,10
	db	"スクロール"
simain8	dw	MENUX+(MENUW-14*8)/2,MENUY+179,14
	db	"プログラム終了"
;
sicol0	dw	MENUX+(MENUW-8*8)/2,MENUY+44,8
	db	"個別設定"
sicol1	dw	MENUX+(MENUW-6*8)/2,MENUY+64,6
	db	"色間隔"
sicol2	dw	MENUX+(MENUW-14*8)/2,MENUY+84,14
	db	"グラデーション"
sicol3	dw	MENUX+(MENUW-8*8)/2,MENUY+104,8
	db	"読み込み"
sicol4	dw	MENUX+(MENUW-5*8)/2,MENUY+124,5
	db	"保 存"
sicol5	dw	MENUX+(MENUW-5*8)/2,MENUY+144,5
	db	"復 元"
data	ends

code	segment	use32 eo
	assume	cs:code,ds:data

entry:	mov	ax,0110h	; TOWNS BIOS
	mov	fs,ax
;-------------------------------
; Initialize CRTC & data
;-------------------------------
	mov	edi,offset egbwork	; initialize EGB
	mov	ecx,EGBSIZ
	xor	ah,ah
	call	pword ptr fs:[20h]
	mov	ax,0100h		; set virtual screen
	mov	dx,12
	call	pword ptr fs:[20h]
	mov	ax,0701h		; set background color
	mov	edx,C$DARK
	call	pword ptr fs:[20h]
;
	mov	esi,offset syspal	; pallet packet address
	mov	ecx,syspalN
init10:	call	setpal			; set pallet
	add	esi,4
	loop	init10
;
	mov	edi,offset palbuf	; pallet data buffer
	mov	dword ptr [edi],0	; pallet number = 0
	mov	esi,offset palpkt	; set display pallet
	mov	eax,0FFFFFFh/100
	mov	ecx,USRCN
	mov	dword ptr bpal,0
init12:	add	dword ptr bpal,eax
	call	setpal
	add	edi,3
	mov	dx,word ptr bpal
	mov	[edi],dx
	mov	dl,gpal
	mov	[edi+2],dl
	inc	palnum
	loop	init12
;-------------------------------
; save parameter & set
; in : es = stack & data segment
;-------------------------------
	push	ds
	mov	ax,0004h	; PSP selector
	mov	ds,ax
	mov	esi,80h			; command line address
	mov	edi,offset pathbuf	; saving address
	movzx	ecx,byte ptr [esi]	; string length
	movsb				; save string length
	rep	movsb			; save command line string
;
	mov	eax,ds:[0000005Ch]	; necessary size
	mov	edx,ds:[00000060h]	; program size
	pop	ds
	add	eax,11b		; round up to 4 times
	and	al,111100b
	mov	buffer,eax	; save calculate data buffer pointer
	sub	edx,eax
	mov	bufsiz,edx	; save buffer size
;
	push	ds
	xor	ax,ax		; read ANK font address
	mov	dx,0810h	; 8*16 dot
	xor	bl,bl		; ANK code = 0
	call	pword ptr fs:[0A0h]	; call font BIOS
	mov	ss:ankfnt,esi	; font offset
	mov	word ptr ss:ankfnt[4],ds	; font selector
	pop	ds
;-------------------------------
; starting screen
;-------------------------------
	mov	ax,0128h	; TOWNS VRAM (1 screen mode)
	mov	es,ax
;
	mov	esi,offset bgblock
	xor	edi,edi
	mov	count1,BGBH	; set block hight counter
init30:	mov	dx,BGBLN	; set block line counter
init32:	mov	bx,BGBCN	; set block column counter
init34:	mov	ecx,BGBW/2
	rep	movsw		; display 1 line of block
	sub	esi,BGBW	; rewind source line address
	dec	bx		; decrese block column counter
	jnz	init34
	add	edi,BGBH*VRAMW-BGBW*BGBCN	; next destination address
	dec	dx
	jnz	init32
	add	esi,BGBW
	sub	edi,BGBLN*BGBH*VRAMW-VRAMW
	dec	count1
	jnz	init30
;
	mov	esi,offset titbox	; title box clear
	mov	al,C$PANEL
	call	boxdwn
	mov	esi,offset scrbox	; screen box clear
	mov	al,C$PANEL
	call	boxdwn
;
	mov	edi,offset egbwork	; work address
	mov	ah,19h			; set font style
	mov	dx,100b			; shadow
	call	pword ptr fs:[20h]
	mov	bx,offset str1		; title string index
	mov	al,C$BLOCK
	call	dspss
;
	mov	ah,19h			; set font style
	xor	dx,dx			; standard
	call	pword ptr fs:[20h]
	mov	bx,offset str2		; starting message index
	mov	al,C$DARK		; string color
	call	dspss			; display strings
	mov	al,C$INT		; string color
	call	color
	mov	esi,offset str20	; "press RUN button"
	mov	ah,60h
	call	pword ptr fs:[20h]
;-------------------------------
; calculate initial screen
;-------------------------------
	mov	ebp,offset idata	; save address
	mov	count1,SCRH/2	; set screen hight counter
	mov	curb,IPOSY+IRESO*SCRH/2	; set y start position
init40:	call	getpad		; get pad button state
	cmp	al,P$RUN	; check press RUN button
	je	init60		; press to intterrupt
	mov	count2,SCRW	; set screen width counter
	mov	cura,IPOSX	; set x start position
init42:	push	ebp
	call	calc		; calculate repeat number
	pop	ebp
	mov	[ebp],al	; save to memory
	inc	ebp		; next memory address
	add	cura,IRESO	; next x position
	dec	count2
	jnz	init42
	inc	islin		; line calculated counter up
	add	curb,IRESO	; set next y position
	dec	count1
	jne	init40
;
init48:	call	getpad		; get pad button state
	cmp	al,P$RUN	; wait RUN button press
	jne	init48
;-------------------------------
; display rest initial screen
;-------------------------------
init60:	mov	esi,offset parbox	; parameter box clear
	mov	al,C$PANEL
	call	boxdwn
	mov	esi,offset palbox	; pallet box clear
	mov	al,C$PANEL
	call	boxdwn
;
	mov	edi,PTBADR-2*VRAMW-2	; pallet table address
	mov	ax,PTBCN*PTBW+4		; table width
	mov	dx,PTBLN*PTBH+3		; table hight
	call	boxup			; look like box up
;
	mov	dx,PTBLN	; pallet block line number counter
	xor	al,al		; initialize pallet number
	mov	edi,PTBADR	; VRAM start address
init62:	mov	bx,PTBH-1	; block lines counter
init64:	mov	ecx,PTBCN	; block column number
init66:	inc	al
	mov	ah,al
	stosw
	stosw
	loop	init66
	add	edi,VRAMW-PTBW*PTBCN
	sub	al,PTBCN
	dec	bx
	jnz	init64
	add	edi,VRAMW	; skip 1 line
	add	al,PTBCN
	dec	dx
	jnz	init62
;
	mov	bx,offset str4	; strings index
	mov	al,C$DARK	; dark shadow color
	call	dspss
;-------------------------------
; display mandelbrot figure
;-------------------------------
	call	dspis		; display initial screen
main10:	call	dspmain		; display main mandelbrot figure
;-------------------------------
; scroll mode
;-------------------------------
main20:	mov	esi,offset menubox	; menu box clear
	mov	al,C$PANEL
	call	boxdwn
	mov	bx,offset str5	; scroll mode message index
	mov	ax,6		; on drawing message numbers
	cmp	curstat,DS$FULL	; check display state
	jne	main21
	mov	ax,4		; message numbers on completion
main21:	mov	[bx],ax		; set message numbers
	mov	al,C$INT	; string color
	call	dspss		; display messages
;
	xor	ax,ax		; wait no press state
	call	waitp
main22:	call	getpad		; get pad state
	test	ah,P$TRIG1
	jnz	main10		; continue display
	cmp	al,P$SEL
	je	main30		; go to menu mode
	cmp	al,P$FWD
	je	main24		; go to scroll down
	cmp	al,P$BACK
	je	main26		; go to scroll up
	cmp	al,P$LEFT
	je	main28		; go to scroll right
	cmp	al,P$RIGHT
	jne	main22		; go to get new state
;
	call	srlft		; scroll left
	jmp	main22
main24:	call	srdwn		; scroll down
	jmp	main22
main26:	call	srup		; scroll up
	jmp	main22
main28:	call	srrgt		; scroll right
	jmp	main22
;-------------------------------
; menu mode
;-------------------------------
main30:	mov	esi,offset menubox
	mov	al,C$PANEL
	call	boxdwn		; menu box clear
	mov	bx,offset simain	; selector data address
	mov	ax,offset simain7
	cmp	curstat,DS$FULL
	jne	main32
	mov	ax,offset simain9
main32:	mov	[bx+18],ax
	call	select		; select item
	jc	main20		; escape to scroll mode
	shl	ax,2		; make offset
	cwde
	jmp	cmdtbl1[eax]	; jump destination procedure
;-------------------------------
; procedures for exit
;-------------------------------
main99:	mov	ax,4C00h		; exit to DOS
	int	21h

;*******************************
; srdwn : scroll down
;
; in : step = half scroll step
;           (0 is 1 step)
; call: dspbl,putfp
; use: eax,ebx,ecx,edx,esi,edi,ebp
;
srdwn	proc
;-------------------------------
; calculate new position
;-------------------------------
	movzx	ebx,step	; current dispaling step
	shl	ebx,1		; scroll step
	jnz	srdw10
	inc	ebx		; scroll step = 1
srdw10:	mov	eax,ebx
	mul	reso		; scroll amount
	sub	posy,eax	; new y position
	cmp	posy,-2 shl 24	; check lower limit
	jge	srdw20		; OK!
	add	posy,eax	; recover
	ret
;-------------------------------
; display new y position
;-------------------------------
srdw20:	push	ebx
	mov	eax,posy	; new position y
	neg	eax
	mov	edi,LPOSY	; display position
	call	putfp
	pop	ebx
;-------------------------------
; move down current screen
; in : ebx = scroll step
;-------------------------------
	mov	edi,(SCRY+SCRH-1)*VRAMW+SCRX
	mov	esi,edi
	imul	eax,ebx,VRAMW
	sub	esi,eax		; source start address
	mov	dx,SCRH
	sub	dx,bx		; move line counter
srdw40:	mov	ecx,SCRW/4
	rep	movs	dword ptr [edi],es:[esi]
	sub	esi,SCRW+VRAMW
	sub	edi,SCRW+VRAMW
	dec	dx
	jnz	srdw40
;-------------------------------
; display block line
; in : ebx = scroll step
;-------------------------------
	mov	edi,SCRADR
	mov	eax,posy	; start y position
	mov	curb,eax
	call	dspbl		; display block line
	ret
srdwn	endp

;*******************************
; srup : scroll up
;
; in : step = half scroll step
;           (0 is 1 step)
; call: dspbl,putfp
; use: eax,ebx,ecx,edx,esi,edi,ebp
;
srup	proc
;-------------------------------
; calculate new position
;-------------------------------
	movzx	ebx,step	; current dispaling step
	shl	ebx,1		; scroll step
	jnz	srup10
	inc	ebx		; scroll step = 1
srup10:	mov	eax,ebx
	mul	reso		; scroll amount
	imul	edx,reso,SCRH
	add	edx,posy
	add	edx,eax
	cmp	edx,2 shl 24	; check uppper limit
	jg	srup90		; over
	add	posy,eax	; new y position
;-------------------------------
; display new y position
;-------------------------------
	push	ebx
	mov	eax,posy	; new position y
	neg	eax
	mov	edi,LPOSY	; display position
	call	putfp
	pop	ebx
;-------------------------------
; move up current screen
; in : ebx = scroll step
;-------------------------------
	mov	edi,SCRADR
	imul	esi,ebx,VRAMW
	add	esi,edi		; source start address
	mov	dx,SCRH
	sub	dx,bx		; move line counter
srup20:	mov	ecx,SCRW/4
	rep	movs	dword ptr [edi],es:[esi]
	add	esi,-SCRW+VRAMW
	add	edi,-SCRW+VRAMW
	dec	dx
	jnz	srup20
;-------------------------------
; display block line
; in : ebx = scroll step
;      edi = block line address
;-------------------------------
	mov	eax,SCRH	; screen hight
	sub	eax,ebx		; screen position
	mul	reso		; offset y position
	add	eax,posy	; start y position
	mov	curb,eax
	call	dspbl		; display block line
srup90:	ret
srup	endp

;*******************************
; srrgt : scroll right
;
; in : step = half scroll step
;           (0 is 1 step)
; call: putfp,dspbc
; use: eax,ebx,ecx,edx,esi,edi,ebp
;
srrgt	proc
;-------------------------------
; calculate new position
;-------------------------------
	movzx	ebx,step	; current dispaling step
	shl	ebx,1		; scroll step
	jnz	srrt10
	inc	ebx		; scroll step = 1
srrt10:	mov	eax,ebx
	mul	reso		; scroll amount
	sub	posx,eax	; new x position
	cmp	posx,-2 shl 24	; check lower limit
	jge	srrt20		; OK!
	add	posx,eax	; recover
	ret
;-------------------------------
; display new x position
;-------------------------------
srrt20:	push	ebx
	mov	eax,posx	; new position x
	mov	edi,LPOSX	; display position
	call	putfp
	pop	ebx
;-------------------------------
; move right current screen
; in : ebx = scroll step
;-------------------------------
	std			; set direction flag
	mov	edi,SCRY*VRAMW+SCRX+SCRW-4
	mov	esi,edi
	sub	esi,ebx		; source start address
	mov	eax,SCRW	; screen width
	sub	eax,ebx		; move width
	mov	ebp,eax
	add	ebp,VRAMW-3	; VRAM step
	mov	dx,SCRH		; move line counter
	push	ebx
	mov	ebx,eax
	shr	eax,2
	and	ebx,11b
srrt30:	mov	ecx,eax		; set column counter
	rep	movs	dword ptr [edi],es:[esi]
	add	esi,3
	add	edi,3
	mov	ecx,ebx
	rep	movs	byte ptr [edi],es:[esi]
	add	esi,ebp		; next line
	add	edi,ebp
	dec	dx
	jnz	srrt30
	pop	ebx
	cld			; clear direction flag
;-------------------------------
; display block column
; in : ebx = scroll step
;-------------------------------
	mov	edi,SCRADR
	mov	eax,posx	; start x position
	mov	cura,eax
	call	dspbc		; display block column
	ret
srrgt	endp

;*******************************
; srlft : scroll left
;
; in : step = half scroll step
;           (0 is 1 step)
; call: putfp,dspbc
; use: eax,ebx,ecx,edx,esi,edi,ebp
;
srlft	proc
;-------------------------------
; calculate new position
;-------------------------------
	movzx	ebx,step	; current dispaling step
	shl	ebx,1		; scroll step
	jnz	srlt10
	inc	ebx		; scroll step = 1
srlt10:	mov	eax,ebx
	mul	reso		; scroll amount
	imul	edx,reso,SCRW
	add	edx,posx
	add	edx,eax
	cmp	edx,2 shl 24	; check uppper limit
	jg	srlt90		; over
	add	posx,eax	; new x position
;-------------------------------
; display new x position
;-------------------------------
	push	ebx
	mov	eax,posx	; new position x
	mov	edi,LPOSX	; display position
	call	putfp
	pop	ebx
;-------------------------------
; move left current screen
; in : ebx = scroll step
;-------------------------------
	push	ebx
	mov	edi,SCRADR
	mov	esi,edi
	add	esi,ebx		; source start address
	mov	eax,SCRW	; screen width
	sub	eax,ebx		; move width
	mov	ebp,VRAMW
	sub	ebp,eax		; VRAM step
	mov	dx,SCRH		; move line counter
	mov	ebx,eax
	shr	eax,2
	and	ebx,11b
srlt22:	mov	ecx,eax		; set column counter
	rep	movs	dword ptr [edi],es:[esi]
	mov	ecx,ebx
	rep	movs	byte ptr [edi],es:[esi]
	add	esi,ebp		; next line
	add	edi,ebp
	dec	dx
	jnz	srlt22
	pop	ebx
;-------------------------------
; display block column
; in : ebx = scroll step
;-------------------------------
	mov	edi,SCRADR+SCRW
	sub	edi,ebx		; block VRAM address
	mov	eax,SCRW
	sub	eax,ebx
	mul	reso
	add	eax,posx	; start x position
	mov	cura,eax
	call	dspbc		; display block column
srlt90:	ret
srlft	endp

;*******************************
; zoomin : zoom in command
;*******************************
zoomin	proc
;------------------------------
; dispaly message
;------------------------------
	mov	esi,offset mzoin	; display menu items
	call	dspmenu
	xor	ax,ax			; wait no press state
	call	waitp
	mov	esi,offset frame	; frame data address
	call	dspzx			; display zoom in x position
	call	dspzy			; display zoom in y position
	call	revfr			; display frame
;-------------------------------
; command input
;-------------------------------
zoin20:	call	getpad
	test	ax,ax
	jz	zoin20
	push	ax
	call	waitv			; wait VSYNC trigger
	call	revfr			; clear frame
	pop	ax
	test	ah,P$TRIG1
	jnz	zoin80			; decision
	test	ah,P$TRIG2
	jnz	main30			; return to main menu
	cmp	al,P$RUN
	je	zoin40			; magnify
	cmp	al,P$SEL
	je	zoin50			; reduce
	cmp	al,P$FWD
	je	zoin32			; move up
	cmp	al,P$BACK
	je	zoin36			; move down
	cmp	al,P$LEFT
	je	zoin38			; move left
;-------------------------------
; move frame
; in : esi = frame data address
;-------------------------------
	add	word ptr [esi],2	; move right
	call	revrl			; revise right limit
zoin30:	call	revfr			; display frame
	call	dspzx			; display zoom in x position
	jmp	zoin20
;
zoin32:	sub	word ptr [esi+2],2	; move up
	cmp	word ptr [esi+2],SCRY	; check upper limit
	jge	zoin34			; OK!
	mov	word ptr [esi+2],SCRY	; adjust
zoin34:	call	revfr			; display frame
	call	dspzy			; display zoom in y position
	jmp	zoin20
;
zoin36:	add	word ptr [esi+2],2	; move down
	call	revdl			; revise down limit
	jmp	zoin34
;
zoin38:	sub	word ptr [esi],2	; move left
	cmp	word ptr [esi],SCRX	; check left limit
	jge	zoin30			; OK!
	mov	word ptr [esi],SCRX	; adjust
	jmp	zoin30
;-------------------------------
; magnify frame size
; in : esi = frame data address
;-------------------------------
zoin40:	add	word ptr [esi+4],2	; extend width
	add	word ptr [esi+6],2	; extend hight
	dec	word ptr [esi]		; x position -1
	dec	word ptr [esi+2]	; y position -1
	cmp	word ptr [esi+4],SCRW	; check width (unite hight)
	jbe	zoin42			; OK!
	mov	word ptr [esi+4],SCRW	; adjust width
	mov	word ptr [esi+6],SCRW	; adjust hight
;
zoin42:	cmp	word ptr [esi+2],SCRY	; check upper limit
	jge	zoin44			; OK!
	mov	word ptr [esi+2],SCRY	; adjust y position
zoin44:	call	revdl			; revise down limit
	cmp	word ptr [esi],SCRX	; check left limit
	jge	zoin46			; OK!
	mov	word ptr [esi],SCRX	; adjust x position
zoin46:	call	revrl			; revise right limit
zoin48:	call	revfr			; display frame
	call	dspzx			; display zoom in x position
	call	dspzy			; display zoom in y position
	jmp	zoin20
;-------------------------------
; reduce frame size
; in : esi = frame data address
;-------------------------------
zoin50: sub	word ptr [esi+4],2	; narrow width
	sub	word ptr [esi+6],2	; narrow hight
	inc	word ptr [esi]		; x position +1
	inc	word ptr [esi+2]	; y position +1
	cmp	word ptr [esi+4],MINFR	; check frame size
	jge	zoin48			; OK!
	mov	word ptr [esi+4],MINFR	; adjust frame size
	mov	word ptr [esi+6],MINFR
	dec	word ptr [esi]		; x position -1
	dec	word ptr [esi+2]	; y position -1
	jmp	zoin48
;-------------------------------
; change region
;-------------------------------
zoin80:	movzx	eax,word ptr [esi+4]	; frame width
	mul	reso
	mov	ecx,SCRW	; screen width
	div	ecx		; calculate new resolution
	test	eax,eax		; check effectiveness
	jz	main30		; interrupt to menu mode
	push	eax		; save new resolution
;
	mov	ax,[esi]	; frame x position
	sub	ax,SCRX		; x pixcel position in screen
	cwde
	mul	reso
	add	posx,eax	; new x position
;
	mov	ax,[esi+2]	; frame y position
	sub	ax,SCRY		; y pixcel position in screen
	cwde
	mul	reso
	add	posy,eax	; new y position
;
	pop	eax		; load new resolution
	mov	reso,eax	; set new resolution
;
	call	dspfp		; display new frame parameter
	mov	curstat,DS$NONE	; display start
	jmp	main10		; go to display

;1111111111111111111111111111111
; dspzx : display position x
;          in zoom in frame
;
; in : esi = frame data address
; call: putfp
; use: all except for esi
;
dspzx	proc
	mov	ax,[esi]	; frame x position
	sub	ax,SCRX		; x pixcel position in screen
	cwde
	mul	reso
	add	eax,posx	; new x position
	mov	edi,LZPOSX
	push	esi
	call	putfp
	pop	esi
	ret
dspzx	endp

;1111111111111111111111111111111
; dspzy : display position y
;          in zoom in frame
;
; in : esi = frame data address
; call: putfp
; use: all except for esi
;
dspzy	proc
	mov	ax,[esi+2]	; frame y position
	sub	ax,SCRY		; y pixcel position in screen
	cwde
	mul	reso
	add	eax,posy	; new y position
	neg	eax		; neagative for display
	mov	edi,LZPOSY
	push	esi
	call	putfp
	pop	esi
	ret
dspzy	endp

;1111111111111111111111111111111
; revdl : revise down limit
; in : esi = frame data address
;
revdl	proc
	mov	ax,SCRY+SCRH		; down limit + 1
	sub	ax,[esi+2]		; effective hight
	sub	ax,[esi+6]		; check frame hight
	jge	revdl9			; OK!
	add	[esi+2],ax		; adjust y position
revdl9:	ret
revdl	endp

;1111111111111111111111111111111
; revrl : revise right limit
; in : esi = frame data address
;
revrl	proc
	mov	ax,SCRX+SCRW		; right limit + 1
	sub	ax,[esi]		; effective width
	sub	ax,[esi+4]		; check frame width
	jge	revrl9			; OK!
	add	[esi],ax		; adjust x position
revrl9:	ret
revrl	endp
zoomin	endp

;*******************************
; zoomout : zoom out command
;*******************************
zoomout	proc
	shl	reso,1			; change resolution
	imul	eax,reso,SCRW/4
	sub	posx,eax		; change x position
	sub	posy,eax		; change y position
	cmp	reso,(4 shl 24)/SCRW	; check resolution limit
	jbe	zout10			; OK!
	mov	reso,(4 shl 24)/SCRW	; adjust resolution
;
zout10:	mov	esi,offset posx		; revise position x
	call	revpos
	mov	esi,offset posy		; revise position y
	call	revpos
;
	call	dspfp			; display new frame parameter
	mov	curstat,DS$NONE		; display start
	jmp	main10			; go to display

;1111111111111111111111111111111
; revpos : revise position x|y
; in : esi = position data address
;
revpos	proc
	cmp	dword ptr [esi],-2 shl 24	; check lower limit
	jge	revp10				; OK!
	mov	dword ptr [esi],-2 shl 24	; adjust position
	jmp	short revp90
revp10:	mov	ecx,2 shl 24			; upper limit
	sub	ecx,[esi]			; effective width
	imul	eax,reso,SCRW			; screen width
	sub	ecx,eax
	jge	revp90				; OK!
	add	[esi],ecx			; adjust position
revp90:	ret
revpos	endp
zoomout	endp

;*******************************
; whole : return to  whole
;*******************************
whole	proc
	call	dspis		; display initial screen
	jmp	main30		; go to menu mode
whole	endp

;*******************************
; chglim : change limit
;*******************************
chglim	proc
	mov	ax,limit	; current limit
	mov	count1,ax	; initialize new limit
;-------------------------------
; display screen
;-------------------------------
	mov	esi,offset mcgl
	call	dspmenu		; display menu items
	mov	ax,limit	; display current limit
	mov	edi,LCL1
	call	putdec
;-------------------------------
; command input
;-------------------------------
	xor	ax,ax		; wait no press state
	call	waitp
;
cgl20:	call	waitv		; wait VSYNC trigger
	mov	ax,count1	; display limit
	mov	edi,LCL2
	call	putdec
cgl22:	call	getpad		; get pad state
	cmp	al,P$FWD
	je	cgl40		; limit up
	cmp	al,P$BACK
	je	cgl50		; limit down
	cmp	al,P$RUN
	je	cgl70		; automatically limit additon
	cmp	al,P$SEL
	je	cgl60		; automatically limit up
	test	ah,P$TRIG2
	jnz	main30		; cancel to return main menu
	test	ah,P$TRIG1
	jz	cgl22		; invalid
;-------------------------------
; decision upper limit
;-------------------------------
	mov	ax,count1	; new limit number
	mov	limit,ax	; set mew limit
	mov	edi,LLIMIT	; display new limit
	call	putdec
	mov	curstat,DS$NONE	; request redisplay
	jmp	main10		; go to display
;-------------------------------
; limit up
;-------------------------------
cgl40:	add	count1,10	; limit up
	jnc	cgl20
	sub	count1,10	; recover
	jmp	cgl22
;-------------------------------
; limit down
;-------------------------------
cgl50:	sub	count1,10	; limit down
	ja	cgl20
	add	count1,10	; recover
	jmp	cgl22
;-------------------------------
; automatically limit up
;-------------------------------
cgl60:	cmp	bufsiz,SCRW*SCRW*8	; check memorey
	jb	cgl68		; can't execute
;
	mov	esi,offset mautup	; auto up menu index
	call	dspmenu		; display menu items
	call	calup		; calculate up method
	jnc	cgl68		; calculate up end
	test	ah,P$TRIG1
	jz	cgl68		; quit end
;
	mov	ax,hbnum	; next limit number
	dec	ax		; new limit number
	mov	limit,ax	; set new limit
	mov	edi,LLIMIT	; display new limit
	call	putdec
cgl68:	jmp	main20		; go to scroll mode
;-------------------------------
; automatically additon
;-------------------------------
cgl70:	call	dspmain		; display main mandelbrot figure
	jc	cgl90		; interrupted
;
	mov	esi,offset mautad	; auto additon menu index
	call	dspmenu
	push	limit		; save current limit
cgl76:	shl	limit,1		; double limit
	jc	cgl78		; limit over
	mov	ax,limit	; display limit
	mov	edi,LAUP
	call	putdec
	call	dspadd		; display additive
	jnc	cgl76		; not intrrupted
;
	test	ah,P$TRIG1	; press A button ?
	jz	cgl78		; no then end without changing limit
	mov	ax,limit	; interrupted limit
	shr	ax,1		; new limit
	mov	[esp],ax	; set new limit on stack
	mov	edi,LLIMIT	; display new limit
	call	putdec
cgl78:	pop	limit		; set limit
;
cgl90:	jmp	main20		; go to scroll mode
chglim	endp

;*******************************
; load : load data
;*******************************
load	proc
;-------------------------------
; file select and open
;-------------------------------
	mov	exts,EXTALL	; set extension
load10:	call	open		; file open
	jc	main30		; quit to menu mode
;-------------------------------
; read location data
; in : ax = file handle
;-------------------------------
	mov	bx,ax			; file handel
	mov	ecx,size locdat		; location data size
	mov	edx,offset work1	; buffer pointer
	mov	ah,3Fh			; read file
	int	21h
	jnc	load30			; complete
;
load20:	mov	ah,3Eh			; file close
	int	21h
	jmp	load10			; repeat file open
;-------------------------------
; check location data & set
; in : edx = data address
;-------------------------------
load30:	mov	eax,[edx].locdatr	; resolution
	test	eax,eax
	jz	load20			; too small
	cmp	eax,(4 shl 24)/SCRW	; check range
	ja	load20			; too big
	mov	ecx,-2 shl 24		; location low limit
	mov	esi,[edx].locdatx	; position x
	cmp	esi,ecx			; check x low limit
	jl	load20			; too small
	mov	edi,[edx].locdaty	; position y
	cmp	edi,ecx			; check y low limit
	jl	load20			; too small
	push	eax
	imul	eax,SCRW		; screen width/hight
	neg	ecx			; location hight limit
	sub	ecx,eax
	pop	eax
	cmp	esi,ecx			; check x high position
	jg	load20			; too big
	cmp	edi,ecx			; check y high position
	jg	load20			; too big
;
	mov	posx,esi		; set position x
	mov	posy,edi		; set position y
	mov	reso,eax		; set resolution
	mov	ax,[edx].locdatl	; limit
	mov	limit,ax		; set limit
;-------------------------------
; load color data
; in : bx = file handle
;-------------------------------
	call	savpal			; backup color data
	mov	edx,offset palbuf
	mov	ecx,(1+USRCN)*3		; color data byte size
	mov	ah,3Fh			; read file
	int	21h
;-------------------------------
; file close & ending
; in : bx = file handle
;-------------------------------
	mov	ah,3Eh			; file close
	int	21h
;
	call	dspfp			; display frame parameter
	mov	ax,limit		; limit
	mov	edi,LLIMIT		; display limit
	call	putdec
	call	setdp			; set display pallet
;
	mov	curstat,DS$NONE		; request full display
	jmp	main10			; go to display
load	endp

;*******************************
; open : file open
;     with file selector
;
; in : exts = extension
;      buffer = file name buffer pointer
; out: cf = set for quit
;      ax = file handel
; call: dspmenu,waitp,chgsc,getpad
;       waitv,makpath
; use: all register
;      work1,count1,count2,hbnum
;
SCRSTEP	equ	3	; scroll step
MAXFIN	equ	8	; maximum file item number
open	proc
;-------------------------------
; intialize
;-------------------------------
	mov	esi,offset mload
	call	dspmenu		; display menu items
	xor	ax,ax
	mov	count1,ax	; file number of top item
	mov	count2,ax	; item number
	mov	hbnum,ax	; file number of current DTA
;
	xor	ax,ax		; item number
	call	dspfn		; display file name
	jc	open90		; quit end
	mov	ax,1
open10:	push	ax
	call	dspfn		; display file name
	pop	ax
	jc	open18		; no exist
	inc	ax
	cmp	ax,MAXFIN-1
	jbe	open10
;
open18:	xor	ax,ax		; wait no press state
	call	waitp
	mov	repcnt,INIREP	; clear pad input counter
;-------------------------------
; intesify current item
;-------------------------------
open20:	movzx	edi,count2
	imul	edi,18*VRAMW
	add	edi,(MENUY+35)*VRAMW+MENUX+28
	mov	bx,8*8+1	; string witdh
	mov	ax,C$DARK+C$INT*256
	call	chgsc		; intensify string
;-------------------------------
; input pad
;-------------------------------
open40:	call	getpad
	test	ax,ax		; press key ?
	jz	open40		; no press state
	test	ah,P$TRIG1	; A button
	jnz	open80		; go to open
	test	ah,P$TRIG2	; B button
	jnz	open90		; quit
	cmp	al,P$BACK
	je	open70		; move down
	cmp	al,P$FWD
	je	open50		; move up
;
	mov	repcnt,INIREP	; clear pad input counter
	jmp	open40
;-------------------------------
; cursor move up
; in : edi = string box address
;-------------------------------
open50:	mov	ax,count2	; current item number
	dec	ax		; move up
	jns	open60		; executable
	mov	ax,count1	; current top file number
	dec	ax
	js	open40		; can't scroll down
	mov	count1,ax	; new top file number
;
	mov	eax,C$PANEL+(C$PANEL shl 8)+(C$PANEL shl 16)+(C$PANEL shl 24)
	mov	bx,18/SCRSTEP
open52:	mov	esi,(MENUY+32+18*MAXFIN-SCRSTEP)*VRAMW+MENUX+28
	mov	edi,(MENUY+32+18*MAXFIN)*VRAMW+MENUX+28
	mov	dx,18*MAXFIN-2-SCRSTEP
	call	waitv		; wait VSYNC trigger
open54:	mov	ecx,8*8/4
	rep	movs	dword ptr [edi],es:[esi]
	sub	esi,VRAMW+8*8
	sub	edi,VRAMW+8*8
	dec	dx
	jnz	open54
	mov	dx,SCRSTEP
open56:	mov	ecx,8*8/4
	rep	stosd
	sub	edi,VRAMW+8*8
	dec	dx
	jnz	open56
	dec	bx
	jnz	open52
;
	xor	ax,ax		; top item
	call	dspfn		; display file name
	mov	edi,(MENUY+35+18)*VRAMW+MENUX+28	; next item address
	jmp	short open62
;-------------------------------
; check repeatable & set new item
; in : edi = string box address
;      ax = new item number
;-------------------------------
open60:	call	repable		; repeatalbe ?
	jc	open40		; invalid
	mov	count2,ax	; renew item number
open62:	mov	bx,8*8+1	; string width
	mov	ax,C$INT+C$DARK*256
	call	chgsc		; weaken string
	jmp	open20		; go to display cursor
;-------------------------------
; cursor move down
; in : edi = string box address
;-------------------------------
open70:	mov	ax,count2	; current item number
	add	ax,count1	; current file number
	inc	ax		; next file number
	push	edi
	call	getfp		; get file name string pointer
	pop	edi
	jc	open40		; no exist
;
	mov	ax,count2	; current item number
	inc	ax		; next item number
	cmp	ax,MAXFIN-1	; check down limit
	jbe	open60		; OK!
;
	mov	eax,C$PANEL+(C$PANEL shl 8)+(C$PANEL shl 16)+(C$PANEL shl 24)
	mov	bx,18/SCRSTEP
open72:	mov	esi,(MENUY+35+SCRSTEP)*VRAMW+MENUX+28
	mov	edi,(MENUY+35)*VRAMW+MENUX+28
	mov	dx,18*MAXFIN-2-SCRSTEP
	call	waitv		; wait VSYNC trigger
open74:	mov	ecx,8*8/4
	rep	movs	dword ptr [edi],es:[esi]
	add	esi,VRAMW-8*8
	add	edi,VRAMW-8*8
	dec	dx
	jnz	open74
	mov	dx,SCRSTEP
open76:	mov	ecx,8*8/4
	rep	stosd
	add	edi,VRAMW-8*8
	dec	dx
	jnz	open76
	dec	bx
	jnz	open72
;
	inc	count1		; new top file number
	mov	ax,MAXFIN-1	; bottom item
	call	dspfn		; display file name
	mov	edi,(MENUY+35+18*(MAXFIN-2))*VRAMW+MENUX+28	; weaken item
	jmp	open62
;-------------------------------
; file open
;-------------------------------
open80:	mov	ax,count1	; top item file number
	add	ax,count2	; destination file number
	call	getfp		; get file name string pointer
	jc	open90		; don't exist
	mov	eax,exts	; extension string
	call	makpath		; make pathlist
	mov	edx,offset pathbuf+1
	mov	ax,3D00h	; read open
	int	21h
	ret
open90:	stc		; quit end
	ret

;*******************************
; getfp : get file name stinrg pointer
;    with 6 byte header
;
; in : ax = file number
;      hbnum = current readin number
; out: esi = file name pointer
; err: cf = set by no exist
;
getfp	proc
	push	es
	mov	dx,0004h	; PSP selector
	mov	es,dx
	mov	esi,buffer	; saving buffer pointer
	cmp	ax,hbnum	; check read in
	jb	getfp7		; red
	mov	bx,ax		; save destination file number
;-------------------------------
; read file names in buffer
; in : bx = destination file number
;      esi = buffer pointer
;-------------------------------
	mov	ax,6+13
	mul	hbnum
	cwde
	add	esi,eax		; saving start address
	test	ax,ax		; first read ?
	jz	getfp4		; yes
;
getfp1:	mov	ah,4Fh		; search next file
	int	21h
	jc	getfp9		; don't find
;
getfp2:	mov	edi,80h+1Eh	; file name offset in DTA buffer
	mov	word ptr [esi+4],-5	; clear file name length
	mov	ecx,esi
	add	ecx,6		; skip header bytes
getfp3:	mov	al,es:[edi]
	mov	byte ptr [ecx],al
	inc	word ptr [esi+4]	; count up file name length
	inc	edi		; proceed addresses
	inc	ecx
	test	al,al		; check string end
	jnz	getfp3		; go to read next charactor
	inc	hbnum		; renew readin number
	cmp	bx,hbnum	; check file number
	jb	getfp8		; found
	add	esi,6+13	; next file name saving address
	jmp	getfp1
;
getfp4:	mov	edx,offset pathbuf+1	; search pathlist pointer
	movzx	ecx,byte ptr [edx-1]	; directory list length
	mov	byte ptr [edx+ecx],'*'	; set wild card
	mov	eax,exts		; extension string
	mov	[edx+ecx+1],eax		; set extension(ex. ".MDL")
	mov	byte ptr [edx+ecx+5],0	; null terminate
	xor	cx,cx		; normal attribute
	mov	ah,4Eh		; search first file
	int	21h
	jc	getfp9		; don't find
	jmp	getfp2
;-------------------------------
; return file string pointer
; in : ax = file number
;      esi = buffer pointer
;-------------------------------
getfp7:	imul	ax,6+13
	cwde
	add	esi,eax
getfp8:	clc
getfp9:	pop	es
	ret
getfp	endp

;*******************************
; dspfn : display file name
;
; in : ax = item number
;      count1 = top file number
;      fs = TOWNS BIOS selector
; err: cf = set by no exist
; call: getfp
;
dspfn	proc
	push	ax
	add	ax,count1	; distination file number
	call	getfp		; get file name pointer
	pop	ax
	jc	dspfn9		; no exist
;
	mov	word ptr [esi],MENUX+28	; set x position
	imul	ax,18
	add	ax,MENUY+50
	mov	[esi+2],ax	; set y position
	mov	ah,60h		; display string
	mov	edi,offset egbwork
	call	pword ptr fs:[20h]
	clc
dspfn9:	ret
dspfn	endp

;*******************************
; makpath : make pathlist
;
; in : esi = file name string
;          4(2) byte length
;          6(n) file name
;      eax = extension (.MDL/.MDC)
;      pathbuf = directory list
; out: pathbuf = pathlist buffer
;          1(n) pathlist (ASCIZ)
; err: cf = set by invalid file name
; use: ecx,esi,edi
;
makpath	proc
	push	es
	mov	cx,ds			; set es selector
	mov	es,cx
	mov	edi,offset pathbuf	; pathlist buffer pointer
	movzx	ecx,byte ptr [edi]	; directory list length
	inc	ecx			; add byte of length
	add	edi,ecx			; directory tail address
	movzx	ecx,word ptr [esi+4]	; file name byte length
	cmp	ecx,1			; check length
	jc	makpa9			; invalid
	add	esi,6			; file name start address & clear carry
	rep	movsb			; copy file name
	mov	[edi],eax		; set extension (ex. ".MDL")
	mov	byte ptr [edi+4],0	; null terminate
makpa9:	pop	es
	ret
makpath	endp
open	endp

;*******************************
; save : save data
;*******************************
save	proc
;-------------------------------
; input file name and create
;-------------------------------
save10:	mov	eax,EXTALL	; extension
	call	create		; file create
	jc	save90		; quit
;-------------------------------
; write data
; in : ax = file handle
;-------------------------------
	mov	edx,offset posx	; data pointer
	mov	ecx,size locdat	; location data byte size
	mov	bx,ax		; file handle
	mov	ah,40h		; write
	int	21h
	jc	save50
	mov	edx,offset palbuf
	mov	ecx,(1+USRCN)*3	; color data byte size
	mov	ah,40h		; write
	int	21h
;-------------------------------
; handle close
; in : bx = file handle
;      cf = error flag
;-------------------------------
save50:	pushf
	mov	ah,3Eh		; file close
	int	21h
	popf
	jc	save10		; repeat input
save90:	jmp	main30		; go to menu mode
save	endp

;*******************************
; create : create file
;
; in : eax = extension
;      pathbuf = directory path
; out: cf = set for quit
;      ax = file handel
; call: dspmenu,getstr,makpath
; use: all reg & work1
;
LOCFI	equ	(MENUX+(MENUW-8*8)/2)+((MENUY+80) shl 16)
create	proc
	push	eax		; save extension
;-------------------------------
; display screen
;-------------------------------
crte10:	mov	esi,offset msave
	call	dspmenu		; display menu items
;-------------------------------
; get file name
;-------------------------------
	mov	esi,offset work1
	mov	dword ptr [esi],LOCFI	; location of file input
	mov	cx,8		; maximum length
	call	getstr		; get string from keybord
;-------------------------------
; make pathlist
; in : esi = string buffer base
;-------------------------------
	mov	eax,[esp]	; extension
	call	makpath		; make pathlist
	jc	crte99		; quit
;-------------------------------
; file create
;-------------------------------
	mov	edx,offset pathbuf+1
	mov	ah,3Ch		; file create
	xor	cx,cx		; common attribute
	int	21h
	jc	crte10		; go to repeat
;
crte99:	pop	ecx		; abandon
	ret
create	endp

;*******************************
; chgcol : change color
;*******************************
chgcol	proc
	mov	spflg,FALSE	; save pallet flag off
chgco1:	mov	esi,offset mcgc
	call	dspmenu		; display menu items
	mov	bx,offset sicol	; selector data address
	call	select		; select item
	jc	main30		; escape to main menu mode
	shl	ax,2		; make offset
	cwde
	jmp	cmdtbl2[eax]	; jump destination procedure
chgcol	endp

;*******************************
; indcol : change color individually
;*******************************
indcol	proc
;-------------------------------
; initailize
;-------------------------------
	mov	numwid,3	; set display width of integer
	mov	cura,SCRX+SCRW/2	; cross cursor x position
	mov	curb,SCRY+SCRH/2	; cross cursor y position
;
indc10:	mov	esi,offset mindc
	call	dspmenu		; display menu items
	mov	repcnt,INIREP	; intialize repeat counter
	xor	ax,ax		; wait no press state
	call	waitp
;-------------------------------
; display current color data
;-------------------------------
indc20:	call	dsppbs		; display panel & bars
;-------------------------------
; command input
;-------------------------------
indc40:	call	getpad		; get pad state
	cmp	al,P$LEFT
	je	indc50		; pallet code down
	cmp	al,P$RIGHT
	je	indc60		; pallet code up
	mov	repcnt,INIREP	; intialize repeat counter
	cmp	al,P$SEL
	je	extpix		; go to extract pallet number from poxcel
	test	ah,P$TRIG1
	jnz	coledit		; go to edit mode
	test	ah,P$TRIG2
	jz	indc40		; invalid
;
indc90:	mov	numwid,5	; restore width of integer
	jmp	chgco1		; go to change color menu mode
;-------------------------------
; color number down
;-------------------------------
indc50:	call	repable		; repeatable ?
	jc	indc40		; invalid
	movzx	ax,colnum	; current color number
	sub	ax,1		; number down
	jb	indc40		; invalid
	mov	colnum,al	; set new number
	jmp	indc20		; to display
;-------------------------------
; color number up
;-------------------------------
indc60:	call	repable		; repeatable ?
	jc	indc40		; invalid
	movzx	ax,colnum	; current color number
	inc	ax		; number up
	cmp	ax,USRCN	; check
	ja	indc40		; invalid
	mov	colnum,al	; set new number
	jmp	indc20		; go to dispaly
indcol	endp

;*******************************
; dsppbs : display panel & bars
; copy bpal,rpal,gpal from colbuf
;
; in : colnum = color number
;      palbuf = pallet buffer
; out: bpal,rpal,gpal
; call: getpal,dspcp,dspbar
; use: all
;
dsppbs	proc
	call	getpal		; get pallet data
	call	dspcp		; display color panel
	xor	al,al		; blue
	call	dspbar		; display bar
	mov	al,1		; red
	call	dspbar		; display bar
	mov	al,2		; green
	call	dspbar		; display bar
	ret
dsppbs	endp

;*******************************
; getpal : get pallet data
;   from palbuf to palpkt
;
; in : colnum = color number
;      palbuf = pallet buffer
; out: bpal,rpal,gpal
; use: eax,esi
;
getpal	proc
	movzx	esi,colnum
	imul	esi,3		; pallet data offset
	mov	eax,dword ptr ss:palbuf[esi]	; level data + 1
	mov	dword ptr bpal,eax	; set level data
	ret
getpal	endp

;*******************************
; dspcp : display color panel
;    with color code number
;
; in : colnum = color number
; call: putdec
;
LINDCC	equ	MENUX+(MENUW-24)/2+(MENUY+44)*VRAMW	; color code
dspcp	proc
	movzx	ax,colnum	; dispaly current color number
	mov	edi,LINDCC
	call	putdec
;
	mov	edi,(MENUY+47)*VRAMW+MENUX+(MENUW-74)/2
	mov	bx,16		; set hight counter
	mov	al,colnum	; color number
	mov	ah,al		; extend AL to AX
dscp10:	mov	ecx,74/2	; set width counter
	rep	stosw
	add	edi,VRAMW-74
	dec	bx
	jnz	dscp10
	ret
dspcp	endp

;*******************************
; dspbar : display level bar
;
; in : al = RGB species
;           B=0,R=1,G=2
;      bpal,rpal,gpal
; call: putdec
;
LINDCB	equ	MENUX+(MENUW-70)/2+72+(MENUY+92)*VRAMW	; blue level number
dspbar	proc
	movzx	esi,al		; RGB offset
	add	esi,offset bpal	; destination address
	movzx	edi,al
	imul	edi,16*VRAMW
	add	edi,LINDCB	; destination display VRAM address
	movzx	ax,byte ptr [esi]	; destination level
	push	edi
	push	ax
	call	putdec
	pop	dx		; destination level
	pop	edi
	add	edi,-14*VRAMW-72+3
;-------------------------------
; draw color level bar
; in : edi = bar address
;      dl = color level
;-------------------------------
	xor	dh,dh
	add	dx,11b		; round
	shr	dx,2
	mov	dh,64		; total width
	sub	dh,dl		; top blank width
	mov	bh,12		; set hight counter
dsbar1:	movzx	ecx,dl
	mov	al,C$INT
	rep	stosb
	movzx	ecx,dh
	mov	al,C$PANEL
	rep	stosb
	add	edi,VRAMW-64	; next line
	dec	bh
	jnz	dsbar1
	ret
dspbar	endp

;*******************************
; coledit : color edit
;*******************************
coledit	proc
;-------------------------------
; initailize
;-------------------------------
	mov	esi,offset mced
	call	dspmenu		; display menu items
	call	dsppbs		; display color panel & bars
	xor	ax,ax		; wait no press state
	call	waitp
	mov	al,colnum
	mov	palnum,al
	mov	al,C$INT	; string color
	call	dspRGB		; display destination RGB string
	cmp	spflg,TRUE	; check save pallet flag
	je	ced10
	call	savpal		; save all pallets
	mov	spflg,TRUE
ced10:	mov	repcnt,INIREP	; intialize repeat counter
;-------------------------------
; command input
;-------------------------------
ced40:	call	getpad		; get pad state
	cmp	al,P$SEL
	je	ced60		; RGB rotate
	mov	repcnt,INIREP	; intialize repeat counter
	cmp	al,P$RIGHT
	je	ced50		; level up
	cmp	al,P$LEFT
	je	ced55		; level down
	test	ah,P$TRIG2
	jnz	ced80		; cancel
	test	ah,P$TRIG1
	jz	ced40		; invalid
;
	movzx	edi,colnum
	imul	edi,3		; destination color offset
	mov	ax,word ptr bpal		; new pallet levels
	mov	word ptr ss:palbuf[edi],ax	; save new color data
	mov	al,gpal
	mov	ss:palbuf[edi+2],al
	jmp	indc10		; return to color select mode
;-------------------------------
; color level up
;-------------------------------
ced50:	call	repable		; repeatable ?
	jc	ced40		; invalid
	movzx	esi,currgb	; current RGB
	add	esi,offset bpal	; destination RGB parameter address
	inc	byte ptr [esi]	; increment level
	jnz	ced52		; OK!
	mov	byte ptr [esi],255	; to maximum value
ced52:	mov	esi,offset palpkt
	call	setpal		; set pallet register
	mov	al,currgb	; current RGB
	call	dspbar		; display bar
	jmp	ced40
;-------------------------------
; color level down
;-------------------------------
ced55:	call	repable		; repeatable ?
	jc	ced40		; invalid
	movzx	esi,currgb	; current RGB
	add	esi,offset bpal	; destination RGB parameter address
	sub	byte ptr [esi],1	; decriment level
	jnc	ced52		; OK!
	inc	byte ptr [esi]	; to minimum value = 0
	jmp	ced40
;-------------------------------
; distination RGB rotate
;-------------------------------
ced60:	call	repable		; repeatable ?
	jc	ced40		; invalid
	mov	al,C$DARK	; intensity off
	call	dspRGB
	inc	currgb		; change current RGB species
	cmp	currgb,2
	jbe	ced62		; change OK!
	mov	currgb,0	; round
ced62:	mov	al,C$INT	; intensity on
	call	dspRGB
	jmp	ced40		; to get next command
;-------------------------------
; cancel
;-------------------------------
ced80:	call	getpal		; set pallet data from palbuf to palpkt
	call	waitv		; wait VSYNC trigger
	mov	esi,offset palpkt
	call	setpal		; set pallet register
	jmp	indc10		; return to color select mode

;*******************************
; dspRGB : display RGB string
;
; in : currgb = current RGB species
;      al = string color code
; call: color
;
dspRGB	proc
	call	color		; set string color
	mov	esi,offset strRGB
	mov	al,strRGBL	; string data length
	mul	currgb		; current RGB string offset
	cwde
	add	esi,eax		; current RGB string address
	mov	ah,60h		; display string
	call	pword ptr fs:[20h]
	ret
dspRGB	endp
coledit	endp

;*******************************
; savpal : save pallets
;   backup pallets destroy
;
; in : palbuf = current pallets
;      palbak = saving area
; use: ax,ecx,esi,edi
;
savpal	proc
	mov	esi,offset palbuf
	mov	edi,offset palbak
	mov	ecx,USRCN+1
savpa1:	lodsw
	mov	[edi],ax
	lodsb
	mov	[edi+2],al
	add	edi,3
	loop	savpa1
	ret
savpal	endp

;*******************************
; extpix : extact pallet number
;        from pixcel
;*******************************
extpix	proc
;-------------------------------
; initialize
;-------------------------------
	mov	esi,offset mexp
	call	dspmenu		; display menu items
	xor	ax,ax		; wait no press state
	call	waitp
	mov	al,C$PANEL
	xchg	al,colnum	; initialize number except display color
	mov	palnum,al	; save color number
;-------------------------------
; read pixcel & display
;-------------------------------
expi10:	imul	esi,curb,VRAMW
	add	esi,cura
	mov	al,es:[esi]	; destination pixcel data
	cmp	al,colnum	; check same color
	je	expi48		; same to skip draw
	mov	colnum,al	; save pallet number
	call	dspcros		; display cross cursor
	call	dsppbs		; display panel & bars
;-------------------------------
; command input
;-------------------------------
expi40:	call	getpad		; get pad state
	test	ax,ax
	jz	expi40		; no press
	call	waitv		; wait VSYNC
	call	dspcros		; erase cross cursor
;
	cmp	al,P$LEFT
	je	expi50		; left move
	cmp	al,P$RIGHT
	je	expi55		; right move
	cmp	al,P$FWD
	je	expi60		; up move
	cmp	al,P$BACK
	je	expi65		; down move
	test	ah,P$TRIG1
	jnz	indc10		; go to color number select mode
	test	ah,P$TRIG2
	jnz	expi70		; quit end
;
expi48:	call	dspcros		; display cross cursor
	jmp	expi40		; go to get pad state
;-------------------------------
; cross cursor left
;-------------------------------
expi50:	mov	eax,cura	; current x position
	dec	eax		; decrement
	cmp	eax,SCRX	; check limit
	jae	expi52		; OK!
	mov	eax,SCRX	; correction
expi52:	mov	cura,eax	; save x position
	jmp	expi10		; go to display
;-------------------------------
; cross cursor right
;-------------------------------
expi55:	mov	eax,cura	; current x position
	inc	eax		; increment
	cmp	eax,SCRX+SCRW	; check limit
	jb	expi52		; OK!
	mov	eax,SCRX+SCRW-1	; correction
	jmp	expi52		; go to save
;-------------------------------
; cross cursor up
;-------------------------------
expi60:	mov	eax,curb	; current y position
	dec	eax		; decrement
	cmp	eax,SCRY	; check limit
	jae	expi62		; OK!
	mov	eax,SCRY	; correction
expi62:	mov	curb,eax	; save y position
	jmp	expi10		; go to dislay
;-------------------------------
; crosss cursor down
;-------------------------------
expi65:	mov	eax,curb	; current y position
	inc	eax		; increment
	cmp	eax,SCRY+SCRH	; check limit
	jb	expi62		; OK!
	mov	eax,SCRY+SCRH-1	; correction
	jmp	expi62		; go to save
;-------------------------------
; quit end
;-------------------------------
expi70:	mov	al,palnum	; resotre color number
	mov	colnum,al
	jmp	indc10		; return to color number select mode

;*******************************
; dspcros : dsplay cross cursor
;
; in : cura = current x position
;      curb = current y position
;      es = VRAM selector
; use: ecx,edi
;
dspcros	proc
;-------------------------------
; horizon line
;-------------------------------
	imul	edi,curb,VRAMW
	add	edi,SCRX	; line start address
	mov	ecx,SCRW/4
dscrs1:	not	dword ptr es:[edi]
	add	edi,4
	loop	dscrs1
;-------------------------------
; vertical line
;-------------------------------
	mov	edi,SCRY*VRAMW
	add	edi,cura	; line start address
	mov	ecx,SCRH
dscrs2:	not	byte ptr es:[edi]
	add	edi,VRAMW
	loop	dscrs2
	ret
dspcros	endp
extpix	endp

;*******************************
; setcs : set color step
;*******************************
setcs	proc
;-------------------------------
; initialize
;-------------------------------
	mov	esi,offset msetcs
	call	dspmenu		; display menu items
	mov	count1,1	; color step
	mov	count2,1	; color step change unit
	mov	hbnum,0		; auto change flag off
	mov	currgb,P$FWD	; auto command
	mov	ax,count2	; display current change unit
	mov	edi,LCSTEP1
	call	putdec
	xor	ax,ax		; wait no press state
	call	waitp
;-------------------------------
; display screen
;-------------------------------
stcs10:	mov	ax,count1	; display current step
	mov	edi,LCSTEP2
	call	putdec
;
	mov	esi,offset work1	; pallet packet
	mov	dword ptr [esi],0	; initialize pallet number & levels
	mov	bx,PALSBN		; set pallet block counter
	movzx	eax,count1		; color step
	mov	ecx,PALSBR-1		; set rest pallet number
stcs12:	call	waitv			; wait VSYNC
stcs14:	inc	byte ptr [esi]		; next pallet number
	add	[esi+1],eax		; set new level
	call	setpal			; set pallet code
	loop	stcs14
	mov	ecx,PALSBS		; set pallet block size
	dec	bx
	jnz	stcs12
;-------------------------------
; command input
;-------------------------------
stcs30:	call	getpad		; get pad state
stcs32:	cmp	al,P$FWD
	je	stcs50		; step up
	cmp	al,P$BACK
	je	stcs55		; step down
	cmp	al,P$LEFT
	je	stcs60		; unit up
	cmp	al,P$RIGHT
	je	stcs65		; unit	down
	cmp	al,P$RUN
	je	stcs70		; switch auto change
;
	cmp	hbnum,0		; check auto change flag
	je	stcs34		; off
	mov	al,currgb	; load auto command
	jmp	stcs32		; go to dispatch

stcs34:	test	ah,P$TRIG2
	jnz	stcs80		; cancel
	test	ah,P$TRIG1
	jz	stcs30		; invalid
;-------------------------------
; decision end
;-------------------------------
	cmp	spflg,TRUE	; check save pallet flag
	je	stcs40
	call	savpal		; save all pallets
	mov	spflg,TRUE
;
stcs40:	mov	edi,offset palbuf	; pallet buffer
	mov	ecx,USRCN		; set pallet number counter
	movzx	eax,count1		; color step
	xor	edx,edx			; initialize color level
stcs42:	add	edi,3		; next pallet address
	add	edx,eax		; next color level
	mov	[edi],edx	; set color level + 1
	loop	stcs42
	jmp	chgcol		; return to color menu
;-------------------------------
; step up or down
; in : al = command code
;-------------------------------
stcs50:	mov	currgb,al	; set auto command
	mov	ax,count2	; change unit
	add	count1,ax	; step up
	jnz	stcs10		; go to change pallet
	inc	count1		; skip zero step
	jmp	stcs10
;
stcs55:	mov	currgb,al	; set auto command
	mov	ax,count2	; change unit
	sub	count1,ax	; step down
	jnz	stcs10		; go to change pallet
	dec	count1		; skip zero step
	jmp	stcs10
;-------------------------------
; unit up or down
;-------------------------------
stcs60:	inc	count2		; cahnge unit up
	jns	stcs62
	dec	count2
stcs62:	call	waitv		; wait VSYNC trigger
	mov	ax,count2	; display current change unit
	mov	edi,LCSTEP1
	call	putdec
	jmp	stcs30		; go to pad input
;
stcs65:	dec	count2		; change unit down
	jnz	stcs62
	inc	count2
	jmp	stcs62		; go to display
;-------------------------------
; auto change switch
;-------------------------------
stcs70:	not	hbnum		; switch auto change flag
	xor	ax,ax		; wait no press state
	call	waitp
	jmp	stcs30		; go to pad input
;-------------------------------
; quit end
;-------------------------------
stcs80:	call	setdp		; set display pallet by old data
	jmp	chgcol		; return to color menu
setcs	endp

;*******************************
; grad : gradation
;*******************************
grad	proc
;-------------------------------
; initialize
;-------------------------------
	mov	esi,offset mgrad
	call	dspmenu		; display menu items
	mov	count1,111b	; color number 1 = White
	mov	count2,000b	; color number 250 = Black
	mov	hbnum,0		; select number = 250
	mov	edi,(MENUY+60-17+2)*VRAMW+MENUX+40
	mov	al,1		; color number 1
	call	gradp		; draw gradation panel
	mov	edi,(MENUY+120-17+2)*VRAMW+MENUX+40
	mov	al,250		; color number 250
	call	gradp		; draw gradation panel
	call	dspgcn		; display gradation color number
;-------------------------------
; change pallet
;-------------------------------
grad20:	mov	esi,offset work1	; pallet packet
	call	makgd			; make gradation data
	mov	bx,PALSBN		; set pallet block counter
	mov	ecx,PALSBR-1		; set rest pallet number execpt 0
grad26:	call	waitv			; wait VSYNC
grad28:	call	setpal			; set pallet code
	inc	byte ptr [esi]		; next pallet number
	mov	al,[esi+4]
	add	[esi+1],al		; new blue level
	mov	al,[esi+5]
	add	[esi+2],al		; new red level
	mov	al,[esi+6]
	add	[esi+3],al		; new green level
	loop	grad28
	mov	ecx,PALSBS		; set pallet full block size
	dec	bx
	jnz	grad26
;-------------------------------
; command input
;-------------------------------
grad30:	xor	ax,ax		; wait no press state
	call	waitp
grad32:	call	getpad		; get pad state
	cmp	al,P$RIGHT
	je	grad50		; next color
	cmp	al,P$LEFT
	je	grad60		; previous color
	cmp	al,P$SEL
	je	grad70		; select 0 or 250
	test	ah,P$TRIG2
	jnz	grad80		; cancel
	test	ah,P$TRIG1
	jz	grad32		; invalid
;-------------------------------
; decision end
;-------------------------------
	cmp	spflg,TRUE	; check save pallet flag
	je	grad40
	call	savpal		; save all pallets
	mov	spflg,TRUE
;
grad40:	mov	esi,offset work1	; pallet packet
	call	makgd			; make gradation data
	mov	edi,offset palbuf+3	; user pallet buffer address
	mov	ecx,USRCN		; set pallet number counter
	mov	ax,[esi+1]	; blue,red start level
	mov	dl,[esi+3]	; green start level
grad42:	mov	[edi],ax	; set green,red level
	mov	[edi+2],dl	; set blue level
	add	edi,3		; next pallet address
	add	al,[esi+4]	; new blue level
	add	ah,[esi+5]	; new red level
	add	dl,[esi+6]	; new green level
	loop	grad42
	jmp	chgcol		; return to color menu
;-------------------------------
; next color
;-------------------------------
grad50:	cmp	hbnum,0		; check destination
	je	grad52
	inc	count1
	jmp	grad20
grad52:	inc	count2
	jmp	grad20
;-------------------------------
; previous color
;-------------------------------
grad60:	cmp	hbnum,0		; check destination
	je	grad62		; color 250
	or	count1,1000b
	dec	count1
	jmp	grad20
grad62:	or	count2,1000b
	dec	count2
	jmp	grad20
;-------------------------------
; select 0 or 250
;-------------------------------
grad70:	not	hbnum		; change destination color
	call	dspgcn		; display gradatino color number
	jmp	grad30		; go to next command
;-------------------------------
; cancel end
;-------------------------------
grad80:	call	setdp		; set display pallet by old data
	jmp	chgcol		; return to color menu

;*******************************
; gradp : draw gradation panel
;
; in : edi = start address
;      al = color code
;
gradp	proc
	mov	bx,16		; set hight counter
	mov	ah,al
gradp1:	mov	ecx,76/2	; set width counter
	rep	stosw
	add	edi,VRAMW-76
	dec	bx
	jnz	gradp1
	ret
gradp	endp

;*******************************
; dspgcn : display gradation
;      color number
;   select item is intensified
;
; in : hbnum = color number flag
;         00 = 250
;         FF = 1
; call: color
;
gcnstr1	dw	MENUX+8+16,MENUY+60,1	; lowest color number string
	db	"1"
gcnstr2	dw	MENUX+8,MENUY+120,3	; highest color number string
	db	"250"
;
dspgcn	proc
	mov	ax,(C$DARK shl 8)+C$INT
	cmp	hbnum,0
	je	dpgcn1			; highest number
	xchg	ah,al
dpgcn1:	push	ax
	mov	al,ah
	call	color			; set color
	mov	edi,offset egbwork	; EGB work address
	mov	esi,offset gcnstr1	; lowest number
	mov	ah,60h			; display string
	call	pword ptr fs:[20h]
	pop	ax
	call	color			; set color
	mov	esi,offset gcnstr2	; highest number
	mov	ah,60h			; display string
	call	pword ptr fs:[20h]
	ret
dspgcn	endp

;*******************************
; makgd : make gradation data
;
; in : esi = work buffer
;        0(1) pallet number
;        1(1) blue level
;        2(1) red level
;        3(1) green level
;        4(1) blue step
;        5(1) red step
;        6(1) green step
;      count1 = color 0 level flag
;      count2 = color 250 level flag
;
makgd	proc
	mov	byte ptr [esi],1	; initialize pallet number
	mov	dx,count1		; color 1 level flag
	mov	bx,count2		; color 250 level flag
	mov	ecx,3
makgd1:	mov	ax,255-USRCN		; AL = lowest level
	shr	dx,1
	jnc	makgd2
	mov	ax,(-1 shl 8)+USRCN	; AL = highest level
makgd2:	mov	[esi+ecx],al		; set initial level
	shr	bx,1
	adc	ah,0
	mov	[esi+ecx+3],ah		; set level step (-1|0|+1)
	loop	makgd1
	ret
makgd	endp
grad	endp

;*******************************
; cload : load color data
;*******************************
cload	proc
	mov	exts,EXTCOL		; set extension
	call	open			; file open
	jc	clod90			; quit
	mov	bx,ax			; file handel
;
	cmp	spflg,TRUE		; check save pallet flag
	je	clod10
	call	savpal			; save all pallets
	mov	spflg,TRUE
;
clod10:	mov	edx,offset palbuf	; pallet buffer
	mov	ecx,(1+USRCN)*3		; color data byte size
	mov	ah,3Fh			; read file
	int	21h
	mov	ah,3Eh			; file close
	int	21h
;
	call	setdp			; set display pallet
clod90:	jmp	chgcol			; return to color menu
cload	endp

;*******************************
; csave : save color data
;*******************************
csave	proc
csav10:	mov	eax,EXTCOL	; extension
	call	create		; file create
	jc	csav90		; quit
;
	mov	edx,offset palbuf
	mov	ecx,(1+USRCN)*3	; data byte size
	mov	bx,ax		; file handle
	mov	ah,40h		; write
	int	21h
	pushf
	mov	ah,3Eh		; file close
	int	21h
	popf
	jc	csav10		; error then input repeat
csav90:	jmp	chgcol		; return to color menu
csave	endp

;*******************************
; crest : restore color data
;*******************************
crest	proc
	mov	esi,offset palbak	; backup pallets
	mov	edi,offset palbuf	; pallet buffer
	mov	ecx,1+USRCN		; number of pallets
crest1:	lodsw
	xchg	[edi],ax
	mov	[esi-2],ax
	lodsb
	xchg	[edi+2],al
	mov	[esi-1],al
	add	edi,3
	loop	crest1
;
	mov	spflg,FALSE	; clear save pallet flag
	call	setdp		; set display pallets
	jmp	chgcol		; return to color menu
crest	endp


;*******************************
; boxdwn : box down
;    look like down area
;    by C$LIGHT,C$DARK
;
; in : esi = box data base
;         0 : base address
;         4 : width(4*n)
;         6 : hight
;      al = fill color code
; use: bx,ecx,edx
;
boxdwn	proc
	push	esi
	push	edi
	mov	ah,al			; extend AL to EAX
	mov	dx,ax
	shl	eax,16
	mov	ax,dx
	mov	edi,[esi].boxadr	; start VRAM address
	mov	bx,[esi].boxh		; set hight counter
	movzx	esi,[esi].boxw		; width
	mov	edx,esi
	sub	esi,VRAMW		; negative line distance
	shr	edx,2			; double word counter
bxdw10:	mov	byte ptr es:[edi-1],C$DARK
	mov	ecx,edx			; set width counter
	rep	stosd
	mov	byte ptr es:[edi],C$LIGHT
	sub	edi,esi			; next line address
	dec	bx			; line count down
	jnz	bxdw10
	pop	edi
	pop	esi
	ret
boxdwn	endp

;*******************************
; revfr : reverse frame
;
; in : esi = box address
;       0 : x position
;       2 : y position
;       4 : width
;       6 : hight
; use: eax,ebx,ecx,edx
;
revfr	proc
	push	edi
	movzx	eax,word ptr [esi+2]	; y position
	imul	eax,VRAMW
	movzx	edi,word ptr [esi]
	add	edi,eax			; base address
;
	movzx	ecx,word ptr [esi+4]	; width counter
	mov	edx,ecx			; save
revf10:	not	byte ptr es:[edi+ecx-1]	; reverse top line
	loop	revf10
;
	add	edi,VRAMW		; next line address
	movzx	ecx,word ptr [esi+6]	; hight
	sub	ecx,2			; intermediate lines counter
revf20:	not	byte ptr es:[edi]	; reverse left pixcel
	not	byte ptr es:[edi+edx-1]	; reverse right pixcel
	add	edi,VRAMW		; next line address
	loop	revf20
;
	mov	ecx,edx			; width counter
revf30:	not	byte ptr es:[edi+ecx-1]	; reverse bottom line
	loop	revf30
	pop	edi
	ret
revfr	endp

;*******************************
; boxup : look like box up
;      use C$LIGHT,C$DARK
;
; in : edi = box start address
;      ax = box width
;      dx = box hight
; use: none
;
boxup	proc
	push	edi
	push	ax
	push	ebx
	push	ecx
	push	dx
	movzx	ebx,ax		; save box width
	mov	al,C$LIGHT
	mov	ecx,ebx		; width counter
	rep	stosb		; draw top line
	sub	edi,ebx
	add	edi,VRAMW	; next line address
;
	sub	dx,2
	movzx	ecx,dx		; middle line counter
bxup10:	mov	es:[edi],al
	mov	byte ptr es:[edi+ebx-1],C$DARK
	add	edi,VRAMW	; next line address
	loop	bxup10
;
	mov	al,C$DARK
	mov	ecx,ebx		; width counter
	rep	stosb		; draw bottom line
	pop	dx
	pop	ecx
	pop	ebx
	pop	ax
	pop	edi
	ret
boxup	endp

;*******************************
; chgsc : string color change
;     except for right pixcel
;
; in : edi = box start address
;      bx = box width
;      al = destination color
;      ah = source color
;      es = VRAM selector
; use: ecx,edx,ebp
;
chgsc	proc
	push	edi
	movzx	ebx,bx
	mov	ebp,VRAMW
	sub	ebp,ebx		; distance between lines
	mov	dx,16		; string hight counter
cgbx10:	mov	ecx,ebx		; set width counter
cgbx12:	repne	scasb
	jcxz	cgbx14
	mov	es:[edi-1],ah	; change color
	jmp	cgbx12
cgbx14:	add	edi,ebp		; next line address
	dec	dx
	jnz	cgbx10
	pop	edi
	ret
chgsc	endp

;*******************************
; color : set foreground color
;
; in : al = color code
; use: ax,edx,edi
;
color	proc
	mov	edi,offset egbwork	; EGB work address
	movzx	edx,al			; color code
	mov	ax,0700h		; set foreground color
	call	pword ptr fs:[20h]
	ret
color	endp

;*******************************
; dspss : display strings
;
; in : bx = string index address
;      al = string color
;      fs = TOWNS BIOS
; call: color
; use: ax,bx,ecx,edi
;
dspss	proc
	push	esi
	call	color			; set color
	mov	edi,offset egbwork	; EGB work address
	movzx	ecx,word ptr [bx]	; number of string
dpss10:	add	bx,2
	movsx	esi,word ptr [bx]
	mov	ah,60h
	call	pword ptr fs:[20h]
	loop	dpss10
	pop	esi
	ret
dspss	endp

;*******************************
; dspfp : display frame parameter
;     posx,posy,reso
;
; use: putfp
;
dspfp	proc
	mov	eax,posx	; position x
	mov	edi,LPOSX
	call	putfp
	mov	eax,posy	; position y
	neg	eax
	mov	edi,LPOSY
	call	putfp
	mov	eax,reso	; resolution
	mov	edi,LRESO
	call	putfp
	ret
dspfp	endp

;*******************************
; dspmenu : display menu items
;
; in : esi = menu items index
;        0(2) buttons pointer
;        2(2) buttons number
;        4(2) strings pointer
; call: boxdwn,boxup,dspss
; use: all
;
dspmenu	proc
	mov	edi,esi			; save index pointer
	mov	esi,offset menubox	; menu box pointer
	mov	al,C$PANEL		; with panel color
	call	boxdwn			; clear box
;
	push	edi			; save index pointer
	mov	si,[edi].butptr		; buttons pointer
	movzx	ecx,[edi].butnum	; buttons number
dsme10:	mov	edi,[si].butadr		; start address
	mov	ax,[si].butw		; box width
	mov	dx,[si].buth		; box hight
	call	boxup			; button up
	add	si,8			; next box
	loop	dsme10
	pop	edi			; load index pointer
;
	mov	bx,[edi].strptr		; strings pointer
	mov	al,C$DARK		; dark shadow color
	call	dspss			; display strings
	ret
dspmenu	endp

;*******************************
; getpad : get pad button state
;
; out: ah = trigger
;      al = move, run and select
; use: dx
;
getpad	proc
	xor	ax,ax
	mov	dx,04D6h	; set pad output register
	mov	al,00010011b
	out	dx,al
	mov	dx,04D0h	; get pad 1 input
	in	al,dx
	test	al,01000000b	; check COM input
	jz	gtpd22		; no exist
	call	gtpd30		; analyze pad 1 state
	test	ax,ax		; press any key ?
	jnz	gtpd99		; yes
;
gtpd22:	mov	dx,04D6h	; set pad output register
	mov	al,00101100b
	out	dx,al
	mov	dx,04D2h	; get pad 2 input
	in	al,dx
	test	al,01000000b	; check COM input
	jz	gtpd99		; no exist
	call	gtpd30		; analyze pad 2 state
gtpd99:	ret

gtpd30:	mov	ah,al
	not	ah
	and	ah,00110000b	; mask off trigger bits
	shr	ah,4		; make return data
	and	al,00001111b	; mask off other button state
	cmp	al,0111b	; check RIGHT state
	je	gtpd50		; on
	cmp	al,1011b	; check LEFT state
	je	gtpd52		; on
	cmp	al,1101b	; check BACK state
	je	gtpd54		; on
	cmp	al,1110b	; check FWD state
	je	gtpd56		; on
	cmp	al,0011b	; check RUN state
	je	gtpd58		; on
	cmp	al,1100b	; check SELECT state
	je	gtpd60		; on
;
	xor	al,al		; not press
	ret
gtpd50: mov	al,P$RIGHT 
	ret
gtpd52:	mov	al,P$LEFT
	ret
gtpd54:	mov	al,P$BACK
	ret
gtpd56: mov	al,P$FWD
	ret
gtpd58:	mov	al,P$RUN
	ret
gtpd60:	mov	al,P$SEL
	ret
getpad	endp

;*******************************
; waitp : wait special pad state
;
; in : ax = pad state
; call: getpad
; use: ax,cx,dx
;
waitp	proc
	mov	cx,ax	; dave destination state
waip10:	call	getpad	; get pad state
	cmp	cx,ax	; compare pad state
	jne	waip10	; difference
	ret
waitp	endp

;*******************************
; waitv : wait VSYNC happen
;
; use: none
;
waitv	proc
	push	dx
	push	ax
	mov	dx,0FDA0h	; SUB status register I/O address
waiv10:	in	al,dx
	test	al,1b		; VSYNC
	jnz	waiv10		; wait VSYNC off
waiv20:	in	al,dx
	test	al,1b		; VSYNC
	jz	waiv20		; wait VSYNC on
	pop	ax
	pop	dx
	ret
waitv	endp


;*******************************
; repable : check repeatble
;
; in : repcnt = repeat count
; out: cf = able is clear
; call: waitv
; use: none
;
repable	proc
	call	waitv
	inc	repcnt
	jz	repab9		; first input
	cmp	repcnt,PADREP
	jb	repabE		; invalid
repab9:	mov	repcnt,0	; clear counter
	clc			; repeatable
repabE:	ret
repable	endp

;*******************************
; select : select menu item
;
; in : bx = selector data address
;      fs = TOWNS BIOS
; out: ax = selector number
; err: cf = set by escape
; call: boxup,dspss,waitp
;      getpad,repable,color
; use: ax,ecx,dx,esi
;
select	proc
	mov	repcnt,INIREP	; clear pad input counter
;-------------------------------
; initialize screen
;-------------------------------
	push	bx
	movzx	ecx,word ptr [bx+2]	; set item counter
	add	bx,4		; first item pointer address
	mov	ax,MENUW-6	; selector box width
	mov	dx,19		; selector box hight
sel10:	mov	di,[bx]		; item pointer
	movsx	edi,word ptr [di+2]	; item y position
	sub	edi,16		; box top y position
	imul	edi,VRAMW
	add	edi,MENUX+3	; box base VRAM address
	call	boxup		; look like box up
	add	bx,2		; next item pointer address
	loop	sel10
	pop	bx
;
	push	bx
	add	bx,2		; strings index address
	mov	al,C$DARK	; dark shdow color
	call	dspss		; display strings
	pop	bx
;
	xor	ax,ax		; wait no press state
	call	waitp
;-------------------------------
; display current item
; in : bx = menu data address
;-------------------------------
sel20:	mov	si,[bx]			; current item number
	test	si,si			; check under limit
	jns	sel22			; OK!
	mov	si,[bx+2]		; arround highest number
	dec	si
sel22:	cmp	si,[bx+2]		; check upper limit
	jb	sel24			; OK!
	xor	si,si			; arround lowest number
sel24:	mov	[bx],si			; save adjust number
;
	shl	si,1
	movsx	esi,word ptr [bx+si+4]	; current string address
	movsx	edi,word ptr [esi+2]	; item y position
	sub	edi,15		; box top panel y position
	imul	edi,VRAMW
	add	edi,MENUX+4	; box top panel base VRAM address
	push	bx
	mov	bx,MENUW-8	; box top panel width
	mov	ax,C$DARK+C$INT*256
	call	chgsc		; change box color
	pop	bx
;-------------------------------
; input pad
; in : bx = selector data address
;-------------------------------
sel30:	call	getpad		; get pad button state
	cmp	al,P$FWD
	je	sel40		; cursor up
	cmp	al,P$BACK
	je	sel44		; cursor down
	mov	repcnt,INIREP	; clear counter
	test	ah,P$TRIG2
	jnz	sel38		; escape
	test	ah,P$TRIG1
	jz	sel30		; invalid
;
	mov	ax,[bx]		; select item number
	clc			; clear carry
	ret
sel38:	stc			; set carry
	ret
;-------------------------------
; move cursor
; in : edi = current box top address
;      bx = menu data address
;-------------------------------
sel40:	call	repable		; repeatalbe ?
	jc	sel30		; invalid
	dec	word ptr [bx]	; to lower item
	jmp	short sel48
;
sel44:	call	repable		; repeatalbe ?
	jc	sel30		; invalid
	inc	word ptr [bx]	; to upper item
;
sel48:	push	bx
	mov	bx,MENUW-8	; box top panel width
	mov	ax,C$INT+C$DARK*256
	call	chgsc		; change string color
	pop	bx
	jmp	sel20
select	endp

;*******************************
; dspmain : display main
;       mandelbrot figure
;
; in : curstat = current display state
;      step = display step
; out: curstat = new display state
;      step = new step
; err: cf = set by interrupted
; call: dspmenu,putdec,getpad
;       dsp8s,dsp3q
; use: all
;
dspmain	proc
	cmp	curstat,DS$FULL	; if full figure display completion
	je	dsma99		; then end with do nothing
	mov	esi,offset mdrawon	; display menu items
	call	dspmenu
	cmp	curstat,DS$ON	; dispaly on the way ?
	je	dsma10		; continue
;
	mov	ax,8		; display step number
	mov	edi,LDSTEP	; display position
	call	putdec
	call	dsp8s		; first display by 8 step
	mov	curstat,DS$ON	; first display completion
	mov	step,4		; set display step
	call	getpad		; get pad state
	test	ah,P$TRIG2	; press B button ?
	jnz	dsma90		; interrupt
;
dsma10:	mov	ax,step		; display step
	mov	edi,LDSTEP	; display position
	call	putdec
	call	dsp3q		; display 3/4
	jc	dsma99		; interrupted end
	shr	step,1		; set next step
	jnz	dsma10
	mov	curstat,DS$FULL	; display completion
	clc		; clear carry for completed
	ret
dsma90: stc		; set carry for interrupted
dsma99:	ret
dspmain	endp

;*******************************
; dspis : display initial screen
;     and initial parameter
;
; in : idata= initial data
;      islin = calculated lines
;      es = VRAM selector
; call: dspfp,putdec,calc
; use: eax,ecx,edx,esi,edi,ebx,ebp
;      count1
;
dspis	proc
;-------------------------------
; initialize parameter & display
;-------------------------------
	mov	posx,IPOSX	; initial position x
	mov	posy,IPOSY	; initial position y
	mov	reso,IRESO	; initial resolution
	call	dspfp		; display frame parameter
	mov	ax,ILIMIT	; initial limit
	mov	limit,ax	; set limit
	mov	edi,LLIMIT	; display limit
	call	putdec
	mov	curstat,DS$FULL	; display complete
	mov	step,0
;-------------------------------
; display calculated data
;-------------------------------
	mov	esi,offset idata	; calculated data address
	mov	ebp,(SCRY+SCRH/2-1)*VRAMW+SCRX	; upper line VRAM address
	mov	ebx,(SCRY+SCRH/2)*VRAMW+SCRX	; lower line VRAM address
	mov	dx,islin		; set line counter
	test	dx,dx
	jz	dsis40
dsis20:	mov	edi,ebp			; upper line VRAM address
	mov	ecx,SCRW/4		; set screen width counter
	rep	movsd			; write upper line
	sub	esi,SCRW		; rewind data line address
	mov	edi,ebx			; lower line VRAM address
	mov	ecx,SCRW/4		; set screen width counter
	rep	movsd			; write lower line
	sub	ebp,VRAMW		; new upper line start address
	add	ebx,VRAMW		; new lower line start address
	dec	dx
	jne	dsis20
;-------------------------------
; calculate & display rest lines
; in : ebp = upper line VRAM address
;      ebx = lower line VRAM address
;      esi = data saving address
;-------------------------------
dsis40:	movzx	eax,islin	; calculated lines
	cmp	ax,SCRH/2
	jae	dsis90		; needless
;
	add	eax,SCRH/2	; start y pixcel
	imul	eax,RESO	; start y offset position
	add	eax,IPOSY	; start y position
	mov	curb,eax	; set start y position
	mov	edi,ebp		; upper line VRAM address
dsis50:	mov	count2,SCRW	; set screen width counter
	mov	cura,IPOSX	; set position x
dsis52:	push	esi
	push	ebx
	push	edi
	call	calc		; calculate repeat number
	pop	edi		; upper pixcel VRAM address
	pop	ebx		; lower pixcel VRAM address
	pop	esi		; data saving address
	stosb			; write upper pixcel
	mov	es:[ebx],al	; write lower pixcel
	mov	[esi],al	; save data
	inc	ebx		; next lower pixcel address
	inc	esi		; next saving address
	add	cura,IRESO	; next x position
	dec	count2		; line end ?
	jnz	dsis52
	sub	edi,VRAMW+SCRW	; next upper line start address
	add	ebx,VRAMW-SCRW	; next lower line start address
	add	curb,IRESO	; next y positon
	inc	islin		; line count up
	cmp	islin,SCRH/2	; check line end
	jb	dsis50
;
dsis90:	ret
dspis	endp

;*******************************
; dsp8s : display by 8 step
;    don't permit interrupt
;
; call: calc
; use: eax,ebx,ecx,edx,esi,edi
;
dsp8s	proc
	mov	edi,SCRADR
	mov	count1,SCRH/8	; set screen hight counter
	mov	eax,posy	; set y position
	mov	curb,eax
ds8s10:	mov	count2,SCRW/8	; set screen width counter
	mov	eax,posx	; set x position
	mov	cura,eax
ds8s12:	push	edi
	call	calc		; calculate repeat number
	pop	edi
ds8s20:	sub	ax,USRCN	; adjust color code
	ja	ds8s20
	add	ax,USRCN
	mov	ah,al
	mov	dx,ax
	shl	eax,16
	mov	ax,dx
	mov	ecx,8
ds8s30:	mov	es:[edi],eax	; write VRAM
	mov	es:[edi+4],eax	; write VRAM
	add	edi,VRAMW
	loop	ds8s30
	sub	edi,VRAMW*8-8	; next block VRAM address
	mov	eax,reso	; resolution
	shl	eax,3		; 8 step
	add	cura,eax	; new current real part
	dec	count2		; line end ?
	jnz	ds8s12
	add	edi,VRAMW*8-SCRW	; new line start address
	mov	eax,reso	; resolution
	shl	eax,3		; 8 step
	add	curb,eax	; new current imaginary part
	dec	count1		; exist rest lines ?
	jnz	ds8s10
	ret
dsp8s	endp

;*******************************
; dsp3q : display 3/4
;   check B button per lines
;
; in : step = display step(1,2,4,8)
; out: cf = set by interruption
; call: getpad,calc
; use: eax,ebx,ecx,edx,esi,edi
;
dsp3q	proc
;-------------------------------
; initialize
;-------------------------------
	mov	esi,SCRADR	; VRAM start address
	movzx	ebx,step	; display step
	imul	eax,ebx,VRAMW	; block line step
	sub	eax,SCRW	; for rewind
	mov	bstep,eax	; save block line VRAM step
;
	mov	ax,SCRW		; display screen width
	cwd			; extend DX:AX
	div	bx		; block number in horizon
	mov	hbnum,ax	; save horizon block number
	mov	ax,SCRH		; screen pixcel hight
	cwd			; extend DX:AX
	div	bx 		; block number of vertical
	mov	count1,ax	; set block hight counter
;
	mov	eax,posy	; set start y position
	mov	curb,eax
	imul	ebx,reso	; position step
	mov	pstep,ebx	; save position step
;-------------------------------
; start display a block line
;-------------------------------
ds3q10:	call	getpad		; get pad state
	test	ah,P$TRIG2	; press B button ?
	jnz	ds3q95		; interruption
;
	mov	eax,posx	; set block line x position
	mov	cura,eax
	mov	ax,hbnum	; horizon block number
	mov	count2,ax	; set block counter of 1 line
;-------------------------------
; calculate repeat number
;-------------------------------
ds3q20:	bt	count1,0
	jc	ds3q22		; odd line block
	bt	count2,0
	jc	ds3q22		; odd column block
;
	movzx	ebx,step	; display step
	jmp	short ds3q50	; skip to next block
;
ds3q22:	push	esi
	call	calc		; calculate repeat number
	pop	esi
;-------------------------------
; genarate color code
; in : ax = repeat number
;-------------------------------
ds3q30:	sub	ax,USRCN	; adjust color code
	ja	ds3q30
	add	ax,USRCN	; AL is effective
;-------------------------------
; display 1 block
; in : al = color code
;      esi = block VRAM address
;-------------------------------
	mov	edi,esi		; set block VRAM address
	movzx	ebx,step	; display step
	mov	dx,bx		; set block line counter
ds3q40:	mov	ecx,ebx		; set block width counter
	rep	stosb		; write VRAM by 1 block line
	sub	edi,ebx		; rewind VRAM address
	add	edi,VRAMW	; next block line VRAM address
	dec	dx
	jnz	ds3q40
;-------------------------------
; move on right block
; in : ebx = display step
;      esi = block VRAM address
;-------------------------------
ds3q50:	add	esi,ebx		; next block VRAM address
	mov	eax,pstep	; position step
	add	cura,eax	; next x position
	dec	count2		; check block end of 1 line
	jnz	ds3q20		; go tn right block
;-------------------------------
; move on down block line
; in : ebx = display step
;      eax = position step
;-------------------------------
	add	esi,bstep	; next block line VRAM base address
	add	curb,eax	; next y position
	dec	count1		; check block line end
	jnz	ds3q10		; go to next block line
;-------------------------------
; ending procedure
;-------------------------------
	clc	; clear carry for completion end
	ret
ds3q95:	stc	; set carry for intteruption end
	ret
dsp3q	endp

;*******************************
; dspadd : display additive
;   calculate only C$NULL pixcel
;   check A,B button per pixcel
;
; out: cf = set by interruption
;      ax = button state
; call: getpad,calc
; use: eax,ebx,ecx,edx,esi,edi,ebp
;
dspadd	proc
	mov	edi,SCRADR
	mov	eax,posy	; set y position
	mov	curb,eax
	mov	count1,SCRH	; set screen hight counter
dsad10:	mov	eax,posx	; set x position
	mov	cura,eax
	mov	count2,SCRW	; set screen width counter
dsad20:	cmp	byte ptr es:[edi],0	; check VRAM state
	jne	dsad28		; skip to next pixcel
	call	getpad		; get pad state
	test	ah,ah		; press A or B button ?
	jnz	dsad95		; interruption
	push	edi
	call	calc		; calculate repeat number
	pop	edi
dsad22:	sub	ax,USRCN	; adjust color code
	ja	dsad22
	add	ax,USRCN
	mov	es:[edi],al	; write VRAM
dsad28:	inc	edi		; next VRAM position
	mov	eax,reso	; resolution
	add	cura,eax	; next x position
	dec	count2
	jnz	dsad20
	add	edi,VRAMW-SCRW	; new line start address
	mov	eax,reso	; resolution
	add	curb,eax	; next y position
	dec	count1
	jne	dsad10
;
	clc	; clear carry for completion end
	ret
dsad95:	stc	; set carry for intteruption end
	ret
dspadd	endp

;*******************************
; dspbl : dsplay block line
;
; in : edi = block start VRAM address
;      ebx = display step
;      curb = start y position
;      reso = resolution
; call: dspbk
; use: eax,ecx,edx,esi,edi,ebx,ebp
;      count1,count2,pstep,cura
;
dspbl	proc
	mov	esi,edi		; VRAM address
	mov	count2,bx	; save display step
	mov	ax,SCRW		; display screen width
	cwd			; extend DX:AX
	div	bx		; block number in horizon
	mov	count1,ax	; set block counter of 1 line
	imul	ebx,reso
	mov	pstep,ebx	; save position step
	mov	eax,posx	; set block line x position
	mov	cura,eax
;-------------------------------
; display block
; in : esi = block VRAM address
;-------------------------------
dsbl10:	call	dspbk		; display block
;-------------------------------
; move on right block
; in : ebx = display step
;      esi = block VRAM address
;-------------------------------
	add	esi,ebx		; next block VRAM address
	mov	eax,pstep	; position step
	add	cura,eax	; next x position
	dec	count1		; check block end of 1 line
	jnz	dsbl10		; go to right block
	ret
dspbl	endp

;*******************************
; dspbc : dsplay block column
;
; in : edi = block start VRAM address
;      ebx = display step
;      cura = start x position
;      reso = resolution
; call: dspbk
; use: eax,ecx,edx,esi,edi,ebx,ebp
;      count1,count2,pstep,curb
;
dspbc	proc
	mov	esi,edi		; VRAM address
	mov	count2,bx	; save display step
	mov	ax,SCRH		; display screen hight
	cwd			; extend DX:AX
	div	bx		; block number in vertical
	mov	count1,ax	; set block counter of 1 column
	mov	eax,posy	; set block line y position
	mov	curb,eax
	imul	ebx,reso
	mov	pstep,ebx	; save position step
;-------------------------------
; display block
; in : esi = block VRAM address
;-------------------------------
dsbc10:	call	dspbk		; display block
;-------------------------------
; move on down block
; in : ebx = display step
;      edi = next block VRAM address
;-------------------------------
	mov	esi,edi		; next block VRAM address
	mov	eax,pstep	; position step
	add	curb,eax	; next y position
	dec	count1		; check block end of 1 column
	jnz	dsbc10		; go to down block
	ret
dspbc	endp

;*******************************
; dspbk : dsplay block
;
; in : esi = block VRAM address
;      count2 = display step
; out: ebx = display step
;      esi = block VRAM address
;      edi = down block VRAM address
; use: eax,ecx,edx,esi,edi,ebx,ebp
;
dspbk	proc
;-------------------------------
; calculate repeat number
;-------------------------------
	push	esi
	call	calc		; calculate repeat number
	pop	esi
;-------------------------------
; genarate color code
; in : ax = repeat number
;-------------------------------
dsbk20:	sub	ax,USRCN	; adjust color code
	ja	dsbk20
	add	ax,USRCN	; AL is effective
;-------------------------------
; display block
; in : al = color code
;      esi = block VRAM address
;-------------------------------
	mov	edi,esi		; set block VRAM address
	movzx	ebx,count2	; display step
	mov	dx,bx		; set block line counter
dsbk50:	mov	ecx,ebx		; set block width counter
	rep	stosb		; write VRAM by 1 block line
	sub	edi,ebx		; rewind VRAM address
	add	edi,VRAMW	; next block line VRAM address
	dec	dx
	jnz	dsbk50
	ret
dspbk	endp

;*******************************
; calc : calculate repeat number
;
; in : cura = real part
;      curb = imaginary part
;      limit = upper limit of number
; out: ax = repeat number
; use: ecx,edx,esi,edi,ebx,ebp
;
calc	proc
	movzx	ecx,limit	; upper limit of number
	mov	ebx,cura	; real part
	mov	ebp,curb	; imaginary part
	mov	esi,ebx		; current x
	mov	edi,ebp		; current y
;
calc10:	mov	eax,esi		; current x
	imul	eax		; x^2
	shrd	eax,edx,24	; adjust fixed point
	xchg	eax,esi		; esi=x^2, eax=x
	imul	edi		; x*y
	shrd	eax,edx,23	; adjust fixed point and 2 times
	add	eax,ebp		; new y = 2xy+b
	xchg	edi,eax		; save new y and load old y
	imul	eax		; y^2
	shrd	eax,edx,24	; adjust fixed point
	mov	edx,esi		; x^2
	add	edx,eax		; x^2+y^2
	jz	calc80		; mandelbrot set or round error
	cmp	edx,4 shl 24	; if not |z|<2 then
	jae	calc90		; goto end
	sub	esi,eax		; x^2-y^2
	add	esi,ebx		; new x
	loop	calc10
;
calc80:	xor	ax,ax		; over => 0
	ret
calc90:	mov	ax,limit
	sub	ax,cx		; repeat number
	ret
calc	endp

;*******************************
; calup : calculate up method
;     interrupt by A,B button
;
; in : es = VRAM selector
;      posx = position x
;      posy = position y
;      reso = resolution
; out: cf = set by quit end
;      ax = pad state
;      hbnum = next limit number
; call: boxdwn,putdec,getpad
; use: all
;
calup	proc
;-------------------------------
; initialize buffer & screen
;-------------------------------
	mov	edi,buffer	; calculate buffer address
	mov	ebx,posy	; base position y
	mov	edx,reso	; resolution
	mov	ebp,SCRH	; set screen hight counter
clup10:	mov	eax,posx	; set base position x
	mov	ecx,SCRW	; set screen width counter
clup12:	mov	[edi],eax	; save position x
	mov	[edi+4],ebx	; save position y
	add	edi,8		; next address
	add	eax,edx		; next position x
	loop	clup12
	add	ebx,edx		; next position y
	dec	ebp
	jnz	clup10
;	
	mov	esi,offset scrbox	; screen box pointer
	mov	al,C$NULL		; with NULL color
	call	boxdwn			; clear box
;-------------------------------
; preparation for 1 number start
;-------------------------------
	mov	hbnum,0		; initiarize repeat number
clup20:	mov	ax,hbnum	; current number
	mov	edi,LAUP	; display position
	push	esi
	call	putdec
	pop	esi
;
	mov	esi,buffer	; calculate buffer address
	mov	edi,reso	; set resolution
	mov	ebp,posy	; start position y
	mov	count1,SCRW	; set higth counter
clup30:	mov	ebx,posx	; start position x
	mov	count2,SCRW	; set width counter
clup40:	cmp	dword ptr [esi],0	; check completed
	jne	clup50
	cmp	dword ptr [esi+4],0
	je	clup70		; skip
;-------------------------------
; calculate 1 limit step
; in : ebx = a
;      ebp = b
;      esi = x,y data pointer
;-------------------------------
clup50:	mov	eax,[esi]	; current x
	imul	eax		; x^2
	shrd	eax,edx,24	; adjust fixed point
	mov	ecx,eax		; save x^2
;
	mov	eax,[esi+4]	; current y
	imul	dword ptr [esi]	; x*y
	shrd	eax,edx,23	; adjust fixed point and 2 times
	add	eax,ebp		; 2x*y+b
;
	xchg	[esi+4],eax	; load eax=y and save new y=2x*y+b
	imul	eax		; y^2
	shrd	eax,edx,24	; adjust fixed point
;
	mov	edx,ecx		; x^2
	add	edx,eax		; x^2+y^2
	jz	clup84		; mandelbrot element
	cmp	edx,4 shl 24	; if not |z|<2 then
	jae	clup80		; goto dispaly pixcel
;
	sub	ecx,eax		; x^2-y^2
	add	ecx,ebx		; x^2-y^2+a
	mov	[esi],ecx	; save new x
;-------------------------------
; repeat end check
;-------------------------------
clup70:	add	esi,8		; next (x,y) data pointer
	add	ebx,edi		; left pixcel position a
	dec	count2		; width counter down
	jnz	clup40		; go to left pixcel
	add	ebp,edi		; next line position b
	dec	count1		; hight counter down
	jnz	clup30		; go to next line
;
	inc	hbnum		; repeat number up
	jz	clup90		; limit over
	call	getpad		; get pad state
	test	ah,ah		; press A or B button ?
	jz	clup20		; no go to next repeat number
;-------------------------------
; ending
;-------------------------------
	stc	; quit end
clup90:	mov	curstat,DS$FULL	; display completion
	mov	step,0
	ret
;-------------------------------
; display pixcel
; in : edi = VRAM address
;-------------------------------
clup80:	mov	cx,hbnum	; repeat number
clup82:	sub	cx,USRCN	; adjust color code
	ja	clup82
	add	cx,USRCN
	mov	ax,SCRY+SCRH
	sub	ax,count1
	cwde
	imul	eax,VRAMW
	add	eax,SCRX+SCRW
	movzx	edx,count2
	sub	eax,edx
	mov	es:[eax],cl	; write VRAM
clup84:	mov	dword ptr [esi],0	; set complete flag
	mov	dword ptr [esi+4],0
	jmp	clup70
calup	endp

;*******************************
; putdec : put decimal number
;      within 5 column
;
; in : ax = binary
;      edi = display VAM base address
;      numwid = display width of number
; call: bn2dec,dspank
; use: ax,ecx,dx,ebx,esi,edi
;      work1
;
putdec	proc
	mov	ebx,offset work1+2
	movzx	ecx,numwid		; display width
	mov	[ebx-2],cx
	call	bn2dec
	mov	esi,offset work1	; string data address
	call	dspank
	ret
putdec	endp

;*******************************
; putfp : put fixed point
;    within 10 column
;
; in : eax = fixed point
;      edi = base VRAM address
; call: bn4dec,dspank
; use: all
;      work1
;
putfp	proc
	mov	ebx,offset work1	; destination address
	call	bn4dec			; convert to decimal
	mov	esi,offset work1	; string data address
	movzx	ecx,word ptr [esi]	; effective lenght
	mov	al,20h			; SPAC
putfp1:	mov	[esi+ecx+2],al
	inc	ecx
	cmp	ecx,10
	jb	putfp1
	mov	word ptr [esi],10
	call	dspank			; display ANK strings
	ret
putfp	endp

;*******************************
; bn2dec : 2 binary to decimal
;
; in : ax = unsigned binary
;      ecx = column width
;      ebx = destination address
; use: ax,ecx,dx
;
bn2dec	proc
	push	si
	mov	si,10
bn2de1:	xor	dx,dx
	div	si
	add	dl,'0'
	mov	[ebx+ecx-1],dl	; save digit
	test	ax,ax		; check end
	loopnz	bn2de1
;
bn2de4:	jcxz	bn2de9
	mov	byte ptr [ebx+ecx-1],20h	; sapce padding
	dec	ecx
	jmp	bn2de4
bn2de9:	pop	si
	ret
bn2dec	endp

;*******************************
; bn4dec : signed 4 byte fixed
;   point binary to decimal
;
; in : eax = binary
;      ebx = destination address
;      cs = ds
; out: ebx = fixed decimal
;         0(2) byte length n+3
;         2(1) sign ('-' or ' ')
;         3(1) integer part
;         4(1) decimal point
;         5(n) decimal part
; use: eax,ecx,edx,ebx
;
bn4de0	dd	10000000
	dd	1000000
	dd	100000
	dd	10000
	dd	1000
	dd	100
	dd	10
	dd	1
;
bn4dec	proc
	push	esi
	push	ebx
	add	ebx,2		; skip length area
	mov	byte ptr [ebx],' '
	test	eax,eax
	jns	bn4de1
	mov	byte ptr [ebx],'-'
	neg	eax
bn4de1:	inc	ebx
;
	mov	esi,offset bn4de0
	mul	dword ptr [esi]	; significant figure
	shrd	eax,edx,24
	adc	eax,0		; round
;
	xor	edx,edx		; integer part
	div	dword ptr [esi]
	add	al,'0'
	mov	ah,'.'
	mov	[ebx],ax
	add	esi,4
	add	ebx,2
	mov	eax,edx
;
	mov	ecx,7
bn4de2:	xor	edx,edx		; extend dividend EDX:EAX
	div	dword ptr [esi]
	add	al,'0'
	mov	[ebx],al	; save quotient
	add	esi,4		; next divisor address
	inc	ebx		; next save address
	mov	eax,edx		; set new dividend
	test	eax,eax
	loopnz	bn4de2
;
	pop	eax		; destination address
	sub	ebx,eax
	sub	bx,2
	mov	[eax],bx	; save length
	pop	esi
	ret
bn4dec	endp

;*******************************
; setdp : set display pallets
;         0 to USRCN
;
; in : palbuf = pallet data buffer
; call: waitv,setpal
; use: all & work1
;
setdp	proc
	mov	edi,offset palbuf	; pallet data buffer
	mov	esi,offset work1	; pallet packet
	mov	byte ptr [esi],0	; initialize pallet number
	mov	bx,PALSBN		; set pallet block counter
	mov	ecx,PALSBR		; set rest pallet number
setdp1:	call	waitv			; wait VSYNC
setdp2:	mov	eax,[edi]		; level data + 1
	mov	[esi+1],eax		; set level data
	call	setpal			; set pallet code
	add	edi,3			; next pallet address
	inc	byte ptr [esi]		; next pallet number
	loop	setdp2
	mov	ecx,PALSBS		; set pallet block size
	dec	bx
	jnz	setdp1
	ret
setdp	endp

;*******************************
; setpal : set pallet data
;
; in : (ds:esi) = data address
; use: dx
;
setpal	proc
	push	esi
	mov	dx,0FD90h	; pallet code
	outsb
	mov	dx,0FD92h	; blue pallet data
	outsb
	mov	dx,0FD94h	; red pallet data
	outsb
	mov	dx,0FD96h	; green pallet data
	outsb
	pop	esi
	ret
setpal	endp

;*******************************
; dspank : display ank
;    string color is C$DARK
;    backgraund is C$PANEL
;
; in : esi = string address
;      edi = base VRAM address
;         0(2) byte size (n)
;         2(n) byte string
;      es = VRAM selector
; use: none
;
dspank	proc
	push	fs
	push	ebp
	push	esi
	push	edi
	push	edx
	push	ecx
	push	ebx
	push	eax
;
	lfs	ebx,pword ptr ss:[ankfnt]
	lodsw
	movzx	ecx,ax		; length counter
dpank1:	lodsb			; ANK code
	call	dpankA		; character display
	add	edi,8		; next character address
	loop	dpank1
;
	pop	eax
	pop	ebx
	pop	ecx
	pop	edx
	pop	edi
	pop	esi
	pop	ebp
	pop	fs
	ret
;------------------------------
; in : al = ANK code
;      fs:ebx = font ROM address
;      es:edi = base VRAM address
; use: ax
;
dpankA	proc
	push	edi
	push	ecx
	xor	ah,ah
	shl	ax,4
	add	ax,15
	movzx	ebp,ax		; destination base offset
	mov	dx,16		; hight counter
dpakA1:	mov	ah,fs:[ebx+ebp]
	mov	ecx,8
dpakA2:	mov	al,C$DARK	; number color
	shl	ah,1
	jc	dpakA3
	mov	al,C$PANEL	; backgraund color fixed
dpakA3:	stosb
	loop	dpakA2
	dec	ebp
	sub	edi,VRAMW+8
	dec	dx
	jnz	dpakA1
	pop	ecx
	pop	edi
	ret
dpankA	endp
dspank	endp

;*******************************
; getstr : get string from keybord
;     with echo
;     only 0-9,A-Z
;     control code BS,CR,ESC
;
; in : (ds:esi) = string address
;          0(2) position x
;          2(2) position y
;       cx = maximum string length
;       es = VRAM selector
;       fs = TOWNS BIOS selector
; out: (ds:esi)
;          4(2) inputed string length
; call: waitp,getpad
; use: eax,ebx,ecx,edx
;
getstr	proc
	push	edi
;-------------------------------
; initialize
;-------------------------------
	mov	ax,0600h	; clear keybord buffer
	int	90h
	xor	ax,ax		; wait no press state
	push	cx
	call	waitp
	pop	cx
	mov	word ptr [esi+4],0	; clear counter
;-------------------------------
; get key or button & analyze it
;-------------------------------
gtst10:	mov	ax,0901h	; read charactor without waiting
	int	90h
	test	ah,ah		; go well ?
	jnz	gtst12		; read error
	cmp	dh,0FFh		; exist input charactor ?
	jne	gtst14		; go to analyze
;
gtst12:	call	getpad		; get pad state
	test	ah,P$TRIG1	; A button
	jnz	gtst99		; input end
	test	ah,P$TRIG2	; B button
	jnz	gtst90		; quit
	jmp	gtst10
;
gtst14:	cmp	dl,1BH		; ESC
	je	gtst90		; quit
	cmp	dl,0Dh
	je	gtst99		; input end
	cmp	dl,08h		; CTRL+H
	je	gtst40		; back space
	cmp	dl,'0'
	jb	gtst10		; invalid
	cmp	dl,'9'
	jbe	gtst22		; number
	cmp	dl,'A'
	jb	gtst10		; invalid
	cmp	dl,'Z'
	jbe	gtst22		; capital
	cmp	dl,'a'
	jb	gtst10		; invalid
	cmp	dl,'z'
	ja	gtst10		; invalid
;-------------------------------
; save and display
; in : esi = string address
;      cx = maximum length
;-------------------------------
gtst20:	add	dl,'A'-'a'	; capitalize
gtst22:	movzx	eax,word ptr [esi+4]	; current length
	cmp	ax,cx		; check max length
	jae	gtst10		; invalid
	inc	ax		; renew length
	mov	[esi+4],ax
	mov	byte ptr [esi+eax+5],dl	; save charactor
	mov	edi,offset egbwork
	mov	ax,6001h	; display ASCII string
	call	pword ptr fs:[20h]
	jmp	gtst10
;-------------------------------
; back space
; in : esi = string address
;-------------------------------
gtst40:	movzx	eax,word ptr [esi+4]
	test	ax,ax
	jz	gtst10		; invalid
	dec	ax
	mov	[esi+4],ax
;
	push	ecx
	shl	ax,3		; string pixcel width
	add	ax,[esi]	; clear start x position
	movzx	edi,ax
	movzx	eax,word ptr [esi+2]
	imul	eax,VRAMW
	add	edi,eax		; clear start address
	mov	ecx,16
	mov	eax,C$PANEL+(C$PANEL shl 8)+(C$PANEL shl 16)+(C$PANEL shl 24)
gtst42:	mov	es:[edi],eax
	mov	es:[edi+4],eax
	sub	edi,VRAMW
	loop	gtst42
	pop	ecx
	jmp	gtst10
;-------------------------------
; input end
;-------------------------------
gtst90:	mov	word ptr [esi+4],0	; cancel string
gtst99:	pop	edi
	ret
getstr	endp
code	ends

stack	segment stack use32 rw
pathbuf	db	80h dup(?)	; for pathlist
idata	db	SCRW*SCRH/2 dup(?)	; for initial screen data
ankfnt	dd	?	; ANK font offset
	dw	?	; ANK font selector
palbuf	db	(USRCN+1)*3 dup(?)	; pallet data buffer
	db	?	; dummy
palbak	db	(USRCN+1)*3 dup(?)	; pallet data backup buffer
	db	?	; dummy
work1	db	80 dup(?)	; public work 1
egbwork	db	EGBSIZ dup(?)	; EGB work area
	db	256*256 dup(?)	; stack for EGB
	db	6*1024 dup (?)	; stack area
stack	ends

	end entry
