; ***************************************************************************
;  Intro for the BBS that's world head quarters of the best demogroup ever:
;
;                             I  G  U  A  N  A
;
;      WHQ:                B L A S T E R S O U N D
;
;              Dedicated to its SYSOP, for being such a nice guy
;                               Coded by
;
;                               Yann/Iguana
;
;                       AKA: Jon Beltr n de Heredia
;              (Alright, the idea of the pixelys isn't mine.
;                   And the Bres without jumps is Jare's)  :-)
; ***************************************************************************
; Credits: Jare for the Bresenham without jumps; the effect appeared years ago
;  in the spanish Microhobby magazine; and the number-shuffling is based on
;  code by Draeden. Ah! and the profiling macros SetBorder and SetBorder2 are
;  Future Crew's. The rest (that's the other three lines of code :-) is mine.
; ***************************************************************************

	.MODEL	SMALL
	LOCALS
	.STACK
; --------------------------------------------------------------------------
; Here we have global data
; --------------------------------------------------------------------------
	.DATA

;SinTable created by Jon Beltran de Heredia
;Sines are in 8.8 fixedpoint, from 0 degree to 360+90 degree (in order to
; calculate the cosines with the same table)
SinTbl	LABEL	WORD
dw 0,4,9,13,18,22,27,31,36,40,44,49,53,58,62
dw 66,71,75,79,83,88,92,96,100,104,108,112,116,120,124
dw 128,132,136,139,143,147,150,154,158,161,165,168,171,175,178
dw 181,184,187,190,193,196,199,202,204,207,210,212,215,217,219
dw 222,224,226,228,230,232,234,236,237,239,241,242,243,245,246
dw 247,248,249,250,251,252,253,254,254,255,255,255,256,256,256
dw 256,256,256,256,255,255,255,254,254,253,252,251,250,249,248
dw 247,246,245,243,242,241,239,237,236,234,232,230,228,226,224
dw 222,219,217,215,212,210,207,204,202,199,196,193,190,187,184
dw 181,178,175,171,168,165,161,158,154,150,147,143,139,136,132
dw 128,124,120,116,112,108,104,100,96,92,88,83,79,75,71
dw 66,62,58,53,49,44,40,36,31,27,22,18,13,9,4
dw 0,-4,-9,-13,-18,-22,-27,-31,-36,-40,-44,-49,-53,-58,-62
dw -66,-71,-75,-79,-83,-88,-92,-96,-100,-104,-108,-112,-116,-120,-124
dw -128,-132,-136,-139,-143,-147,-150,-154,-158,-161,-165,-168,-171,-175,-178
dw -181,-184,-187,-190,-193,-196,-199,-202,-204,-207,-210,-212,-215,-217,-219
dw -222,-224,-226,-228,-230,-232,-234,-236,-237,-239,-241,-242,-243,-245,-246
dw -247,-248,-249,-250,-251,-252,-253,-254,-254,-255,-255,-255,-256,-256,-256
dw -256,-256,-256,-256,-255,-255,-255,-254,-254,-253,-252,-251,-250,-249,-248
dw -247,-246,-245,-243,-242,-241,-239,-237,-236,-234,-232,-230,-228,-226,-224
dw -222,-219,-217,-215,-212,-210,-207,-204,-202,-199,-196,-193,-190,-187,-184
dw -181,-178,-175,-171,-168,-165,-161,-158,-154,-150,-147,-143,-139,-136,-132
dw -128,-124,-120,-116,-112,-108,-104,-100,-96,-92,-88,-83,-79,-75,-71
dw -66,-62,-58,-53,-49,-44,-40,-36,-31,-27,-22,-18,-13,-9,-4
dw 0,4,9,13,18,22,27,31,36,40,44,49,53,58,62
dw 66,71,75,79,83,88,92,96,100,104,108,112,116,120,124
dw 128,132,136,139,143,147,150,154,158,161,165,168,171,175,178
dw 181,184,187,190,193,196,199,202,204,207,210,212,215,217,219
dw 222,224,226,228,230,232,234,236,237,239,241,242,243,245,246
dw 247,248,249,250,251,252,253,254,254,255,255,255,256,256,256,256

FontData	LABEL BYTE
		INCLUDE font.inc

