;#################################################
; S H I F T    L E F T
;
;INPUT:
;none
;OUTPUT:
;Shifts screen and buffers left, displays char.
;bc	- 0
;de'	- -16
;#################################################
shift_left:
	ld	ix,item_image+31
	ld	a,06h
	out	(10h),a
	ld	c,47
	call	fetch_state_and_mask
	exx
	ld	de,-16
	ld	hl,vid+(95*16)
	ld	a,(hl)
	rla
	exx
	ld	hl,vid+(96*16)-1
	call	shift_left_h_buffer
	call	onscreen_shift_left
	ex	af,af'
;#################################################
; S H I F T    L E F T    B L O C K
;
;INPUT:
;hl' 	- seed ptr
;de'	- seed increment, -16 here
;hl	- rotate ptr
;b	- lines to shift
;OUTPUT:
;This function shifts left b lines with wrap
;hl'	- seed ptr + b lines
;de'	- seed increment, -16 here
;hl	- rotate ptr + b lines
;b	- 0
;NOTES:
;	Be aware that an accurate bit must be in
;	the carry when the function is called
;#################################################

#DEFINE	RLDEC rl (hl) \ dec hl
#DEFINE DWAIT in a,($10) \ and %10010000 \ jr nz, $-4

shift_left_h_buffer:
	ld	b,16
shift_left_blocK:
	RLDEC
	RLDEC
	RLDEC
	RLDEC
	RLDEC
	RLDEC
	RLDEC
	RLDEC
	RLDEC
	RLDEC
	RLDEC
	RLDEC
	RLDEC
	RLDEC
	RLDEC
	RLDEC
	exx
	add	hl,de
	ld	a,(hl)
	exx
	rla
	djnz shift_left_block
	ret

;#################################################
; S H I F T    R I G H T
;
;INPUT:
;none
;OUTPUT:
;Shifts screen and buffers right, displays char.
;bc	-	0
;de'	-	16
;#################################################
shift_right:
	ld	ix,item_image
	ld	a,07h
	out	(10h),a
	ld	c,0
	call	fetch_state_and_mask
	exx
	ld	de,16			;fetch_state_and_mask leaves 0 in d'
	ld	hl,vid+15
	ld	a,(hl)
	rra				;get an accurate bit in the carry
	exx
	ld	hl,vid
	call	shift_right_h_buffer
	call	onscreen_shift_right
	ex	af,af'
;#################################################
; S H I F T    R I G H T    B L O C K
;
;INPUT:
;hl' 	- seed ptr
;de'	- seed increment, 16 here
;hl	- rotate ptr
;b	- lines to shift
;OUTPUT:
;This function shifts left b lines with wrap
;hl'	- seed ptr + b lines
;de'	- seed increment, 16 here
;hl	- rotate ptr
;b	- 0
;NOTES:
;	Be aware that an accurate bit must be in
;	the carry when the function is called
;#################################################

#DEFINE RRINC rr (hl) \ inc hl
shift_right_h_buffer:
	ld	b,16
shift_right_blocK:
	RRINC
	RRINC
	RRINC
	RRINC
	RRINC
	RRINC
	RRINC
	RRINC
	RRINC
	RRINC
	RRINC
	RRINC
	RRINC
	RRINC
	RRINC
	RRINC
	exx
	add	hl,de
	ld	a,(hl)
	exx
	rra
	djnz shift_right_block
	ret


display_change_item:
	ld	bc,change_item
	exx
	ld	de,change_item+48
	jp	display_screen_lemme_do_it
display_screen_clear:
	ld	bc,clear
	exx
	ld	de,clear_mask
	jr	display_screen_lemme_do_it
;#################################################
; D I S P L A Y    S C R E E N
;
;INPUT:
;none
;OUTPUT:
;This function copies the byte in vid to the lcd
;driver as well as overlaying the character
;according to the animation states
;hl	- vid + 1536
;de	- mask + 48
;bc	- A800h
;bc'	- data + 48
;#################################################
display_screen:			;cycles
	ld	c,0
	call	fetch_state_and_mask
display_screen_lemme_do_it:
	ld	a,07h		;7
	out	(10h),a		;11
	ld	ix,item_image	;12?
	ld	hl,onvid-2	;10
	ld	b,80h-1		;7
screen_y:
	inc	b		;4
	ld	a,b		;4
mod_disp_bounds:
	cp	80h+64		;7
	ret	z		;5 (when not taken, of course)
	out	(10h),a		;11
	cp	80h+4		;7
	jr	c,screen_bounds	;10
	cp	80h+40		;7
	ccf			;4
screen_bounds:
	push	hl		;11
	pop	hl		;10
	ld	a,20h		;7
	out	(10h),a		;11
	inc	hl
	inc	hl
	jp	nc,screen_x_image
;=================================================
screen_x:
	ld	c,12
screen_x_loop:			;cycles		;bytes
	push	hl		;11		;1
	pop	hl		;10		;1
	nop			;4		;1
	ld	a,(hl)		;7		;1
	inc	hl		;6		;1
	out	(11h),a		;11		;2
	dec	c		;4		;1
	jr	nz,screen_x_loop ;12		;2
