From 8e0a5c7d29350808f0bc569b09e0aee67e63a7f8 Mon Sep 17 00:00:00 2001 From: Philip Smart Date: Wed, 11 Mar 2020 15:41:27 +0000 Subject: [PATCH] Added interrupt driven keyboard buffer with autorepeat Interrupt driven cursor flash with NO, CAPS and SHIFTLOCK modes. Optimised some of the code and removed redundancies --- software/CPM/CPM_RFS_1/{ddt.com => DDT.COM} | Bin 4864 -> 4864 bytes software/CPM/CPM_RFS_1/ZSID.COM | Bin 10240 -> 10240 bytes software/CPM/ROMRFS/RAW/CPM_RFS_1.RAW | Bin 245760 -> 245760 bytes software/MZF/CPM_RFS_1.MZF | Bin 245888 -> 245888 bytes software/asm/cbios.asm | 1265 ++++++++++--------- software/asm/cbios_bank1.asm | 443 +++---- software/asm/cbios_bank2.asm | 251 ++-- software/asm/cbios_bank3.asm | 7 +- software/asm/cbios_bank4.asm | 7 +- software/asm/include/CPM_Definitions.asm | 87 +- software/asm/rfs.asm | 10 +- software/asm/rfs_bank1.asm | 19 +- software/asm/rfs_bank2.asm | 18 +- software/asm/rfs_bank3.asm | 17 +- software/asm/rfs_bank4.asm | 93 -- software/asm/sa1510.asm | 2 +- software/roms/MROM_256.bin | Bin 506624 -> 506624 bytes software/roms/USER_ROM_256.bin | Bin 521472 -> 521472 bytes software/roms/cbios.rom | Bin 4096 -> 4096 bytes software/roms/cbios_bank1.rom | Bin 2048 -> 2048 bytes software/roms/cbios_bank2.rom | Bin 2048 -> 2048 bytes software/roms/cbios_bank3.rom | Bin 2048 -> 2048 bytes software/roms/cbios_bank4.rom | Bin 2048 -> 2048 bytes software/roms/monitor_80c_SA1510.rom | Bin 4096 -> 4096 bytes software/roms/monitor_SA1510.rom | Bin 4096 -> 4096 bytes software/roms/rfs.rom | Bin 8192 -> 8192 bytes 26 files changed, 1091 insertions(+), 1128 deletions(-) rename software/CPM/CPM_RFS_1/{ddt.com => DDT.COM} (94%) delete mode 100644 software/asm/rfs_bank4.asm diff --git a/software/CPM/CPM_RFS_1/ddt.com b/software/CPM/CPM_RFS_1/DDT.COM similarity index 94% rename from software/CPM/CPM_RFS_1/ddt.com rename to software/CPM/CPM_RFS_1/DDT.COM index 83f8603f93e61057d63c994de083a1fd83e29781..ed0cf2966fe6f748d4b852a410ba7c53b19f9243 100644 GIT binary patch delta 50 zcmV-20L}k^CV(ad0lW{xi;)F}87k}nBIgJrBJBt|>j5&=3Nq>sGV~C`JpqxVM+5gT I0I}{861?XU1poj5 delta 50 zcmZorYfxil+{1s^b|Pz=B%i=pRtBSZxs!@%as}FjTB&lc`2;~i6PLI%1KAtj2?+rJ DdDahr diff --git a/software/CPM/CPM_RFS_1/ZSID.COM b/software/CPM/CPM_RFS_1/ZSID.COM index 221c0ae6a58eb8209b3fd8d479cefd3fb3cca94f..91f66893fb128e8f1e4c0ac0345c530050cf1880 100644 GIT binary patch delta 46 zcmZn&Xb4y!z;3{x*v6-1xS3sG6%*t4$(w|H7{71+FVx2kr26EffMT0hDulBG0A||| AI{*Lx delta 46 zcmZn&Xb4y!z;3~y*v6-1xtU#H6%*tC$(w|H82@knFVx2kr26EffMT0hDulBG0Ba)< AYXATM diff --git a/software/CPM/ROMRFS/RAW/CPM_RFS_1.RAW b/software/CPM/ROMRFS/RAW/CPM_RFS_1.RAW index c4ec38763bca2d2dbb3d70e3a07591adba650c0d..413309fb87d121db905845b57525190ca1b2e02e 100644 GIT binary patch delta 111 zcmZo@;BRQ)-@sDA*gcuGqD@lk4WrU?4rQgc99FLxjjnPTz2Z0eB5>H2aq^N1cjoT~ z49)K<+TT?$0x{F}cNNS+%F#rmIDe(XR delta 89 zcmZo@;BRQ)-@sDAXgis;qK%DD;4CYH(e#Nq%(>0~D%$^5Faj~t_J0-3Ow8;S42o@h qN|xK%YnWFtG5(*vsgBu)@&ES!bH2ak5IKJM(t~ zhUUD=_Pk0)AZFU0SII2I%x=J-*v6-1xV^oGc@-1m_vuFU%s!0Yx7XJ*_i+PhzHVkI MpzwChUgmIP0MMx>`~Uy| delta 89 zcmZo@ 500000 days! +TIMESET: DI + PUSH BC + PUSH DE + PUSH HL + ; + LD (TIMESEC),HL ; Load lower 16 bits. + EX DE,HL + LD (TIMESEC+2),HL ; Load middle 16 bits. + PUSH BC + POP HL + LD (TIMESEC+4),HL ; Load upper 16 bits. + ; + LD HL,CONTF + LD (HL),074H ; Set Counter 1, read/load lsb first then msb, mode 2 rate generator, binary + LD (HL),0B0H ; Set Counter 2, read/load lsb first then msb, mode 0 interrupt on terminal count, binary + DEC HL + LD DE,TMRTICKINTV ; 100Hz coming into Timer 2 from Timer 1, set divisor to set interrupts per second. + LD (HL),E ; Place current time in Counter 2 + LD (HL),D + DEC HL + LD (HL),03BH ; Place divisor in Counter 1, = 315, thus 31500/315 = 100 + LD (HL),001H + NOP + NOP + NOP + ; + POP HL + POP DE + POP BC + ;EI + RET + + ; Time Read; + ; Returns BC:DE:HL where HL is lower 16bits, DE is middle 16bits and BC is upper 16bits of milliseconds since 01/01/1980. +TIMEREAD: LD HL,(TIMESEC+4) + PUSH HL + POP BC + LD HL,(TIMESEC+2) + EX DE,HL + LD HL,(TIMESEC) + RET ?MODE: LD HL,KEYPF LD (HL),08AH @@ -705,183 +1065,84 @@ L06F0: LD A,B LD (HL),001H RET -?GET: PUSH BC - PUSH HL - LD B,009H - LD HL,SWPW+1 - CALL ?CLRFF - POP HL - POP BC - CALL ?KEY - SUB 0F0H - RET Z - ADD A,0F0H - JP ?DACN - -?KEY: PUSH BC - PUSH DE - PUSH HL - CALL ?SWEP - LD A,B - RLCA - JR C,?KY2 - LD A,0F0H -?KY1: LD E,A - CALL AUTCK - LD A,(KDATW) + ; Method to check if a key has been pressed and stored in buffer.. +CHKKY: ;CALL ?SAVE + LD A, (KEYCOUNT) OR A - JR Z,?KY11 - CALL DLY12 - CALL ?SWEP - LD A,B - RLCA - JR C,?KY2 -?KY11: LD A,E - CP 0F0H - JR NZ,?KY9 -?KY10: POP HL - POP DE - POP BC - RET -?KY2: RLCA - RLCA - RLCA - JP C,L06E7 - RLCA - JP C,BRK - LD H,000H - LD L,C - LD A,C - CP 038H - JR NC,?KY6 - LD A,(KANAF) - OR A - LD A,B - RLCA - JR NZ,?KY4 - LD B,A - LD A,(SFTLK) - OR A - LD A,B - JR Z,L0917 - RLA - CCF - RRA -L0917: RLA - RLA - JR NC,?KY3 -L091B: LD DE,KTBLC -?KY5: ADD HL,DE - LD A,(HL) - JR ?KY1 -?KY3: RRA - JR NC,?KY6 - LD DE,KTBLS - JR ?KY5 -?KY6: LD DE,KTBL ; 00BEAH - JR ?KY5 -?KY4: RLCA - JR C,?KY7 - RLCA - JR C,L091B - LD DE,KTBLG - JR ?KY5 -?KY7: LD DE,KTBLGS - JR ?KY5 -?KY9: CALL AUTCK - INC A - LD A,E - JR ?KY10 - -DLY12: PUSH BC - LD B,023H -DLY12A: CALL DLY3 - DJNZ DLY12A - POP BC - RET - -DLY3: NEG - NEG - LD A,02AH - JP L0762 -L09AB: ADD A,C - DJNZ L09AB - POP BC - LD C,A - XOR A - RET - -L0760: LD A,00DH -L0762: DEC A - JP NZ,L0762 - RET - - ; Method to check if a key has been pressed. -CHKKY: CALL ?SAVE - LD A, (KEYBUF) - CP 0FFH JR Z,CHKKY2 - JR CHKKY3 -CHKKY2: CALL ?KEY - CALL ?FLAS - CALL ?LOAD - JR Z,CHKKY4 - LD (KEYBUF),A -CHKKY3: LD A,0FFH + ;CALL ?LOAD + LD A,0FFH RET -CHKKY4: XOR A +CHKKY2: ;CALL ?FLAS + ;CALL ?LOAD + XOR A RET -GETKY: LD A,(KEYBUF) - CP 0FFH +GETKY: PUSH HL + LD A,(KEYCOUNT) + OR A JR Z,GETKY2 +GETKY1: DI ; Disable interrupts, we dont want a race state occurring. + LD A,(KEYCOUNT) + DEC A ; Take 1 off the total count as we are reading a character out of the buffer. + LD (KEYCOUNT),A + LD HL,(KEYREAD) ; Get the position in the buffer where the next available character resides. + LD A,(HL) ; Read the character and save. PUSH AF - LD A,0FFH - LD (KEYBUF),A + INC L ; Update the read pointer and save. + LD A,L + AND KEYBUFSIZE-1 + LD L,A + LD (KEYREAD),HL POP AF - JR ?PRCKEY + EI ; Interrupts back on so keys and RTC are actioned. + JR ?PRCKEY ; Process the key, action any non ASCII keys. ; -GETKY2: CALL ?SAVE -GETKY3: CALL ?KEY - CALL ?FLAS +GETKY2: ;CALL ?SAVE ; No key available so loop and exercise the flashing cursor until one becomes +GETKY3: LD A,(KEYCOUNT) ; available. + OR A + ;CALL ?FLAS JR Z,GETKY3 - CALL ?LOAD + ;CALL ?LOAD + JR GETKY1 ; ?PRCKEY: ;PUSH AF ;CALL ?PRTHX ;POP AF - CP CR ; CR - JR NZ,?PRCKY1 - JR ?PRCKYE -?PRCKY1: CP 0C9H ; GRAPH -> ALPHA - JR NZ,?PRCKY2 - XOR A - LD (KANAF),A - JR GETKY2 -?PRCKY2: CP 0CAH ; ALPHA -> GRAPH + CP CR ; CR JR NZ,?PRCKY3 - LD A,001H - LD (KANAF),A - JR GETKY2 -?PRCKY3: CP 0C5H ; HOME + JR ?PRCKYE +;?PRCKY1: CP GRAPHALPHA ; GRAPH -> ALPHA +; JR NZ,?PRCKY2 +; XOR A +; LD (KANAF),A +; JR GETKY2 +;?PRCKY2: CP ALPHAGRAPH ; ALPHA -> GRAPH +; JR NZ,?PRCKY3 +; LD A,001H +; LD (KANAF),A +; JR GETKY2 +?PRCKY3: CP HOMEKEY ; HOME JR NZ,?PRCKY4 JR GETKY2 -?PRCKY4: CP 0C6H ; CLR +?PRCKY4: CP CLRKEY ; CLR JR NZ,?PRCKY5 JR GETKY2 -?PRCKY5: CP 0C8H ; INSERT +?PRCKY5: CP INSERT ; INSERT JR NZ,?PRCKY6 JR GETKY2 -?PRCKY6: CP DBLZERO ; 00 +?PRCKY6: CP DBLZERO ; 00 JR NZ,?PRCKY7 LD A,'0' - LD (KEYBUF),A ; Place a character into the keybuffer so we double up on 0 + LD (KEYBUF),A ; Place a character into the keybuffer so we double up on 0 JR ?PRCKYX -?PRCKY7: -?PRCKYX: ;CALL ?DACN ; Convert to ASCII ready for return of key value. -?PRCKYE: ;PUSH AF - ;CALL ?PRTHX - ;POP AF +?PRCKY7: CP BREAKKEY ; Break key processing. + JR NZ,?PRCKY8 + +?PRCKY8: +?PRCKYX: +?PRCKYE: + POP HL RET CLR8Z: XOR A @@ -905,127 +1166,6 @@ L09E8: LD (HL),D DJNZ ?DINT RET -AUTCK: LD HL,KDATW - LD A,(HL) - INC HL - LD D,(HL) - LD (HL),A - SUB D - RET NC - INC (HL) - RET - -?SWEP: PUSH DE - PUSH HL - XOR A - LD (KDATW),A - LD B,0FAH - LD D,A - CALL BREAK - JR NZ,SWEP6 - LD D,088H - JR SWEP9 -SWEP6: LD HL,SWPW - PUSH HL - JR NC,SWEP11 - LD D,A - AND 060H - JR NZ,SWEP11 - LD A,D - XOR (HL) - BIT 4,A - LD (HL),D - JR Z,SWEP0 -SWEP01: SET 7,D -SWEP0: DEC B - POP HL - INC HL - LD A,B - LD (KEYPA),A - CP 0F0H - JR NZ,SWEP3 - LD A,(HL) - CP 003H - JR C,SWEP9 - LD (HL),000H - RES 7,D -SWEP9: LD B,D - POP HL - POP DE - RET - -SWEP11: LD (HL),000H - JR SWEP0 -SWEP3: LD A,(KEYPB) - LD E,A - CPL - AND (HL) - LD (HL),E - PUSH HL - LD HL,KDATW - PUSH BC - LD B,008H -SWEP8: RLC E - JR C,SWEP7 - INC (HL) -SWEP7: DJNZ SWEP8 - POP BC - OR A - JR Z,SWEP0 - LD E,A -SWEP2: LD H,008H - LD A,B - DEC A - AND 00FH - RLCA - RLCA - RLCA - LD C,A - LD A,E -L0743: DEC H - RRCA - JR NC,L0743 - LD A,H - ADD A,C - LD C,A - JP SWEP01 - -BRK: LD A,0CBH - OR A - JP ?KY10 - -BREAK: LD A,0F0H - LD (KEYPA),A - NOP - LD A,(KEYPB) - OR A - RLA - JR NC,L0D37 - RRA - RRA - JR NC,L0D27 - RRA - JR NC,L0D2B - CCF - RET - -L0D27: LD A,040H - SCF - RET - -L0D2B: LD A,(KDATW) - LD A,001H - LD (KDATW),A - LD A,010H - SCF - RET - -L0D37: AND 002H - RET Z - - LD A,020H - SCF - RET ; HL = Start ; DE = End @@ -1044,8 +1184,9 @@ DUM2: CALL SPHEX CP 020h JR NC,L0D51 LD A,02Eh -L0D51: CALL ?ADCN - CALL ?PRNT3 +L0D51: ;CALL ?ADCN + ;CALL ?PRNT3 + CALL ?PRNT LD A,(DSPXY) INC C SUB C @@ -1068,9 +1209,11 @@ L0D78: DJNZ DUM2 DEC A LD (TMPCNT),A JR NZ,DUM3 -DUM4: CALL ?KEY +DUM4: LD A,(KEYBUF) + CP 0FFH + ;CALL ?KEY JR Z,DUM4 - CALL ?DACN + ;CALL ?DACN CP 'D' JR NZ,DUM5 LD A,8 @@ -1970,7 +2113,7 @@ DATASTOP: LD A,0D8H ; Force CPL OUT (FDC_CR),A CALL WAITRDY ; Wait for controller to become ready, acknowledging interrupt. - CALL CHECKTIMER + ;CALL CHECKTIMER IN A,(FDC_STR) ; Check for errors. CPL AND 0FFH @@ -1984,12 +2127,13 @@ UPDSECTOR: PUSH HL ADD A,(HL) ; Update sector to account for sectors read. NB. All reads will start at such a position LD (HL), A ; that a read will not span a track or head. Ensure that disk formats meet an even 512byte format. POP HL -MOTOROFF: LD A,MTROFFSECS ; Schedule motor to be turned off. +MOTOROFF: LD A,MTROFFMSECS ; Schedule motor to be turned off. LD (MTROFFTIMER),A ; SCF ; CCF ; CALL DEBUG XOR A ; Successful read, return 0 + EI RET SEEKRETRY: LD B,A ; Preserve the FDC Error byte. @@ -2020,13 +2164,13 @@ DSKCMD: LD (FDCCMD),A ; Store CPL ; Inverse (FDC is reverse bit logic). RET -CHECKTIMER: PUSH AF - LD A,(TIMFG) - CP 0F0H - JR NZ,CHKTIM1 - EI -CHKTIM1: POP AF - RET +;CHECKTIMER: PUSH AF +; LD A,(TIMFG) +; CP 0F0H +; JR NZ,CHKTIM1 +; EI +;CHKTIM1: POP AF +; RET ; Seek to programmed track. SEEK: LD A,01BH ; Seek command, load head, verify stepping 6ms. @@ -2168,6 +2312,7 @@ HDLERROR: CALL ERRPRTSTR CALL DSKINIT CALL DSKMTRON LD A,001H ; Indicate error by setting 1 in A register. + EI RET ERRPRTSTR: EX DE,HL @@ -2335,18 +2480,18 @@ INFOMSG4: DB ",HL=", 000H INFOMSG5: DB ",SP=", 000H ENDIF -KTBL: ; Strobe 0 - DB '2' - DB '1' +KTBL: ; Strobe 0 + DB '"' + DB '!' DB 'W' DB 'Q' DB 'A' - DB DELETE + DB INSERT DB NULL DB 'Z' ; Strobe 1 - DB '4' - DB '3' + DB '$' + DB '#' DB 'R' DB 'E' DB 'D' @@ -2354,8 +2499,8 @@ KTBL: ; Strobe 0 DB 'X' DB 'C' ; Strobe 2 - DB '6' - DB '5' + DB '&' + DB '%' DB 'Y' DB 'T' DB 'G' @@ -2363,8 +2508,8 @@ KTBL: ; Strobe 0 DB 'V' DB 'B' ; Strobe 3 - DB '8' - DB '7' + DB '(' + DB '\'' DB 'I' DB 'U' DB 'J' @@ -2372,32 +2517,32 @@ KTBL: ; Strobe 0 DB 'N' DB SPACE ; Strobe 4 - DB '0' - DB '9' + DB '_' + DB ')' DB 'P' DB 'O' DB 'L' DB 'K' - DB ',' + DB '<' DB 'M' ; Strobe 5 - DB '^' - DB '-' - DB '[' - DB '@' - DB ':' - DB ';' - DB '/' - DB '.' - ; Strobe 6 - DB HOME - DB '\\' - DB CURSRIGHT + DB '~' + DB '=' + DB '{' + DB '`' + DB '*' + DB '+' DB CURSLEFT + DB '>' + ; Strobe 6 + DB HOMEKEY + DB '|' + DB CURSRIGHT + DB CURSUP DB CR - DB 'J' + DB '}' DB NULL - DB '?' + DB CURSUP ; Strobe 7 DB '8' DB '7' @@ -2415,215 +2560,149 @@ KTBL: ; Strobe 0 DB NULL DB '3' DB NULL - DB ',' + DB ',' -KTBLS: ; Strobe 0 - DB '"' - DB '!' - DB 'w' - DB 'q' - DB 'a' - DB INSERT - DB NULL - DB 'z' - ; Strobe 1 - DB '$' - DB '#' - DB 'r' - DB 'e' - DB 'd' - DB 's' - DB 'x' - DB 'c' - ; Strobe 2 - DB '&' - DB '%' - DB 'y' - DB 't' - DB 'g' - DB 'f' - DB 'v' - DB 'b' - ; Strobe 3 - DB '(' - DB '\'' - DB 'i' - DB 'u' - DB 'j' - DB 'h' - DB 'n' - DB SPACE - ; Strobe 4 - DB '-' - DB ')' - DB 'p' - DB 'o' - DB 'l' - DB 'k' - DB '<' - DB 'm' - ; Strobe 5 - DB '~' - DB '=' - DB '{' - DB '`' - DB '*' - DB '+' - DB '<' - DB '>' - ; Strobe 6 - DB CLR - DB '|' - DB CURSLEFT - DB CURSDOWN - DB CR - DB '}' - DB NULL - DB '^' - -KTBLG: ; GRAPHIC MODE - ; Strobe 0 - DB 03EH - DB 037H - DB 038H - DB 03CH - DB 053H - DB DELETE - DB NULL - DB 076H - ; Strobe 1 - DB 07BH - DB 07FH - DB 030H - DB 034H - DB 047H - DB 044H - DB 06DH - DB 0DEH - ; Strobe 2 - DB 05EH - DB 03AH - DB 075H - DB 071H - DB 04BH - DB 04AH - DB 0DAH - DB 06FH - ; Strobe 3 - DB 0BDH - DB 01FH - DB 07DH - DB 079H - DB 05CH - DB 072H - DB 032H - DB SPACE - ; Strobe 4 - DB 09CH - DB 0A1H - DB 0D6H - DB 0B0H - DB 0B4H - DB 05BH - DB 060H - DB 01CH - ; Strobe 5 - DB 09EH - DB 0D2H - DB 0D8H - DB 0B2H - DB 0B6H - DB 042H - DB 0DBH - DB 0B8H - ; Strobe 6 - DB HOME - DB 0D4H - DB CURSRIGHT - DB CURSUP - DB CR - DB 04EH - DB NULL - DB 0BAH - -KTBLGS: ; GRAPHIC MODE AND SHIFT ON - ; Strobe 0 - DB 036H - DB 03FH - DB 078H - DB 07CH - DB 046H - DB INSERT - DB NULL - DB 077H - ; Strobe 1 - DB 03BH - DB 07EH - DB 070H - DB 074H - DB 048H - DB 041H - DB 0DDH - DB 0D9H - ; Strobe 2 - DB 01EH - DB 07AH - DB 035H - DB 031H - DB 04CH - DB 043H - DB 0A6H - DB 06EH - ; Strobe 3 - DB 0A2H - DB 05FH - DB 03DH - DB 039H - DB 05DH - DB 073H - DB 033H - DB SPACE - ; Strobe 4 - DB 09DH - DB 0A3H - DB 0B1H - DB 0D5H - DB 056H - DB 06CH - DB 0D0H - DB 01DH - ; Strobe 5 - DB 09FH - DB 0D1H - DB 0B3H - DB 0D7H - DB 04DH - DB 0B5H - DB 01BH - DB 0B9H - ; Strobe 6 - DB CLR - DB 0D3H - DB CURSLEFT - DB CURSDOWN - DB CR - DB 0B7H - DB NULL - DB 0BBH +KTBLS: ; Strobe 0 + DB '2' + DB '1' + DB 'w' + DB 'q' + DB 'a' + DB DELETE + DB NULL + DB 'z' + ; Strobe 1 + DB '4' + DB '3' + DB 'r' + DB 'e' + DB 'd' + DB 's' + DB 'x' + DB 'c' + ; Strobe 2 + DB '6' + DB '5' + DB 'y' + DB 't' + DB 'g' + DB 'f' + DB 'v' + DB 'b' + ; Strobe 3 + DB '8' + DB '7' + DB 'i' + DB 'u' + DB 'j' + DB 'h' + DB 'n' + DB SPACE + ; Strobe 4 + DB '0' + DB '9' + DB 'p' + DB 'o' + DB 'l' + DB 'k' + DB ',' + DB 'm' + ; Strobe 5 + DB '^' + DB '-' + DB '[' + DB '@' + DB ':' + DB ';' + DB '/' + DB '.' + ; Strobe 6 + DB CLRKEY + DB '\\' + DB CURSLEFT + DB CURSDOWN + DB CR + DB ']' + DB NULL + DB '?' +KTBLCL: ; Strobe 0 + DB '2' + DB '1' + DB 'W' + DB 'Q' + DB 'A' + DB DELETE + DB NULL + DB 'Z' + ; Strobe 1 + DB '4' + DB '3' + DB 'R' + DB 'E' + DB 'D' + DB 'S' + DB 'X' + DB 'C' + ; Strobe 2 + DB '6' + DB '5' + DB 'Y' + DB 'T' + DB 'G' + DB 'F' + DB 'V' + DB 'B' + ; Strobe 3 + DB '8' + DB '7' + DB 'I' + DB 'U' + DB 'J' + DB 'H' + DB 'N' + DB SPACE + ; Strobe 4 + DB '0' + DB '9' + DB 'P' + DB 'O' + DB 'L' + DB 'K' + DB ',' + DB 'M' + ; Strobe 5 + DB '^' + DB '-' + DB '[' + DB '@' + DB ':' + DB ';' + DB '/' + DB '.' + ; Strobe 6 + DB CLRKEY + DB '\\' + DB CURSLEFT + DB CURSDOWN + DB CR + DB ']' + DB NULL + DB '?' + KTBLC: ; CTRL ON ; Strobe 0 - DB 0F0H - DB 0F0H + DB NOKEY + DB NOKEY DB CTRL_W DB CTRL_Q DB CTRL_A - DB 0F0H + DB NOKEY DB 000H DB CTRL_Z ; Strobe 1 - DB 0F0H - DB 0F0H + DB NOKEY + DB NOKEY DB CTRL_R DB CTRL_E DB CTRL_D @@ -2631,8 +2710,8 @@ KTBLC: ; CTRL ON DB CTRL_X DB CTRL_C ; Strobe 2 - DB 0F0H - DB 0F0H + DB NOKEY + DB NOKEY DB CTRL_Y DB CTRL_T DB CTRL_G @@ -2640,40 +2719,40 @@ KTBLC: ; CTRL ON DB CTRL_V DB CTRL_B ; Strobe 3 - DB 0F0H - DB 0F0H + DB NOKEY + DB NOKEY DB CTRL_I DB CTRL_U DB CTRL_J DB CTRL_H DB CTRL_N - DB 0F0H + DB NOKEY ; Strobe 4 - DB 0F0H - DB 0F0H + DB NOKEY + DB NOKEY DB CTRL_P DB CTRL_O DB CTRL_L DB CTRL_K - DB 0F0H + DB NOKEY DB CTRL_M ; Strobe 5 DB CTRL_CAPPA DB CTRL_UNDSCR DB ESC DB CTRL_AT - DB 0F0H - DB 0F0H - DB 0F0H - DB 0F0H + DB NOKEY + DB NOKEY + DB NOKEY + DB NOKEY ; Strobe 6 - DB 0F0H + DB NOKEY DB CTRL_SLASH - DB 0F0H - DB 0F0H - DB 0F0H + DB NOKEY + DB NOKEY + DB NOKEY DB CTRL_RB - DB 0F0H + DB NOKEY ; SIGN ON BANNER CBIOSSIGNON:DB "** CBIOS v1.11, (C) P.D. Smart, 2020 **", CR, NUL diff --git a/software/asm/cbios_bank1.asm b/software/asm/cbios_bank1.asm index 20710c3..0651eea 100644 --- a/software/asm/cbios_bank1.asm +++ b/software/asm/cbios_bank1.asm @@ -33,283 +33,194 @@ ; USER ROM CPM CBIOS BANK 1 ; ;====================================== - ORG UROMADDR + ORG UROMADDR ;----------------------------------------------------------------------------------------- ; Common code spanning all banks to ensure that a Monitor is selected upon power up/reset. ;----------------------------------------------------------------------------------------- NOP - XOR A ; We shouldnt arrive here after a reset, if we do, select MROM bank 0 - LD (RFSBK1),A ; and start up - ie. SA1510 Monitor. + XOR A ; We shouldnt arrive here after a reset, ensure MROM and UROM are set to bank 0 + LD (RFSBK1),A ; then a restart will take place as Bank 0 will jump to vector 00000H + LD (RFSBK2),A NOP - JP 00000h + ; After switching in Bank 0, it will automatically continue processing in Bank 0 at the XOR A instructionof ROMFS: ; Jump table for entry into this pages public functions. - JP ?MLDY ; 9 QMELDY - JP ?TEMP ; 12 QTEMP - JP MLDST ; 15 QMSTA - JP MLDSP ; 18 QMSTP - JP ?BEL ; 21 QBEL - JP ?TMST ; 24 QTIMST - JP ?TMRD ; 27 QTIMRD + JP ?REBOOT ; 9 REBOOT + JP ?MLDY ; 12 QMELDY + JP ?TEMP ; 15 QTEMP + JP MLDST ; 18 QMSTA + JP MLDSP ; 21 QMSTP + JP ?BEL ; 24 QBEL + + ; Method to reboot the machine into startup mode, ie. Monitor at MROM Bank 0, UROM at Bank 0. +?REBOOT: LD A,(MEMSWR) ; Switch memory to power up state, ie. Monitor ROM at 00000H + JP UROMADDR ; Now run the code at the bank start which switches to bank 0, intitialises and then calls 00000H + + + ; Melody function. +?MLDY: PUSH BC + PUSH DE + PUSH HL + LD A,002H + LD (OCTV),A + LD B,001H +MLD1: LD A,(DE) + CP 00DH + JR Z,MLD4 + CP 0C8H + JR Z,MLD4 + CP 0CFH + JR Z,MLD2 + CP 02DH + JR Z,MLD2 + CP 02BH + JR Z,MLD3 + CP 0D7H + JR Z,MLD3 + CP 023H + LD HL,MTBL + JR NZ,MLD1A + LD HL,M?TBL + INC DE +MLD1A: CALL ONPU + JR C,MLD1 + CALL RYTHM + JR C,MLD5 + CALL MLDST + LD B,C + JR MLD1 +MLD2: LD A,003H +MLD2A: LD (OCTV),A + INC DE + JR MLD1 +MLD3: LD A,001H + JR MLD2A +MLD4: CALL RYTHM +MLD5: PUSH AF + CALL MLDSP + POP AF + POP HL + POP DE + POP BC + RET + +ONPU: PUSH BC + LD B,008H + LD A,(DE) +ONP1A: CP (HL) + JR Z,ONP2 + INC HL + INC HL + INC HL + DJNZ ONP1A + SCF + INC DE + POP BC + RET + +ONP2: INC HL + PUSH DE + LD E,(HL) + INC HL + LD D,(HL) + EX DE,HL + LD A,H + OR A + JR Z,ONP2B + LD A,(OCTV) +ONP2A: DEC A + JR Z,ONP2B + ADD HL,HL + JR ONP2A +ONP2B: LD (RATIO),HL + LD HL,OCTV + LD (HL),002H + DEC HL + POP DE + INC DE + LD A,(DE) + LD B,A + AND 0F0H + CP 030H + JR Z,ONP2C + LD A,(HL) + JR ONP2D +ONP2C: INC DE + LD A,B + AND 00FH + LD (HL),A +ONP2D: LD HL,OPTBL + ADD A,L + LD L,A + LD C,(HL) + LD A,(TEMPW) + LD B,A + XOR A + JP MLDDLY + +RYTHM: LD HL,KEYPA + LD (HL),0F0H + INC HL + LD A,(HL) + AND 081H + JR NZ,L02D5 + SCF + RET + +L02D5: LD A,(SUNDG) + RRCA + JR C,L02D5 +L02DB: LD A,(SUNDG) + RRCA + JR NC,L02DB + DJNZ L02D5 + XOR A + RET + +MLDST: LD HL,(RATIO) + LD A,H + OR A + JR Z,MLDSP + PUSH DE + EX DE,HL + LD HL,CONT0 + LD (HL),E + LD (HL),D + LD A,001H + POP DE + JR L02C4 +MLDSP: LD A,034H + LD (CONTF),A + XOR A +L02C4: LD (SUNDG),A + RET + +MLDDLY: ADD A,C + DJNZ MLDDLY + POP BC + LD C,A + XOR A + RET +?TEMP: PUSH AF + PUSH BC + AND 00FH + LD B,A + LD A,008H + SUB B + LD (TEMPW),A + POP BC + POP AF + RET -?MLDY: PUSH BC - PUSH DE - PUSH HL - LD A,002H - LD (OCTV),A - LD B,001H -MLD1: LD A,(DE) - CP 00DH - JR Z,MLD4 - CP 0C8H - JR Z,MLD4 - CP 0CFH - JR Z,MLD2 - CP 02DH - JR Z,MLD2 - CP 02BH - JR Z,MLD3 - CP 0D7H - JR Z,MLD3 - CP 023H - LD HL,MTBL - JR NZ,MLD1A - LD HL,M?TBL - INC DE -MLD1A: CALL ONPU - JR C,MLD1 - CALL RYTHM - JR C,MLD5 - CALL MLDST - LD B,C - JR MLD1 -MLD2: LD A,003H -MLD2A: LD (OCTV),A - INC DE - JR MLD1 -MLD3: LD A,001H - JR MLD2A -MLD4: CALL RYTHM -MLD5: PUSH AF - CALL MLDSP - POP AF - POP HL - POP DE - POP BC - RET - -ONPU: PUSH BC - LD B,008H - LD A,(DE) -ONP1A: CP (HL) - JR Z,ONP2 - INC HL - INC HL - INC HL - DJNZ ONP1A - SCF - INC DE - POP BC - RET - -ONP2: INC HL - PUSH DE - LD E,(HL) - INC HL - LD D,(HL) - EX DE,HL - LD A,H - OR A - JR Z,ONP2B - LD A,(OCTV) -ONP2A: DEC A - JR Z,ONP2B - ADD HL,HL - JR ONP2A -ONP2B: LD (RATIO),HL - LD HL,OCTV - LD (HL),002H - DEC HL - POP DE - INC DE - LD A,(DE) - LD B,A - AND 0F0H - CP 030H - JR Z,ONP2C - LD A,(HL) - JR ONP2D -ONP2C: INC DE - LD A,B - AND 00FH - LD (HL),A -ONP2D: LD HL,OPTBL - ADD A,L - LD L,A - LD C,(HL) - LD A,(TEMPW) - LD B,A - XOR A - JP MLDDLY - -RYTHM: LD HL,KEYPA - LD (HL),0F0H - INC HL - LD A,(HL) - AND 081H - JR NZ,L02D5 - SCF - RET - -L02D5: LD A,(SUNDG) - RRCA - JR C,L02D5 -L02DB: LD A,(SUNDG) - RRCA - JR NC,L02DB - DJNZ L02D5 - XOR A - RET - -MLDST: LD HL,(RATIO) - LD A,H - OR A - JR Z,MLDSP - PUSH DE - EX DE,HL - LD HL,CONT0 - LD (HL),E - LD (HL),D - LD A,001H - POP DE - JR L02C4 -MLDSP: LD A,034H - LD (CONTF),A - XOR A -L02C4: LD (SUNDG),A - RET - -MLDDLY: ADD A,C - DJNZ MLDDLY - POP BC - LD C,A - XOR A - RET - - -?TEMP: PUSH AF - PUSH BC - AND 00FH - LD B,A - LD A,008H - SUB B - LD (TEMPW),A - POP BC - POP AF - RET - - -?BEL: PUSH DE - LD DE,00DB1H - CALL ?MLDY - POP DE - RET - -?TMST: DI - PUSH BC - PUSH DE - PUSH HL - LD (AMPM),A - LD A,0F0H - LD (TIMFG),A - LD HL,0A8C0H - XOR A - SBC HL,DE - PUSH HL - INC HL - EX DE,HL - LD HL,CONTF - LD (HL),074H - LD (HL),0B0H - DEC HL - LD (HL),E - LD (HL),D - DEC HL - LD (HL),00AH - LD (HL),000H - INC HL - INC HL - LD (HL),080H - DEC HL -L0323: LD C,(HL) - LD A,(HL) - CP D - JR NZ,L0323 - LD A,C - CP E - JR NZ,L0323 - DEC HL - NOP - NOP - NOP - LD (HL),00CH - LD (HL),07BH - INC HL - POP DE -L0336: LD C,(HL) - LD A,(HL) - CP D - JR NZ,L0336 - LD A,C - CP E - JR NZ,L0336 - POP HL - POP DE - POP BC - EI - RET - -?TMRD: PUSH HL - LD HL,CONTF - LD (HL),080H - DEC HL - DI - LD E,(HL) - LD D,(HL) - EI - LD A,E - OR D - JR Z,?TMR1 - XOR A - LD HL,0A8C0H - SBC HL,DE - JR C,?TMR2 - EX DE,HL - LD A,(AMPM) - POP HL - RET - -?TMR1: LD DE,0A8C0H -?TMR1A: LD A,(AMPM) - XOR 001H - POP HL - RET - -?TMR2: DI - LD HL,CONT2 - LD A,(HL) - CPL - LD E,A - LD A,(HL) - CPL - LD D,A - EI - INC DE - JR ?TMR1A - + +?BEL: PUSH DE + LD DE,00DB1H + CALL ?MLDY + POP DE + RET MTBL: DB 043H diff --git a/software/asm/cbios_bank2.asm b/software/asm/cbios_bank2.asm index bd8b385..5c41ded 100644 --- a/software/asm/cbios_bank2.asm +++ b/software/asm/cbios_bank2.asm @@ -39,25 +39,17 @@ ; Common code spanning all banks to ensure that a Monitor is selected upon power up/reset. ;----------------------------------------------------------------------------------------- NOP - XOR A ; We shouldnt arrive here after a reset, if we do, select MROM bank 0 - LD (RFSBK1),A ; and start up - ie. SA1510 Monitor. + XOR A ; We shouldnt arrive here after a reset, ensure MROM and UROM are set to bank 0 + LD (RFSBK1),A ; then a restart will take place as Bank 0 will jump to vector 00000H + LD (RFSBK2),A NOP - JP 00000h + ; After switching in Bank 0, it will automatically continue processing in Bank 0 at the XOR A instructionof ROMFS: ; Jump table for entry into this pages functions. - JP ?NL ; 9 QNL - JP ?PRTS ; 12 QPRTS - JP ?PRNT ; 15 QPRNT - JP ?DACN ; 18 QDACN - JP ?ADCN ; 21 QADCN - JP ?PRTHX ; 24 QPRTHX - JP ?SAVE ; 27 QSAVE - JP ?LOAD ; 30 QLOAD - JP ?FLAS ; 33 QFLAS - JP PRNT3 ; 36 QPRNT3 - JP PRTHL ; 39 QPRTHL - JP ?DPCT ; 42 QDPCT - JP ?ANSITERM ; 45 QANSITERM + JP ?PRNT ; 9 QPRNT + JP ?PRTHX ; 12 QPRTHX + JP ?PRTHL ; 15 QPRTHL + JP ?ANSITERM ; 18 QANSITERM ; CR PAGE MODE1 @@ -113,47 +105,50 @@ DPCT1: ADD HL,BC EX DE,HL JP (HL) -?SAVE: LD HL,FLSDT - LD (HL),0EFH - LD A,(KANAF) - OR A - JR Z,L0270 - LD (HL),0FFH -L0270: LD A,(HL) - PUSH AF - CALL ?PONT - LD A,(HL) - LD (FLASH),A - POP AF - LD (HL),A - XOR A - LD HL,KEYPA - LD (HL),A - CPL - LD (HL),A - RET - -?LOAD: PUSH AF - LD A,(FLASH) - CALL ?PONT - LD (HL),A - POP AF - RET - -?FLAS: PUSH AF - PUSH HL - LD A,(KEYPC) - RLCA - RLCA - JR C,FLAS1 - LD A,(FLSDT) -FLAS2: CALL ?PONT - LD (HL),A -FLAS3: POP HL - POP AF - RET -FLAS1: LD A,(FLASH) - JR FLAS2 +;?SAVE: LD HL,FLSDT +; LD A,(SFTLK) +; OR A +; LD (HL),043H ; Thick block cursor when lower case. +; JR Z,SAVE1 +; CP 1 +; LD (HL),03EH ; Thick underscore when CAPS lock. +; JR Z,SAVE1 +; LD (HL),0EFH ; Block cursor when SHIFT lock. +;SAVE1: LD A,(HL) +; PUSH AF +; CALL ?PONT +; LD A,(HL) +; LD (FLASH),A +; POP AF +; LD (HL),A +; XOR A +; LD HL,KEYPA +; LD (HL),A +; CPL +; LD (HL),A +; RET +; +;?LOAD: PUSH AF +; LD A,(FLASH) +; CALL ?PONT +; LD (HL),A +; POP AF +; RET +; +;?FLAS: PUSH AF +; PUSH HL +; LD A,(KEYPC) +; RLCA +; RLCA +; JR C,FLAS1 +; LD A,(FLSDT) +;FLAS2: CALL ?PONT +; LD (HL),A +;FLAS3: POP HL +; POP AF +; RET +;FLAS1: LD A,(FLASH) +; JR FLAS2 ?PRT: LD A,C @@ -204,25 +199,113 @@ L098C: SUB 00AH JR NZ,L098C RET + ; Delete a character on screen. +?DELCHR: LD A,0C7H + CALL ?DPCT + JR ?PRNT1 + +?NEWLINE: CALL ?NL + JR ?PRNT1 + + ; + ; Function to disable the cursor display. + ; +CURSOROFF: DI + CALL CURSRSTR ; Restore character under the cursor. + LD HL,FLASHCTL ; Indicate cursor is now off. + RES 7,(HL) + EI + RET + + ; + ; Function to enable the cursor display. + ; +CURSORON: DI + CALL DSPXYTOADDR ; Update the screen address for where the cursor should appear. + LD HL,FLASHCTL ; Indicate cursor is now on. + SET 7,(HL) + EI + RET + + ; + ; Function to restore the character beneath the cursor iff the cursor is being dislayed. + ; +CURSRSTR: PUSH HL + PUSH AF + LD HL,FLASHCTL ; Check to see if there is a cursor at the current screen location. + BIT 6,(HL) + JR Z,CURSRSTR1 + RES 6,(HL) + LD HL,(DSPXYADDR) ; There is so we must restore the original character before further processing. + LD A,(FLASH) + LD (HL),A +CURSRSTR1: POP AF + POP HL + RET + + ; + ; Function to convert XY co-ordinates to a physical screen location and save. + ; +DSPXYTOADDR:PUSH HL + PUSH DE + PUSH BC + LD BC,(DSPXY) ; Calculate the new cursor position based on the XY coordinates. + LD DE,COLW + LD HL,SCRN - COLW +DSPXYTOA1: ADD HL,DE + DEC B + JP P,DSPXYTOA1 + LD B,000H + ADD HL,BC + RES 3,H + LD (DSPXYADDR),HL ; Store the new address. + LD A,(HL) ; Store the new character. + LD (FLASH),A +DSPXYTOA2: POP BC + POP DE + POP HL + RET + + ; + ; Function to print a space. + ; ?PRTS: LD A,020H -?PRNT: CP 00DH - JR Z,?NL + + ; Function to print a character to the screen. If the character is a control code it is processed as necessary + ; otherwise the character is converted from ASCII display and displayed. + ; +?PRNT: DI + CALL CURSRSTR ; Restore char under cursor. + CP 00DH + JR Z,?NEWLINE CP 00AH - JR Z,?NL + JR Z,?NEWLINE + CP 07FH + JR Z,?DELCHR + CP BACKS + JR Z,?DELCHR PUSH BC LD C,A LD B,A CALL ?PRT LD A,B POP BC +?PRNT1: CALL DSPXYTOADDR + EI RET -PRTHL: LD A,H + ; + ; Function to print out the contents of HL as 4 digit Hexadecimal. + ; +?PRTHL: LD A,H CALL ?PRTHX LD A,L JR ?PRTHX - LD B,E - LD B,E + RET + + ; + ; Function to print out the contents of A as 2 digit Hexadecimal + ; ?PRTHX: PUSH AF RRCA RRCA @@ -233,11 +316,6 @@ PRTHL: LD A,H POP AF CALL ASC JP ?PRNT -L03D5: POP DE - POP HL - POP BC - POP AF - RET ASC: AND 00FH CP 00AH @@ -376,17 +454,12 @@ CLRS1: LD A,(SCLDSP) HOM0: LD HL,00000H JP CURS3 -ALPHA: XOR A -ALPHI: LD (KANAF),A ?RSTR: POP HL ?RSTR1: POP DE POP BC POP AF RET -KANA: LD A,001H - JR ALPHI - DEL: LD HL,(DSPXY) LD A,H OR L @@ -518,8 +591,8 @@ DACN1: OR A DW CLRS DW DEL DW INST - DW ALPHA - DW KANA + DW ?RSTR + DW ?RSTR DW ?RSTR DW REV DW .CR @@ -838,22 +911,22 @@ ANSI_NN: CP "?" ; Simpl CP "@" ; Is it a letter? JP C,ANSIEXIT ; Abandon if not letter; something wrong -ANSIFOUND: LD HL,(NUMBERPOS) ; Get value of number buffer +ANSIFOUND: CALL CURSRSTR ; Restore any character under the cursor. + LD HL,(NUMBERPOS) ; Get value of number buffer LD A,(HAVELOADED) ; Did we put anything in this byte? OR A JR NZ,AF1 LD (HL),255 ; Mark the fact that nothing was put in AF1: INC HL LD A,254 - LD (HL),A ; Mark end of sequence (for unlimited length - ; sequences) - ;*** Disable cursor, because it might well move! - LD A,(CURSORON) - OR A ; Well, what do we have here?! - ; CALL NZ,ToggleCursor ; If cursor on, then remove + LD (HL),A ; Mark end of sequence (for unlimited length sequences) + + ;Disable cursor as unwanted side effects such as screen flicker may occur. + LD A,(FLASHCTL) + BIT 7,A + CALL NZ,CURSOROFF XOR A - LD (CURSORON),A ; And cursor is now off LD (CURSORCOUNT),A ; Restart count LD A,0C9h LD (CHGCURSMODE),A ; Disable flashing temp. @@ -886,7 +959,8 @@ AF1: INC HL CP "u" JP Z,RCP ; Restore the cursor position -ANSIEXIT: LD HL,NUMBERBUF ; Numbers buffer position +ANSIEXIT: CALL CURSORON ; If t + LD HL,NUMBERBUF ; Numbers buffer position LD (NUMBERPOS),HL XOR A LD (CHARACTERNO),A ; Next time it runs, it will be the @@ -947,8 +1021,7 @@ AnsiNumber: LD HL,(NUMBERPOS) ; Get a LD (HAVELOADED),A ; Yes, we _have_ put something in! JP AnsiMore -AN1: - LD A,(HL) ; Stored value in A; TBA in C +AN1: LD A,(HL) ; Stored value in A; TBA in C ADD A,A ; 2 * LD D,A ; Save the 2* for later ADD A,A ; 4 * @@ -1040,7 +1113,7 @@ CUB: CALL GetNumber ; Numbe CUBget: LD A,(DSPXY) ; A <- Column CP B ; Too far? JR C,CUB1a - SUB B + SUB B JR CUB1b CUB1a: LD A,0 CUB1b: LD (DSPXY),A ; Column <-A @@ -1137,7 +1210,7 @@ ED1_2: EX DE,HL ; Value LD HL,(DSPXY) ; _that_ value again! POP BC ; Number to blank CALL CALCSCADDR - CALL CLRSCRN ; Now do it! + CALL CLRSCRN ; Now do it! JP ANSIEXIT ; Then exit properly ;*** Option 1 - clear from cursor to beginning of screen @@ -1159,7 +1232,7 @@ ED2_2: EX DE,HL ; Value PUSH HL ; Value saved for later LD HL,0 ; Find the begining! POP BC ; Number to blank - CALL CLRSCRN ; Now do it! + CALL CLRSCRN ; Now do it! JP ANSIEXIT ; Then exit properly ; *** ANSI CLEAR LINE diff --git a/software/asm/cbios_bank3.asm b/software/asm/cbios_bank3.asm index f620e0d..bf2bae7 100644 --- a/software/asm/cbios_bank3.asm +++ b/software/asm/cbios_bank3.asm @@ -38,10 +38,11 @@ ; Common code spanning all banks to ensure that a Monitor is selected upon power up/reset. ;----------------------------------------------------------------------------------------- NOP - XOR A ; We shouldnt arrive here after a reset, if we do, select MROM bank 0 - LD (RFSBK1),A ; and start up - ie. SA1510 Monitor. + XOR A ; We shouldnt arrive here after a reset, ensure MROM and UROM are set to bank 0 + LD (RFSBK1),A ; then a restart will take place as Bank 0 will jump to vector 00000H + LD (RFSBK2),A NOP - JP 00000h + ; After switching in Bank 0, it will automatically continue processing in Bank 0 at the XOR A instructionof ROMFS: ; Jump table for entry into this pages functions. diff --git a/software/asm/cbios_bank4.asm b/software/asm/cbios_bank4.asm index b3072a2..b12cabe 100644 --- a/software/asm/cbios_bank4.asm +++ b/software/asm/cbios_bank4.asm @@ -38,10 +38,11 @@ ; Common code spanning all banks to ensure that a Monitor is selected upon power up/reset. ;----------------------------------------------------------------------------------------- NOP - XOR A ; We shouldnt arrive here after a reset, if we do, select MROM bank 0 - LD (RFSBK1),A ; and start up - ie. SA1510 Monitor. + XOR A ; We shouldnt arrive here after a reset, ensure MROM and UROM are set to bank 0 + LD (RFSBK1),A ; then a restart will take place as Bank 0 will jump to vector 00000H + LD (RFSBK2),A NOP - JP 00000h + ; After switching in Bank 0, it will automatically continue processing in Bank 0 at the XOR A instructionof ROMFS: ; Jump table for entry into this pages functions. diff --git a/software/asm/include/CPM_Definitions.asm b/software/asm/include/CPM_Definitions.asm index 3daba48..973d212 100644 --- a/software/asm/include/CPM_Definitions.asm +++ b/software/asm/include/CPM_Definitions.asm @@ -74,9 +74,10 @@ DPBLOCK7 EQU DPBLOCK6 + DPSIZE ; BIOS equates NDISKS EQU 4 ; Number of Disk Drives +KEYBUFSIZE EQU 16 ; Ensure this is a power of 2, max size 256. ; Debugging -ENADEBUG EQU 1 ; Enable debugging logic, 1 = enable, 0 = disable +ENADEBUG EQU 0 ; Enable debugging logic, 1 = enable, 0 = disable ;----------------------------------------------- ; Configurable settings. @@ -92,9 +93,8 @@ SECMSK EQU HSTBLK-1 ; secto WRALL EQU 0 ; write to allocated WRDIR EQU 1 ; write to directory WRUAL EQU 2 ; write to unallocated -MTROFFSECS EQU 10 ; Time from last access to motor being switched off in seconds. - - +TMRTICKINTV EQU 5 ; Number of 0.010mSec ticks per interrupt, ie. resolution of RTC. +MTROFFMSECS EQU 100 ; Time from last access to motor being switched off in seconds in TMRTICKINTV ticks. COLW: EQU 80 ; Width of the display screen (ie. columns). ROW: EQU 25 ; Number of rows on display screen. SCRNSZ: EQU COLW * ROW ; Total size, in bytes, of the screen display area. @@ -106,29 +106,18 @@ MODE80C: EQU 1 ;------------------------------------------------------- ; Public functions in CBIOS User ROM Bank 1. -QMELDY EQU 9 + UROMADDR -QTEMP EQU 12 + UROMADDR -QMSTA EQU 15 + UROMADDR -QMSTP EQU 18 + UROMADDR -QBEL EQU 21 + UROMADDR -QTIMST EQU 24 + UROMADDR -QTIMRD EQU 27 + UROMADDR +QREBOOT EQU 9 + UROMADDR +QMELDY EQU 12 + UROMADDR +QTEMP EQU 15 + UROMADDR +QMSTA EQU 18 + UROMADDR +QMSTP EQU 21 + UROMADDR +QBEL EQU 24 + UROMADDR ; Public functions in CBIOS User ROM Bank 1. -QNL EQU 9 + UROMADDR -QPRTS EQU 12 + UROMADDR -QPRNT EQU 15 + UROMADDR -QDACN EQU 18 + UROMADDR -QADCN EQU 21 + UROMADDR -QPRTHX EQU 24 + UROMADDR -QSAVE EQU 27 + UROMADDR -QLOAD EQU 30 + UROMADDR -QFLAS EQU 33 + UROMADDR -QPRNT3 EQU 36 + UROMADDR -QPRTHL EQU 39 + UROMADDR -QDPCT EQU 42 + UROMADDR -QANSITERM EQU 45 + UROMADDR - +QPRNT EQU 9 + UROMADDR +QPRTHX EQU 12 + UROMADDR +QPRTHL EQU 15 + UROMADDR +QANSITERM EQU 18 + UROMADDR ;----------------------------------------------- @@ -264,18 +253,30 @@ CTRL_RB EQU 01DH CTRL_CAPPA EQU 01EH CTRL_UNDSCR EQU 01FH CTRL_AT EQU 000H -CURSRIGHT EQU 0F0H -CURSLEFT EQU 0F1H -CURSUP EQU 0F2H -CURSDOWN EQU 0F3H -DBLZERO EQU 0F4H -INSERT EQU 0F5H -CLR EQU 0F6H +NOKEY EQU 0F0H +CURSRIGHT EQU 0F1H +CURSLEFT EQU 0F2H +CURSUP EQU 0F3H +CURSDOWN EQU 0F4H +DBLZERO EQU 0F5H +INSERT EQU 0F6H +CLRKEY EQU 0F7H +HOMEKEY EQU 0F8H +BREAKKEY EQU 0FBH ;----------------------------------------------- ; BIOS WORK AREA (MZ80A) ;----------------------------------------------- ORG CBIOSDATA + + ; Keyboard processing, ensure starts where LSB = 0. +VARSTART EQU $ ; Start of variables. +KEYBUF: DS virtual KEYBUFSIZE ; Interrupt driven keyboard buffer. +KEYCOUNT: DS virtual 1 +KEYWRITE: DS virtual 2 ; Pointer into the buffer where the next character should be placed. +KEYREAD: DS virtual 2 ; Pointer into the buffer where the next character can be read. +KEYLAST: DS virtual 1 ; KEY LAST VALUE +KEYRPT: DS virtual 1 ; KEY REPEAT COUNTER ; SPV: IBUFE: ; TAPE BUFFER (128 BYTES) @@ -286,8 +287,11 @@ DTADR: DS virtual 2 ; DATA EXADR: DS virtual 2 ; EXECUTION ADDRESS SWPW: DS virtual 10 ; SWEEP WORK KDATW: DS virtual 2 ; KEY WORK -KANAF: DS virtual 1 ; KANA FLAG (01=GRAPHIC MODE) +;KANAF: DS virtual 1 ; KANA FLAG (01=GRAPHIC MODE) DSPXY: DS virtual 2 ; DISPLAY COORDINATES +DSPXYLST: DS virtual 2 ; Last known cursor position, to compare with DSPXY to detect changes. +FLASHCTL: DS virtual 1 ; CURSOR FLASH CONTROL. BIT 0 = Cursor On/Off, BIT 1 = Cursor displayed. +DSPXYADDR: DS virtual 2 ; Address of last known position. MANG: DS virtual 6 ; COLUMN MANAGEMENT MANGE: DS virtual 1 ; COLUMN MANAGEMENT END PBIAS: DS virtual 1 ; PAGE BIAS @@ -310,8 +314,8 @@ ONTYO: DS virtual 1 ; ONTYO OCTV: DS virtual 1 ; OCTAVE WORK RATIO: DS virtual 2 ; ONPU RATIO ;BUFER: DS virtual 81 ; GET LINE BUFFER -KEYBUF: DS virtual 1 ; KEY BUFFER -KEYRPT: DS virtual 2 ; KEY REPEAT COUNTER +;KEYBUF: DS virtual 1 ; KEY BUFFER +TIMESEC DS virtual 6 ; RTC 48bit TIME IN MILLISECONDS FDCCMD DS virtual 1 ; LAST FDC COMMAND SENT TO CONTROLLER. MOTON DS virtual 1 ; MOTOR ON = 1, OFF = 0 INVFDCDATA: DS virtual 1 ; INVERT DATA COMING FROM FDC, 1 = INVERT, 0 = AS IS @@ -374,7 +378,6 @@ JSW_FF DS virtual 1 ; Byte JSW_LF DS virtual 1 ; Byte value to turn on/off LF routine CHARACTER DS virtual 1 ; To buffer character to be printed. CURSORPOS DS virtual 2 ; Cursor position, default 0,0. -CURSORON DS virtual 1 ; Cursor on/off toggle value BOLDMODE DS virtual 1 HIBRITEMODE DS virtual 1 ; 0 means on, &C9 means off UNDERSCMODE DS virtual 1 @@ -382,9 +385,15 @@ ITALICMODE DS virtual 1 INVMODE DS virtual 1 CHGCURSMODE DS virtual 1 ANSIMODE DS virtual 1 ; 1 = on, 0 = off -VARIABLEEND DS virtual 1 COLOUR EQU 0 - DS virtual 128 -BIOSSTACK EQU $ ; Perhaps change to 0080? ; BIOS Stack. SPSAVE: DS virtual 2 ; CPM Stack save. +SPISRSAVE: DS virtual 2 +VAREND EQU $ ; End of variables + + ; Stack space for the CBIOS. + DS virtual 128 +BIOSSTACK EQU $ + ; Stack space for the Interrupt Service Routine. + DS virtual 32 ; Max 8 stack pushes. +ISRSTACK EQU $ diff --git a/software/asm/rfs.asm b/software/asm/rfs.asm index c206468..1e77dbb 100644 --- a/software/asm/rfs.asm +++ b/software/asm/rfs.asm @@ -43,7 +43,15 @@ ; Common code spanning all banks. ;-------------------------------- ROMFS: NOP - LD A, (ROMBK1) ; Ensure all banks are at default on + JR ROMFS_0 ; Skip the reset vector. + NOP + NOP + NOP + NOP + NOP + NOP + JP 00000H ; Common point when an alternate bank needs to reset the system. +ROMFS_0: LD A, (ROMBK1) ; Ensure all banks are at default on CP 4 ; If the ROMBK1 value is 255, an illegal value, then the machine has just started so skip. JR C, ROMFS_2 XOR A ; Clear the lower stack space as we use it for variables. diff --git a/software/asm/rfs_bank1.asm b/software/asm/rfs_bank1.asm index 51bd180..a4bc369 100644 --- a/software/asm/rfs_bank1.asm +++ b/software/asm/rfs_bank1.asm @@ -38,19 +38,12 @@ ; Common code spanning all banks. ;-------------------------------- ROMFS1: NOP - LD A, (ROMBK1) ; Ensure all banks are at default on - CP 4 ; If the ROMBK1 value is 255, an illegal value, then the machine has just started so skip. - JR C, ROMFS1_2 - XOR A ; Clear the lower stack space as we use it for variables. - LD B, 7*8 - LD HL, 01000H -ROMFS1_1: LD (HL),A - INC HL - DJNZ ROMFS1_1 -ROMFS1_2: LD (RFSBK1),A ; start up. - LD A, (ROMBK2) - LD (RFSBK2),A - JP MONITOR + XOR A ; We shouldnt arrive here after a reset, if we do, select UROM bank 0 + LD (RFSBK1),A + LD (RFSBK2),A ; and start up - ie. SA1510 Monitor. + ALIGN_NOPS 0E829H + + ; After switching in Bank 0, it will automatically continue processing in Bank 0 at the XOR A instructionof ROMFS: ; ; Bank switching code, allows a call to code in another bank. diff --git a/software/asm/rfs_bank2.asm b/software/asm/rfs_bank2.asm index 7a02c0f..7a6bb76 100644 --- a/software/asm/rfs_bank2.asm +++ b/software/asm/rfs_bank2.asm @@ -38,21 +38,11 @@ ; Common code spanning all banks. ;-------------------------------- ROMFS2: NOP - LD A, (ROMBK1) ; Ensure all banks are at default on - CP 4 ; If the ROMBK1 value is 255, an illegal value, then the machine has just started so skip. - JR C, ROMFS2_2 - XOR A ; Clear the lower stack space as we use it for variables. - LD B, 7*8 - LD HL, 01000H -ROMFS2_1: LD (HL),A - INC HL - DJNZ ROMFS2_1 -ROMFS2_2: LD (RFSBK1),A ; start up. - LD A, (ROMBK2) - LD (RFSBK2),A - JP MONITOR + XOR A ; We shouldnt arrive here after a reset, if we do, select UROM bank 0 + LD (RFSBK1),A + LD (RFSBK2),A ; and start up - ie. SA1510 Monitor. + ALIGN_NOPS 0E829H - ; ; Bank switching code, allows a call to code in another bank. ; This code is duplicated in each bank such that a bank switch doesnt affect logic flow. ; diff --git a/software/asm/rfs_bank3.asm b/software/asm/rfs_bank3.asm index ddd7dda..f1bb819 100644 --- a/software/asm/rfs_bank3.asm +++ b/software/asm/rfs_bank3.asm @@ -43,19 +43,10 @@ MODE80C EQU 0 ; Common code spanning all banks. ;-------------------------------- ROMFS3: NOP - LD A, (ROMBK1) ; Ensure all banks are at default on - CP 4 ; If the ROMBK1 value is 255, an illegal value, then the machine has just started so skip. - JR C, ROMFS3_2 - XOR A ; Clear the lower stack space as we use it for variables. - LD B, 7*8 - LD HL, 01000H -ROMFS3_1: LD (HL),A - INC HL - DJNZ ROMFS3_1 -ROMFS3_2: LD (RFSBK1),A ; start up. - LD A, (ROMBK2) - LD (RFSBK2),A - JP MONITOR + XOR A ; We shouldnt arrive here after a reset, if we do, select UROM bank 0 + LD (RFSBK1),A + LD (RFSBK2),A ; and start up - ie. SA1510 Monitor. + ALIGN_NOPS 0E829H ; ; Bank switching code, allows a call to code in another bank. diff --git a/software/asm/rfs_bank4.asm b/software/asm/rfs_bank4.asm deleted file mode 100644 index c6bcfe2..0000000 --- a/software/asm/rfs_bank4.asm +++ /dev/null @@ -1,93 +0,0 @@ -;-------------------------------------------------------------------------------------------------------- -;- -;- Name: rfs_bank4.asm -;- Created: October 2018 -;- Author(s): Philip Smart -;- Description: Sharp MZ series Rom Filing System. -;- This assembly language program is written to utilise the banked flashroms added with -;- the MZ-80A RFS hardware upgrade. -;- -;- Credits: -;- Copyright: (c) 2018 Philip Smart -;- -;- History: October 2018 - Merged 2 utilities to create this compilation. -;- -;-------------------------------------------------------------------------------------------------------- -;- This source file is free software: you can redistribute it and-or modify -;- it under the terms of the GNU General Public License as published -;- by the Free Software Foundation, either version 3 of the License, or -;- (at your option) any later version. -;- -;- This source file is distributed in the hope that it will be useful, -;- but WITHOUT ANY WARRANTY; without even the implied warranty of -;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;- GNU General Public License for more details. -;- -;- You should have received a copy of the GNU General Public License -;- along with this program. If not, see . -;-------------------------------------------------------------------------------------------------------- - - ;====================================== - ; - ; USER ROM BANK 4 - ; - ;====================================== - ORG 0E800h - - ;-------------------------------- - ; Common code spanning all banks. - ;-------------------------------- -ROMFS4: NOP - LD A, (ROMBK1) ; Ensure all banks are at default on - CP 4 ; If the ROMBK1 value is 255, an illegal value, then the machine has just started so skip. - JR C, ROMFS4_2 - XOR A ; Clear the lower stack space as we use it for variables. - LD B, 7*8 - LD HL, 01000H -ROMFS4_1: LD (HL),A - INC HL - DJNZ ROMFS4_1 -ROMFS4_2: LD (RFSBK1),A ; start up. - LD A, (ROMBK2) - LD (RFSBK2),A - JP MONITOR - - ; - ; Bank switching code, allows a call to code in another bank. - ; This code is duplicated in each bank such that a bank switch doesnt affect logic flow. - ; -BKSW4to0: PUSH AF - LD A, ROMBANK4 ; Calling bank (ie. us). - PUSH AF - LD A, ROMBANK0 ; Required bank to call. - JR BKSW4_0 -BKSW4to1: PUSH AF - LD A, ROMBANK4 ; Calling bank (ie. us). - PUSH AF - LD A, ROMBANK1 ; Required bank to call. - JR BKSW4_0 -BKSW4to2: PUSH AF - LD A, ROMBANK4 ; Calling bank (ie. us). - PUSH AF - LD A, ROMBANK2 ; Required bank to call. - JR BKSW4_0 -BKSW4to3: PUSH AF - LD A, ROMBANK4 ; Calling bank (ie. us). - PUSH AF - LD A, ROMBANK3 ; Required bank to call. - ; -BKSW4_0: PUSH BC ; Save BC for caller. - LD BC, BKSWRET4 ; Place bank switchers return address on stack. - PUSH BC - LD (RFSBK2), A ; Bank switch in user rom space, A=bank. - LD (TMPSTACKP),SP ; Save the stack pointer as some old code corrupts it. - JP (HL) ; Jump to required function. -BKSWRET4: POP BC - POP AF ; Get bank which called us. - LD (RFSBK2), A ; Return to that bank. - POP AF - RET ; Return to caller. - - - ALIGN 0EFFFh - DB 0FFh diff --git a/software/asm/sa1510.asm b/software/asm/sa1510.asm index a399e63..8364bbc 100644 --- a/software/asm/sa1510.asm +++ b/software/asm/sa1510.asm @@ -73,7 +73,7 @@ SS1: LD (SWRK),A JR FD2 ST1: CALL NL - LD A,03EH + LD A,'*' CALL PRNT LD DE,BUFER CALL GETL diff --git a/software/roms/MROM_256.bin b/software/roms/MROM_256.bin index 1bbffa391aae2d9a48f818fae92ad7827f6bb39f..2d755c55986f9e0f8a06b2fd99f205498e20ee3c 100644 GIT binary patch delta 3006 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 Z|19jMaM*BU;IQLx;BZF6epmRZe*%JROwj-U delta 3161 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 aof|LXyH@Nt;80{Wl?iHRnV|XPj{gFO)>0(^ delta 17197 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 diff --git a/software/roms/cbios.rom b/software/roms/cbios.rom index b96c39048fd1f199f085b9b8543fbdd2ec2be9be..7467f315a34d5f6d68999b40fd496dc2f4f42379 100644 GIT binary patch literal 4096 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 literal 4096 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 diff --git a/software/roms/cbios_bank1.rom b/software/roms/cbios_bank1.rom index 5abd0c61abf87e8e6597a8d827c4561cb4810cce..16b88564f81186878c4785af1a4f9b445d79c0ad 100644 GIT binary patch delta 175 zcmV;g08syc5P%RU0IxFq?=t=G0K*&T!y)Ly1nI-z=)?2q!xHH_5a7cA=*89LJ_0gm zktH808|fefAv5U{&3EWH*UiJ|I2Fy{=s_6FJ_9mnyb~D2J^>i^&BN&R&GV6NAuwpX zJtzYy82TbOzeX1qtQ!~K!J9|38R d-zyGgyutCw)e*4`%^~Q~$+MRMX$F(v0enJ6Q%wK> delta 304 zcmZn=Xb@0kSa0;_J;PxJhQo3%4l}+yeD}rS4=)b$zdS7Q@^I42qgS8WF&X(z)R5Pj z{!)QOas5l-vn4MquAe>d!b0@y-4~7$XY81beD?@T9I<1R_y!dIdiKM_LPcKRJ+>Om zni9X1{PrmNPMj~UbNpp%zMqx%9{2T!f4xv-cwqKHx$aq`0+abkD~<>J7QaBG!7qVN z>rZO=O?;$X@4e^X$CFnDH}am9dvWpPXP`rjJoeaqF!J1^cwoi)w?R*pUn{adFe@?J zpj}*~ZN_EBpsZ}xpzT+;OW}9rZiVmK3=9lrJZ9C(7vVw=FCP4T@+nAHgZAgRu;102 yH2Bs7O?w+;A@JJDW6#5rf(KRr>356|Px5_MWP4DjA77^*{##h$^=4_tOf~?w4v@zH diff --git a/software/roms/cbios_bank2.rom b/software/roms/cbios_bank2.rom index 4a15fd6d43c2cd9d2f7eb93c47c8499fd143b72f..12a4ec29df0f3a23adec5c3cf7adc35d42d26e65 100644 GIT binary patch literal 2048 zcmcgsjaL*^6rb6ZT`&!h%vmVgWzi-~qM>LTXe9JRX0~J+6`^HiUlx`XZULgDsC{Wk zA7*J~MTRZ*;q)<0EbAgOyCbX}tn3_ft>x@2JG%m6AL^s~cEhMYpxtxsy!(5DZ zzhqe?)bp3r&`In$M<_iz@rWA=Rw}T?!kX%OtM}YJ-pQ$bxkZB16ST}0oLY6oLhW9s zH`AMCA-YZ3*9!r^6fdo^ExZhPb;#ZxQlVKkOJ5;rEhO9_72sNE8l3|jqZVL~rwgV~ z{Rw)${$i>Z+FFZDw!>2?;J9-`c#Eg?(8rzB6%GQJP4SxP-M!4vEOXMPn)klJqAz#a1kToOM`n^#8-<%YV|!)i#? zho^@#!?y79a6$aPRGk>YE8mfU!Tnt)e*688KTn=IjfMlRcK2RS$I)MY4fgg$W5Bl4)jL9iu&l)%W?9{aM z2^r^1Ja-ah%A9xWe6e`ns?|?Fvu17My7e2LeeU@eUfj6prI$B1z4Gd7uWu0=O5STL z`R2{tpMUw;Tc7OtO5FA-|Mj=;uG#V4`cufE*0{%z;8YhQWi zqn#UGXx;Vv2hAV8_}s@WZ)|^E_@beRT~_?aZCA~_dB)`H&a2{XzhKeAE1p_e_+)*- zoa@hDTDjut%P)H@-}d;GbE_X_YMyv>d0FjEm)`Kuwb#_m%DTl-ddF!mF&U;~$j%-R zdGpy0l-2Hva3pg;bazJBy&^9w5eF)gk3~?vEeWxQ3>umtcScajq2>roOm4f#wm_t= zaM;SB8Wv`6<=)Palkte0#P~(a$D#vWE$3;dRGzJ&netK%&63w@=vw)04K2auI{7CJ zJtPlA(H!}nC|WMBi=oHmO)=%W5JYFUi%w>*$h3%%%?Y|FBO+)$9=`b84#TE{*(D+x ztE$B24LKBXH%GWifZ;h>Vmw<5ezy^Hoa11A4L1z=0jzJVXlz`)3J~ld)M=FzS}Q}t zW}ShAq5Z<9-w0QbV2TAu%)+Ua?NEl%lm=uvv_#{m1ZC7#k^_li9~V{HqRNj^h;cHV@e<+DmQQFwj@k@Fo;H@j_?gm9_XW7}rs}DL2@kF7Oc*%9 z+W!zS2_RP@F&0b6O;`mOgbgXTB&0xe9u@=X$Z{gV2MkVvfd)M2AAQhV12Mu*Q1REH zcGg_@Nb$5GA=96NzYf9qRT&;tD*Uvyp-&;S4c literal 2048 zcmcgt`+pSG6`$FVT@r;P1a&qM+|A}O@(7#JY_}sF5kl7&-DoLMDX49Q)<>ZNE`ekl zK#XDxQHc+X6%_+w%OpG;ALEo{x{#gSDXcWKAAZmzcKPhg?(7muEKqXOb9YTe|A6if zXXbqG_niB^=iD<(@XX~DArpj5YO+<6i#7SAE+5n7YE9l2llR5sLoxYWOrE95t7CFu zLfxR{eQs!#L@A=^38nH$t)xsOn=A#y3484cqbqK%RX@|oBBG!|w9}%|oJvJhE5?PsQ@QT*wo5_Ih9=QND3|^s z;Pt5C*!rGegIcXMQl6E^b}rcZ9C}Ff=_cKBG(w_DAiNB5$m! zTW+l6Lq(xtJ8{BVQY8*Xg6YaZ0agRA5qW!uH0Xuf9(R!r7aW+b)Rly9h_9W4Ui*{spQHR`JPu z3Tg>^*Kuq1IbJstIiU_LgQrZ~n9q@aIT(oA^Wt!ua{SbkK(rs6#mh*7G`eXscNUrx z6lNOtHc}%CV~X|n^=YU!gf;RqzZCocq^bkAMB|3l}f_=kh2T z8|>+o{}MPl^wmG3XX44!dE((;{PI_itXTQ$-#qr{oEep~ZT1pJX<2y%eWQ2QJu~a> z_!()+nviX_Ow7r>>gq|8^YRO(6i&V7+UqE5(Y^OCmgXMYw0Xo(pv|GPyhVx*4^)Q?r46tWAkfI zztpzn#Z5b3eYyR)xB2IvdF7oC_HAqJ`qK-0_P)QpW&a=F*!8;jQPVB#>bbvr;71FV z+&cZv>z8pqzv02c1nWMm#9a#DDebxy0Z~` znl#X@ikv|6PIo3|?3UP82!r``aLC8*mjs^KFEM*0F322`>}^s#x=p#!K=YLv11(Ti z8mLCuWT4xX4g;;g=1%35fu2x|B)Us^D2di6TT*D9(vpJElHC%|bV^LC1gUrsL|G6) zXWTL)1Q>pV`W!*kVR+D(&15EFYCm#kwZYvZm~s&kv#{&Z-p<5#C{4(E`eB2kGL$Qp z%ETsA>o##-24?U(L1o|O9bZCY;gbeJ*c5%9a&3c_<+Gq zFv);NBUf&;$V`m0GgSOpXsB5PUnzk$XJkfl@Mj^qcv)e9_ZeM1g9XGyD|qZ)30zzj zkbuj0Lkda=h74DykSSb~LKDJ|q)>KvNeY> delta 12 TcmZorXi%6ilhJPDtTcWA9OMLP diff --git a/software/roms/monitor_SA1510.rom b/software/roms/monitor_SA1510.rom index 0dc12970530a27eefeb7068ac5aa526294d97c7f..54e274c6664929e69a043448d68c18ae6c812bfb 100644 GIT binary patch delta 12 TcmZorXi%6ilTmBqtTcWA9DoE> delta 12 TcmZorXi%6ilhJPDtTcWA9OMLP diff --git a/software/roms/rfs.rom b/software/roms/rfs.rom index 599982de3896669a9e41d4cfcd9091654246c34e..095432e872b19e1996acd0f2df9a9df476ae4e4f 100644 GIT binary patch delta 793 zcmb7CUq}=|9G>;=_WlvhX4>9~wu^Mw9i^>c7P%^kMBoW&6hyrRQV;baWq_|4n zgTj)6Y*@2nt=EC`oY&&6eYU?&3^8tBl}f`^%Ds*Eb1=%vog4R6y7^XN z-OB8wQKl?#=^xnY-z;oru!}*MK`T|-;3Uh;WmI!{P5nfd_1kchiHLk~t5y9BrdVc{ zd(W>cUbw=>6qf06$`9czlLxJj81R7U9!|XtsdS$jdV1r%1}|k| zf!y^}2yf#rJvBny^xEwIktWWkiHq&$vv4YY4BvC^K>ywga{jb@V(S^k6TAQko780? zo~1(>lrECETwi!2&((7hL?qoI>+(){;Fn5@SwI&g6oGb{XeG_Q>m_}(`}s&8T^Z%I v=B<&R(hD-{3l;<@iTbvbK!B>wnOdaUXTm+)xZ5%hkUjow!khR}|A6Bs?vgiR delta 725 zcmZuvPe>F|9Db9#vwz0$O{UGx;x@xV$Zoc}!6Jc^ScrPi%1(h0)gdG*im1h~g^UhC zu)M;Pks(A~3Z@Pw1iBfGyH6047IMHnDD&RBg=~5#oO+`{LBSk8e&5G8AK&*kWQW7bSGfz z2f@bB{Njr^fGPmdo3Cev>F0dR)BMfs2I>yT17EgXapOLceQ#)~`9&V$NeX{xT%3c3 z7R3GNxKF;-Pgd@Haec@PQ)U#K&*STaxflz}_zewtww>#J>{QjfUYIlLlvO7E58L>M z#WKZVijPp-MwA}hOU-3dwac4oo|Lr*c!=`AB&8?vlwCFv^+~b&6z8Z}U_V*;sR;NA zovESbphtR!&rxaA$!_2gs`=wQH1MW{n*8mqVT$|EfIlccB!-sX4sNjaG6nS1ALgd@ ztp6a#w$*K+!nHLQ49Wk_h>1b!br>m@gDLA8YJ{vC5|~j<3y0c9VF9+dIEQAlO#DYl_cxatUWgC z)+fF~tAR*Ekf@%eM62pv>KLV4_@f2W_3AGuld EUqcN}?f?J)