; --------------------------------------------------------------------------
; Macros to profile the intro
; --------------------------------------------------------------------------
SetBorder2	MACRO Color
		push	ax
		push	dx
		cli			; So that the flip-flop isn't
					; uninit-ed by some IRQ...
		mov	dx,3DAh
		in	al,dx		; Init the flip-flop for the
					; attribute controller
		mov	dx,3C0h		; Attribute controller port
		mov	al,31h		; Overscan reg, don't switch ray off
		out	dx,al		; Write Register #
		mov	al,Color
		out	dx,al		; Write Border Color
		sti
		pop	dx
		pop	ax
		ENDM
	
SetBorder	MACRO Color		; To profile
		;SetBorder2 Color
		ENDM

; ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;          Beginning of the code for the intro, functions...
; ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

.DATA
OffScreenSeg DW ?
ScreenSeg DW 0A000h
MulBy320 LABEL WORD
I = 0
REPT 204		; For the travelling points
 DW 320*I
 I = I + 1
ENDM

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Palette init data and function
; Input: AL is the palette offset
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
.DATA
PalLetras LABEL BYTE
I = 0
REPT 16
DB 4*I,63,0
I = I + 1
ENDM
.CODE
InitPal	PROC
	mov	dx,3C8h
	mov	al,10h
	out	dx,al
	inc	dx
	mov	si,OFFSET PalLetras
	mov	cx,16
IPL1:	lodsb
	out	dx,al
	lodsb
	out	dx,al
	lodsb
	out	dx,al
	loop	IPL1
	ret
InitPal	ENDP

; This are usual text-drawing functions not used in this intro. I wrote them
; just to test the font, but here they are for future use...
COMMENT &
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Draw a char
; Input: DI -> to the destination offset in A000
;        AL: ASCII code of the char to draw
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
.DATA
FontChars DB 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789()-:;.,_!?=''/'
NUM_CHARS = $ - FontChars

.CODE
DrawChar	PROC
	mov	bx,ds
	mov	es,bx
	mov	bx,di				; Preserve
	mov	di,OFFSET FontChars
	mov	cx,NUM_CHARS
	repne	scasb				; Find the index of the char
	je	DCL1
	ret
DCL1:	sub	di,1 + OFFSET FontChars		; To get the index
	mov	ax,di
	mov	ah,al
	xor	al,al
	mov	si,OFFSET FontData
	add	si,ax
	mov	di,bx
	mov	es,ScreenSeg
	mov	dx,16
DCL2:	mov	cx,16
DCL3:	lodsb
	or	al,al
	jnz	DCNotZero
	inc	di
	dec	cx
	jz	DCNextScan
	jmp	DCL3
DCNotZero:
	stosb
	dec	cx
	jz	DCNextScan
	jmp	DCL3
DCNextScan:
	add	di,320-16
	dec	dx
	jz	DCL4
	jmp	DCL2
DCL4:	ret
DrawChar	ENDP

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Display a char. Acts automatically with the cursor position.
; Input:  AL: char to be printed
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
.DATA
CursorX	DW 0
CursorY DW 0
MulBy16x320 LABEL WORD
I=0
REPT 12
DW 16*320*I
I=I+1
ENDM
.CODE
DisplayChar	PROC
	mov	bx,CursorY
	add	bx,bx
	mov	di,MulBy16x320[bx]
	mov	bx,CursorX
	REPT 4
	shl	bx,1
	ENDM
	add	di,bx		; Now we have in DI the screen offset
	call	DrawChar
	mov	ax,CursorX
	mov	bx,CursorY
	inc	ax
	cmp	ax,20
	jnz	DiCExit
	mov	ax,0
	inc	bx
	cmp	bx,12
	jnz	DiCExit
	mov	bx,0
DiCExit:mov	CursorX,ax
	mov	CursorY,bx
	ret
DisplayChar	ENDP
	
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Display a string. Acts automatically with the cursor position.
; Input: DX -> to the string to be printed, 0 terminated
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
DisplayString	PROC
	mov	bx,dx
DSL1:	mov	al,[bx]
	or	al,al
	jz	DSExit
	push	bx
	call	DisplayChar
	pop	bx
	inc	bx
	jmp	DSL1
DSExit:	ret
DisplayString	ENDP
&

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Make the background go to and fro
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
.DATA
GOING_UP = 0
GOING_DOWN = 1
PalState DW GOING_DOWN
PalCounter DW 32
UpPalette LABEL BYTE
 I = 0
 REPT 16
  DB 4*I,4*I,4*I
  I = I + 1
 ENDM