screen_x_done:
	inc	hl
	inc	hl
	jp	screen_y
;=================================================
screen_x_image:
	ld	c,5
screen_x_image_loop1:		;cycles		;bytes
	push	hl		;11		;1
	pop	hl		;10		;1
	nop			;4		;1
	ld	a,(hl)		;7		;1
	inc	hl		;6		;1
	out	(11h),a		;11		;2
	dec	c		;4		;1
	jr	nz,screen_x_image_loop1 ;12	;2

	ld	a,b
	cp	144
	jr	c,screen_item

	ld	a,2
screen_character:
	ex	af,af'
	ld	c,(hl)
	inc	hl
	ld	a,(de)
	inc	de
	and	c
	ld	c,a
	exx
	ld	a,(bc)
	inc	bc
	exx
	or	c
	ld	c,a
	ld	a,b
	cp	80h+16+4
	ld	a,c
	jp	c,screen_supplement
screen_out:
	out	(11h),a
	ex	af,af'
	dec	a
	jp	nz,screen_character

screen_item_finish:
	ld	c,5
screen_x_image_loop2:		;cycles		;bytes
	push	hl		;11		;1
	pop	hl		;10		;1
	nop			;4		;1
	ld	a,(hl)		;7		;1
	inc	hl		;6		;1
	out	(11h),a		;11		;2
	dec	c		;4		;1
	jr	nz,screen_x_image_loop2 ;12	;2
	jp 	screen_x_done
;=================================================
screen_supplement:
	ld	a,(item_contents)
	or	a
	ld	a,c
	jr	z,screen_out

	and	(ix+32)
	or	(ix+00)
	inc	ix
	jr	screen_out
;=================================================
screen_item:
	ld	a,(item_contents)
	or	a
	jp	nz,continue_draw_item_screen
	ld	c,7
	jp	screen_x_loop
continue_draw_item_screen:
	ld	c,2
screen_item_inner:
	ld	a,(hl)
	inc	hl
	and	(ix+32)
	or	(ix+00)
	out	(11h),a
	inc	ix
	dec	c
	jp	nz,screen_item_inner
	jp	screen_item_finish


;#################################################
; O N S C R E E N    S H I F T    L E F T (OPTIMIZED, YEAH SCREW YOU)
;
;hl 	- vid pointer
;de 	- sprite mask pointer
;bc' 	- sprite data
;hl' 	- seed pointer
;de' 	- seed adder, -16 here
;#################################################
onscreen_shift_left:
	ld	b,80h+64
shift_left_y:
	ex	af,af'
	dec	b
	ld	a,b
	cp	80h-1
	ret	z
	out	(10h),a
	cp	80h+4
	jp	c,shift_left_bounds	;not particularly intensive
	cp	80h+40
	ccf
shift_left_bounds:
	ex	af,af'
	RLDEC			;right buffer byte 2
	RLDEC			;right buffer byte 1
	ld	a,2Bh
	out	(10h),a
	ex	af,af'
	jp	nc,shift_left_x_image
;=================================================
shift_left_x:
	ex	af,af'
	ld	c,12
shift_left_x_loop:		;cycles
	ld	a,(hl)		;7
	ld	a,(hl)		;7
	ld	a,(hl)		;7
	rla			;4
	ld	(hl),a		;7
	dec	hl		;6
	out	(11h),a		;11
	dec	c		;4
	jr	nz,shift_left_x_loop	;12  
shift_left_x_done:
	RLDEC			;left buffer byte 2
	RLDEC			;left buffer byte 1
	exx
	add	hl,de
	ld	a,(hl)
	exx
	rla
	jp	shift_left_y
;=================================================
shift_left_x_image:
	ex	af,af'
	ld	c,5
shift_left_x_image_loop1:	;cycles
	ld	a,(hl)		;7
	ld	a,(hl)		;7
	ld	a,(hl)		;7
	rla			;4
	ld	(hl),a		;7
	dec	hl		;6
	out	(11h),a		;11
	dec	c		;4
	jr	nz,shift_left_x_image_loop1	;12

	ex	af,af'
	cp	144
	jr	c,shift_left_item 	;not particularly speed intensive

	ex	af,af'			;restore carry

	ld	a,2
shift_left_character:
	ld	c,(hl)
	rl	c
	ex	af,af'			;save carry and counter
	ld	(hl),c
	dec	hl
	ld	a,(de)
	dec	de
	and	c			;mask it
	ld	c,a
	exx
	ld	a,(bc)
	dec	bc
	exx
	or	c			;sprite it
	ld	c,a
	ld	a,b
	cp	94h			;overlay bounds
	ld	a,c
	jp	c,shift_left_supplement
shift_left_out:
	out	(11h),a

	ex	af,af'			;4 restore carry and counter
	dec	a			;4
	jp	nz,shift_left_character	;7
shift_left_x_image_finish:
	ld	c,5
	jp	shift_left_x_loop	;alternate entry
;=================================================
shift_left_supplement:
	ld	a,(item_contents)
	or	a
	ld	a,c			;still has image
	jr	z,shift_left_out	;jr, rare, not intensive

	and	(ix+32)
	or	(ix+00)
	dec	ix
	jr	shift_left_out		;rare, save the byte
