Fishtank by Stuart Gascoigne
The graphics for Fishtank were designed using 'The Advanced Art
Studio' by Rainbird. You can use it to modify the fishtank screen if
you wish. The palette file for the fishtank is included to make life
easier, although the program doesn't use this, (i.e. the inks are
preset to the same values in the program).
The title screen and tank are held in compressed format. The program
CRUNCH converts to this format.
The fishes in the fishtank are also created with AAS. They are drawn
using the same palette, and saved as window files. You can create your
own fish using AAS, define a window around it and save it to a file.
Normally, the window should just enclose the fish. If you add extra
lines of background to the top or bottom of the fish, you will slow it
down. If you add extra pixels of background to the right or left of
the fish, it will appear to turn early. The background for the fishes
must be plain ink 0, anything else is assumed to be part of the fish.
Note that the fishes should point rightwards (unless you want them to
swim backwards!). Each fish window must conform to the following
limits
- a maximum of &6b0 bytes in length
- not more than 96 pixels in height
- not more than 40 bytes (80 pixels) in width.
There must be a maximum of 16kbytes of fishes in total.
You can add your fish(es) to the default set by calling it FISH-x.WIN,
where x is the next letter in sequence, and poking location &3680 with
(the ASCII value of x) - 64 (,i.e. the number of fishes). As provided,
there are 10 fishes, and there is room for up to 15.
Thanks to Sam Farr for the mutant ninja terrapin, mermaid and submarine.
My version of Advanced Art Studio is 2.4, compatability with other
versions is unknown.
The Hisoft GENA assembler is used throughout and sources are included.
NOTICE TEXTE n° 2 (22.57 Ko)
;fishtank, by stuart gascoigne
;the cheapest fishtank on the market
;idea pinched from J Raphael B Salgado's "Aquarium"
;on a ibm pc
;screen is assumed to be not rolled and not scrolled
;it makes the calculations a lot easier
FISHSZ:equ #6b0 ;maximum length of a fish
MAXYSZ:equ 96 ;max height of fish window
MAXXSZ:equ 40 ;max width of fish window
FISH1:equ #100 ;address of fish
MASK1:equ FISH1+FISHSZ ;address of mask
FISH2:equ MASK1+FISHSZ ;fish moved 1 pixel
MASK2:equ FISH2+FISHSZ ;mask for fish 2
FISH1B:equ MASK2+FISHSZ ;backwards fish 1
MASK1B:equ FISH1B+FISHSZ
FISH2B:equ MASK1B+FISHSZ ;backwards fish 2
MASK2B:equ FISH2B+FISHSZ
TEMPFI:equ #4000 ;fishes read into here initially
;overwritten by second screen
CMPSCR:equ #4000 ;compressed piccy's address
BUFFER:equ #8000 ;disc buffer
SCST:equ #8000 ;address of screen store
RAMBAS:equ #c0 ;bank no for unswapped ram
RAMTIT:equ #c4 ;bank no for stored title screen
RAMFIS:equ #c5 ;bank no for stored fishes
RAMTNK:equ #c6 ;bank no for stored tank
org MASK2B+FISHSZ
NOFISH:defb 3 ;number of fishes to choose from
;poke whatever value you like in here
ent $
ld hl,0
add hl,sp ;hl=stack base
ld (STACK),hl ;store away
restrt:call init1 ;load background,etc
call init2 ;select fishes etc
again:call right ;main loop
call left
jr again
STACK:defw 0 ;stack base
START:defb 0 ;starts at zero, set to one once
;we've loaded everything - restart without reloading
right:;move fish right
ld a,(MOVEX)
ld b,a
right1:push bc
call esc ;test for esc key
ld de,MASK1
ld ix,FISH1
call loadfi
res 7,h ;now points at lower screen
ld de,MASK2
ld ix,FISH2
call loadfi
inc iy
inc hl
set 7,h ;and now higher screen
pop bc
djnz right1
ret
left:;move fish left
ld a,(MOVEX)
ld b,a
left1:push bc
call esc ;test for esc key
ld de,MASK1B
ld ix,FISH1B
call loadfi
res 7,h ;now points at lower screen
ld de,MASK2B
ld ix,FISH2B
call loadfi
set 7,h ;and now higher screen
dec iy
dec hl
pop bc
djnz left1
ret
esc:;tests whether esc key is pressed
ld a,(RAM) ;unless we are expanded ignore & ret
cp 1
ret nz
ld a,66 ;esc = key 66
push hl ;save hl
call #bb1e ;km test key
pop hl
ret z ;esc not pressed -return
ld a,#c0 ;reset screen to high location
call #bc08 ;scr set base
ld hl,(STACK) ;load saved stack base
ld sp,hl ;reset stack
jp restrt
loadfi:;moves fish to screen
;hl must contain screen address of top left point
;iy must contain corresponding address of stored background
;de must contain address of mask to use
;ix must address fish to use
;fish is ORed onto the AND of the mask and the stored
;background, then result sent to screen
;this preserves the background inside the fish window
push hl ;save screen addresses
push iy
ld a,(YSIZE)
ld b,a ;b=lines to shift
next3:push bc ;store line count
ld a,(XSIZE)
ld b,a ;no of bytes to shift
push iy ;save background address
push hl ;save screen address
next4:ld a,(de) ;next mask
and (iy) ;add to background
or (ix) ;add fish
ld (hl),a ;result to screen
inc hl
inc de
inc ix
inc iy
djnz next4 ;next byte
pop hl ;start of line again
ld bc,#0800
add hl,bc ;start of next line?
bit 6,h ;gets reset on overflowing screen
jr nz,no3
ld bc,#c050 ;adjust for next screen block
add hl,bc
no3:pop iy ;start of background line
ld bc,#0050
add iy,bc ;start of next line
pop bc ;line count
djnz next3
call #bd19 ;wait frame flyback
ld a,h ;half of screen address
call #bc08 ;switch screens
pop iy;get back screen addresses
pop hl
ret
;****************************
init1:
;loads title screen, loads fishes
ld a,(START) ;are we restarting?
cp 0
jr nz,rest1 ;if yes jump
;test whether expanded machine or not
ld hl,#4000 ;switchable ram address
ld (hl),1 ;if we get a 1 back=ram there
ld bc,#7f00+RAMFIS
out (c),c ;switch banks (possibly)
ld (hl),0 ;if we get a 0 back=ram not there
ld bc,#7f00+RAMBAS
out (c),c ;switch back
ld a,(hl)
ld (RAM),a ;store the answer
ld a,0 ;new screen mode
call #bc0e ;set mode
call zerink ;set inks to 0
ld hl,TITLE ;title screen
call readsc ;read screen into #c000
call setink ;set inks
ld a,(RAM) ;test for expanded memory
cp 1
jr nz,noram1 ;no ram
ld c,RAMTIT ;bank no
call hi2low ;save screen in banked ram
noram1:ld a,5 ;ink 5=bright yellow
call #bbde ;gra set ink
ld hl,80 ;y-coord
ld ix,PLZWT ;message
call wrline
ld a,(NOFISH)
ld b,a ;number of fish to read
ld iy,TEMPFI ;first fish goes here
ld ix,TABLE ;index to where fishes are
nextfi:push bc ;save count
call readfi ;read in fish
pop bc
djnz nextfi ;do next fish
ld a,(RAM)
cp 1 ;if spare ram save fishes
ret nz ;no ram
ld a,RAMBAS ;main bank
ld (FROMBK),a
ld a,RAMFIS
ld (TOBK),a
call low2lw ;save fishes
ret
rest1:;restart
ld c,RAMTIT ;bank no
call low2hi ;reload title screen
ld a,RAMFIS
ld (FROMBK),a
ld a,RAMBAS
ld (TOBK),a
call low2lw ;reload fish
ret
RAM:defb 0 ;64k=0 128k=1
PLZWT:defm "please wait while fish are loaded£"
init2:
;select fish to use and set up tank
call wrmess ;instructions to screen
call select ;display and pick fishes
call where ;ask where fish should go
ld a,(START)
cp 0 ;restarting?
jr nz,rest2 ;jump if yes
ld hl,TANKNM ;screen name
call readsc ;load fish tank
ld a,(RAM)
cp 1 ;extra memory?
jr nz,noram2 ;no ram
ld c,RAMTNK ;bank no
call hi2low ;save tank in banked ram
jr noram2 ;join up with main code again
rest2:ld c,RAMTNK ;bank no
call low2hi ;reload tank
noram2:
ld c,RAMBAS ;bank no=main bank
call hi2low ;duplicate tank screen
ld de,0
ld hl,(SWIMY)
call #bc1d ;get screen address in hl
push hl
call savesc ;move the bit of screen that
;we animate to store (full width)
pop hl ;screen address
ld iy,SCST ;background address
ld a,(XSIZE)
sub 80
neg
ld (MOVEX),a ;movex=80-xsize
ld a,1
ld (START),a ;set flag - can now restart
ret
TANKNM:defm 'FISHTANK.SQR' ;tank background
TITLE:defm 'FISHTITL.SQR' ;title screen
FISHES:defw 0 ;address of fish
XSIZE:defb 0 ;size of fish, horiz, bytes
YSIZE:defb 0 ;size of fish, vert, lines
XSIZEP:defb 0 ;size of fish, horiz pixels
XSPARE:defb 0 ;no of bits from
;window edge to byte boundary
FILENG:defw 0 ;length of fish
MOVEX:defb 0 ;no of bytes to move fish
TABSZ:equ 8 ;bytes/item in table
TABLE:defs TABSZ*15 ;array-for storing fish data
;format of array, indexed by ix, is
;(ix),(ix+1)=address of fish
;(ix+2)=xsize in bytes
;(ix+3)=ysize in lines
;(ix+4)=xsize in pixels
;(ix+5)=xspare (must be 0 or 4 for mode 0 pics)
;(ix+6,7)=length of fish bytes
zerink:;sets all inks to 0
xor a ; a=0
nxtzik:ld bc,0 ;colour=0
push af
call #bc32 ;set ink
pop af
inc a
cp #10
jr nz,nxtzik
ret
setink:;sets inks for picture
ld ix,INKS
xor a ;a=0
nextik:ld b,(ix)
ld c,b
push af
call #bc32 ;set ink a to colour b,c
pop af
inc ix
inc a
cp #10
jr nz,nextik
ret
INKS:defb 2,0,6,26,1,24,20,22,13,9,15,16,21,25,11,3
readsc:;reads screen into #4000
;title of file must be addressed by hl
;decompresses screen into #c000
ld b,12 ;length of name
ld de,BUFFER
call #bc77 ;file open
ld hl,CMPSCR ;screen address
call #bc83 ;read direct
call #bc7a ;close input
;screen is compressed with a self starting decompressor
;on the front. Call it
jp CMPSCR
readfi:;read in fish file
ld (fudge1+2),ix ;array pointer
fudge1:ld (0),iy ;store start address
ld a,b ;file number
or #40 ;turn number to letter
ld (FILENO),a ;part of file name
ld b,10 ;length of name
ld hl,FILENM ;name location
ld de,BUFFER
push ix ;save array pointer
call #bc77 ;file open
pop ix
push ix ;save it again
push bc ;file length
ld hl,-5
add hl,bc ;hl=file length-5
ld (ix+6),l
ld (ix+7),h ;fish size stored in array
call tumuch;test file size
call tumany ;test total fish sizes
push iy ;start address
pop hl ;start address in hl
call #bc83 ;read direct
pop bc ;file length
add iy,bc ;start of next file
pop ix ;get back array pointer
ld a,(iy-4) ;x-coord lower byte
srl a
srl a
rrc (iy-3) ;x-coord higher byte
rrc (iy-3) ;divide by 4
add a,(iy-3) ;add on and then..
ld (ix+4),a ;x-size divided by 4
dec a
srl a
inc a
ld (ix+2),a ;x-size / 8 rounded up
call tuwide ;test width of window
ld a,(iy-2)
ld (ix+3),a ;y-size=no of lines
call tuhigh ;test height of window
ld a,(iy-5)
ld (ix+5),a ;xspare bits stored
ld bc,-5 ;take red tape of end of file
add iy,bc ;by adjusting pointer to next file
call adjust ;tinker with fish pic
ld bc,TABSZ
add ix,bc ;increment pointer
tmerr:push ix ;save array pointer
call #bc7a ;close file
pop ix ;array pointer
ret
FILENM:defm 'FISH-'
FILENO:defb 0
defm '.WIN£'
tumuch:;test if fish is too big
;and give error message if necessary. size is in bc
ld hl,FISHSZ ;max size of a fish
xor a ;resets carry
sbc hl,bc ;neg if fish>max
ret p ;ok - return
pop hl ;discard return address
pop hl ;discard saved data word
;array pointer is still on stack
call cltext ;clear text window
ld hl,60 ;give error message
ld ix,FILENM
call wrline
ld ix,ERR1
call wrline
ld ix,CONT
call wrline
call #bb18 ;wait for key
pop ix ;get back array pointer
jp tmerr ;close file etc
ERR1:defm "is too large - max "
;note that we allow 200 bytes expansion of file for
;adding 2bytes down the side of window
defb FISHSZ-200/1000?10+"0"
defb FISHSZ-200/100?10+"0"
defb FISHSZ-200/10?10+"0"
defb FISHSZ-200/1?10+"0"
defm " bytes allowed£"
CONT:defm "hit any key to continue£"
tumany:;test whether fish will cause
;total size of all fishes to exceed space available
;size is always #4000 - size of a ram bank
push iy ;start address
pop hl ;now in hl
add hl,bc ;add to size
ld bc,TEMPFI+#4000 ;end of fish space
xor a ;reset carry
sbc hl,bc
ret m ;result should be negative
pop hl ;discard return address
pop hl ;discard saved data word
;array pointer is still on stack
call cltext ;clear text window
ld hl,80 ;give error message
ld ix,FILENM
call wrline
ld ix,ERR4
call wrline
call wrline
ld ix,CONT
call wrline
call #bb18 ;wait for key
pop ix ;get back array pointer
jp tmerr ;close file etc
ERR4:defm "is too large - total size£"
ERR5:defm "of all fish must be < 16kbytes£"
tuwide:;test width of window and
;give error if too much. width in a
cp MAXXSZ ;max width
ret m ;ok
call cltext ;clear message window
push ix ;save array pointer
ld hl,60
ld ix,FILENM
call wrline
ld ix,ERR3
call wrline
ld ix,CONT
call wrline
call #bb18 ;wait for key
pop ix ;get back array pointer
ld (fudge5+2),ix ;array pointer
fudge5:ld iy,(0) ;reset start address
pop hl ;discard return address
jp tmerr ;go close file etc
ERR3:defm "is too wide - max "
defb MAXXSZ/10?10+"0"
defb MAXXSZ/1?10+"0"
defm " bytes allowed£"
tuhigh:;test height of window and
;give error if too much. height in a
cp MAXYSZ ;max height
ret m ;ok
push ix ;save array pointer
call cltext ;clear message window
ld hl,60
ld ix,FILENM
call wrline
ld ix,ERR2
call wrline
ld ix,CONT
call wrline
call #bb18 ;wait for key
pop ix ;get back array pointer
ld (fudge6+2),ix ;array pointer
fudge6:ld iy,(0) ;reset start address
pop hl ;discard return address
jp tmerr ;go close file etc
ret
ERR2:defm "is too high - max "
defb MAXYSZ/10?10+"0"
defb MAXYSZ/1?10+"0"
defm " lines allowed£"
wrmess:;write instructions to screen
call cltext ;clear window for messages
ld a,2 ;ink 2=bright red
call #bbde ;gra set pen
ld hl,80 ;y-coord
ld ix,INST1 ;message
call wrline
call wrline
call wrline
ret
INST1:defm "pick a fish, any fish!£"
INST2:defm "SPACE to see next fish£"
INST3:defm "ENTER to select the fish you see£"
wrline:;write a line of text
;using graphics system, and halfsize font
;end of line is indicated by character of £
;ix points at string, hl holds y-coord of message
push hl ;save y coord
ld de,8 ;x-coord
call #bbc0 ;gra move absolute
nextch:ld a,(ix) ;character to print
cp "£"
jr z,endch ;end of string
call #bbfc ;gra wr char
ld a,(ix) ;same character
cp "A"
jp m,back ;if < capital A, backspace
cp "Z"+1
jp m,noback ;if A-Z (capital) no backspace
back:ld de,-16 ;x-coord
ld hl,0 ;y
call #bbc3 ;gra move relative
noback:inc ix
jr nextch
endch:ld de,-20
pop hl ;get back y-coord
add hl,de ;get next y coordinate
inc ix ;get next character
ret
select:;display fishes on title screen
;and let user select one
ld de,136 ;set window -left edge
ld hl,503 ;right edge
call #bbcf ;set win width
ld de,257 ;top edge
ld hl,80 ;bottom edge
call #bbd2 ;set window height
n13:ld ix,TABLE ;pointer to first fish
n12:call disp ;display fish (ix) points at
waitch:call #bb18 ;wait for a key
cp " " ;if space display next fish
jr nz,n11
ld bc,TABSZ
add ix,bc ;point at next
ld a,(ix) ;get half pointer
or (ix+1) ;other half
jr z,n13 ;if pointer=0,we've gone off
;the end, so go back to start, otherwise -
jr n12 ;go display it
n11:cp #0d ;if enter use this fish
jr z,shuffl ;move this fish to start
cp #8b ;other enter or return
jr nz,waitch ;anything else, go again
shuffl:
;fish now selected - move fish that is pointed to
;by (ix) to TEMPFI which is at start, then we can reuse
;the area that the fish were stored in to store masks etc
push ix
pop hl ;source of array
ld de,FISHES ;destination-non array
ld bc,TABSZ
ldir ;move array element to start
ld h,(ix+1)
ld l,(ix) ;hl=start of fish
ld de,TEMPFI ;destination
ld bc,(FILENG)
ldir ;move fish
ld hl,TEMPFI ;fish address
ld (FISHES),hl ;store address
ld ix,FISHES ;ix points at (fish)
;add a byte of background to right side
call addr
;move fish from TEMPFI where
;it was read in, to FISH1, but add a pixel of background
;to the left hand edge. This will overwrite the
;left hand pixels of the previous image as the fish moves
call mover
ld de,FISH1
ld hl,TEMPFI
ld bc,FISHSZ
ldir
;add another pix of background to left and move to FISH2
call mover
ld de,FISH2
ld hl,TEMPFI
ld bc,FISHSZ
ldir
ld hl,MASK1
ld de,FISH1
call setmsk ;create mask
ld hl,MASK2
ld de,FISH2
call setmsk
ld de,FISH1
ld hl,FISH1B
call revfi ;mirror image fish 1
ld de,MASK1
ld hl,MASK1B
call revfi ;mirror mask 1
ld de,FISH2
ld hl,FISH2B
call revfi ;mirror fish 2
ld de,MASK2
ld hl,MASK2B
call revfi ;mirror mask 2
ret
savesc:;moves section of screen to store
;hl must contain screen address of top left point
ld a,(YSIZE)
ld b,a ;b=lines to shift
ld de,SCST ;destination address
next1:push bc ;store line count
ld bc,#50 ;bc=no bytes to shift=80
push hl ;screen address
ldir ;one line to store
pop hl ;start of line
ld bc,#0800 ;space to next line
add hl,bc ;start of next line?
jr nc,no1 ;yes no adjustment
ld bc,#c050 ;adjust for new screen block
add hl,bc
no1:pop bc ;get line count
djnz next1 ;do next line
ret
setmsk:;create mask by checking fish px by px
;any pixels =ink 0 (bright blue in our pallette)
;are changed to àf and assumed to be background
;all others are changed to 0; assumed to be fish
;hl must address mask to set, de fish to use
ld bc,(FILENG) ;fish length
next5:ld a,(de) ;byte of fish
and #aa ;first pixel
jr z,no5
ld (hl),0 ;pixel<>0
jr no6
no5:ld (hl),#aa ;mask pixel set to 15
no6:ld a,(de) ;byte of fish again
and #55 ;next pixel
jr nz,no7 ;if =0 then nothing to do
ld a,#55
or (hl) ;next pixel set to 15
ld (hl),a
no7:inc de
inc hl
dec bc
ld a,b
or c
jr nz,next5
ret
revfi:;L-R invert fish or mask from
;destination (hl) to source (de). All bytes are inverted
;left to right and pixels within bytes are swapped
ld a,(YSIZE)
ld b,a ;no of lines
next11:push bc ;linecount
ld a,(XSIZE)
ld c,a
ld b,0
dec c
add hl,bc ;hl points at end of line
ld b,a
next12:ld a,(de) ;byte of fish
and #55 ;right pixel of this byte
rlca ;turn it into a left pix
ld c,a ;store in c
ld a,(de)
and #aa ;left pixel of this byte
rrca ;turn it into a right pix
or c ;add 2 pix together
ld (hl),a ;put to fish store
dec hl
inc de
djnz next12
ld a,(XSIZE)
ld c,a
ld b,0
add hl,bc ;point at start of next line
inc hl
pop bc ;get line count
djnz next11
ret
disp:;moves fish to title screen
;(ix) points at fish
call #bbdb ;clear graphics window-zaps old fish
ld hl,80 ;x-coord - middle of screen
ld e,(ix+2) ;no of bytes horiz
ld d,0
xor a ;resets carry
sbc hl,de ;hl=80-horiz
push hl ;save x-coord
ld hl,85 ;y-coord - middle of window
ld e,(ix+3) ;no of lines
srl e ;e=e/2
add hl,de ;hl=85-vert/2
pop de ;x-coord back
call #bc1d ;get screen address
ld d,(ix+1)
ld e,(ix) ;de=fish address
ld b,(ix+3) ;b=lines to shift
ex de,hl ;right way round
next2:push bc ;store line count
ld b,0
ld c,(ix+2) ;bc=no bytes to shift
push de ;screen address
ldir ;one line to store
pop de ;start of line
ld bc,#0800 ;space to next line
ex de,hl
add hl,bc ;start of next line?
jr nc,no2 ;yes no adjustment
ld bc,#c050 ;adjust for new screen block
add hl,bc
no2:ex de,hl
pop bc ;get line count
djnz next2 ;do next line
ret
adjust:;adjust a window
;AAS saves windows in whole screen bytes, so the file may
;be either the size of the window, or have a spare pixel
;down left &/or right ends if window started on an odd
;pixel. objective is to get a fish window with a pixel of
;background down left side.
bit 0,(ix+4) ;we test whether window
;is an even or odd number of pixels wide
jr nz,adjodd
bit 2,(ix+5) ;xspare pixels, either 0 or 4
jp z,adjev2
inc (ix+2) ;bump no of bytes/line
;value for file is 1 greater than value of window
call blankl ;blanks out left pix
call blankr ;blanks out right pix
ret
adjev2:
call addr ;adds a byte of bground to right
call mover ;move window right by a pix
ret
adjodd:;adjust an odd size window
bit 2,(ix+5)
jp z,adjod2
call blankl ;blank out left pix
ret
adjod2:
call blankr ;blank out right pix
call mover ;move right by a pix
ret
blankl:;turns left hand pixels of
;file to background
ld b,(ix+3) ;no of lines
ld h,(ix+1)
ld l,(ix) ;hl points at fish
ld e,(ix+2) ;no of bytes per line
ld d,0
next13:ld a,(hl) ;first byte/line
and #55 ;resets left pix
ld (hl),a
add hl,de ;hl=start of next line
djnz next13
ret
blankr:;turns right hand pixels of
;file to background
ld b,(ix+3) ;no of lines
ld h,(ix+1)
ld l,(ix) ;hl points at fish
ld e,(ix+2) ;no of bytes per line
ld d,0
add hl,de ;start of next line
dec hl ;end of first line
next20:ld a,(hl) ;last byte/line
and #aa ;resets right pix
ld (hl),a
add hl,de ;end of next line
djnz next20
ret
addr:;adds a byte (2 pix) onto
;right hand edge of window
xor a ;a=0
ld h,(ix+7)
ld l,(ix+6) ;hl=fish length
ld d,(ix+1)
ld e,(ix) ;de=fish address
add hl,de ;hl=start of next fish
dec hl ;hl=end of fish
ld d,h
ld e,l ;de=end of fish
ld c,(ix+3) ;no of lines
ld b,0 ;bc=no of lines
add hl,bc ;hl=new end of fish
ex de,hl ;swap
push de ;save new eof for later
ld b,(ix+3) ;no of lines
next19:push bc ;linecount
ld c,(ix+2) ;no of bytes
ld b,a ;a=0;bc=no of bytes
ld (de),a ;last byte of line is blank
dec de
lddr ;move a line
pop bc ;get line count
djnz next19
pop iy ;new eof
inc iy ;iy=start of next fish
inc (ix+2) ;bump no of bytes/line
ld h,(ix+7)
ld l,(ix+6) ;hl=filelength
ld c,(ix+3) ;no of new bytes
ld b,0
add hl,bc ;hl=new length
ld (ix+7),h
ld (ix+6),l ;store
ret
mover:;moves window right by one
;pixel, blanking out the vacant pix created on left
;window is left same size, so must have a spare pix
;on the right if truncation is not to occur
ld b,(ix+3) ;no of lines
ld h,(ix+2) ;no of bytes
push ix ;save array pointer
ld d,(ix+7)
ld e,(ix+6) ;de=filelength
ld (fudge8+2),ix
fudge8:ld ix,(0) ;ix=fileaddress
add ix,de ;ix=eof+1
dec ix ;ix=eof
next17:push bc ;linecount
ld b,h
next18:ld a,(ix-1) ;prev byte of fish
and #55 ;right pixel of this byte
rlca ;turn it into a left pix
ld d,a ;store in d
ld a,(ix) ;this byte
and #aa ;left pixel of this byte
rrca ;turn it into a right pix
or d ;add 2 pix together
ld (ix),a ;put to fish store
dec ix
djnz next18
and #55 ;last pixel is set to 0
ld (ix+1),a ;put it to screen
pop bc ;get line count
djnz next17
pop ix ;retrieve array pointer
ret
cltext:;set and clear text window
ld de,0 ;set window -left edge
ld hl,639 ;right edge
call #bbcf ;set win width
ld de,79 ;top edge
ld hl,0 ;bottom edge
call #bbd2 ;set window height
call #bbdb ;gra clear window
ret
where:;ask user where fish swims
;and then make appropriate arrangements
call cltext ;clear text window
ld hl,80 ;y coord
ld ix,WHERE1
call wrline
call wrline
call wrline
call wrline
waitc2:call #bb18 ;wait for a key
and #df ;turn lower to upper case
cp "T" ;t=top
jr nz,n14
ld hl,190 ;top y-value
jr n16
n14:cp "M" ;m=middle
jr nz,n15
ld hl,120 ;middle y
jr n16
n15:cp "B" ;b=bottom
jr nz,waitc2 ;anything else, go again
ld a,(YSIZE) ;no of lines
ld l,8
add a,l ;no of lines+8
ld l,a
ld h,0 ;now in hl
n16:ld (SWIMY),hl ;store away
;display message only if running on 6128
ld a,(RAM) ;test for extra ram
cp 1
ret nz ;no ram
call cltext
ld hl,80
ld ix,ESC1
call wrline
call wrline
call wrline
call #bb18 ;wait for key
ret
WHERE1:defm "where do you want the fish to swim?£"
WHERE2:defm "T for top of tank£"
WHERE3:defm "M for middle of tank£"
WHERE4:defm "B for bottom of tank£"
SWIMY:defw 0 ;store for y val fish swims at
ESC1:defm "when fish is swimming, press£"
ESC2:defm "ESC to restart with another fish£"
ESC3:defm "press any key to start£"
hi2low:;moves a screen from #c000 to #4000
;switches banked ram first, c must have bank no
ld b,#7f
out (c),c
ld hl,#c000
ld de,#4000
ld bc,#4000
ldir
ld bc,#7fc0 ;switch back to main bank
out (c),c
ret
low2hi:;moves a screen from #4000 to #c000
;switches banked ram first, c must have bank no
ld b,#7f
out (c),c
ld hl,#4000
ld de,#c000
ld bc,#4000
ldir
ld bc,#7fc0 ;default bank address
out (c),c
ret
low2lw:;moves a screen from #4000 to
;banked ram at same address via disc buffer
;bank nos must be in FROMBK and TOBK
ld b,8 ;do it in 8 lots of 2k
ld hl,#4000 ;start address
n17:push bc ;save count
push hl ;save base address of this section
ld b,#7f
ld a,(FROMBK)
ld c,a ;bc can now switch rambanks
out (c),c
ld de,BUFFER ;destination address
ld bc,#800 ;2k bytes
ldir
ld b,#7f ;switch ram banks
ld a,(TOBK)
ld c,a
out (c),c ;switch
ld hl,BUFFER ;source address
pop de ;get back base address
ld bc,#800 ;2k
ldir
ex de,hl ;next base address
pop bc ;get back count
djnz n17
ld bc,#7fc0 ;always switch back to main bank
out (c),c
ret
FROMBK:defb 0
*l+
TOBK:defb 0