DownPalette LABEL BYTE
 DB 16 DUP(0,0,0)

CurrentPalette LABEL BYTE
 I = 0
 REPT 16
  DB 4*I,4*I,4*I
  I = I + 1
 ENDM
 
.CODE
AdvanceBackground PROC
	mov	si,OFFSET CurrentPalette
	mov	ax,PalState
	cmp	ax,GOING_UP
	jz	ABL0
	; So we are going down
	mov	di,OFFSET DownPalette
	mov	cx,3*16
ABL1:	lodsb
	cmp	al,[di]
	je	ABL2
	dec	al
	dec	al
	mov	[si-1],al
	cmp	al,[di]
	jge	ABL2
	mov	al,[di]
	mov	[si-1],al
ABL2:	inc	di
	loop	ABL1
	jmp	ABExit

ABL0:	mov	di,OFFSET UpPalette
	mov	cx,3*16
ABL3:	lodsb
	cmp	al,[di]
	je	ABL4
	inc	al
	inc	al
	mov	[si-1],al
	cmp	al,[di]
	jbe	ABL4
	mov	al,[di]
	mov	[si-1],al
ABL4:	inc	di
	loop	ABL3

ABExit:
	dec	PalCounter
	jnz	ABL5
	mov	ax,PalState
	xor	ax,GOING_UP
	xor	ax,GOING_DOWN
	mov	PalState,ax
	mov	PalCounter,32	
ABL5:
	ret
AdvanceBackground ENDP

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Background palette set function
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
.CODE
SetPal	PROC
	cld
	mov	si,OFFSET CurrentPalette
	mov	dx,3C8h
	mov	al,128			; Where the background pal starts
	out	dx,al
	inc	dx
	mov	cx,32
SPL1:	lodsb
	out	dx,al
	lodsb
	out	dx,al
	lodsb
	out	dx,al
	loop	SPL1
	ret
SetPal	ENDP

;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;      Beginning of the code for the spectacular text presentation...
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
.DATA
X1	DW 0
X2	DW 0
Y1	DW 0
Y2	DW 0
NUM_POINTS = 400h
POINTS_SPEED = 2
EVEN
CurrentNumPoints DW 0
PointsDI	DW NUM_POINTS DUP (0)
PointsFrac	DW NUM_POINTS DUP (0)
PointsAdjUp	DW NUM_POINTS DUP (0)
PointsAdjDown	DW NUM_POINTS DUP (0,0)
PointsColor	DW NUM_POINTS DUP (0)
PointsCounter	DW NUM_POINTS DUP (-1)		; -1 marks free point entry
PointsLVar	DW NUM_POINTS DUP (0,0)

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Function to add one point to the list of current points
; Input: (X1,Y1)->(X2,Y2) is the path, AH is the color to use
; Output: CY marks error, NC successful
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
.CODE
AddPoint PROC
	mov	bh,ah			; Keep it
	cmp	CurrentNumPoints,NUM_POINTS
	jne	APL1
	stc
	ret
APL1:	inc	CurrentNumPoints
	mov	ax,ds
	mov	es,ax
	mov	di,OFFSET PointsCounter
	mov	cx,NUM_POINTS
	mov	ax,-1
	repne	scasw				; Find the free entry
	sub	di,2 + OFFSET PointsCounter
	mov	BYTE PTR PointsColor[di],bh	; Store the color for l8r use
	mov	bx,Y1
	mov	ax,Y2
	mov	si,X1
	mov	cx,X2
	mov	bp,bx
	sub	bx,ax				; Y1(bx) will always be larger
	add	bp,bp
	mov	bp,ds:MulBy320[bp]
	add	bp,si				; BP = Start DI
	mov	PointsDI[di],bp
	mov	al,BYTE PTR PointsColor[di]
	mov	es,ScreenSeg
	mov	es:[bp],al
	sub	si,cx
	mov	ax,-1
	jnc	SHORT APL2
	neg	ax
	neg	si
APL2:	cmp	si,bx				; cmp dX,dY
	jnc	SHORT APL3
	;deltaX < deltaY			; bx: major delta (already is)
	mov	dx,si				; dx: minor delta
	mov	si,ax				; si: minor inc
	mov	ax,-320				; ax: major inc
	jmp	SHORT APL4
APL3:	mov	dx,bx				; dx: minor delta
	mov	bx,si				; bx: major delta
	mov	si,-320				; si: minor inc
						; ax: major inc (already is)