;=================================================
shift_left_item:
	ld	a,(item_contents)
	or	a
	jp	nz,continue_draw_item_left
	ld	c,7			;most likely, we're out of here.
	ex	af,af'
	jp	shift_left_x_loop	
continue_draw_item_left:
	ex	af,af'			;restore flags
	ld	a,2			;set counter
shift_left_item_inner:
	ld	c,(hl)
	rl	c
	ex	af,af'			;save flags and counter
	ld	a,c
	ld	(hl),a
	dec	hl
	and	(ix+32)
	or	(ix+00)
	dec	ix
	out	(11h),a
	ex	af,af'			;restore flags and counter
	dec	a
	jp	nz,shift_left_item_inner
	ld	c,5
	jp	shift_left_x_loop	;alternate entry

;#################################################
; S H I F T    D O W N
;
;INPUT:
;none
;OUTPUT:
;Shifts screen and buffers down, displays char.
;bc	-	0
;hl	-	swap+16
;#################################################
shift_down:
	ld	ix,item_image+31
	ld	a,06h
	out	(10h),a
	ld	c,47
	call	fetch_state_and_mask		
;#################################################
; O N S C R E E N    S H I F T    D O W N
;
;hl - shift source pointer
;de - shift receive pointer
;bc' - image data
;de' - image mask
;#################################################
#DEFINE HL_DE_DOWN ld a,(hl) \ ld (de),a \ dec hl \ dec de
onscreen_shift_down:
	ld	bc,16
	ld	de,swap+15
	ld	hl,vid+(96*16)-1
	lddr

	inc	b
	ld	de,vid+(96*16)-1
	lddr

	ld	b,80h+64
shift_down_y:
	dec	b
	ld	a,b
	cp	80h-1
	jp	z,shift_down_top_buffer		;same as ret, not intensive
	out	(10h),a
	cp	$84
	jr	c,bounds_down
	cp	$A8				;7	is it bigger?
	ccf	
bounds_down:
	ex	af,af'
	HL_DE_DOWN
	HL_DE_DOWN
	ld	a,2Bh
	out	(10h),a
	ex	af,af'
	jp	nc,shift_down_x_image

;=================================================
shift_down_x:
	ld	c,12		;7	;2
shift_down_x_loop:	
	HL_DE_DOWN		;26	;4
	inc	hl		;6	;1
	dec	hl		;6	;1
	out	(11h),a		;11	;2
	dec	c		;4	;1
	jr	nz,shift_down_x_loop		;12	;2
;=================================================	
shift_down_x_done:
	HL_DE_DOWN
	HL_DE_DOWN
	jp	shift_down_y
;=================================================
shift_down_x_image:
	ld	c,5
	ex	af,af'
shift_down_x_image_loop1:
	HL_DE_DOWN
	inc	hl
	dec	hl
	out	(11h),a
	dec	c
	jr	nz,shift_down_x_image_loop1

	ex	af,af'
	cp	144
	jr	c,shift_down_item

	ld	a,2
shift_down_character:
	ex	af,af'
	HL_DE_DOWN
	ld	c,a
	exx
	ld	a,(de)
	dec	de
	exx
	and	c
	ld	c,a
	exx
	ld	a,(bc)
	dec	bc
	exx
	or	c
	ld	c,a
	ld	a,b
	cp	94h
	ld	a,c
	jp	c,shift_down_supplement
shift_down_out:
	out	(11h),a
	ex	af,af'
	dec	a
	jp	nz,shift_down_character

shift_down_x_image_finish:
	ld	c,5
	jp	shift_down_x_loop
;=================================================
shift_down_supplement:
	ld	a,(item_contents)
	or	a
	ld	a,c
	jr	z,shift_down_out

	and	(ix+32)
	or	(ix+00)
	dec	ix
	jr	shift_down_out
;=================================================
shift_down_item:
	ld	a,(item_contents)
	or	a
	jp	nz,continue_draw_item_down
	ld	c,7
	jp	shift_down_x_loop
continue_draw_item_down:
	ld	c,2
shift_down_item_inner:
	HL_DE_DOWN
	and	(ix+32)
	or	(ix+00)
	dec	ix
	out	(11h),a
	dec	c
	jp	nz,shift_down_item_inner
	ld	c,5
	jp	shift_down_x_loop
;=================================================
shift_down_top_buffer:
	ld 	bc,16*15		;should about cover top buffer
 	lddr

 	ld 	c,16
 	ld 	hl,swap+15	;and the last line
 	lddr

 	ret

;#################################################
; O N S C R E E N    S H I F T    R I G H T
;
;hl - vid pointer
;hl' - seed pointer
;f - shift flags
;de' - adder, -16 here
;bc' - sprite data
;de - sprite mask
;#################################################
onscreen_shift_right:	
	ld	b,80h-1		;top row-1
shift_right_y:
	ex	af,af'		;4	f' <- shift flags
	inc	b		;4
	ld	a,b		;4
	cp	80h+64		;7 bottom row +1
	ret	z		;1?
	out	(10h),a		;11 set row
	cp	$84
	jp	c,bounds_right
	cp	168		;7	is it bigger?
	ccf			;4	is it?
