	.include "library.inc"
	.include "macro.inc"
	.include "equ.inc"
	.nomlist
	.list

; variables

scanline = $0		; the line number for the scanline interrupt
vsync = $2		; synchro vbl

	; wavy scroll

wave_base = $3		; base index for the wave table
wave_idx = $4		; index in the wave table

	; scroll text

st_flag = $5		; event flag
st_offset = $6		; scroll offset
st_ptr = $8		; pointer in the text string
st_pos = $A		; screen position for the next character
st_width = $B		; width of a character
st_char = $C		; current character

	; sprites

spr_idx = $D		; index for rotating stars
spr_base = $E		; base for the circle
spr_angle = $F		; circle rotation
spr_frac = $10		; for adjusting the angle
spr_radius = $11	; radius for the circle
spr_dir = $12		; direction for the zoom
spr_ptr = $13		; pointer in the sprite table
spr_info = $2200	; the eight sprites

; first, we initialize the interrupt vectors

	.bank 0
	.org  $FFF6

	.dw null_int	;IRQ2,  used by the BRK instruction
	.dw vdc_int	;IRQ1,  interrupt from the VDC
	.dw null_int	;TIMER, not used in this demo
	.dw null_int	;NMI,   never used (or may be by a HuCard!?)
	.dw reset_int	;RESET, the most important one :)

	.org $E000

null_int:
	rti

; reset_int:
; ---------
; it's here that everything starts!

reset_int:
	sei			; disable interrupts 
	csh			; select the 7.16 MHz clock
	cld			; clear the decimal flag 
	ldx   #$FF		; initialize the stack
	txs 
	lda   #$FF		; map the first page to the I/O bank
	tam   #0
	lda   #$F8		; and the second to the RAM bank
	tam   #1
	stz   $2000		; clear all the RAM
	tii   $2000,$2001,$1FFF
	jsr   init_vdc		; initialize the video controller
	jsr   init_psg		; and the sound generator
	stz   $C01		; stop the timer
	stz   $1402		; unmask and enable interrupts
	cli

; now that all the hardware is initialized we can copy our
; sprite and character patterns into the VRAM.

	map   spr_data		; map the sprite bank and the font
	map   font_data		; bank into the memory

	; copy all the data to the VRAM

	vload $1000,spr_data,64*4
	vload $1800,water_data,16*4
	vload $2000,font_data,16*256

	; initialize the palette

	setpal 16,spr_pal,3
	setpal 0,water_pal,2
	setpal 2,font_pal,1

; fill the background

	stwi  .scrtab,<_si	; address of the character table
	stwi  $0,<_di		; set the VRAM address
	jsr   set_write

	lda   #32		; size 32 lines of 32 blocks, each block
.l1:	ldx   #32		; is two 8x8 characters
	pha 
.l2:	cly			; we fill each line with two words
	lda   [_si],Y		; from the table
	iny			
	sta   $0002
	lda   [_si],Y
	iny
	sta   $0003
	lda   [_si],Y
	iny
	sta   $0002
	lda   [_si],Y
	iny
	sta   $0003
	dex			; next block
	bne   .l2
	addwi 4,<_si		; update the pointer in the table
	pla
	dec   A			; next line
	bne   .l1

; initialize the variables and enable the display

	lda   #32		; initialize the scroll-text
	sta   <st_pos
	stwi  stext,<st_ptr

	lda   #65		; initialize the sprites
	sta   <spr_radius
	tii   .sprtab,spr_info,8*12

	vreg  #5		; enable the display and
	lda   #$CC		; interrupts
	sta   <_creg
	sta   $0002

; the main loop, here we rotate the stars and scroll
; the text window

.loop:	stz   <vsync		; synchro vbl
.wait:  lda   <vsync
	beq   .wait

	jsr   star_circle	; update the sprite position
	jsr   scroll_text	; update the scroll text

	bra   .loop		; continue again and again!!

; table for initializing the background,
; two words per line

.scrtab:.dw   $0180,$0181,$0182,$0183,$0180,$0181,$0182,$0183
	.dw   $0180,$0181,$0182,$0183,$0180,$0181,$0182,$0183
	.dw   $0180,$0181,$0182,$0183,$0180,$0181,$0182,$0183
	.dw   $0180,$0181,$0182,$0183,$0180,$0181,$0182,$0183
	.dw   $0180,$0181,$0182,$0183,$0180,$0181,$0182,$0183
	.dw   $2200,$2200,$2220,$2220,$1180,$1181,$0182,$0183
	.dw   $0180,$0181,$0182,$0183,$0180,$0181,$0182,$0183
	.dw   $0180,$0181,$0182,$0183,$0180,$0181,$0182,$0183

; table for initializing the sprite informations

