.286
; we need a stack to use with pusha/popa/pushf
STACKSEG SEGMENT STACK
DD 255 DUP(0)
STACK_TOP LABEL WORD
DD 255 DUP(0)
STACKSEG ENDS

CODE SEGMENT
	assume cs:code, ds:code, ss:stackseg, es:code
START:
	jmp SKIPDATASECT
; the variables reside in the code segment, they are jumped over.
	scr_buf dw 2000 dup(?)	; screen buffer
	myflag	db 0
	myflag2	db 0
	oldint1ch dw 2 dup (0)
	oldint09h dw 2 dup (0)
	scan_codes db  1Eh,30h,2Eh,20h,12h,21h,22h,23h,17h,24h,25h,26h,32h,31h,18h,19h,10h,13h,1Fh,14h,16h,2Fh,11h,2Dh,15h,2Ch
	asci_codes db 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
	int1chcounter dw 0
	mycharseed dw 0F9A4h
	mycolseed  dw 0EDFCh
	mycurrentchar db ?
	mycurrentcol db ?
	mycurrentcolor db 7
	mycurrentrow db 2
	mycurrentpos dw ?
	shotnum dw 0
	PERIOD dw 15

	scr_adr equ 0b800h	; screen segment adres
	ch_wall equ 178
	cl_wall equ 74h




SKIPDATASECT:
; initialize data and stack
	mov ax,cs
	mov ds, ax
	mov es, ax
	mov ax, stackseg
	mov ss, ax
	mov sp, stack_top
	jmp main


main:
	;save screen in scr buf
	call save_screen

	call Draw_Frame
	call Set_Mychar
	call Set_Mycol
	call Init_scr
	call print_score
	
	; save int 1ch address
	mov ax,351ch
	int 21h
	mov oldint1ch[0],bx
	mov oldint1ch[2],es
	; save int 09h address
	mov ax,3509h
	int 21h
	mov oldint09h[0],bx
	mov oldint09h[2],es
	
	; set new int 1ch
	mov ax,251ch
	lea dx,OnTimer
	int 21h
	; set new int 09h
	mov ax,2509h
	lea dx,OnKeyClick
	int 21h
	
; loop until the interrupt service routine places 3 to myflag
infLoop:
	nop
	cmp myflag,3
	jne infLoop
	
	; clear screen
        mov ah,7	
	xor al,al
	mov cx,2000
	xor di,di
	rep stosw
	call print_score 

infLoop2:
	nop
	cmp myflag, 4
	jne infLoop2

	; clear screen
        mov ah,7	; char color
	xor al,al
	mov cx,2000
	xor di,di
	rep stosw

	call restore_screen
; restore everything back...

	mov cx, ds

	mov bx, word ptr oldint1ch[0]
	mov dx, word ptr oldint1ch[2]
	mov ds, dx
	mov dx, bx
	mov ax, 251ch
	int 21h

	mov ds, cx
	mov bx, word ptr oldint09h[0]
	mov dx, word ptr oldint09h[2]
	mov ds, dx
	mov dx, bx
	mov ax, 2509h
	int 21h
	mov ax, 4c00h
	int 21h

	jmp End_Prog

; save screen to scr_buf
save_screen proc near
	push ds
	
	mov ax,scr_adr
	mov ds,ax
	xor si,si
	lea di,scr_buf
	mov cx,2000
	cld
	rep movsw
	
	pop ds
	ret
save_screen endp

; restore screen from scr_buf
restore_screen proc near
	push es
	
	mov ax,scr_adr
	mov es,ax
	xor di,di
	lea si,scr_buf
	mov cx,2000
	cld
	rep movsw
	
	pop es
	ret
restore_screen endp

OnTimer proc near
	cli

	pushf
	call dword ptr cs:oldint1ch
	pusha

	mov ax, cs
	mov ds, ax

	cmp myflag,3
	je endmyint
; our data labels are offsets to the ASSUMED data segment, so we have to restore
; it if we have to access our variables.

	inc int1chcounter
	mov ax, int1chcounter

; control the counter, if it reaches PERIOD, print the next character
	cmp ax, PERIOD
	jz printscreen
	jmp endmyint
printscreen:
	mov word ptr int1chcounter, 0
	mov ax, scr_adr
	mov es, ax

	mov bx,mycurrentpos
	mov al, mycurrentchar	
	mov es:[bx], al
	mov byte ptr es:[bx+1], 0

	add mycurrentpos,160
	inc mycurrentrow
	mov bx,mycurrentpos 
	mov al, mycurrentchar
	mov cl, mycurrentcolor
	mov es:[bx], al
	mov byte ptr es:[bx+1], cl
; if we have already reached bottom line, set the flag so that the program exits from
; its infinite loop
	cmp mycurrentrow, 25
	jnz endmyint
	mov myflag, 3

endmyint:

	popa
	sti
	iret
OnTimer endp


OnKeyClick proc near
	cli
	pusha 
	mov ax, cs
	mov ds, ax

	cmp myflag,3
	jne Continue_Key_Click
	mov myflag,4

	in al,60h
	jmp endint09h
