Rev 922 | Blame | Compare with Previous | Last modification | View Log | Download
DEVICE ZXSPECTRUM128include "../_sdk/sys_h.asm"include "8080.asm"NEDOOS=1;; BD Software C Compiler v1.6; Standard Library Machine Language Functions (part A); Copyright (c) 1982, 1986 by BD Software, Inc.;; This file is in "CSM" format; to convert to CRL format,; use CASM.SUB in conjunction with CASM.COM, ASM.COM and CLOAD.COM.;; Functions appearing in this file:;; [cmode] [iobreak] getchar kbhit ungetch putchar; gets getline; rand srand srand1 nrand; [csw] setmem movmem memcmp; call calla; inp outp peek poke; sleep pause exit; bdos bios biosh; codend [externs] endext topofmem; exec execv; rbrk sbrk rsvstk; index; setjmp longjmp;include "liblib.asm"if 1==1FUNCTION "CMODE"FUNCHEAD cmodeszcall ma1toh ;get argex de,hl ;put in DEld hl,chmode ;get address of char mode flagld d,(hl) ;get old mode in Dld (hl),e ;set new modexor a ;clear pushback bytesta ungetlinc hlld (hl),a ;and line buffer char countld l,d ;return old value of chmodeld h,0retENDFUNC cmodesz,0;dw 0 ;no reloc parsendifif 1==1FUNCTION "IOBREAK"FUNCHEAD iobreakszcall ma1toh ;get argsta iobrfretENDFUNC iobreaksz,0;dw 0 ;no reloc parsendifFUNCTION "GETCHAR"FUNCHEAD getcharszlda ungetl ;any character pushed back?ld l,aor a_1=$+1jp z,getitxor a ;yes. return it and clear the pushbacksta ungetl ;byte in C.CCC.ld h,a ;clear hretgetit:push bcld hl,chmode ;get address of chmode flag;ld a,(hl)xor aor a_2=$+1jp z,single ;jump if single modeinc hlpush hl ;save &nleftld a,(hl) ;get number of chars left in bufor a_3=$+1jp nz,gnext ;jump if characters in buffer;fill buffer:_4=$+1ld de,gcbuff ;DE = buffer addressld c,getlincall bdos ;read console bufferld c,conoutld e,lfcall bdos ;linefeed to console_5=$+1ld hl,gcline_6=$+1shld gcptr ;initialize gcptr_7=$+1lda gcnum ;number of chars just readld hl,nleft ;HL = &nleftld (hl),a ;set number of characterscp maxl_8=$+1jp z,gnext ;if buffer completely full, don't append nlld e,ald d,0 ;DE = number of charactersinc (hl) ;nleft++_9=$+1ld hl,gclineadd hl,de ;HL = addr of next char pos after endld (hl),newlin ;append newline chargnext:pop hl ;now take a char from the bufferdec (hl) ;nleft--_10=$+1lhld gcptr ;get next charld a,(hl)inc hl ;bump ptr_11=$+1shld gcptr_12=$+1jp gotitsingle:;ld c,conin ;get single char from bdos;call bdosYIELDGETKEYLOOPcp cr ;carriage return?_13=$+1jp nz,gotit;ld c,conout ;if so, echo linefeed;ld e,lf;call bdos;ld a,newlin ;and return newline (linefeed)..gotit: ;ld b,a ;save char in B;lda iobrf ;checking for BREAK character?;or a;ld a,b ;restore char into Apop bc ;restore BC_14=$+1jp z,gotit2 ;if not checking for BREAK, skip test;cp cntrlc ;control-C ?;jp z,exit ;if so, exit the program.gotit2: ;cp 1ah ;control-Z ?;ld hl,-1 ;if so, return -1.;ret zld l,a ;else return char in HLld h,0retmaxl equ 79 ;max length of line of buffered console inputgcptr ds 2 ;pointer into line where first char isgcbuff db maxl ;max line length fro BDOS 10gcnum db 0 ;number of characters just read by BDOS 10gcline ds maxl+1 ;buffer for characters, in case BDOS 10 is usedENDFUNC getcharsz,14FUNCTION "KBHIT"FUNCHEAD kbhitszlda ungetl ;any character ungotten?ld h,0ld l,aor aret nz ;if so, return truelda nleft ;get number of chars left in bufferor aret nz ;if any characters in buffer, return truepush bcld c,cstat ;else interrogate console statuscall bdospop bcor a ;0 returned by BDOS if no character readyld hl,0ret z ;return 0 in HL if no character readyinc l ;otherwise return 1 in HLretENDFUNC kbhitsz,0;dw 0 ;no reloc parsFUNCTION "UNGETCH"FUNCHEAD ungetchszlda ungetlld l,apush hlcall ma2tohsta ungetlpop hlld h,0retENDFUNC ungetchsz,0;dw 0 ;no reloc parsFUNCTION "PUTCHAR"FUNCHEAD putcharszcall ma1toh ;get character in Apush bc;ld c,conoutds 2cp newlin ;newline?_1=$+1jp nz,put1 ;if not, just go put out the character;ld e,cr ;else...put out CR-LFld a,cr;call bdosPRCHARds 2;ld c,conoutds 2ld a,lfput1: ;ld e,anop;call bdosPRCHARds 2put2: ;lda iobrf ;checking for BREAK characters on keyboard?xor ads 2or a_2=$+1jp z,put4 ;if not, all doneld c,cstat ;now, is input present at the console?call bdosor a_3=$+1jp nz,put3pop bc ;no...all done.retput3: ld c,conin ;yes. sample it (this will always echo thecall bdos ; character to the screen, alas)cp cntrlc ;is it control-C?jp z,exit ;if so, abort and rebootput4: pop bc ;else ignore it.retENDFUNC putcharsz,3FUNCTION "GETS"FUNCHEAD getsszcall ma1toh ;get destination addresspush bc ;save BCpush hlpush hlld hl,-150 ;use space below stack for reading lineadd hl,sppush hl ;save buffer addressld (hl),88h ;Allow a max of about 135 charactersld c,getlinex de,hl ;put buffer addr in DEcall bdos ;get the input lineld c,conoutld e,lf ;put out a LFcall bdospop hl ;get back buffer addressinc hl ;point to returned char countld b,(hl) ;set B equal to char countinc hl ;HL points to first char of linepop de ;DE points to start destination areacopyls: ld a,b ;copy line to start of bufferor a_1=$+1jp z,gets2sld a,(hl)ld (de),ainc hlinc dedec b_2=$+1jp copylsgets2s: xor a ;store terminating nullld (de),apop hl ;return buffer address in HLpop bcretENDFUNC getssz,2;; Getline(str,lim); char *str;;; Gets a line of text from the console, up to 'lim' characters.;FUNCTION "GETLINE"FUNCHEAD getlineszpush bc ;save BCcall ma3toh ;get max no. of charsld c,a ;save max length in Cdec c ;allow room for final terminating nullld de,10 ;allow a bit extra stack for good measureadd hl,decall cmh ;save amount of space to allocate on stackpush hlcall ma3toh ;get destination addressex (sp),hl ;push dest addr, get back stack offsetadd hl,sp ;allocate space on stackpush hl ;save buffer addressld (hl),c ;Set max # of charactersld c,getlinex de,hl ;put buffer addr in DEcall bdos ;get the input lineld c,conoutld e,lf ;put out a LFcall bdospop hl ;get back buffer addressinc hl ;point to returned char countld b,(hl) ;set B equal to char countinc hl ;HL points to first char of linepop de ;DE points to start destination areald c,b ;save char count in Ccopylln: ld a,b ;copy line to start of bufferor a_1=$+1jp z,gets2lnld a,(hl)ld (de),ainc hlinc dedec b_2=$+1jp copyllngets2ln: xor a ;store terminating nullld (de),ald l,c ;return char count in HLld h,0pop bcretENDFUNC getlinesz,2FUNCTION "RAND"FUNCHEAD randszlhld rseedex de,hlld a,48hand e_1=$+1jp z,rand1_2=$+1jp pe,rand1scfrand1: lhld rseed+2ld a,hrlald h,ald a,lrlald l,ashld rseed+2ld a,drlald h,ald a,erlald l,ashld rseedld a,hand 7fhld h,aretENDFUNC randsz,2FUNCTION "SRAND"FUNCHEAD srandszcall ma1tohld a,hor l_1=$+1jp z,srand2shld rseedshld rseed+2retsrand2:_2=$+1ld de,stg1push bcld c,9call bdosld hl,0bdbdhsrand3: push hlld c,11call bdospop hlinc hlinc hlinc hland 1_3=$+1jp z,srand3shld rseedshld rseed+2ld c,conoutld e,crcall bdosld c,conoutld e,lfcall bdosld c,conin ;clear the charactercall bdospop bcretstg1: db 'Wait a few seconds, and type a CR: $'ENDFUNC srandsz,3FUNCTION "SRAND1"EXTERNAL "PUTS"FUNCHEAD srand1sz_1=$+1jp (1 +1)*3_puts=$jp 0call ma1tohpush hl_2=$+1call _puts ;print prompt stringpop hlpush bcld hl,5678hsr1a: push hlld c,cstatcall bdospop hlinc hlinc hlinc hlor a_3=$+1jp z,sr1ashld rseedshld rseed+2pop bcretENDFUNC srand1sz,3FUNCTION "NRAND"EXTERNAL "PUTS"FUNCHEAD nrandsz_1=$+1jp (1 +1)*3_puts=$jp 0call arghaklhld arg1 ;get n (1st arg)ld a,hand lcp 255 ;was it -1 (set seed) ?_2=$+1jp nz,nrand1lhld arg2 ;copy seed_3=$+1shld seedlhld arg3_4=$+1shld seed+2lhld arg4_5=$+1shld seed+4ret ;all donenrand1: push bcld a,h ;look at first arg againor l_6=$+1jp nz,nrand3 ;is it 0 (randomize)?lhld arg2push hl ;yes. print out string_7=$+1call _puts ;call putspop deld hl,5a97h ;yes. start w/something oddnrand2: push hlld c,cstat ;interrogate console statuscall bdospop hlinc hl ;and keep it oddinc hl ;and growingor a_8=$+1jp z,nrand2 ;until user types something._9=$+1shld seed ;then plaster the value all over the_10=$+1shld seed+2 ;seed._11=$+1shld seed+4pop bcretnrand3:_12=$+1lda seed ;now compute next random number. from thisor 1 ; point on, the code is that of Prof. Paul Gans_13=$+1sta seed ;lsb of SEED must be 1ld b,6 ;clear 6 PROD bytes to 0_14=$+1ld hl,prodrandm1: ld (hl),0inc hldec b_15=$+1jp nz,randm1ld bc,6 ;set byte counterrandm2:_16=$+1ld hl,plier-1add hl,bc ;make addr of lsb of PLIERld a,(hl) ;PLIER bytepush bc ;save byte counterld b,8 ;set bit counterrandm3: ld d,a ;save PLIER byte_17=$+1ld hl,prod ;shift whole PROD left one bitld c,6xor arandm4: ld a,(hl) ;get byterla ;shift leftld (hl),a ;put byteinc hldec c_18=$+1jp nz,randm4ld a,d ;recover PLIER byterla ;look at current high bit_19=$+1jp nc,randm6 ;0 means no add cyclepush af ;add SEED to PRODxor ald c,6_20=$+1ld hl,prod_21=$+1ld de,seedrandm5: ld a,(de)adc (hl)ld (hl),ainc hlinc dedec c_22=$+1jp nz,randm5pop afrandm6: dec b ;test bit counter_23=$+1jp nz,randm3 ;go cycle more bitspop bc ;recover byte counterdec c ;test it_24=$+1jp nz,randm2 ;go process more bytesld b,6 ;complement PROD, add 1 to it,_25=$+1ld hl,seed ;and transfer it to SEED._26=$+1ld de,prodxor accfrandm7: ld a,(de)cpladc a,0ld (hl),ainc hlinc dedec b_27=$+1jp nz,randm7dec hl ;put the two high order bytesld a,(hl) ;into HL for return to C, notand 7fh ;neglecting to zero the highld h,a ;order bit so a positive int_28=$+1lda seed+4 ;is returnedld l,apop bcretplier: db 0c5h,87h,1db 0eh,9ah,0e0hseed: db 1,0,0,0,0,0prod: db 0,0,0,0,0,0ENDFUNC nrandsz,28if 1==1FUNCTION "CSW"FUNCHEAD cswszin a,(255) ;???ld l,ald h,0retENDFUNC cswsz,0endifFUNCTION "SETMEM"FUNCHEAD setmemszcall arghakpush bclhld arg2ex de,hllhld arg1lda arg3ld c,ainc desetm2: dec deld a,dor e_1=$+1jp nz,setm3pop bcretsetm3: ld (hl),cinc hl_2=$+1jp setm2ENDFUNC setmemsz,2FUNCTION "MOVMEM"FUNCHEAD movmemszcall arghaklhld arg3 ;get block lengthld a,hor lret z ;do nothing if zero lengthpush bcld b,hld c,l ;set BC to lengthlhld arg2 ;get dest addrex de,hl ;put in DElhld arg1 ;get source addr in HLcall cmphd;movmcmphd ;if source < dest, do tail-first_1=$+1jp c,tailf ;else do head-firstheadf: ld a,2 ;test for Z-80inc a_2=$+1jp pe,m8080h ;Z80?db 0edh,0b0h ;yes. do block move.pop bcret ;and done.m8080h: ld a,(hl)ld (de),ainc hlinc dedec bcld a,bor c_3=$+1jp nz,m8080hpop bcrettailf: dec bc ;tail first. Compute new sourceadd hl,bc ;and destination addressesex de,hladd hl,bcex de,hlinc bcld a,2 ;test for Z80inc a_4=$+1jp pe,m8080t ;Z80?db 0edh,0b8h ;yes. do block move.pop bcretm8080t: ld a,(hl)ld (de),adec hldec dedec bcld a,bor c_5=$+1jp nz,m8080tpop bcret;NUmovmcmphd: ld a,hcp dret nzld a,lcp eretENDFUNC movmemsz,5FUNCTION "MEMCMP"FUNCHEAD memcmpszcall ma3toh ;get length in HLpush bc ;save BCld b,hld c,l ;move length to BCcall ma3toh ;get block2 address in HLex de,hl ;move to DEcall ma2toh ;get block1 address in HLloop: ld a,b ;all done?or c_1=$+1jp nz,loop1ld hl,1 ;if so, return TRUE, for perfect matchpop bcretloop1: dec bc ;decrement countld a,(de) ;get block2 bytecp (hl) ;compare to block1 byteinc de ;bump pointersinc hl_2=$+1jp z,loop ;if so far so good, go on comparingld hl,0 ;else a mismatchpop bcretENDFUNC memcmpsz,2FUNCTION "CALL"FUNCHEAD callszcall arghakpush bclhld arg5ex de,hllhld arg4ld b,hld c,llda arg2_1=$+1ld hl,call2push hllhld arg1push hllhld arg3retcall2: pop bcretENDFUNC callsz,1FUNCTION "CALLA"FUNCHEAD callaszcall arghakpush bclhld arg5 ;get de valueex de,hllhld arg4 ;get bc valueld b,hld c,llda arg2 ;get a value_1=$+1ld hl,calla2 ;get return addresspush hl ;push itlhld arg1 ;get address of routinepush hllhld arg3 ;get hl valueret ;call routinecalla2: ld l,a ;put A value in HLld h,0 ;clear high bytepop bcretENDFUNC callasz,1FUNCTION "INP"FUNCHEAD inpszcall ma1tohsta iohack+1 ;store as arg to ram area input subroutinecall iohack ;call the subroutine to get valueld l,a ;and put into HLld h,0retENDFUNC inpsz,0FUNCTION "OUTP"FUNCHEAD outpszcall ma1toh ;get port numbersta iohack+4 ;store as arg to ram area output subroutinecall ma2toh ;get data bytecall iohack+3 ;output itretENDFUNC outpsz,0FUNCTION "PEEK"FUNCHEAD peekszcall ma1tohld l,(hl)ld h,0retENDFUNC peeksz,0FUNCTION "POKE"FUNCHEAD pokeszcall arghaklhld arg1lda arg2ld (hl),aretENDFUNC pokesz,0FUNCTION "SLEEP"FUNCHEAD sleepszcall ma1tohpush bcinc hlsl1: dec hlld a,hor l_1=$+1jp nz,sl1apop bcretsl1a: ld de,10000sl2: dec deld a,dor e_2=$+1jp nz,sl2push hlld c,cstatcall bdosor apop hl_3=$+1jp z,sl1push hlld c,conincall bdoscp cntrlcjp z,exitpop hl_4=$+1jp sl1ENDFUNC sleepsz,4FUNCTION "PAUSE"FUNCHEAD pauseszpush bcpaus1: ld c,cstatcall bdosor a_1=$+1jp z,paus1pop bcretENDFUNC pausesz,1FUNCTION "EXIT"FUNCHEAD exitszjp exitENDFUNC exitsz,0FUNCTION "BDOS"FUNCHEAD bdosszcall arghakpush bclda arg1 ;get C valueld c,alhld arg2 ;get DE valueex de,hl ;put in DEcall bdos ;make the bdos callpop bcret ;and return to callerENDFUNC bdossz,0FUNCTION "BIOS"FUNCHEAD biosszcall arghakpush bclhld base+1 ;get addr of jump table + 3dec hl ;set to addr of first jumpdec hldec hllda arg1 ;get function number (1-85)ld b,a ;multiply by 3add aadd bld e,a ;put in DEld d,0add hl,de ;add to base of jump tablepush hl ;and save for laterlhld arg2 ;get value to be put in BCld b,h ;and put it thereld c,l_1=$+1ld hl,biosretadd ;where call to bios will return toex (sp),hl ;get address of vector in HLjp (hl) ;and go to it...biosretadd: ld l,a ;all done. now put return value in HLld h,0pop bcret ;and return to callerENDFUNC biossz,1FUNCTION "BIOSH"FUNCHEAD bioshszcall arghakpush bclhld base+1 ;get addr of jump table + 3dec hl ;set to addr of first jumpdec hldec hllda arg1 ;get function number (1-85)ld b,a ;multiply by 3add aadd bld e,a ;put in DEld d,0add hl,de ;add to base of jump tablepush hl ;and save for laterlhld arg2 ;get value to be put in BCld b,h ;and put it thereld c,llhld arg3 ;get value to be put in DEld d,h ;adn put it thereld e,l_1=$+1ld hl,bioshretadd ;where call to bios will return toex (sp),hl ;get address of vector in HLjp (hl) ;and go to it...bioshretadd: pop bc ;all done. Leave return value in HLret ;and return to callerENDFUNC bioshsz,1FUNCTION "CODEND"FUNCHEAD codendszlhld codendretENDFUNC codendsz,0if 1==1FUNCTION "EXTERNS"FUNCHEAD externsszlhld extrnsretENDFUNC externssz,0endifFUNCTION "ENDEXT"FUNCHEAD endextszlhld freramretENDFUNC endextsz,0FUNCTION "TOPOFMEM"FUNCHEAD topofmemszlhld base+6lda tpa ;check for "NOBOOT" hackerycp 0c3h ; "jp" at start of C.CCC (as inserted by "-n")?dec hl ;if CCC doesn't begin with "ld hl," then top ofret nz ;memory is just below the base of the bdosld de,-2100 ;else subtract CCP size (plus little more for goodadd hl,de ;measure) and return that as top of memory.retENDFUNC topofmemsz,0FUNCTION "EXEC"EXTERNAL "EXECL"FUNCHEAD execsz_1=$+1jp (1 +1)*3_execl=$jp 0call ma1toh ;get filenameld de,0 ;load null parameter in DEpush de ;push null parameterpush hl ;push filename_2=$+1call _execl ;do an execlpop de ;clean up stackpop deretENDFUNC execsz,2FUNCTION "EXECV"EXTERNAL "EXECL"FUNCHEAD execvsz_1=$+1jp (1 +1)*3_execl=$jp 0call arghakpush bc ;save BClhld arg2 ;get -> arg listld b,0 ;clear arg countexecv1: inc b ;bump arg countld e,(hl)inc hlld d,(hl)inc hlld a,dor e ;last arg?_2=$+1jp nz,execv1 ;if not, keep looking for last oneld a,b ;save arg count in case of error_3=$+1sta savcntdec hl ;HL -> next to last argexecv2: ld d,(hl) ;now push args on stackdec hlld e,(hl)dec hldec bpush de_4=$+1jp nz,execv2execv3: lhld arg1 ;get program namepush hl ;save as first arg to execl_5=$+1call _execl ;go do it; shouldn't come back._6=$+1lda savcnt ;woops, we're back. Must've been an error...inc a ;bump to take prog name into considerationadd ald l,a ;put size of passed parameter listld h,0 ;into HL, and adjust stackadd hl,spld sp,hlpop bc ;restore BCld hl,-1 ;return error valueretsavcnt: ds 1 ;save arg count hereENDFUNC execvsz,6FUNCTION "RBRK"FUNCHEAD rbrkszlhld freramshld allocpENDFUNC rbrksz,0FUNCTION "SBRK"FUNCHEAD sbrkszcall ma1toh ;get # of bytes needed in HLld a,h ;check for -1and linc a_1=$+1jp nz,sbrk2 ;go to sbrk2 if HL wasn't FFFFlhld freram ;it WAS ffff: reset sbrk to base of free ramshld allocpretsbrk2: ex de,hl ;put into DElhld allocp ;get current allocation pointerpush hl ;save itadd hl,de ;get tentative last address of new segment_2=$+1jp c,brkerr ;better not allow it to go over the top!dec hlex de,hl ; now last addr is in DElhld alocmx ;get safety factorld a,h ;negatecplld h,ald a,lcplld l,ainc hladd hl,sp ;get HL = (SP - alocmx)_3=$+1call cmpdh ;is DE less than HL?_4=$+1jp nc,brkerr ;if not, can't provide the needed memory.ex de,hl ;else OK.inc hlshld allocp ;save start of next area to be allocatedpop hl ;get pointer to this arearet ;and return with it.brkerr: pop hl ;clean up stackjp error ;and return with -1 to indicate can't allocate.cmpdh: ld a,dcp hret cret nzld a,ecp lretENDFUNC sbrksz,4FUNCTION "RSVSTK"FUNCHEAD rsvstkszcall ma1toh ;get the value to reserveshld alocmx ;and set new safety factorretENDFUNC rsvstksz,0;; Index(str,substr); char *str, *substr;;; Returns index of substr in str, or -1 if not found.;FUNCTION "INDEX"FUNCHEAD indexszcall arghaklhld arg1ex de,hl ;main str ptr in DElhld arg2 ;substr ptr in HLdec deindex1: inc deld a,(de) ;end of str?or a_1=$+1jp nz,index2ld hl,-1 ;yes. not found.retindex2: cp (hl) ;quick check for dissimilarity_2=$+1jp nz,index1 ;loop if not same right herepush de ;else do long comparepush hlindex3: inc hlinc deld a,(hl) ;end of substr?or a_3=$+1jp nz,index4 ;if not, go on testingpop de ;else matchespop de ;get starting address of substr in DElhld arg1 ;subtract beginning of strcall cmhadd hl,de ;and return the resultretindex4: ld a,(de) ;current char match?cp (hl)_4=$+1jp z,index3 ;if so, keep testingpop hl ;else go on to next char in strpop de_5=$+1jp index1ENDFUNC indexsz,5include "deff2b.csm"include "deff2c.csm"FUNCTION "PUTS"EXTERNAL "PUTCHAR"FUNCHEAD putssz_1=$+1jp (1 +1)*3_putchar=$jp 0push bcld hl,0add hl,spld b,hld c,lputs0:call sdli ;short-displacement, double-byte local indirectiondb 4 ;shift from bcld l,(hl)ld a,lor a_2=$+1jp z,putsqld hl,4add hl,bcld e,(hl)inc hlld d,(hl)inc deld (hl),ddec hlld (hl),edec deex de,hlld l,(hl)ld h,0push hl_3=$+1call _putcharpop de_4=$+1jp puts0putsq:pop bcretENDFUNC putssz,4;; Read:;; i = read(fd, buf, n);;; Read a number of sectors using random-record I/O.;; The return value is either the number of sectors successfully; read, 0 for EOF, or -1 on error with errno() returning the error; code (or errmsg(errno()) returning a pointer to an error message).;; The Random Record Field is incremented following each successful; sector is read, just as if the normal (sequential) read function; were being used. "seek" must be used to go back to a previous; sector.;;NOW RETURNS NUMBER OF BYTES, NOT SECTORS!!!if NEDOOSFUNCTION "READ"FUNCHEAD readszcall arghaklda arg1call fgfd ;compute fd address for fd in A: ;return hl=fd addrpush bcld b,(hl)ld de,(arg2)ld hl,(arg3)OS_READHANDLEpop bcor aret zld hl,-1retENDFUNC readsz,0elseFUNCTION "READ"FUNCHEAD readszcall arghaklda arg1call fgfdld d,(hl) ;save fdt entry in Dld a,7 ;prepare for possible "bad fd"or a_1=$+1jp c,rerror;ld a,d;and 2 ;4wrld a,8 ;9wr ;prepare for possible "no read permission"or a_2=$+1jp z,rerrorpush bc;ld a,d ;get fd table entry;call setusr ;set user area to that of the filelda arg1 ;get fdcall fgfcbshld tmp2 ;save fcb addressld hl,0shld tmp2alhld arg3add hl,hlld l,hld h,0shld arg3 ;size/128r2: lhld arg3 ;get countdownld a,hor l ;done?r2aa: lhld tmp2a_3=$+1jp nz,r2ar2done128:xor asrl hrr lrrald h,lld l,a ;count*128r2done: ;call rstusr ;reset user numberpop bc ;yes. return with success count in HLretr2a: lhld arg2 ;get transfer addr in DEex de,hlld c,sdma ;set DMA therecall bdoslhld tmp2ex de,hl;ld c,readr ;code for BDOS random readpush de ;save DE so we can fudge nr field if;call bdos ;we stop reading on extent boundary...OS_FREADpop deor a_4=$+1jp z,r4 ;go to r4 if no problemcp 128 ;0 bytes read in NedoOS ;cp 1 ;ok, we have SOME kind of hangup..._5=$+1jp nz,r2b ;jp z,r2b ;check for EOF condition:cp 4 ; error codes 1 and 4 both indicate reading_6=$+1jp z,r2b ; unwritten data..treat as EOFld b,a ;have we successfully read anything yet?lda tmp2aor ald b,a ;get error code back in A_7=$+1jp nz,r2c ;if we have read something in, don't set errnumsta errnum ;otherwise nothing read, so set error code.r2c: ld hl,-1 ;put ERROR value in HL_8=$+1jp r2doner2b: lhld tmp2a ;return countinc hl ;for NedoOS: we have read at least 1 byte in the last sector_9=$+1jp r2done128r4: lhld arg3 ;decrement countdowndec hlshld arg3lhld arg2 ;bump DMA addressld de,128add hl,deshld arg2lhld tmp2a ;bump success countinc hlshld tmp2alhld tmp2 ;get address of fcbld bc,33 ;get addr of random record fieldadd hl,bcld c,(hl) ;bumpinc hl ; valueld b,(hl) ; ofinc bc ; randomld (hl),b ; fielddec hl ; by oneld (hl),cld a,b ;overflow past 16-bit record count?or c_10=$+1jp nz,r2 ; go for next sector if no overflowinc hl ;else set 3rd byte of random sector countinc hlld (hl),1ld a,14 ;"seek past 65536th record of file"sta errnum_11=$+1jp r2aa ;and don't read any more.rerror: sta errnumjp errorENDFUNC readsz,11endif;zzzif 1==1FUNCTION "SETJMP"FUNCHEAD setjmpszcall ma1tohld (hl),c ;save BCinc hlld (hl),binc hlex de,hlld hl,0add hl,spex de,hlld (hl),e ;save SPinc hlld (hl),dinc hlpop de ;save return addresspush deld (hl),einc hlld (hl),dld hl,0 ;and return 0retENDFUNC setjmpsz,0endifif 1==1FUNCTION "LONGJMP"FUNCHEAD longjmpszcall ma1toh ;get buffer addressld c,(hl) ;restore BCinc hlld b,(hl)inc hlld e,(hl) ;restore SP...first put it in DEinc hlld d,(hl)inc hlshld tmp2 ;save pointer to return addresscall ma2toh ;get return valueex de,hl ;put return val in DE, old SP in HLld sp,hl ;restore SP with old valuepop hl ;pop return address off stacklhld tmp2 ;get back ptr to return addressld a,(hl)inc hlld h,(hl)ld l,a ;HL holds return addressex de,hl ;put ret addr in DE, get return value in HLpush de ;push return address on stackret ;and return...ENDFUNC longjmpsz,0endif;display $-zzz;ds 0;66;include "deffgfx.csm";align 128 ;doesn't helpendsavebin "deff2.crl",begin,end-beginLABELSLIST "../../us/user.l"