;Running the Halls Version 2
;By OneBigDoofus Ç:-) 
;OBD on irc
.nolist

;ported from 82/85 basic game by Harris Novar and David Mazur i think.
;was never released on net i dont think, and i made it on the 82 a thousand
;times and optimized it to about 50% of original speed, but now that it is 
;in asm, it is even faster! if you press 0 at the menu to choose speeds
;you get about the basic speed, if not faster than that
;i also added some graphics to make it a little better than text

;also i added a special version which is similar to urane, though i made the game on 
;basic, and also made it in asm before i knew what urane was, and i believe this one 
;to be a better game anyway, since this is 2 games and has a very small size

;I am always looking for ways to make the game smaller, please send any suggestions
;to me on how to do this without a complete rewrite of the game

#include ion.inc

#define D_HL_DECI _disphl
#define CP_HL_DE _CPHLDE
#define GRAPH_MEM plotsscreen
#define CR_KHAND _GETKEY
#define CR_GRBCopy ionFastCopy
#define TEXT_MEM saferam1
#define D_ZT_STR _puts
#define RAND ionRandom
#define CURSOR_ROW currow

K_RIGHT   =   1
K_LEFT    =   2 
K_1       = $8F
K_2       = $90 
K_MODE    =  $45
star1 = TEXT_MEM+8
star7 = TEXT_MEM+14
star8 = TEXT_MEM+15
cc1 = TEXT_MEM
cc7 = TEXT_MEM+6
cc8 = TEXT_MEM+7
ccy = TEXT_MEM+18
score = TEXT_MEM+16
flag = TEXT_MEM+20
.list
#ifdef TI83P
	.org	progstart-2
	.db	$BB,$6D
#else
	.org	progstart
#endif				
	ret
	jr	nc,start	; jump to the start of the program
 .db "RTH",0
start:
 bcall(_cleargbuf)

loop:
 ld a,18			; make sure a is > 16
 ld hl,cc1			; hit at the beginning, now point hl to cc1
 ld b,a				; load 18 into b, so it repeats 18 times
loop1:				; here for djnz, so we can put it 100 into TEXT_MEM+0-7  
 ld (hl),a			; load a to where hl is pointing, which is TEXT_MEM+7-b
 inc hl				; point hl to next variable
 djnz loop1			; dec b \ jr nz,loop1
 call RAND16			; function in crash to put a random number into a
 ld (ccy),a			; puts the value of a, into ccy, which is where you start
 sbc hl,hl			; puts score at 0(carry flag not set)
 ld (score),hl			;
 call choose_game      	 	; Choose between normal and special
mainloop:
  LD  A, $FF \ OUT ($01), A     ; Reset Port
  LD  A, $BF \ OUT ($01), A     ; Mask out MODE and 2nd
  IN  A, ($01)
  BIT 6, A \ jr z,EXIT              ; If MODE pressed, done
  BIT 5, A \ jr z,pause      ; If 2nd pressed, delay

  LD  A, $FF \ OUT ($01), A     ; Reset Port
  LD  A, $FE \ OUT ($01), A     ; Mask out Arrows
  IN  A, ($01)
  BIT 1, A \ jr Z, moveleft	; not a call here because A is affected
  BIT 2, A \ call Z, moveright 	; fix it to where it is a call and see what i mean
scroll:				; Label here to come back from jumps
 call Scroll_U			; Scrolls up and puts the you sprite back and a new enemy
 ld a,(ccy)			; the value @ ccy is now a
 ld hl,cc8			; hl now points to cc8
 cp (hl)			; compare a to whats at cc8
 jr z,EXIT			; if it is the same, you lose, goto exit
 ld hl,(score)			; hl is the value @ score
 inc hl				; hl=hl+1
 ld (score),hl			; put the new hl back in score
 ld b,c				; ** to change the speed, change c to number of delays, 
;c is set to 11 here		; 11 is default, but anywhere from 8 to 14 is good
delay:				; takes some time
 push bc
 call CR_GRBCopy		; routine takes a while, so it is used to delay game
 pop bc
 djnz delay			; b=b-1 if b is not 0, delay longer
 jr mainloop			; if b is 0, goto beginning

bonus:
 ld hl,(score)			; add 5 to score for bonus
 ld c,5				; of getting a star|b=0
 add hl,bc			;
 ld (score),hl			;
 ret				; moves back

moveright:			; routine to move you right
 ld a,(ccy)			; put the value @ ccy into a
 cp 15				; compare a to 15
 ret z          		; if it is 15, you cant go any farther right, go back
 inc a				; a=a+1
 ld (ccy),a			; put a back into ccy
 ret    			; go back
moveleft:
 ld a,(ccy)			; put the value @ccy into a
 or a				; like cp 0, but shorter/faster
 jr z,scroll           		; if it is 0, go back
 dec a				; a=a-1
 ld (ccy),a			; put a back into ccy
 jr scroll
     			; go back	
pause:
 call dispscore
 bcall(CR_KHAND)			; uncrashable KHAND, lets you 
 cp K_MODE			; if mode is pressed, 				; 
 jr z,EXIT			; quit
 jr mainloop			; go back