Continue_Key_Click:

; get the character scan code
	in al, 60h

	mov cx,26
	cld
	lea SI,	scan_codes
	lea DI, asci_codes

my_loop_label:
	cmp al,[SI]
	jne my_inloop_label
	mov ah,[DI]
	cmp ah,mycurrentchar
	jne my_end_of_loop

	;do what if the true letter is pressed
	mov ax,scr_adr
	mov es,ax

	mov bx,mycurrentpos
	mov al, mycurrentchar	
	mov es:[bx], al
	mov byte ptr es:[bx+1], 0

	dec PERIOD
	cmp PERIOD,1
	jne PERIOD_NOT_1
	inc PERIOD	
PERIOD_NOT_1:
	inc shotnum
	inc mycurrentcolor
	cmp mycurrentcolor,15
	jne color_not_15
	mov mycurrentcolor,7
color_not_15:
	call Set_Mychar
	call Set_Mycol
	call Init_scr
	call print_score
	mov int1chcounter,0	

	jmp my_end_of_loop
my_inloop_label:
	inc SI
	inc DI
	loop my_loop_label

my_end_of_loop:
	
endint09h:	
; send end of interrupt signal
	mov al, 20h
	out 20h, al

	popa
	sti
	iret
OnKeyClick endp



Draw_Frame proc near
	pushf
	push es ds ax bx cx dx
	
        mov ax,scr_adr
	mov es,ax
	
	; clear screen
        mov ah,7	; char color
	xor al,al
	mov cx,2000
	xor di,di
	rep stosw
	
	mov ah,cl_wall
	mov al,ch_wall	; char
	; horizontal walls
	mov di,80*2	; row 2
	mov cx,80
	cld
	rep stosw	
	mov di,80*2*24	; row 25
	mov cx,80
	cld
	rep stosw
	; vertical walls
	mov di,80*2*2	; row 3
	mov cx,22
is_loop:
	mov es:[di],ax	; left walls
	mov es:[di+79*2],ax	; right walls
	add di,80*2	; increment 1 row
	loop is_loop

	pop dx cx bx ax ds es
	popf
	ret
Draw_Frame endp

Set_Mychar proc near
	pushf
	push es ds ax bx cx dx

	xor dx,dx
	mov ax,mycharseed
	shr ax,1
	mov cx,ax
	and ax, 5402h
	cmp ax, 5402h
	jne MyJmp1
	add cx,8000h

MyJmp1:	
	xor bx,bx
	mov bl,mycurrentcol
	add cx,bx
	mov bl,mycurrentcolor
	add cx,bx
	mov dx,cx
	mov mycharseed, dx

	;convert into a char
	mov ax,dx
	xor dx,dx
	mov bx,26
	div bx
	add dl, 'a'
	mov mycurrentchar,dl

	pop dx cx bx ax ds es
	popf
	ret
Set_Mychar endp

Set_Mycol proc near
	pushf
	push es ds ax bx cx dx

	xor dx,dx
	mov ax,mycolseed
	shr ax,1
	mov cx,ax
	and ax, 5402h
	cmp ax, 5402h
	jne MyJmp2
	add cx,8000h

MyJmp2:	
	mov bl,mycurrentcolor
	add cx,bx
	mov bx,mycharseed
	add cx,bx	
	mov dx,cx
	mov mycolseed, dx

	;convert into a char
	mov ax,dx
	xor dx,dx
	mov bx,78
	div bx
	inc dl
	mov mycurrentcol,dl

	pop dx cx bx ax ds es
	popf
	ret
Set_Mycol endp

Init_scr proc near
	pushf
	push es ds ax bx cx dx

	mov mycurrentrow,2
	mov ax, scr_adr
	mov es, ax
	mov al,80
	mul mycurrentrow
	
	xor bx,bx
	mov bl, mycurrentcol	
	add ax,bx
	mov bx,2
	mul bx
	mov bl, mycurrentchar
	mov di,ax
	mov mycurrentpos,ax
	mov es:[di], bl
	mov bl,mycurrentcolor
	mov byte ptr es:[di+1], bl

	pop dx cx bx ax ds es
	popf
	ret
Init_scr endp

print_score proc near
	pushf
	push es ds ax bx cx dx
	
	; calculate score
	xor dx,dx
	mov dx,shotnum
	
prn_norm:
	; print to screen
	mov ax,scr_adr
	mov es,ax
	mov di,148
	cmp myflag,3
	jne Game_Not_Ended
	add di,728

Game_Not_Ended:
	; int 2 char conversion
	mov ax,dx
	mov bx,10000
	mov cx,5
prn_loop:
	xor dx,dx
	div bx
	add al,48
	mov byte ptr es:[di],al
	mov ax,bx
	mov bx,10
	push dx
	xor dx,dx
	div bx
	mov bx,ax
	pop ax
	add di,2
	loop prn_loop
	
	pop dx cx bx ax ds es
	popf
	ret
print_score endp


End_Prog:NOP

	
CODE ENDS
END START

