;*********************************** ;** Source for More v1.4 ** ;** (C) 14.5.96 D.J. Morris ** ;** Not to be modified without ** ;** prior permission. ** ;** This source code is released ** ;** for educational purposes only ** ;** If you use any of my code ** ;** please acknowledge it and ** ;** send me a copy of the program ** ;** If you have any questions at ** ;** all then contact me: ** ;** ** ;** Email: djm@jb.man.ac.uk ** ;** ** ;** Source code released 6/12/97 ** ;** ** ;** FTWHNFC: This is z80 source ** ;** for the ZX Spectrum but is ** ;** optimized for +3 usage ** ;** ** ;*********************************** font: equ 32768+1024 ; 64 column font repeated in both halves text: equ 35000 ; Where the text goes!! stakbc: equ 2D2Bh ; Put bc on the calculator stack bcstak: equ 1E99H ; Get value of bc from calculator stack org 32000 jp 32768 ;Initialize the whole shebang and check for entry params ;Clear the filename store readfi: ld hl,filen ld b,16 clfi1: ld (hl),32 inc hl djnz clfi1 ;Terminate the filename (for use by +3 DOS) ld (hl),255 ld a,208 ld (cheat),a ld hl,(23645) ;Address in BASIC program readf1: ld a,(hl) inc hl cp 230 ;NEW jp z,rdnew cp 251 ;CLS jp z,rdcls cp 234 ;REM jr z,readf2 cp 245 ;PRINT jr nz,readf0 ld (23645),hl ;Replace pointer so BASIC continues call inmem call priou0 pop hl ret readf0: cp 13 jr nz,readf1 ;No REM statement jp inmem ;Check we have a +2A/+3.. ;This is such a naive check..but it works ;(at least on UK Spectrums) readf2: ld a,(14495) dec a jr z,reaf25 rst 8 db 10 ;invalid argument - ain't got a +2a/+3 ;Read in the filename reaf25: ld de,filen ld b,16 readf3: ld a,(hl) cp 13 jr z,readf4 ld (de),a inc hl inc de djnz readf3 ;Open the +3 file readf4: ld hl,filen ld bc,1 ld d,b ld e,c ld iy,262 ;DOS open file call dodos ;Open the header - dummy routine ld iy,header call dodos call setpar ;Clear enuff space for our file ld hl,text ld de,text+1 ld (hl),32 ldir ;Read the file in byte by byte ld hl,text ld de,0 ldloop: push de push hl ld b,0 ld iy,280 ;DOS read byte call dodos pop hl pop de jr nc,ldend ld a,c cp 26 ;Soft EOF jr z,ldend ld (hl),c inc hl inc de jr ldloop ldend: dec de ld (fillen),de ;This is the true file length ;Close the file ld b,0 ld iy,265 call dodos call glinle ret ;Actually open the header and get the file length header: ld b,0 call 271 ld l,(ix+1) ld h,(ix+2) ret ;Clear the space occupied by ;previous file rdcls: ld bc,(fillen) rdcls1: ld (23645),hl ld hl,text ld de,text+1 ld (hl),0 ldir pop hl ret rdnew: ld bc,65536-text jr rdcls1 ;Table to convert +3 DOS errors ;(values 0-9 & 20-36) into rst 8 ;codes contab: db 61,62,63,64,65,66 db 67,68,69,70 db 0,0,0,0,0 db 0,0,0,0,0 db 44,45,46,47,48,49 db 50,51,52,53,54 db 55,56,57,58,59,60 filen: ds 16,0 db 255 textm: db ' More (' textm2: db '%) ' ;The search routine.. search: call versi0 call versi1 ld a,'/' call print ;Check to see if / is pressed again..if so ;then it is a repeat search call gkey cp '/' jp z,searc0 ;Set up the input line, store this character.. push af ld hl,0 ld (sealen),hl ld b,60 ld hl,input searc6: ld (hl),32 inc hl djnz searc6 pop af jr searcg searc7: call versi1 ld de,input-1 call pline call gkey searcg: ld bc,(sealen) ld hl,input cp 13 jr z,searc0 cp 12 jr nz,searc8 dec c jp m,searc7 add hl,bc ld (hl),32 jr searc9 searc8: cp 32 jr c,searc7 cp 127 jr nc,searc7 ld b,a ld a,c cp 60 jr nc,searc7 ld a,b ld b,0 add hl,bc ld (hl),a inc c searc9: ld (sealen),bc jr searc7 ;The actual search engine searc0: ld hl,(statex) ;Start addy text ld de,(endtex) ;End of text exx ld bc,(sealen) ;Length of our input ld a,b or c exx jp z,versi0 ;Empty input..bummer jr searcb searc1: ld de,input ld b,c searc2: ld a,(de) exx cp (hl) jr nz,searc3 inc hl dec b jr z,searca exx inc de djnz searc2 exx pop hl ;Okay, hl=addy of text line... push hl ld c,21 searcc: call gnext jr c,searcd dec c jr nz,searcc pop hl searcf: ld (statex),hl pop hl jp istext searcd: ld c,23 searce: call gprev dec c jr nz,searce pop de jr searcf searc3: dec b inc hl exx jr nz,searc1 exx searca: pop hl searcb: call gnext searci: ld a,64 sub b ld b,a push hl ;Now deal with (endtex) push bc push hl ex de,hl ld hl,(fillen) ld bc,text add hl,bc inc hl and a sbc hl,de pop hl pop bc jr c,searc4 exx jr searc1 searc4: pop hl jp versi0 sealen: dw 0 db '/' input: ds 60,32 db 13 textm3: db 'More v1.4 (C) 14.5' db '.96 D.J.Morris' textm4: db 32,13 textm5: db 'Length: ' textm6: db ' File: ' ;Reset pointer to top of text file.. top: ld hl,text ld (statex),hl pop hl jp istext ;Reset pointer to end of file...but ;have to find it don't we?!?! bottom: ld hl,(fillen) ld bc,text add hl,bc inc hl ex de,hl ld hl,(endtex) botto1: push de call gnext ex de,hl and a sbc hl,de pop hl ex de,hl jr nc,botto1 push hl ld c,22 jp searce info: call versi1 ld de,textm4 call pline call versi1 ld hl,textm5 ld e,8 call texpri ld hl,(fillen) ld b,254 call prttho ld a,(filen) cp 32 jr z,info1 ld hl,textm6 ld e,8 call texpri ld hl,filen ld e,16 call texpri info1: call versi3 ret org 32768 ;The real entry to the program..everything ;comes through here intogod: call readfi istext: call cls call pscr cheat: ret nc menu: call versi1 ;Set up 80 column bit so to ;do inverse stuff.. ld hl,14127 ld (plotc),hl ld a,l ld (char2),a ;Calculate the % of the text file ld hl,(endtex) ld bc,text and a sbc hl,bc ld b,h ld c,l call stakbc ld bc,(fillen) call stakbc rst 28h db 5,56 ;divide ld bc,100 call stakbc rst 28h db 4,56 ;divide ld hl,textm ld e,9 call texpri call bcstak ld h,b ld l,c ld b,254 call prhuns ld hl,textm2 ld e,4 call texpri ld hl,167 ld (plotc),hl ld a,h ld (char2),a ld hl,menu push hl menu0: menu1: call gkey cp 13 jr z,down cp 10 jr z,down cp 'n' jr z,pdown cp 'b' jr z,pup cp ' ' jr z,pdown cp 'p' jp z,up cp 11 jp z,up cp 'z' jp z,priout cp 'v' jr z,versin cp '/' jp z,search cp 'i' jp z,info cp 't' jp z,top cp 'e' jp z,bottom cp 'q' jr nz,menu0 pop hl ret versin: call versi1 ld de,textm3 call pline versi3: call gkey versi0: call versi1 ld de,textm4 jp pline versi1: ld h,23 versi2: ld l,0 ld (chrloc),hl ret pdown: ld b,22 pdown1: push bc call down pop bc ret c djnz pdown1 ret pup: ld b,22 pup1: push bc call up pop bc ret c djnz pup1 ret down: ld hl,(statex) call gnext push hl ld hl,(endtex) call gnext down1: ex de,hl ld hl,(fillen) ld bc,text add hl,bc inc hl and a sbc hl,de pop bc ret c ld (statex),bc ld (endtex),de call uscrol ld a,1 and a ret up: ld hl,(endtex) call gprev push hl ld hl,(statex) call gprev ex de,hl ld hl,text-1 and a sbc hl,de pop bc ccf ret c up2: ld (statex),de ld (endtex),bc call dscrol ld a,1 and a ret gprev: dec hl gprev0: ld a,(hl) cp 10 ;13 jr nz,gprev2 gprev3: dec hl ld a,(hl) cp 13 jr nz,gprev2 dec hl gprev2: ld b,64 ;64 gprev1: ld a,(hl) inc hl cp 10 ret z cp 13 ret z dec hl ex de,hl ld hl,text and a sbc hl,de ex de,hl ret nc dec hl djnz gprev1 inc hl ret gnext: ld b,64 gnext1: ld a,(hl) inc hl cp 13 jr z,gnext2 cp 10 ret z djnz gnext1 ld a,(hl) cp 13 ret nz inc hl gnext2: ld a,(hl) cp 10 ret nz inc hl ret pscr: ld b,22 ld de,(statex) ld h,0 pscr1: call versi2 push bc push hl push de ld (endtex),de call pline pop hl call gnext push hl ld de,text and a sbc hl,de ld de,(fillen) and a sbc hl,de pop de pop hl pop bc ret nc inc h djnz pscr1 scf ret statex: dw 35000 endtex: dw 0 pline: ex de,hl pline1: ld e,64 call texpri ex de,hl ret ;Top 2/3 Screen Cls ;a=attribute byte cls: ld hl,16384 ld de,16385 ld bc,6191 ld (hl),l ldir ld a,(23693) ld hl,22528 ld de,22529 ld bc,767 ld (hl),a ldir rrca rrca rrca and 7 jp 8859 invcol: db 0 ;Dump the file to the printer (aka #3) ;Uses standard ROM3 routines so will work ;with any interface...but have to trap ;errors *sigh* priout: call priou0 pop hl jp istext priou0: call cls ld de,text ld (pvar1),de ld hl,(23613) ld (pvar2+1),hl ld hl,prierr push hl ld (23613),sp priou1: ld h,0 call versi2 ld de,(pvar1) call pline ld a,3 call 5633 ld hl,(pvar1) priou9: ld b,64 priou2: ld a,(hl) cp 10 jr z,priou3 cp 13 jr z,priou3 rst 16 inc hl djnz priou2 priou3: ld a,13 rst 16 ld hl,(pvar1) call gnext ld (pvar1),hl ex de,hl ld hl,(fillen) ld bc,text add hl,bc and a sbc hl,de jr nc,priou1 pop hl prierr: pvar2: ld hl,0 ld (23613),hl outta: ld a,2 jp 5633 ;Scroll Text down dscrol: ld a,16 ld (count),a ld b,168 dscro1: push bc ld a,(count) ld b,a ld c,0 ld a,191 call 8876 push hl ld a,(count) add 8 ld b,a ld c,0 ld a,191 call 8876 pop de ld bc,32 ldir ld hl,count inc (hl) pop bc djnz dscro1 ld h,0 call versi2 ld de,(statex) jp pline ;Scroll text up uscrol: ld a,191 ld (count),a ld b,168 uscro1: push bc ld a,(count) ld b,a ld c,0 ld a,191 call 8876 push hl ld a,(count) sub 8 ld b,a ld c,0 ld a,191 call 8876 pop de ld bc,32 ldir ld hl,count dec (hl) pop bc djnz uscro1 ld de,(endtex) ld h,21 call versi2 ld de,(endtex) jp pline ;Print the number held in hl ;Switchable entry points for ;various sizes of number ;Entry: hl=number ; b=print flag (see below) prttho: ld de,10000 call numcal ld de,1000 call numcal prhuns: ld de,100 call numcal prtens: ld de,10 call numcal prunit: ld de,1 ld b,0 ;b=print norm, b=255 do space ;b=254 don't print numcal: ld a,255 numca1: inc a and a sbc hl,de jr nc,numca1 add hl,de and a jr z,numca2 ld b,0 numca2: add 48 ld c,a ld a,b and a jr z,numca3 inc a ret nz ld c,32 numca3: ld a,c push bc push hl call print pop hl pop bc ret ;Texpri hl=addy, de=length fillen: dw 65536-text count: db 0 texpri: push hl push de ld a,(hl) call print pop de pop hl inc hl jr nc,texpr1 dec e jr nz,texpri ret texpr1: push de ld a,32 call print pop de dec e jr nz,texpr1 ret ;Print routine - elaborate ;print1 looks silly, but look ;at the code..it isn't (hint, ;self modifying!!) print: cp 10 jr z,print0 cp 13 jr nz,print1 print0: and a ret ;Normal print routine... ;Exit with carry set if OK.. print1: jp prin64 prin64: ld l,a ld h,0 add hl,hl add hl,hl add hl,hl ld de,font add hl,de exx ;Get screen address in hl from ;64 column position in bc ld bc,(chrloc) xypos: srl c ex af,af' ld a,b and 248 add 64 ld h,a ld a,b and 7 rrca rrca rrca add c ld l,a ex af,af' ld a,240 jr c,gotpos ld a,15 gotpos: ld c,a exx cpl ld c,a ;c=char mask, hl=char addr ;c'=scr mask, hl'=scr addr ld b,8 char1: ld a,(hl) char2: db 0 and c inc hl exx ; screen ld b,a ld a,(hl) and c or b ld (hl),a inc h exx djnz char1 exx cbak: ld hl,(chrloc) inc l bit 6,l jr z,char3 cbak1: ld l,0 inc h char3: scf char4: ld (chrloc),hl ld hl,10072 exx ret ;80 column print routine...great fun!!! ;Warning, very self modifying!!! prin80: push hl ex af,af' ;First of all calculate the jump into ;The shift code - depends on x position ld a,(xpos) inc a ld b,a ld c,3 xor a sub c calcx1: add a,c djnz calcx1 ld c,a and 7 ld b,a add a,a add a,b add a,a ld b,a ld a,42 sub b ld (shiftx+1),a srl c srl c srl c ld a,(ypos) ld b,a and 248 add 64 ld d,a add a,b and 7 rrca rrca rrca add a,c ld e,a ;At this point de=screen address ex af,af' ld l,a nocnrt: ld h,0 add hl,hl add hl,hl add hl,hl ld bc,font add hl,bc ld a,8 plot: ex af,af' ld a,(hl) and 240 ;Little bit of self modifying stuff ;to speed up the print routine plotc: db 0 ;/cpl db 0 ;and a/scf ld b,a plot1: rl b ld c,0 ld a,255 shiftx: jr shifin srl b rr c srl a srl b rr c srl a srl b rr c srl a srl b rr c srl a srl b rr c srl a srl b rr c srl a srl b rr c srl a shifin: ex de,hl ld (shif1+1),a cpl and (hl) or b ld (hl),a shif1: ld a,0 inc l jp z,shif2 and (hl) or c ld (hl),a shif2: dec l ex de,hl inc d inc hl ex af,af' dec a jp nz,plot ld hl,xpos inc (hl) pwid1: ld a,84 cp (hl) jp nc,out rowin: ld (hl),0 inc hl inc (hl) scf out: ccf pop hl ret chrloc: xpos: db 0 ypos: db 0 ;Get a key.. gkey: xor a ld (23560),a ld (23658),a ld (cheat),a gkey1: ld a,(23560) and a jr z,gkey1 ret pvar1: dw 0 ;Set up the parameters for ;the viewer.. ;Entry: hl=file length setpar: ld (fillen),hl ld bc,512 add hl,bc ld c,l ld b,h ld hl,text ld (statex),hl ret glinle: push bc ld hl,text ld bc,(fillen) ld de,257 setpa0: ld a,(hl) cp 13 jr z,setpa1 cp 10 jr z,setpa1 inc d setpa4: inc hl dec bc ld a,b or c jr nz,setpa0 setpa6: ld b,64 ld hl,prin64 ld a,e dec a jr z,setpa2 ld a,64 cp e jr nc,setpa2 ld b,83 ld hl,prin80 ;Set up the line lenfs here setpa2: ld a,b ld (searci+1),a ld (gprev2+1),a ld (gnext+1),a ld (pline1+1),a ld (priou9+1),a ld (print1+1),hl pop bc ret setpa1: ld a,d cp e ld d,0 jr c,setpa6 ld e,a jr setpa6 ;Scan the memory for the text ;file, ignoring LF/CR inmem: ld hl,text ld d,0 inmem1: ld a,(hl) cp 10 jr z,inmem0 cp 13 jr z,inmem0 cp 32 jr c,inmem2 cp 144 jr nc,inmem2 inmem0: inc d res 6,d inc hl ld a,h or l jr nz,inmem1 inc hl ;Okay, have found the end of ;the file, hl=addy of eof, d ;charposn.. inmem2: push hl ld a,90 sub d and a jr z,inmem4 ld b,a inmem3: ld (hl),32 inc hl djnz inmem3 inmem4: pop hl ld bc,text and a sbc hl,bc ld a,h or l jr z,inmem5 call setpar call glinle ret inmem5: rst 8 db 25 ;parameter error ;+3 DOS call routine dodos: di push af push bc ld a,7 ld bc,32765 out (c),a ld (23388),a pop bc pop af ei call cjump di push af push bc ld bc,32765 ld a,16 out (c),a ld (23388),a pop bc pop af ld iy,23610 ei dcheat: ret c ;Converter for +3 errors errou: cp 25 ret z ld c,a ld b,0 ld hl,contab add hl,bc ld a,(hl) ld (errou1),a ;This line needed so not to confuse DiSCDOS ld (23390),a rst 8 errou1: db 0 cjump: jp (iy) END