EXIT:
 call dispscore
 ld hl,high_str
 bcall(D_ZT_STR)		; display "High:"
 ld hl,(high)
 ld de,(score)
 bcall(CP_HL_DE)
 jr c,newhigh
 bcall(D_HL_DECI)
 jr wait
newhigh:
 ld de,high
 ld hl,score
 ldi
 ldi
 call dispsconly
wait:				;waits after score is displayed
 bcall(CR_KHAND) 
 sub K_RIGHT			; if user presses right left while being hit
 jr z,wait			; this safeguards so user can see score
 dec a	;cp K_LEFT 
 jr z,wait
 ret

Scroll_U:                       ; [16228 Clock Cycles]--slightly modified for RTH
  LD  HL, GRAPH_MEM+96          ; Copy from 7th row below top
  LD  DE, GRAPH_MEM             ;   to top row
  LD  BC, 660                   ;   672 bytes	; dont need bottom
  LDIR                          ; another routine by Crash man
  LD HL,GRAPH_MEM+672
  LD DE,GRAPH_MEM+673
  LD C,84		; b is 0, and not over 8 bits so it doesnt matter
  LD (HL),B		; b is 0, clears last 6 lines
  LDIR
putyou:			;puts a little guy on the screen
 ld a,(ccy)		;puts value of ccy into a
 ld ix, you
 ld hl,GRAPH_MEM             ;y coord is always 0
 call DrwSpr
movevars:
 ld hl,star7
 ld de,star8
 ld c,15
 lddr           ; i cannot use ldir here so i use lddr
 call RAND16	;
 ld (cc1),a
putenmy:                ;puts enemy
 ld hl,GRAPH_MEM+672
 ld ix, enmy1
 call DrwSpr
 ld a,(flag)
 or a
 ret z		; if it is special, continue
movestars:
; ld hl,star7
; ld de,star8
; ld bc,7
; lddr
 ld hl,star8
 ld a,(ccy)
 cp (hl)
 call z,bonus
RAND1:
 call RAND16
 ld hl,cc1
 cp (hl)
 jr z,RAND1
 ld (star1),a
 ld hl,GRAPH_MEM+672
 ld ix,star
DrwSpr:		;great sprite routine by crash man, slightly optimized and modified
  
  LD  d, a	;do x*6+1
  ADD a, a	;x=2x
  ADD a, d	;x=x+OX(original x)   or x*3
  add a, a	;x=2x
  inc a
  LD  e, A                      ; Do x/4
  ld  d,b
  SRL e \ SRL e \ SRL e
  ADD HL, de
  AND %00000111                 ; Get the remainder of x/8
  LD  E, 7                      ; Line loop
  LD  D, A                      ; B=how many bits to shift each line
_DS_LineLoop:
  ld  c, b
  LD  B, D                      ; Shift loop
  LD  A, (IX+0)                 ; Get sprite data
_DS_ShiftLoop:
  RRA \ RR  C                   ; Shift Sprite Line
  DJNZ _DS_ShiftLoop
  INC IX                        ; Inc spritepointer
  OR (HL) \ LD  (HL), A        ; Write line to graphbuf
  INC HL
  LD  A, C
  OR (HL) \ LD  (HL), A
  LD  C, 11                    ; Calculate next line address
  ADD HL, BC
  DEC E
  JR  NZ, _DS_LineLoop          ; Next line
  RET

dispscore:
 LD  HL,0      		; set up coords for displaying "Score:"
 LD  (CURSOR_ROW),HL		; 
 ld hl,score_str		; write "score:"	
 bcall(D_ZT_STR)		; function to do it
dispsconly:
 ld hl,(score)
 bcall(D_HL_DECI)
 ret

normal:
 xor a
special:
 ld (flag),a
 ret

choose_game:
 call CR_GRBCopy
 sbc hl,hl ; ld hl,0  works in place in this situation
 ld (CURSOR_ROW),hl		
 ld hl,choose_str
 bcall(D_ZT_STR)

kloop:
 bcall(CR_KHAND)
 cp K_1
 jr z, normal
 cp K_2
 jr z, special 
 cp K_MODE
 jr nz,kloop
 pop hl			;get rid of last area to return to
;runs rand routine, then returns to shell(saves a byte)
RAND16:			; gets a random number 0-15
 call RAND
 and %1111
 ret


high:
 .dw 0

enmy1:
 	.db %01110000
 	.db %11111000
 	.db %10101000
 	.db %11111000
you: 	.db %01110000	;overlapping sprites, saves 3 bytes
 	.db %01010000
 	.db %01110000
 	.db %11111000
 	.db %01110000
 	.db %01010000
 	.db %01010000
score_str:
 .db "Score:",0
high_str:
 .db "      High:",0

choose_str:
 .db "1)Normal        2)Special"
star:				;0s overlap on string/sprite, saves a whole byte!
 .db 0
 .db 0
 .db %00100000
 .db %11111000
 .db %01110000
 .db %11011000
 .db %10001000
.end
.end
