; NOSLTPOP.AZM A sample program to demonstrate a pop-up clock ; display for the SMT no-slot clock. ; Assemble with Z80MR. R.Gaspari 11-20-87 ORG 0100h CALL SETUP ; load overlay that traps ^A and ^B GET$CHAR: LD C,1 ; CALL 5 ; get a char from console CP 3 ; if ^C then exit JP Z,0 JP GET$CHAR ; otherwise go back for next char ; end of main program ; ************************************ ; PART I - HARDWARE EQUATES ; ************************************ ROW EQU 0 ; row and column where pop-up clock COL EQU 50 ; display will be seen on crt CA1 EQU 1BH ; cursor addressing sequence CA2 EQU '=' CA3 EQU ROW+20H CA4 EQU COL+20H CV1 EQU 18H ; make cursor visible CV2 EQU 0 ; (2 bytes avail) CI1 EQU 19H ; make cursor invisible CI2 EQU 0 ; (2 bytes avail) CURPTR EQU 0F400H+21EH ; location in your bios where the pointer ; to current cursor location is stored HKEY1 EQU 01H ; hot-key 1 = single display of clock (^A) HKEY2 EQU 02H ; hot-key 2 - continuous clk display (^B) M6 EQU -6 ; a constant KBA EQU 0D700H ; base addr below which code below is loaded KKS EQU 300H ; how far below kba the code will go ; ****************************** ; PART II - SETUP ; ****************************** SETUP: LD HL,(6) ; get bdos vector DF06 LD (KREM6),HL ; store it for future use LD DE,M6 ; get -6 ADD HL,DE ; HL now has DF00 (source) LD DE,KBA-KKS ; DE now has D300 (destination) LD BC,9 ; move 9 bytes LDIR LD HL,(1) ; get warm boot vector ED03 (source) LD DE,KBA-KKS+9 ; DE now has D309 (destination) LD BC,12 ; move 12 bytes LDIR LD DE,KBA-KKS+21 ; DE has D315 (destination) LD HL,KKODE+21 ; HL points to code below LD BC,KSIZE ; move bytes LDIR LD HL,KBDOS ; get new bdos vector LD (6),HL ; put it in place LD HL,(1) ; point to actual table (dest) EX DE,HL ; LD HL,KBOOT ; point to replace table (source) LD BC,12 ; move the 12 replacement bytes LDIR RET ; done with SETUP ; *********************************************** ; PART III - CODE MOVED TO HIGH MEMORY ; *********************************************** KKODE: OK EQU (KBA-KKS)-KKODE ; offset KSER EQU $+OK DS 6 ; space for serial number KBDOS EQU $+OK DS 3 ; space for bdos jump BBOOT EQU $+OK DS 3 ; orig warm boot jmp vector BSTAT EQU $+OK DS 3 ; orig console status BCONIN EQU $+OK DS 3 ; orig console input BCONOUT EQU $+OK DS 3 ; orig console output KBOOT EQU $+OK JP KBT ; new warm boot vector KCSTAT EQU $+OK JP KST ; new console status KCONIN EQU $+OK JP KIN ; new console input KCONOUT EQU $+OK JP BCONOUT ; new console output KBT EQU $+OK ; NEW WARM BOOT ROUTINE LD HL,(KREM6) ; get orig bdos jmp vector LD (6),HL ; put it back LD DE,(1) ; point to ED03 LD HL,BBOOT ; get orig actual data LD BC,12 ; move 12 bytes LDIR JP 0 ; reboot to cpm ccp KREM6 EQU $+OK DW 0 ; temp storage for orig bdos (DF06) KST EQU $+OK ; NEW CONSOLE STATUS TEST FOR DATA READY CALL CLKPOP ; if pop-up clk in effect, display it JP BSTAT ; then go to normal bios status CLKPOP EQU $+OK LD A,(CLKFLG) ; see if pop-up flag is set OR A RET Z ; if no, return to call clkpop LD A,(CLKCTR) ; if yes, get the delay counter INC A ; display clk only every 256 iterations LD (CLKCTR),A ; update the counter RET NZ ; if NZ, go back to call clkpop JP CDSP ; otherwise, display clock CLKFLG EQU $+OK DB 0 ; set 0FFh for continuous pop-up display CLKCTR EQU $+OK DB 0 ; temp storage for 256 state counter KIN EQU $+OK ; NEW CONSOLE INPUT ROUTINE KIN2: CALL KST ; see if something is there to input OR A JR Z,KIN2 ; if not, go back and wait CALL BCONIN ; if yes, get the byte using actual bios CP HKEY1 ; see if it's HOTKEY1 JP Z,CDSP ; (single pop-up clock request) CP HKEY2 ; see if it's HOTKEY2 JR Z,CLKREQ ; (continuous pop-up clk display) CP 7FH ; see if it's a "delete" RET NZ ; if not, return with it LD A,08H ; if yes, get the 7F replacement RET ; and return with it CLKREQ: LD A,(CLKFLG) ; prepare to toggle the pop-up flag CPL ; complement the accumulator LD (CLKFLG),A ; store it back again XOR A ; put 0 in accum before return RET ; retn from conin ; **************************************** ; PART IIIb - CLOCK READ ROUTINE ; **************************************** ; see NOSLT20.LBR for more info TIME EQU $+OK ; 1. - CLOCK ENABLE routine CALL TIXR ; READ with addr bit A2 high LD HL,TIMREG ; point to bit stream LD A,(HL) ; get first byte TIBYT: LD B,A ; b contains byte LD C,8 ; do this for 8 bits TIBIT: SRL B ; 0->b7...b0->cy TIWR: DI LD A,084H ; select PROM memory OUT 0A0H,A ; map it to 0000h to 4000h JR NC,TIX1 LD A,(00003H) ; WRITE with bit A2 low & bit A0 high JR TIX2 TIX1: LD A,(00002H) ; WRITE with bit A2 low & bit A0 low TIX2: LD A,0 ; select normal RAM memory OUT 0A0H,A ; map it onto 0000h to 4000h EI ; done with TIWR DEC C JR NZ,TIBIT ; do all 8 bits INC HL ; point to next byte LD A,(HL) ; get next byte OR A ; set zero flag JR NZ,TIBYT ; go do next byte ; code enable complete... TIREAD: ; 2. - CLOCK READ routine LD HL,TIBUF ; set up buffer LD E,8 ; do 8 bytes TIRBYT: LD D,8 ; do 8 bits TIRBIT: CALL TIXR SRL A ; shift bit into cy RR (HL) ; shift bit into (hl) DEC D ; dec bit counter JR NZ,TIRBIT ; read next bit INC HL ; point to next buf location DEC E ; dec byte counter JR NZ,TIRBYT ; read next byte LD HL,TIBUF+1 ; point to data loc before RET RET ; and return from TIME TIXR EQU $+OK DI ; subroutine to enable PROM LD A,084H ; select PROM memory OUT 0A0H,A ; map it onto 0000h - 4000h LD A,(00004H) ; READ with bit A2 high LD B,A ; store in B for the return LD A,0 ; select normal RAM memory OUT 0A0H,A ; map it onto 0000h - 4000h LD A,B EI RET ; normal return from TIME TIMREG EQU $+OK DB 0c5h,3ah,0a3h,5ch ; comparison reg DB 0c5h,3ah,0a3h,5ch,0 ; definition TIBUF EQU $+OK ; (example) Tues 10/20/87 5:15pm DB 0,0 ; seconds (0000) DB 0 ; minutes (15h) DB 0 ; hour (17h) DB 0 ; day (03h) DB 0 ; date (20h) DB 0 ; month (10h) DB 0 ; year (87h) ; **************************************** ; PART IIIc - POP-UP CLOCK DISPLAY ; **************************************** CDSP EQU $+OK ; clock display code LD HL,(CURPTR) ; get current cursor location PUSH HL ; save it (@1) CALL TIME ; call TIME & retn with pointer LD A,(TIBUF+7) ; point to year LD (TIBUF+4),A ; overwrite year onto weekday LD B,6 ; convert 6 binary bytes to ascii LD DE,CDABUF+23 ; point to end of ascii data buffer CDS2: LD A,(HL) ; get the binary data CALL CDASC ; convert it & store at HL & HL-1 INC HL ; point to next binary data DEC DE ; point to next ascii buffer loc DEC B ; countdown 6 binary bytes JR NZ,CDS2 ; LD HL,CDABUF ; point HL to start of cdabuf LD B,25 ; count 25 bytes to send out CDS4: LD C,(HL) ; get the byte to send to console CALL BCONOUT ; N* Adv bios conout INC HL ; point to next loc DEC B ; continue for all 25 bytes JR NZ,CDS4 POP HL ; get orig cursor location LD (CURPTR),HL ; put cursor back in bios LD C,CV1 ; make the cursor visible again CALL BCONOUT ; (use bios conout) LD C,CV2 ; byte 2 of cursor visible CALL BCONOUT ; XOR A ; load 0 into A before ret RET ; normal retn from CDSP CDABUF EQU $+OK DB CI1,CI2 ; make cursor display invisible DB CA1,CA2,CA3,CA4 ; move to location row & col DB ' ' DB 0,0,'/' ; month ascii DB 0,0,'/' ; day ascii DB 0,0,' ' ; year ascii DB 0,0,':' ; hour ascii DB 0,0,':' ; min ascii DB 0,0,' ' ; sec ascii CDASC EQU $+OK LD C,A ; binary to ascii conversion AND 0FH ; mask lower nibble CALL CDAS2 ; LD A,C ; get byte back AND 0F0H ; mask upper nibble RLCA ; shift right 4 times RLCA ; (or left 4 times) RLCA ; RLCA ; CDAS2 EQU $+OK OR 30H ; convert to ascii LD (DE),A ; store it DEC DE ; move to prev loc for upper nibble RET ; retn CDAS2 & retn CDASC KREF1 EQU $ ; location of end of code (local) KREF2 EQU $+OK ; location of end (after it's moved) KSIZE EQU $-KKODE ; the size of code to be moved end ; nosltpop.azm 11-20-87