bounds_right:
	ex	af,af'		;4	f' <- bounds test
				;	f <- shift flags
	ld	a,20h		;7
	RRINC			;13? rotate 2 buf bytes
	RRINC			;13? rotate 2 buf bytes
	out	(10h),a		;11

	ex	af,af'		;4	f <- bounds test
				;	f' <- shift flags
	jp	nc,shift_right_x_image
;=================================================
shift_right_x:
	ld 	c,12		;7
	ex	af,af'		;4	f <- shift flags
shift_right_x_loop:
	ld	a,(hl)		;7
	ld	a,(hl)		;7
	ld	a,(hl)		;7
	rra			;4
	ld	(hl),a		;7
	inc	hl		;6
	out	(11h),a		;11
	dec	c		;4
	jr	nz,shift_right_x_loop	;12,5
shift_right_x_done:
	RRINC
	RRINC
	exx
	add	hl,de
	ld 	a,(hl)
	exx
	rra
	jp	shift_right_y
;=================================================
shift_right_x_image:
	ld	c,5		;5 to the right of image
	ex	af,af'		;f <- shift flags
shift_right_x_image_loop1:
	ld	a,(hl)		;7
	ld	a,(hl)		;7
	ld	a,(hl)		;7
	rra			;4
	ld	(hl),a		;7
	inc	hl		;6
	out	(11h),a		;11
	dec	c		;4
	jp	nz,shift_right_x_image_loop1

	ex	af,af'
	cp	144
	jr	c,shift_right_item

	ex	af,af'

	ld	a,2
shift_right_character:
	ld	c,(hl)
	rr	c
	ex	af,af'
	ld	(hl),c
	inc	hl
	ld	a,(de)
	inc	de
	and	c
	ld	c,a
	exx
	ld	a,(bc)
	inc	bc
	exx
	or	c
	ld	c,a
	ld	a,b
	cp	94h
	ld	a,c
	jp	c,shift_right_supplement
shift_right_out:
	out	(11h),a

	ex	af,af'
	dec	a
	jp	nz,shift_right_character
shift_right_x_image_finish:
	ld	c,5
	jp	shift_right_x_loop
;=================================================
shift_right_supplement:
	ld	a,(item_contents)
	or	a
	ld	a,c
	jr	z,shift_right_out
	
	and	(ix+32)
	or	(ix+00)
	inc	ix
	jr	shift_right_out
;=================================================
shift_right_item:
	ld	a,(item_contents)
	or	a
	jp	nz,continue_draw_item_right
	ex	af,af'
	ld	c,7
	jp	shift_right_x_loop
continue_draw_item_right:
	ex	af,af'
	ld	a,2
shift_right_item_inner:
	ld	c,(hl)
	rr	c
	ex	af,af'
	ld	a,c
	ld	(hl),a
	inc	hl
	and	(ix+32)
	or	(ix+00)
	inc	ix
	out	(11h),a
	ex	af,af'
	dec	a
	jp	nz,shift_right_item_inner
	ld	c,5
	jp	shift_right_x_loop	

;#################################################
; S H I F T    U P
;
;INPUT:
;none
;OUTPUT:
;Shifts screen and buffers up, displays char.
;bc	-	0
;hl	-	swap
;#################################################
shift_up:
	ld	ix,item_image
	ld	a,07h
	out	(10h),a		
	ld	c,0
	call	fetch_state_and_mask
;#################################################
; O N S C R E E N    S H I F T    U P
;
;hl - source shifter
;de - destination shifter
;bc' - data pointer
;de' - mask pointer
;#################################################
#DEFINE HL_DE_UP ld a,(hl) \ ld (de),a \ inc hl \ inc de
onscreen_shift_up:
	ld	bc,16
	ld	de,swap
	ld	hl,vid
	ldir

	inc	b
	ld	de,vid
	ldir

	ld	b,80h-1
shift_up_y:
	inc	b
	ld	a,b
	cp	80h+64
	jp	z,shift_up_bottom_buffer
	out	(10h),a		;11
	cp	$84
	jr	c,bounds_up
	cp	168		;7
	ccf			;4
bounds_up:
	ex	af,af'		;4
	HL_DE_UP
	HL_DE_UP
	ld	a,20h		;7
	out	(10h),a		;11
	ex	af,af'		;4
	jp	nc,shift_up_x_image

;=================================================
shift_up_x:
	ld	c,12
shift_up_x_loop:
	HL_DE_UP		;26
	inc	hl		;6
	dec	hl		;6
	out	(11h),a		;11
	dec	c		;4
	jr	nz,shift_up_x_loop	;12	;2
;=================================================
shift_up_x_done:
	HL_DE_UP
	HL_DE_UP	
	jp	shift_up_y
;=================================================
shift_up_x_image:
	ld	c,5
	ex	af,af'
shift_up_x_image_loop1:
	HL_DE_UP		;26
	inc	hl		;6
	dec	hl		;6
	out	(11h),a		;11
	dec	c		;4
	jr	nz,shift_up_x_image_loop1

	ex	af,af'
	cp	144
	jr	c,shift_up_item

	ld	a,2