.sprtab:.dw   120,152,0,$0080
	.dw   120,152,0,$0081
	.dw   120,152,0,$0082
	.dw   120,152,0,$0080
	.dw   120,152,0,$0081
	.dw   120,152,0,$0082
	.dw   120,152,0,$0080
	.dw   120,152,0,$0081
	.dw   120,152,0,$0082
	.dw   120,152,0,$0080
	.dw   120,152,0,$0081
	.dw   120,152,0,$0082

; vdc_int:
; -------
; interrupt for the VDC

vdc_int:
	pha
	phx
	phy
	lda   $0000		; load the status register

; vertical blanking interrupt code

.vbl:	bit   #$20		; vbl?
	beq   .hbl

	st0   #6		; restart the scanline counter on the first
	stwi  $40,$0002		; line
	stwi  $40,<scanline
	lda   <wave_base	; change the index base for the wavy
	add   #4		; scrolling
	sta   <wave_base
	sta   <wave_idx
	inc   <vsync		; vsync flag
	jmp   .exit

; scanline interrupt code

.hbl:	bit   #$04		; scanline?
	bne   .h1
	jmp   .exit

	; update the scrolling

.h1:	lda   <scanline		; check in what area we are
	cmp   #224
	blo   .h2
	cmp   #239
	bhs   .h2

	st0   #7		; text area
	movw  <st_offset,$0002
	bra   .h3

.h2:	st0   #7		; wavy area
	lda   <wave_idx
	lsr   A
	lsr   A
	tax
	lda   .wave,X
	sta   $0002
	stz   $0003

.h3:	lda   <scanline		; update the index in the
	bit   #$03		; wave table
	bne   .h4
	inc   <wave_idx

	; reprogram the scanline counter for the next line

.h4:	st0   #6
	incw  <scanline
	movw  <scanline,$0002
	jmp   .exit

	; the wave table

.wave:	.db   5,6,7,8,8,9,9,10,10,10,9,9,8,8,7,6
	.db   5,4,3,2,2,1,1,0,0,0,1,1,2,2,3,4
	.db   5,6,7,7,8,8,9,9,9,9,9,8,8,7,7,6
	.db   5,4,3,3,2,2,1,1,1,1,1,2,2,3,3,4

; exit the interrupt handler

.exit:	lda   <_vreg
	sta   $0000
	ply
	plx
	pla
	rti

; star_circle:
; -----------
; update the circle.

star_circle:
	; initialize the variables

	stwi  spr_info,<spr_ptr
	lda   <spr_base
	sta   <spr_angle
	inc   <spr_base
	inc   <spr_idx
	stz   <spr_frac

	; update the radius, zoom effect

	lda   <spr_radius
	ldx   <spr_dir
	bne   .z1
	inc   A			; add
	cmp   #106
	blo   .z2
	dec   <spr_dir
.z1:	dec   A			; sub
	cmp   #65
	bhs   .z2
	inc   <spr_dir
	inc   A
.z2:	sta   <spr_radius

	; calculate the position for the 12 stars

	lda   #12
.v1:    pha
	lda   <spr_radius	; the angle
	sta   <_al
	lda   <spr_angle
	sta   <_bl
	jsr   rotate

	lda   <spr_frac		; update the angle for
	add   #86		; the next star
	sta   <spr_frac
	lda   <spr_angle
	adc   #21
	sta   <spr_angle

	cly			; center the Y position
	lda   #140
	add   <_cl
	sta   [spr_ptr],Y
	cla
	adc   <_ch
	iny
	sta   [spr_ptr],Y
	iny

	lda   #152		; center the X position
	add   <_dl
	sta   [spr_ptr],Y
	cla
	adc   <_dh
	iny
	sta   [spr_ptr],Y
	iny

	lda   <spr_idx		; the sprite number
	lsr   A
	and   #$6
	add   #$80
	sta   [spr_ptr],Y

	addwi 8,<spr_ptr	; go to the next sprite
	pla
	dec   A
	bne   .v1

	; copy the sprite data into the SATB

	setspr 0,spr_info,12
	rts

; rotate:
; ------
; rotate a point.
;
; IN:   _AL = radius  (0 - 127)
;       _BL = angle in degree (0-255)
;
; OUT:  _CX/_DX = signed 16bit coordinates

rotate:
	; calculate Y coordinate

.y:	ldx   <_bl
	lda   .sinus,X
	bsr   .muls
	sta   <_cl
	stz   <_ch
	bit   #$80
	beq   .x
	lda   #$FF
	sta   <_ch

	; calculate X coordinate

.x:	lda   <_bl
	add   #64
	tax
	lda   .sinus,X
	bsr   .muls
	sta   <_dl
	stz   <_dh
	bit   #$80
	beq   .exit
	lda   #$FF
	sta   <_dh
	
	; return results