APL4:	mov	PointsCounter[di],bx		; Total number of pels (dX+1)
	neg	bx				; StartFrac = -dX
	mov	PointsFrac[di],bx
	add	dx,dx
	mov	PointsAdjUp[di],dx
	add	di,di
	add	bx,bx
	mov	PointsAdjDown[di],bx		; AdjDown = -2*dX
	mov	PointsAdjDown[di+2],0
	add	si,ax
	mov	PointsLVar[di],si		; Inc DI when overflow
	mov	PointsLVar[di+2],ax		; Inc DI when not overflow
	clc
	ret
AddPoint ENDP

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Function to advance the points, erasing them and redrawing them
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
AdvancePoints PROC
	mov	ax,ds
	mov	es,ax
	mov	di,OFFSET PointsCounter
	mov	cx,NUM_POINTS
AdPL1:	or	cx,cx
	jnz	AdPL5
	jmp	AdPExit
AdPL5:	mov	ax,-1
	repe	scasw
	jne	AdPL2
	jmp	AdPExit
AdPL2:	push	es
	push	di
	push	cx
	sub	di,2 + OFFSET PointsCounter
	mov	es,OffScreenSeg
	mov	bp,PointsDI[di]
	mov	al,es:[bp]
	mov	es,ScreenSeg
	mov	es:[bp],al			; Restore previous color
	mov	ax,PointsFrac[di]
	mov	cx,PointsAdjUp[di]
	mov	dx,PointsCounter[di]
	add	di,di
	REPT POINTS_SPEED
	add	ax,cx
	sbb	bx,bx
	add	bx,bx
	add	bp,PointsLVar[di+2+bx]
	add	ax,PointsAdjDown[di+2+bx]
	dec	dx
	jz	AdPL3
	ENDM
AdPL3:
	shr	di,1
	mov	PointsDI[di],bp
	mov	PointsFrac[di],ax
	mov	al,BYTE PTR PointsColor[di]
	mov	es,ScreenSeg
	mov	es:[bp],al
	mov	PointsCounter[di],dx
	cmp	dx,0
	jg	AdPL4
	mov	es,OffScreenSeg
	mov	es:[bp],al
	mov	PointsCounter[di],-1
	dec	CurrentNumPoints
AdPL4:	
	pop	cx
	pop	di
	pop	es
	jmp	AdPL1
AdPExit:
	ret
AdvancePoints ENDP
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Function to add a point to print the message
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
.DATA
FontChars DB 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789()-:;.,_!?=''/'
NUM_CHARS = $ - FontChars
MPNextChar DW OFFSET IntroMsg
MPCurrentDX DW 0
MPCurrentDY DW 0
MPCharX DW 0
MPCharY DW 0
MPZero	DB 0
MPCannonIndex DW 0
MPCannonShuffle LABEL WORD
	INCLUDE rand.inc
.CODE
MakePoint PROC
	mov	bx,ds
	mov	es,bx
MPL1:	mov	bx,MPNextChar
	mov	al,[bx]
	or	al,al
	jnz	MPL2
	ret
MPL2:	mov	di,OFFSET FontChars
	mov	cx,NUM_CHARS
	repne	scasb
	jz	MPL3
	inc	MPNextChar
	mov	ax,MPCharX
	mov	bx,MPCharY
	add	ax,16
	cmp	ax,20*16
	jne	MPL4
	mov	ax,0
	add	bx,16
	cmp	bx,12*16
	jne	MPL4
	mov	MPNextChar,OFFSET MPZero
MPL4:	mov	MPCharX,ax
	mov	MPCharY,bx
	jmp	MPL1
MPL3:	sub	di,1 + OFFSET FontChars
	mov	ax,di
	mov	ah,al
	xor	al,al
	add	ax,OFFSET FontData
	mov	bx,MPCurrentDY
	mov	cl,4
	shl	bx,cl			; DX*16
	add	bx,MPCurrentDX
	add	bx,ax
MPL5:	mov	al,[bx]
	inc	bx
	or	al,al
	jnz	MPL6
	mov	ax,MPCurrentDX
	mov	cx,MPCurrentDY
	inc	ax
	cmp	ax,16
	jnz	MPL7
	mov	ax,0
	inc	cx
	cmp	cx,16
	jnz	MPL7
	mov	MPCurrentDX,0
	mov	MPCurrentDY,0
	inc	MPNextChar
	mov	ax,MPCharX
	mov	bx,MPCharY
	add	ax,16
	cmp	ax,20*16
	jnz	MPL9
	mov	ax,0
	add	bx,16
	cmp	bx,12*16
	jnz	MPL9
	mov	MPNextChar,OFFSET MPZero
	ret