shift_up_character:
	ex	af,af'
	HL_DE_UP
	ld	c,a
	exx
	ld	a,(de)
	inc	de
	exx
	and	c
	ld	c,a
	exx
	ld	a,(bc)
	inc	bc
	exx
	or	c
	ld	c,a
	ld	a,b
	cp	94h
	ld	a,c
	jp	c,shift_up_supplement
shift_up_out:
	out	(11h),a		;11
	ex	af,af'
	dec	a
	jp	nz,shift_up_character

shift_up_x_image_finish:
	ld	c,5
	jp	shift_up_x_loop
;=================================================
shift_up_supplement:
	ld	a,(item_contents)
	or	a
	ld	a,c
	jr	z,shift_up_out

	and	(ix+32)
	or	(ix+00)
	inc	ix
	jr	shift_up_out
;=================================================
shift_up_item:
	ld	a,(item_contents)
	or	a
	jp	nz,continue_draw_item_up
	ld	c,7
	jp	shift_up_x_loop
continue_draw_item_up:
	ld	c,2
shift_up_item_inner:
	HL_DE_UP
	and	(ix+32)
	or	(ix)
	inc	ix
	out	(11h),a
	dec	c
	jp	nz,shift_up_item_inner
	ld	c,5
	jp	shift_up_x_loop
;=================================================
shift_up_bottom_buffer:
	ld 	bc,16*15			;should about cover top buffer
 	ldir

 	ld 	c,16
 	ld 	hl,swap
 	ldir
 	ret

;#################################################
;U P D A T E    C O L U M N
;
;bc - map data offset pointer
;de - vid address of column
;#################################################
#DEFINE DE_HL_ROW ld a,(de) \ ld (hl),a \ inc hl \ inc de \ ld a,(de) \ ld (hl),a \ inc de \ add hl,bc
update_column:
	ld	hl,(map)
	add	hl,bc		;hl <- memory ptr
	push	de		;stack <- vid
	
	ld	bc,(map_width)
	ld	a,(shift_v)
	or	a
	push	af		;stack <- shift
	jp	p,positive_column_update
negative_column_update:
	add	hl,bc
	push	hl		;stack <- modded memory ptr
	ld	bc,0100h	;video offset
	ld	h,$FF		;negative hl
	jp	begin_column_update
positive_column_update:
	push	hl
	ld	bc,0000h
	ld	h,b		;ld h,0 op
begin_column_update:
	ld	l,a		;multiply shift by 16
	add	hl,hl
	add	hl,hl		;x4
	add	hl,hl		;x8
	add	hl,hl		;x16	

	add	hl,bc		;add with vid mem offset, 0 i +, 16*16 i -
	add	hl,de		;add with column location
	ld	bc,15
	exx
	ld	c,5
	pop	hl		;hl' gets pointer to data
	ld	de,(map_width)
;######### DRAW FIVE ROWS
column_update_loop:
	ld	a,(hl)
	add	hl,de		;de' = map_width
	exx
	call	look_up_tile
	ld	a,16
column_image_loop:
	ex	af,af'
	DE_HL_ROW
	ex	af,af'
	dec	a
	jp	nz,column_image_loop
	exx
	dec	c
	jp	nz,column_update_loop

	pop	af
	jp	m,draw_row_0

draw_row_5:
	sub	16
	neg
	ex	af,af'
	ld	a,(hl)
	exx
	call	look_up_tile
	ex	af,af'
top_portionp_loop:
	ex	af,af'
	DE_HL_ROW
	ex	af,af'
	dec	a
	jp	nz,top_portionp_loop
	pop	hl		;hl <- row 0 location
	ld	a,(shift_v)
	or	a
	ret	z
bottom_portionp_loop:
	ex	af,af'
	DE_HL_ROW
	ex	af,af'
	dec	a
	jp	nz,bottom_portionp_loop
	ret

draw_row_0:
	neg
	ex	af,af'	
	ld	de,(map_width_n5)
	add	hl,de
	ld	de,(map_width_n)
	add	hl,de
	ld	a,(hl)
	exx
	call	look_up_tile
	ex	af,af'
top_portionn_loop:
	ex	af,af'
	DE_HL_ROW
	ex	af,af'
	dec	a
	jp	nz,top_portionn_loop
	pop	hl		;hl <- row 0 location
	ld	a,(shift_v)
	add	a,16
bottom_portionn_loop:
	ex	af,af'
	DE_HL_ROW
	ex	af,af'
	dec	a
	jp	nz,bottom_portionn_loop
	ret


;#################################################
; U P D A T E   R O W 
;
;bc - memory offset of map
;hl' - vid location of buffer (top left)
;#################################################
update_row:
	ld	hl,(map)
	add	hl,bc		;hl points to img 0

	ld	a,(shift_h)
	or	a
	jp	p,shift_h_positive

shift_h_negative:
	inc	hl
	inc	hl		;next please.
	ld	c,a
	neg
	and	00000111b
	ld	b,a		;remainder in b
	ex	af,af'		;remainder in a'
	ld	a,c
	neg
	sra	a
	sra	a
	sra	a		;divide by 8

	exx			;primes active
	or	a		;c-0 z-?
	jp	nz,la1		;c-0 z- (1 if shift is 0-7) (0 if shift is 8-15)
	inc	hl	