.exit:	rts

; multiplication sub_routine

.muls:
	clx
	bit   #$80
	beq   .s1
	inx
	neg
.s1:	asl   A
	sta   <_ah

	cla
	ldy   #7
.l1:
	asl   a
	rol   <_ah
	bcc   .s2
	add   <_al
	bcc   .s2
	inc   <_ah
.s2:
	dey
	bne   .l1
	lda   <_ah
	cpx   #0
	beq   .s3
	neg
.s3:	rts

.sinus: .include "sin.inc"

; scroll_text:
; -----------
; update the scroll text.

scroll_text:
	lda   <st_offset
	and   #$7
	bne   .s3

	; check if a new character is needed

	inc   <st_char
	dec   <st_width
	bpl   .s2

	; extract a character from the text string

	lda   [st_ptr]		; get the character
	bne   .s1		; loop if end reached
	stwi  stext,<st_ptr
	lda   stext
.s1:	incw  <st_ptr		; update the index
	tax			; get the width of the character
	ldy   swidth-32,X
	sty   <st_width
	asl   A			; store the character number
	sta   <st_char

	; adjust the character number to match the font

.s2:	lda   <st_char
	sec
	sbc   #64
	sta   <_al
	and   #$60
	asl   A
	sta   <_ah
	lda   <_al
	and   #$1F
	ora   <_ah

	; copy the character

	ldx   #5		; change the VRAM increment to 64
	stx   <_vreg
	st0   #5
	st2   #$10
	ldx   #0		; set the VRAM write address
	stx   <_vreg
	st0   #0
	ldx   <st_pos
	stx   $0002
	st2   #$05
	ldx   #2		; copy the data
	stx   <_vreg
	st0   #2
	sta   $0002
	st2   #$22
	add   #$20
	sta   $0002
	st2   #$22
	ldx   #5		; VRAM increment back to 1
	stx   <_vreg
	st0   #5
	st2   #$00

	; incremente the counters

	lda   <st_pos		; character position
	inc   A
	and   #$3F
	sta   <st_pos

.s3:	addwi 2,<st_offset	; scroll offset
	rts

	; string for the scroll

stext:	.db "                                "
	.db "YO!!  THE MAGIC TEAM IS PROUD TO PRESENT... THE FIRST "
	.db "PC ENGINE DEMO!    "
	.db "IT'S NOT MUCH AND SOUND IS MISSING "
	.db "BUT IT'S JUST THE BEGINNING :)    "
	.db "AT LEAST WE HOPE IT WILL "
	.db "GIVE YOU THE ENVY TO MAKE NEW DEMOS!    "
	.db "AND PERHAPS WE WILL HAVE SOON "
	.db "A GREAT DEMO SCENE ON THE PC ENGINE...  WHO KNOWS!"
	.db "                                "
	.db "CREDITS :  CODE BY RONY AND GFX BY PHOENIX."
	.db "                                "
	.db "GREETINGS TO ALL OUR FRIENDS "
	.db "AND TO ALL THE TGHACK-LIST MEMBERS!!"
	.db "                                "
	.db "PERSONAL MESSAGES :  FROM RONY  "
	.db "- TO INDI \"WOOOO HOOOO!!\"    "
	.db "- TO MAURO G. \"I NEED A MAGIC TEAM LOGO, ANY IDEA?\"    "
	.db "- TO SHAUN J. \"OK, THE NEXT TIME I WILL ENCODE THE TEXT! ;)\"    "
	.db "- TO ERIC Y. \"WHEN DO YOU MAKE A DEMO TOO? :)\"    "
	.db "- TO ZOOP \"J'SUIS SUR QUE TU PEUX PAS FAIRE MIEUX!\"    "
	.db "- TO KAZ M. \"CHIWA!! :)\""
	.db "                                "
	.db "                                "
	.db " RESTARTING..."
	.db "                                "
	.db 0

	; info on the width of a character (8 or 16)

swidth: .db 0,0,1,1,1,1,1,0,0,0,1,1,0,1,0,1
	.db 1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1
	.db 1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1
	.db 1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1

;ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ

	.include "library.asm"

;ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ

	.bank 1
	.org $8000

spr_data:   .incspr "block.pcx",0,80,4,1
spr_pal:    .incpal "block.pcx",1
	    .incpal "block.pcx",4,2
water_data: .incchr "block.pcx",0,96,2,2
water_pal:  .incpal "block.pcx",0
            .incpal "block.pcx",3
font_pal:   .incpal "block.pcx",2

	.bank 2
	.org $A000

font_data:  .incchr "block.pcx",0,0,32,8