MPL9:	mov	MPCharX,ax
	mov	MPCharY,bx
	jmp	MPL1
MPL7:	mov	MPCurrentDX,ax
	mov	MPCurrentDY,cx
	jmp	MPL5

MPL6:	mov	bx,MPCharX
	add	bx,MPCurrentDX
	mov	X2,bx
	mov	bx,MPCharY
	add	bx,MPCurrentDY
	mov	Y2,bx
	mov	bx,MPCannonIndex
	add	bx,bx
	mov	bx,MPCannonShuffle[bx]
	mov	X1,bx
	mov	Y1,201
	mov	ah,al
	call	AddPoint
	jnc	MPL11			; Advance pointer only if successful
	ret
MPL11:
	mov	ax,MPCannonIndex
	inc	ax
	cmp	ax,320
	jne	MPL12
	mov	ax,0
MPL12:	mov	MPCannonIndex,ax
	mov	ax,MPCurrentDX
	mov	bx,MPCurrentDY
	inc	ax
	cmp	ax,16
	jnz	MPL8
	mov	ax,0
	inc	bx
	cmp	bx,16
	jnz	MPL8
	mov	MPCurrentDX,0
	mov	MPCurrentDY,0
	inc	MPNextChar
	mov	ax,MPCharX
	mov	bx,MPCharY
	add	ax,16
	cmp	ax,20*16
	jnz	MPL10
	mov	ax,0
	add	bx,16
	cmp	bx,12*16
	jnz	MPL10
	mov	MPNextChar,OFFSET MPZero
MPL10:	mov	MPCharX,ax
	mov	MPCharY,bx
	ret
MPL8:	mov	MPCurrentDX,ax
	mov	MPCurrentDY,bx
	ret
MakePoint ENDP

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; Main proc
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°

.DATA
;                   oooooooooooooooooooo
IntroMsg	DB '  BLASTERSOUND BBS  '
		DB '    34-58-293583    '
		DB '   GRANADA--SPAIN   '
		DB '   SPECIALIZED IN:  '
		DB '   - SB AND GUS -   '
		DB '-LAST NEWEST DEMOS!-'
		DB '  - SOUND  FILES -  '
		DB 'SBCNET: 14:4500/200 '
		DB 'CDNET:  94:620/200  '
		DB 'FIDONET: 2:345/805  '
		DB 'IGUANA WORLD HQ! ;-)'
		DB 'ZYXEL 19.2K,FREQ 24H'
		DB 0				; End of msg

IntroMsg2	LABEL BYTE
DB 0Dh, 0Ah
DB '                                BLASTERSOUND BBS  ', 0Dh, 0Ah
DB '                                  34-58-293583    ', 0Dh, 0Ah
DB '                                 GRANADA--SPAIN   ', 0Dh, 0Ah
DB '                                 SPECIALIZED IN:  ', 0Dh, 0Ah
DB '                                 - SB AND GUS -   ', 0Dh, 0Ah
DB '                              -LAST NEWEST DEMOS!-', 0Dh, 0Ah
DB '                                - SOUND  FILES -  ', 0Dh, 0Ah
DB '                              SBCNET: 14:4500/200 ', 0Dh, 0Ah
DB '                              CDNET:  94:620/200  ', 0Dh, 0Ah
DB '                              FIDONET: 2:345/805  ', 0Dh, 0Ah
DB '                              IGUANA WORLD HQ! ;-)', 0Dh, 0Ah
DB '                              ZYXEL 19.2K,FREQ 24H', 0Dh, 0Ah
DB '$'				; End of msg

ErrorMsg DB '                   Sorry, I couldn''t allocate the 104K I need'
	DB 0Dh, 0Ah, 0Dh, 0Ah

ByeText DB '                             BlasterSound BBS Intro', 0Dh, 0Ah
	DB '                          34-58-293583 Granada (Spain)', 0Dh, 0Ah
	DB '                           Intro coded by Yann/Iguana', 0Dh, 0Ah
	DB '$'