la1:
	ex	af,af'		;save z flag and remainder active
	cp	4
	jp	nc,la2		;c- (1 if remainder is 0-3) (0 if remainder is 4-7)
	inc	hl
	ex	af,af'		;restore z flag
	scf
	jp	done_left_adjust
la2:
	ex	af,af'
	or	a		;reset carry flag
done_left_adjust:
	jp	done_right_adjust

shift_h_positive:
	ld	c,a		;c<-shift_h
	and	00000111b
	ld	b,a		;b<-remainder
	ex	af,af'		;a'<-remainder
	ld	a,c		;a<-shift_h
	sra	a
	sra	a
	sra	a		;shift_h/8

	exx			;primes active
	or	a		;is shift/8 zero?
	jp	z,ra1
	inc	hl
ra1:
	ex	af,af'		;a<-remainder f'<-z 1 or 0
	cp	4
	jp	c,ra2
	inc	hl
	ex	af,af'
	scf
	jp	done_right_adjust
ra2:
	ex	af,af'		;a'<-remainder  f<-z 1 or 0
	or	a		;reset carry
done_right_adjust:
	ld	bc,15
	exx
	ld	a,b		;a<-remainder
	push	af
;########################## draw the seven allowed for sure
draw_7:
	ld	b,7
draw_7_loop:
	ld	a,(hl)
	inc	hl
	inc	hl
	exx			;primes active
	call	look_up_tile
	call	draw_i

	ld	de,-(16*16)+2
	add	hl,de
	exx
	djnz	draw_7_loop

	ld	a,c
	or	a
	jp	m,handle_case_negative


;################ H A N D L E   C A S E   P O S I T I V E
handle_case_positive:
	pop	af
	ld	b,a		;b<-remainder
	jp	nz,SHIFTP_8_15
;############ S H I F T P___0___7
SHIFTP_0_7:
	jp	c,shiftp_4_7
;######## S H I F T P___0___3
shiftp_0_3:
	ld	a,(hl)
	exx
	call	look_up_tile
	call	draw_i
	exx
	ld	a,b
	or	a
	ret	z
bottom_half_0_3_ext:
	exx
	ld	de,(-16*16)+1		;skipped
;#### B O T T O M    H A L F    S H I F T P____0____3
bottom_half_shiftp_0_3:			;has to account for half or full.
	add	hl,de
	ex	de,hl
	ld	hl,-15
	add	hl,de
	jp	rotate_buffer_right
;%%%% E N D   B O T T O M    H A L F    S H I F T P____0____3
;%%%%%%%% E N D   S H I F T P___0___3
;######## S H I F T P___4___7
shiftp_4_7:
	call	fill_blank_halves
	ld	a,8
	sub	b
;#### B O T T O M   H A L F   S H I F T P___4___7
bottom_half_shiftp_4_7:			;regardless of half or full.
	exx				;primes active
	ld	de,-16
	add	hl,de
	ex	de,hl			;de holds seed pointer
	ld	hl,15
	add	hl,de			;hl holds shift pointer
	jp	rotate_buffer_left
;%%%% E N D   B O T T O M   H A L F   S H I F T P___4___7
;%%%%%%%% E N D   S H I F T P___4___7
;%%%%%%%%%%%% E N D   S H I F T P___0___7

;############ S H I F T P___8___15
SHIFTP_8_15:
	jp	c,shiftp_12_15
;######## S H I F T P___8___11
shiftp_8_11:
	call	fill_blank_halves
	ld	a,b
	or	a
	ret	z
	exx
	ld	de,(-16*16)+15		;de holds seed pointer
	jp	bottom_half_shiftp_0_3
;%%%%%%%% E N D   S H I F T P___8___11
;######## S H I F T P___12___15
shiftp_12_15:
	ld	a,(hl)
	exx
	ld	de,-16

;after draw 7, vid points to plus 16, we want plus 0


;0  2  4  6  8  10 12 14 16
;DATA
;_______________________;__;
;  ;  ;  ;  ;  ;  ;  ;  ;xx;
;__;__;__;__;__;__;__;__;xx;
; \  \  \  \  \  \  \  \
;VID  \  \  \  \  \  \ 	\
;B  v  v  v  v  v  v  v  E-----,
;  ;  ;  ;  ;  ;  ;  ;  ;xx;   |
;^_;__;__;__;__;__;__;__;xx;   |
; \                            |
;  '---------------------------'

	add	hl,de
	call	look_up_tile		;IMG 7
	call	draw_i
	exx
	ld	a,8
	sub	b
	jp	bottom_half_shiftp_4_7 	;shift left
;%%%%%%%% E N D   S H I F T P___12___15
;%%%%%%%%%%%% E N D   S H I F T P___8___15
;%%%%%%%%%%%%%%%% E N D   H A N D L E   C A S E   P O S I T I V E
;################ H A N D L E   C A S E   N E G A T I V E
handle_case_negative:
	ld	de,-16
	add	hl,de
	pop	af
	ld	b,a
	jp	nz,SHIFTN_8_15
;############ S H I F T N___1___7
SHIFTN_1_7:
	jp	nc,shiftn_4_7
