;CLOCKS/ASM - LS-DOS 6.2 SUBTTL '' PAGE OFF *MOD ; ; Model IV time clock & blinking cursor ; TIMETBL DB 60,60,24,30 ;Sec/min, min/hr, hr/day TIMTSK$ LD A,(CRSAVE) ;If cursor not on, OR A ; then don't blink LD HL,VFLAG$ ;Point to video flag JR Z,$?2 ;Check if blinking BIT 7,(HL) ;Check system INHIBIT RES 7,(HL) ;Allow blink next time JR NZ,$?2 INC (HL) ;Increment the counter BIT 3,(HL) ; & see if to 8 JR Z,$?2 ;Not this time RES 3,(HL) ;Reset counter BIT 6,(HL) ;Check if SOLID cursor JR Z,NOSOLID ;If not, then blink SET 5,(HL) ;Force SOLID mode NOSOLID CALL ENADIS_DO_RAM ;Bring up the video RAM LD A,(HL) ;Grab the toggle bit XOR 20H ; and flip it LD (HL),A AND 20H ;Was it on? LD DE,(CURSOR) ;Get the cursor pos LD A,(CRSAVE) ; and char under cursor JR NZ,$?1 ;Put character if flip on LD A,(CRSCHAR) ; else put the cursor $?1 LD (DE),A ;Put the char $?2 LD IX,TIMETBL ;Point to data area DEC (IX+3) ;Count down by 30 RET NZ ;Back if not one second IF @HZ50 LD (IX+3),25 ;Set for 50 hertz HERTZ$ EQU $-1 ELSE ; else use 60 hertz LD (IX+3),30 ;Reset for one second HERTZ$ EQU $-1 ENDIF BIT 4,(HL) ;Is clock on? (VFLAG$) JR Z,$?3 ;Go if off LD DE,CLOCK ;Set to display clock PUSH DE $?3 LD B,3 LD HL,TIME$ LD DE,TIMETBL ;Pt to max sec, min, hr TIMER1 INC (HL) ;Bump time parm LD A,(DE) SUB (HL) RET NZ ;Ret if not max LD (HL),A ; else set to 0 INC L ;Pt to next parm INC E DJNZ TIMER1 ;Loop thru 3 parms ; ; Update date at midnight ; LD L,DATE$+2&0FFH ;Point to day of month LD A,(HL) ;Get the month OR A ;See if date used RET Z ;Back if not DEC L LD DE,MAXDAY$ ;Point to test table INC (HL) ;Bump the day ADD A,E LD E,A LD A,(DE) ;P/u max days CP (HL) ;Is day in range? RET NC ;Return if it is LD (HL),1 ; else reset day to 1 INC L ; & bump the month INC (HL) LD A,(HL) ;If went past Dec, SUB 12+1 ; then need to fix RET C LD (HL),1 ;Correct to Jan DEC L ;Backup to year DEC L INC (HL) RET ; ; Clock display processor ; CLOCK CALL ENADIS_DO_RAM ;Bring up the video LD HL,CRTBGN$+69 ;Point to display CRT @TIME LD DE,TIME$+2 ;Point to time$ LD C,':' ;Set the separator TIME1 LD B,3 ;Init for three fields TIME2 LD A,(DE) ;Get a field item LD (HL),2FH ;Init display TIME3 INC (HL) ;Bump until proper digit SUB 10 JR NC,TIME3 ADD A,3AH ;Correct the remainder INC HL ;Bump to next display LD (HL),A ; & stuff the digit INC HL DEC B RET Z ;Back when done LD (HL),C ; else stuff separator INC HL DEC DE ;Point to next field JR TIME2 ; & loop ; ; Return formatted date, HL => user buffer ; IF @BLD631 DATELO$ ;<631> ELSE @DATE ENDIF LD DE,DATE$+2 LD C,'/' JR TIME1 ; PCSAVE$ DW 00 ;PC at entry to RST 38 ; ; Dynamic Trace routine ; TRACE_INT DW $+2 LD HL,(PCSAVE$) EX DE,HL ;Program counter to DE CALL ENADIS_DO_RAM ;Bring up the video LD HL,CRTBGN$+62 ;Crt trace adr ; ; Hexadecimal display routine ; @HEX16 LD A,D ;Convert reg D to CALL @HEX8 ; two hex digits LD A,E ;Convert reg E to @HEX8 PUSH AF ; two hex digits RRA ;Do left nybble first RRA RRA RRA CALL HXD1 ;Bits 0-3 stuffed in hex POP AF ;Reget the byte HXD1 AND 0FH ; & use right nybble ADD A,90H ;Convert nybble to hex DAA ADC A,40H DAA LD (HL),A ;Stuff in (HL) INC HL RET ; ; Scan for PAUSE or BREAK & set KFLAG$ ; SHIFT EQU 0F480H IF @USA KB1 EQU 0F401H ENDIF IF @GERMAN KB1 EQU 0F420H ENDIF IF @FRENCH KB1 EQU 0F408H ENDIF KB7 EQU 0F440H KCK@ CALL ENADIS_DO_RAM ;Bring up the keyboard LD HL,KFLAG$ ;Hang onto flag LD A,(SHIFT) ;P/u SHIFT row & ignore AND 7 ; CTRL key pressed CPL BIT 2,A RET Z ;Back if CTRL ; ; Set carry flag if a SHIFT key is down ; ADD A,1 ;Set CF if no SHIFT CCF ;Set CF if SHIFT JR NC,KCK1 ;No pause if no SHIFT LD A,(KB1) ;Test for "@" IF @USA BIT 0,A ENDIF IF @INTL BIT 4,A ;Foriegn keyboard ENDIF JR Z,KCK1A ;Bypass if no "@" SET 1,(HL) ;Turn on pause bit JR KCK1A ; ; Inhibit test of unshifted BREAK if nested ENA_DO ; KCK1 LD A,(OPREG_SV_PTR) ;If not at highest level SUB OPREG_SV_AREA+1&0FFH ; then don't allow JR NZ,KCK1B ; tasker BREAK handler KCK1A LD A,(KB7) ;Check on BREAK & ENTER BIT 0,A ;Check on ENTER JR Z,KCK1B ;Go if not SET 2,(HL) ; else note set KCK1B BIT 2,A ;Is depressed? PUSH AF JR Z,KCK2 ;Go if not JR C,KCK2 ;Ignore if shifted LD A,(SFLAG$) ;Permit break bit only BIT 4,A ; if BREAK enabled? JR NZ,KCK2 SET 0,(HL) ;Turn on BREAK bit KCK2 POP AF ;C=shift, NZ=break RET ; ; Routine to enable video RAM & change stack if necessary ; *MOD ENADIS_DO_RAM DI ;Can't while we test stack LD (HLSAV),HL ;Save HL but not on stack PUSH AF ;Save AF POP HL LD (AFSAV),HL LD HL,0C03H ;Can't exceed X'F3FC' ADD HL,SP JR NC,$?1 ; ; Switch to the system stack ; POP HL ;Transfer RET address LD (SPSAV),SP ;Save stack pointer LD SP,STACK$-40H ;Keep room at top PUSH HL ;Put RET back $?1 LD HL,DIS_DO_RAM ;Stack return to disable EX (SP),HL ; video RAM below RET PUSH HL LD HL,OPREG_SV_AREA OPREG_SV_PTR EQU $-2 INC HL ;Get next save location LD A,(OPREG$) ;P/u port mask JR NC,$?2 ;Bypass if NC (no stack switch) AND 7FH ;Strip bit 7 to use as flag $?2 LD (HL),A ;Save current state AND 0FCH ;Strip SEL1 & SEL0 OR 82H ;Set SEL1,0 = (1,0) & NZ condx JR DOOPREG ;Set new assignment ; ; Routine to disable video RAM ; DIS_DO_RAM DI ;Interrupts off LD (HLSAV),HL ;Save off of stack PUSH AF POP HL ;Save AF LD (AFSAV),HL LD HL,(OPREG_SV_PTR) LD A,(HL) ;P/u previous state BIT 7,A ;Test if we switch stack SET 7,A ;Make sure PAGE is set DEC HL ; DOOPREG LD (OPREG_SV_PTR),HL LD (OPREG$),A ;Restore port image OUT (@OPREG),A ; and the port JR NZ,$?3 ; ; Switch back to the old stack ; LD SP,$-$ ;Get the old stack SPSAV EQU $-2 $?3 LD HL,$-$ AFSAV EQU $-2 PUSH HL ;Restore AF POP AF LD HL,$-$ ;Restore HL HLSAV EQU $-2 EI ;Interrupts back on RET OPREG_SV_AREA EQU $-1 DB 0,0,0,0,0,0,0,0 ; ; Bank selection SVC handler ; HL=> transfer address for function B=0 ; C => Bank request <0-2>; Set bit 7 to transfer ; B => Request function ; 0 => Select bank C ; 1 => Reset in-use bit of bank C ; 2 => Test in-use bit of bank C ; 3 => Set in-use bit of bank C ; *MOD @BANK AND 7FH ;Strip possible bit 7 CP 2+1 ;Bank out of range? JP NC,PERR DEC B ;Check option JP M,$?3 ;Go if bank select LD C,86H ;Set for reset BUR$ JR Z,$?1 ;Go if function 1 LD C,46H ;Set for test BUR$ DEC B JR Z,$?1 ;Go if function 2 DEC B JR Z,$?0 ;Go on set BUR$ DEC B PERRX JP NZ,PERR ;SVC parameter error LD A,(LBANK$) ;P/u current bank CP A RET $?0 LD B,A ;Save the bank requested CALL $?1 ;Test if in use already RET NZ ;Back if error LD A,B ;Reget the request # LD C,0C6H ;Set for set BUR$ $?1 AND 7 ;Strip to bank 0-7 RLCA ;Shift <0-2> to <3-5> RLCA RLCA OR C ;Merge the code type LD ($?2+1),A ;Change the OP code XOR A ;Init Z-flag LD A,8 ;Init "Device not avail PUSH HL ;Don't alter HL LD HL,BUR$ ;Point to bank-used-RAM $?2 BIT 0,(HL) ;*** Modified instruction POP HL RET $?3 PUSH HL ;Ck if stack is in upper LD HL,8005H ; bank area ADD HL,SP POP HL JP C,PERR ;Error if > X'7FFE' CP 1 ;Change <0, 1, 2, 3> RLA ; to <1, 2, 4, 6> LD B,A ; & save for later LD A,(BAR$) ;P/u Bank Avail Ram AND B ;Is the bank installed? JR NZ,PERRX ;Error if not in machine LD A,B ;Get the requested bank RRA ;Change <1, 2, 4> to CCF ; <0, 2, 3> {CF on 0 ADC A,0 ; switched to 2 & 4} RLCA ;Shift bits 0-1 RLCA ; to 4-5 (MBIT0,1) RLCA RLCA LD B,A ;Save bit mask LD A,(OPREG$) ;P/u current memory AND 08FH ; configuration & OR B ; mask off old & LD (OPREG$),A ; merge the new OUT (@OPREG),A ;Switch the hardware LD A,(LBANK$) ;Get old bank # LD B,A ; & save it LD A,C ;P/u new bank # AND 7FH ;Strip any bit-7 LD (LBANK$),A ; & save new bank # XOR C ;Keep bit-7 OR B ;Merge in new bank # LD C,A ; & replace into C BIT 7,C ;Transfer to new bank? LD B,0 ;Init for invoke later RET Z ;No if bit-7 = 0 EX (SP),HL ;Exchange RET with new CP A ; transfer & go to it RET