NotVGAMsg DB '                 Sorry, I need a VGA and you don''t seem to have one'
	DB 0Dh, 0Ah, 0Dh, 0Ah
	DB '                             BlasterSound BBS Intro', 0Dh, 0Ah
	DB '                          34-58-293583 Granada (Spain)', 0Dh, 0Ah
	DB '                           Intro coded by Yann/Iguana', 0Dh, 0Ah
	DB '$'

.CODE
Main	PROC
	cld
	mov	bx,2560			; Allocate 40K for the program
	mov	ah,4Ah
	int	21h
	mov	ax,@DATA
	mov	ds,ax
	mov	ax,1A00h
	int	10h			; Get video display combination
	cmp	bl,7
	jnc	ML2
	mov	dx,OFFSET NotVgaMsg
	mov	ah,9
	int	21h
	mov	dx,OFFSET IntroMsg2
	mov	ah,9
	int	21h
	mov	ax,4CFFh
	int	21h
ML2:	mov	ah,48h
	mov	bx,4096			; 64K
	int	21h
	mov	OffScreenSeg,ax
	jnc	ML0
	mov	dx,OFFSET ErrorMsg
	mov	ah,9
	int	21h
	mov	dx,OFFSET IntroMsg2
	mov	ah,9
	int	21h
	mov	ax,4CFFh
	int	21h
ML0:	mov	ax,13h
	int	10h			; Sets standard 320x200x256

	mov	dx,3DAh
W0:	in	al,dx
	test	al,8
	jnz	W0
W1:	in	al,dx
	test	al,8
	jz	W1
	
	mov	dx,3C8h
	mov	al,128
	out	dx,al
	inc	dx
	xor	al,al
	mov	cx,3*33
ML1:	out	dx,al
	loop	ML1

	mov	es,ScreenSeg
	mov	di,0
	mov	ax,8181h
	mov	cx,32000
	rep	stosw

	mov	bp,0
HorLoop:push	bp
	mov	si,0
VerLoop:push	si

	; Now we have in bp the X coor and in si the Y coor
	mov	bx,si			; Get coor Y
	add	bx,10
	add	bx,bx
	mov	di,MulBy320[bx]
	add	di,bp			; DI = 320 * Y + X
	add	di,70
	mov	bx,bp			; Get coor X
	add	bx,bx
	mov	cx,SinTbl[bx]
	mov	bx,si			; Get coor Y
	add	bx,bx
	mov	ax,SinTbl[bx]
	imul	cx
	REPT 3
	shr	dx,1
	rcr	ax,1
	ENDM
	cmp	ah,16
	jc	DontNeg
	sub	ah,32
	neg	ah
DontNeg:
	cmp	ah,0
	jne	ItsNotZero
	inc	ah
ItsNotZero:
	add	ah,127			; Color between 128 & 128+15
	mov	es:[di],ah

	pop	si
	inc	si
	cmp	si,180			; End of vertical?
	je	ExitVerLoop
	jmp	VerLoop
ExitVerLoop:
	pop	bp
	inc	bp
	cmp	bp,180			; End of horizontal?
	je	ExitHorLoop
	jmp	HorLoop
ExitHorLoop:

	cld
	push	ds
	mov	es,OffScreenSeg
	mov	ds,ScreenSeg
	xor	si,si
	xor	di,di
	mov	cx,32768
	rep	movsw
	pop	ds

	call	InitPal

	call	SetPal
; ...........................................................................
MainLoop:
	SetBorder 15
	REPT 4
	call	MakePoint
	ENDM
	SetBorder 7
	call	AdvancePoints
	SetBorder 1
	call	AdvanceBackground
	SetBorder 0
	mov	dx,3DAh
MW2:	in	al,dx
	test	al,8
	jnz	MW2
MW3:	in	al,dx
	test	al,8
	jz	MW3
	
	call	SetPal

	mov	ah,1
	int	16h			; Get kbd state
	jnz	ExitMainLoop
	jmp	MainLoop
ExitMainLoop:
; ...........................................................................
	mov	ah,0
	int	16h		; Flush the kbd buffer out
	mov	ax,3
	int	10h		; Set a wildly unknown video mode
	mov	ah,9
	mov	dx,OFFSET ByeText
	int	21h		; Use undoc. DOS function to print string
	mov	es,OffScreenSeg
	mov	ah,49h
	int	21h
	mov	ax,4C00h
	int	21h		; Exit to MeSsy-DOS
Main	ENDP

	END	Main