;######## S H I F T N___1___3
shiftn_1_3:
	ld	a,(hl)
	exx
	ld	de,-16
	add	hl,de
	call	look_up_tile		;IMG 0 compare to shiftp_12_15
	call	draw_i
	exx
	ld	a,b
	jp	bottom_half_shiftp_4_7
;%%%%%%%% E N D   S H I F T N___1___3
;######## S H I F T N___4___7
shiftn_4_7:
	call	fill_blank_halves
	ld	a,8
	sub	b
	exx
	ld	de,(-16*16)+15
	jp	bottom_half_shiftp_0_3
;%%%%%%%% E N D   S H I F T N___4___7
;%%%%%%%%%%%% E N D   S H I F T N___1___7
;############ S H I F T N___8___15
shiftn_8_15:
	jp	nc,shiftn_12_15
;######## S H I F T N___8___11
shiftn_8_11:
	call	fill_blank_halves
	ld	a,b
	or	a
	ret	z
	jp	bottom_half_shiftp_4_7
;%%%%%%%% E N D   S H I F T N___8___11
;######## S H I F T N___12___15
shiftn_12_15:
	ld	a,(hl)
	exx
	call	look_up_tile
	call	draw_i
	exx
	ld	a,8
	sub	b
	jp	bottom_half_0_3_ext
;%%%%%%%% E N D   S H I F T N___12___15
;%%%%%%%%%%%% E N D   S H I F T N___8___15
;%%%%%%%%%%%%%%%% E N D   H A N D L E   C A S E   N E G A T I V E


;########################################
; R O T A T E    B U F F E R    L E F T
;
;a	- amount of times to shift
;hl	- shift pointer
;de	- seed pointer
;########################################
rotate_buffer_left:
	push	de
	exx
	ld	de,-16
	pop	hl
rotate_left_loop:
	push	hl
	ex	af,af'
	ld	a,(hl)
	rla
	exx
	push	hl
	call	shift_left_h_buffer
	ex	af,af'
	pop	hl
	exx
	pop	hl
	dec	a
	jp	nz,rotate_left_loop
	ret

;#######################################
; R O T A T E    B U F F E R    R I G H T
;
;a	- amount of times to shift
;hl	- shift pointer
;de	- seed pointer
;#######################################
rotate_buffer_right:
	push	de
	exx
	ld	de,16
	pop	hl
rotate_right_loop:
	push	hl
	ex	af,af'
	ld	a,(hl)
	rra
	exx
	push	hl
	
	call	shift_right_h_buffer
	ex	af,af'
	pop	hl
	exx
	pop	hl
	dec	a
	jp	nz,rotate_right_loop
	ret

;#######################################
; S H I F T    L E F T    F U L L
;
;c 	- times to shift
;#######################################
shift_left_full:
	ld	hl,vid+(16*95)
	ld	a,(hl)
	rla
	ld	de,-16
	exx
	ld	hl,vid+(16*96)-1
	ld	b,96
	call	shift_left_block
	exx
	dec	c
	jr	nz,shift_left_full
	ret
;#######################################
; S H I F T    R I G H T    F U L L
;
;c	- times to shift
;#######################################
shift_right_full:
	ld	hl,vid+15
	ld	a,(hl)
	rra
	ld	de,16
	exx
	ld	hl,vid
	ld	b,96
	call	shift_right_block
	exx
	dec	c
	jr	nz,shift_right_full
	ret
;#####################################
; F I L L    B L A N K    H A L V E S
;
;hl	- pointer to img token of grid space to be split
;bc'	- must be 15 when function is called
;hl'	- must point to grid space to be drawn in vid
;#####################################
fill_blank_halves:
	ld	a,(hl)
	exx
	inc	bc		;15->16
	call	look_up_tile
	push	de		;left half
	call	draw_h
	ld	de,(-16*16)-15
	;2                             1;
	; | ; | ; | ; | ; | ; | ; | ; | ;

	add	hl,de
	pop	de
	inc	de		;left half->right half
	call	draw_h
	exx
	ret

;#################
; D R A W   I M A G E
;#################
draw_i:
	ld	a,16
draw_i_loop:
	ex	af,af'
	ld	a,(de)
	ld	(hl),a
	inc	hl
	inc	de
	ld	a,(de)
	ld	(hl),a
	add	hl,bc
	inc	de
	ex	af,af'
	dec	a
	jp	nz,draw_i_loop

	ret

;#################
; D R A W    H A L F
;#################
draw_h:
	ld	a,16
draw_h_loop:
	ex	af,af'
	ld	a,(de)
	ld	(hl),a
	inc	de
	inc	de
	add	hl,bc
	ex	af,af'
	dec	a
	jp	nz,draw_h_loop

	ret


;#################################################
; U P D A T E    F U L L
;
;hl - pointer to map data
;NOTES:	
; Strangely, it can be called in segments.  It can
; be adapted to just draw a row
;
; destroys:
; de
; hl
; b'
; bc
;#################################################
update_full:
	ld	de,vid
	ld	hl,(map)
	exx
	ld	b,8		;6 columns
draw_column:
	exx
	push	hl		;save the data pointer
	push	de		;save the vid pointer
	ld	c,6	
draw_row:	
	push	hl		;save the data pointer
	ld	a,(hl)		;load a with the tile to be drawn
	ex	de,hl
	call	look_up_tile	;loads DE with the tile (overwrites data pointer)
	ld	b,16		;16 rows in an image
draw_block:
	ld	a,(de)
	ld	(hl),a		;the tile data
	inc	de		;next byte of tile please
	inc	l		;h won't need to help yet, l = 40h
	ld	a,(de)
	ld	(hl),a
	inc	de
	ld	a,15		
	add	a,l		
	ld	l,a		
	jr	c,inc_h_needed
	djnz	draw_block	
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
	ex	de,hl		;de gets video
	pop	hl		;pop data pointer into hl
	ld	a,c
map_width = $+1
	ld	bc,0000h	;patched by load_level initially, I believe
	add	hl,bc
	ld	c,a
	dec	c		;we'll have 6 rows to draw
	jr	nz,draw_row
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
	pop	de
	inc	de
	inc	de		;next video column
	pop	hl
	inc	hl
	inc	hl		;next data column
	exx
	djnz 	draw_column
	ret
	
inc_h_needed:
	inc	h
	djnz	draw_block

;#################################################
; O V E R L A Y    S P R I T E
;
;INPUT:
;hl 	- vid pointer for overlay
;de 	- sprite mask
;bc 	- sprite start y,x 	;in bytes +80h,20h
;de' 	- sprite end y,x	;in bytes +80h,20h
;bc' 	- sprite data
;OUTPUT:
;Overlays a sprite without touching vid
;hl	- vid+sprite_height*16
;de	- sprite_mask+sprite size (next sprite)
;b	- sprite end
;bc'	- sprite_data+sprite size (this sprite's mask)
;#################################################
overlay_sprite:			;cycles
	ld	a,07h		;7
	out	(10h),a		;11
overlay_sprite_skip_out:
	dec	b		;4
overlay_sprite_y:
	inc	b		;4
	ld	a,b		;4
	exx			;4 primes active
	cp	d		;4 
	exx			;4 regs active
	ret	z		;1?
	push	hl		;10
	inc	hl		;6
	pop	hl		;11
	out	(10h),a		;11

	push	hl		;11
	pop	hl		;10
	inc	hl		;6
	dec	hl		;6
	push	bc		;11 push counters
	push	hl		;11 push vid pointer
	ld	a,c		;4
	out	(10h),a		;11
overlay_sprite_x:
	inc	a		;4
	ex	af,af'		;4
	ld	a,(de)		;7
	inc	de		;6
	and	(hl)		;7?
	inc	hl		;6
	exx			;4 primes active
	ld	h,a		;4
	ld	a,(bc)		;7
	inc	bc		;6
	or	h		;4
	out	(11h),a		;11
	ex	af,af'		;4
	cp	e		;4 x max
	exx			;4 regs active
	jp	nz,overlay_sprite_x	;10

	pop	hl		;pop vid pointer
	ld	bc,16
	add	hl,bc
	pop	bc		;pop counters
	jp	overlay_sprite_y

;#################################################
; N E X T    S T A T E
;
;INPUT:
;none
;OUTPUT:
;Moves to next animation state
;#################################################
next_state:
	ld	hl,animation_counter
	dec	(hl)
	ret	nz			;get out, not next frame
next_frame:
	ld	a,11			;frames per step
	ld	(animation_counter),a
	ld	hl,(state)

	inc	hl
	ld	a,$FF
	cp	(hl)
	jr	z,cycle_state

	ld	(state),hl		;next image offset
	ret
cycle_state:
	ld	hl,animation_states
	ld	(state),hl
	ret

;#################################################
; F E T C H    S T A T E    A N D    M A S K
;
;INPUT:
;c	-	offset
;OUTPUT:
;bc'	- character image ptr
;de	- character mask ptr
;de'	- character mask ptr
;h'	- 0
;l'	- 48
;#################################################
fetch_state_and_mask:
	ld	a,(gen_state)		;00000011
	ld	b,a
	rrca				;10000001	;all screwed up
	rrca				;11000000	;x64
	rrca				;01100000	;x32
	ld	hl,(state)		
	add	a,(hl)			;11000000	;672
	jr	nc,b_good1
	inc	b
b_good1:
	add	a,c			;10111111		
	jr	nc,b_good2
	inc	b
b_good2:					;at this point bc holds offset of what direction we're facing and image inc/dec offset (0 or 95)
	ld	c,a			;and offset of animation; all that remains is offset of carry or run
run_state:
	ld	a,(speed)
	cp	run_speed
	jr	nz,walk_or_carry
	ld	hl,animation_images+down_run1-down_stand
finish_state_and_mask:
	add	hl,bc
	ld	b,h
	ld	c,l
	ld	de,48
	add	hl,de
	push	hl
	ex	de,hl			;put mask in de
	exx
	pop	de
	ret
walk_or_carry:
	ld	a,(item_contents)
	or	a
	jr	nz,carry_state

	ld	hl,animation_images
	jr	finish_state_and_mask
carry_state:
	ld	hl,animation_images+down_stand_hold-down_stand
	jr	finish_state_and_mask