;------------------------------------------------------ ; ; Monitor multi-firmware per start-up ; computer Z80 Nuova Elettronica ; ; Copyright Roberto Bazzano 2006 - 2018 ; ;------------------------------------------------------ ; ; BANCHI 2 e 3 - Allocati da F800h a FFFFh ; ; NOTA: durante tutto il codice il registro B' contiene 00h se c'è la scheda video vecchia. Se non c'è contiene FFh ; Il registro C' contiene il numero della pagina di menù visualizzata a video ; ;------------------------------------------------------ ; .org 00000h ; solo per debug con simulatore ;------------------------------------------------------ banco .equ 05fh ; porta di I/O per la selezione del banco di memoria della EPROM .org 0f800h jp start start: di ; disabilita gli interrupt ld a,0c9h ; inizializza il vettore per l'NMI ld (0066h),a xor a ; spegne il motore del floppy out (0d6h),a ld hl,0ebffh ; cerca dove posizionare lo SP prima di EC00 sp1: ld a,(hl) cpl ld (hl),a cp (hl) jr z,sp3 sp2: dec hl jr sp1 sp3: cpl ld (hl),a cp (hl) jr nz,sp2 ld sp,hl ld a,01h ; seleziona il banco della 2390 out (banco),a call 0f0a5h ; inizializza i registri del SY6545 ed i PIO call checv ; imposta il registro B' che indica se esiste la scheda video vecchia tast0: call initn ; pulisce il video nuovo call initv ; pulisce il video vecchio ld hl,out0 ; visualizza il messaggio "SELECT" sui display call msg call vmenu1 ; visualizza il menù tast0a: call input ; input da tastiere cp 10h ; se è stato premuto CR salta subito al controllo del tasto jr z,tast1 cp 0Fh ; controlla se è stato digitato un numero tra 1 e E jr nc,tast0a cp 01h jr c,tast0a ld hl,curs ; calcola la posizione sul video vecchio per visualizzare il numero digitato call vloc ; calcola in DE l'indirizzo del video in base alla riga/colonna nella locazione puntata da HL e HL+1 push af ; visualizza il numero digitato cp 0Ah jr nc,tast0b ; se A >= 0ah addiziona 037h, altrimenti 030h add a,030h jr tast0c tast0b: add a,037h tast0c: ld (de),a ; sul video vecchio call writen ; e sul video nuovo - Il cursore è già posizionato pop af tast1: cp 01h ; se 1 lancia il boot del basic da 5.5 K jr nz,tast2 ld hl,out10 ; visualizza il messaggio sui display call msg call initn ; pulisce il video nuovo call curoff ; spegne il cursore sul video nuovo ld a,19h ; seleziona il banco del basic da 5.5 K out (banco),a jp 0f000h tast2: cp 02h ; se 2 lancia il boot vecchio jr nz,tast3 ld hl,out1 ; visualizza il messaggio sui display call msg call initn ; pulisce il video nuovo call curoff ; spegne il cursore sul video nuovo ld a,00h ; seleziona il banco della 1390 out (banco),a jp 0f000h tast3: cp 03h ; se 3 lancia il boot grafic jr nz,tast4 ld hl,out2 ; visualizza il messaggio sui display call msg call initv ; pulisce il video vecchio ld a,01h ; seleziona il banco della 2390 out (banco),a jp 0f000h tast4: cp 04h ; se 4 lancia il boot del S.O.N.E. jr nz,tast5 ld hl,out11 ; visualizza il messaggio sui display call msg call initv ; pulisce il video vecchio ld a,1Ah ; seleziona il banco del s.o.n.e. out (banco),a jp 0f000h tast5: cp 05h ; se 5 lancia il basic in rom rilocato in ram jr nz,tast6 ld hl,out3 ; visualizza il messaggio sui display call msg call initn ; pulisce il video nuovo call curoff ; spegne il cursore sul video nuovo ld a,08h ; seleziona il primo banco del basic in rom ld de,00000h tast5a: out (banco),a ; sposta gli 8 banchi da 2K in ram ld bc,0800h ld hl,0f000h ldir inc a inc a cp 18h jr nz,tast5a jp 0000h ; salta al basic tast6: cp 06h ; se 6 lancia il monitor esadecimale originale non rilocato jr nz,tast7 ; con il firmware non rilocato per il programmatore di eprom call initv ; pulisce il video vecchio call initn ; pulisce il video nuovo call curoff ; spegne il cursore sul video nuovo ld a,04h ; seleziona il banco del monitor esadecimale originale out (banco),a ld hl,0f000h ; sposta i due monitor in ram ld de,08000h ld bc,0800h ldir jp 8000h tast7: cp 07h ; se 7 lancia il monitor esadecimale non rilocato con lo SP rilocato prima di EC00 jr nz,tast8 ; con il firmware non rilocato per il programmatore di eprom call initv ; pulisce il video vecchio call initn ; pulisce il video nuovo call curoff ; spegne il cursore sul video nuovo ld a,20h ; seleziona il banco del monitor esadecimale con SP rilocato out (banco),a ld hl,0f000h ; sposta i due monitor in ram ld de,08000h ld bc,0800h ldir jp 8000h tast8: cp 08h ; se 8 lancia il monitor esadecimale rilocato con lo SP rilocato prima di EC00 jr nz,tast9 ; per la tastiera alfanumerica con il firmware rilocato per il programmatore di eprom ld hl,out4 ; visualizza il messaggio sui display call msg call initv ; pulisce il video vecchio call initn ; pulisce il video nuovo call curoff ; spegne il cursore sul video nuovo ld a,1Ch ; seleziona il banco del monitor esadecimale rilocato per la tastiera alfanumerica out (banco),a jp 0f000h tast9: cp 09h ; se 9 lancia il monitor esadecimale rilocato con lo SP rilocato prima di EC00 jr nz,tastA ; per la tastiera esadecimale con il firmware rilocato per il programmatore di eprom call initv ; pulisce il video vecchio call initn ; pulisce il video nuovo call curoff ; spegne il cursore sul video nuovo ld a,1Eh ; seleziona il banco del monitor esadecimale rilocato per la tastiera esadecimale out (banco),a jp 0f000h tastA: cp 0Ah ; se A lancia direttamente il bootstrap multiplo jr nz,tastB ld hl,out7 ; visualizza il messaggio sui display call msg call initv ; pulisce il video vecchio call initn ; pulisce il video nuovo call curoff ; spegne il cursore sul video nuovo ld a,06h ; seleziona il banco della 2390 modificata per non fare il check sul disco di boot out (banco),a jp 0f17dh ; salta direttamente al BOOT tastB: cp 0Bh ; se B lancia il loader del basic da 5.5 K jr nz,tastC call initn ; pulisce il video nuovo call curoff ; spegne il cursore sul video nuovo ld a,04h ; seleziona il banco del monitor esadecimale originale out (banco),a ld hl,0f000h ; sposta il monitor in ram ld de,08000h ld bc,0400h ldir ld a,18h ; seleziona il banco del loader del basic da 5.5 K out (banco),a ld hl,0f000h ; sposta il loader in ram ld de,00000h ld bc,0400h ldir jp 0069h ; salta al loader tastC: cp 0Ch ; se C lancia la prova tastiera jr nz,tastD ld hl,out8 ; visualizza il messaggio sui display call msg call initn ; pulisce il video nuovo call curoff ; spegne il cursore sul video nuovo jp key tastD: cp 0Dh ; se D lancia il basic in rom (salta a 0000h) jr nz,tastE ld hl,out9 ; visualizza il messaggio sui display call msg call initv ; pulisce il video vecchio call initn ; pulisce il video nuovo call curoff ; spegne il cursore sul video nuovo jp 0000h tastE: cp 0Eh ; se E salta a 1000h senza modificare i display ed i monitor jr nz,tastF jp 01000h tastF: cp 0Fh ; se F sposta le routines di stampa per monitor esadecimale a 0070 jr nz,tast10 ld a,07h ; seleziona il banco delle routines di stampa out (banco),a ld hl,0f000h ; sposta le routines in ram ld de,00070h ld bc,0400h ldir jp tast0 tast10: cp 10h ; se RETURN cambia pagina di menù jr nz,tastFF call initv ; pulisce il video vecchio call initn ; pulisce il video nuovo exx ; carica il numero di pagina visualizzata in A ld a,c exx cp 01h ; confronta il valore di A con 1 call z,vmenu2 ; visualizza la pagina di menù appropriata call nz,vmenu1 jp tast0a tastFF: jp tast0a ;------------------------------------------------------ ; controlla se la scheda video vecchia è presente. Per farlo verifica il cambiamento della ritraccia video ; se la scheda video vecchia esiste ritorna 00h in B' ; se la scheda video vecchia non esiste ritorna FFh in B' checv: push af push hl exx ; mette 00h in B' ld b,00h exx ld hl,00000h ; inizializza il contatore checv1: inc hl ; attende al massimo fino a che HL non diventa 1000h ld a,h ; Infatti la ritraccia a "1" come tempo resta al massimo con HL a 0111h cp 10h ; Se impiega più tempo significa che la scheda LX.388 non è presente jr nz,checv2 exx ; se la LX.388 non è presente carica FF in B' ed esce ld b,0ffh exx jr checv3 checv2: in a,(0ebh) ; attende la ritraccia video bit 7,a jr nz,checv1 checv3: pop hl pop af ret ;------------------------------------------------------ ; controlla se è stata rilevata la scheda video vecchia ; ritorna Z a 0 se non c'è, Z a 1 se c'è chect: exx ; recupera il valore dal registro B' ld a,b exx or a ; imposta il flag Z ret ;------------------------------------------------------ ; pulizia del video vecchio initv: push hl push de push bc ld hl,0ec00h ld de,0ec01h ld (hl),20h ld bc,01ffh call waitv ; attende la ritraccia ldir pop bc pop de pop hl ret ;------------------------------------------------------ ; attende la ritraccia del video vecchio waitv: push af call chect ; esce se non esiste la scheda video vecchia jr nz,waitv2 waitv1: in a,(0ebh) ; attende la ritraccia video bit 7,a jr nz,waitv1 waitv2: pop af ret ;------------------------------------------------------ ; pulizia del video nuovo initn: push af ld hl,0h initn1: call lf06e ; carica in R18 e R19 l'indirizzo (HL) del carattere da visualizzare ld a,20h ; imposta il carattere a "blank" call writen ; scrive il carattere inc hl ld a,l cp 81h jr nz,initn1 ld a,h cp 07h jr nz,initn1 pop af ret ;------------------------------------------------------ ; spegne il cursore sul video nuovo curoff: push af ld a,0ah ; seleziona il registro R10 out (8ch),a ld a,020h ; scrive il valore 32 (20h) per spegnere il cursore out (8dh),a pop af ret ;------------------------------------------------------ ; Subroutine per la visualizzazione del menù sui video ; vmenu1: ld hl,menu1 ; visualizza la 1° pagina del menu exx ; carica in C' il numero della pagina visualizzata ld c,01h exx jr vis vmenu2: ld hl,menu2 ; visualizza la 2° pagina del menu exx ; carica in C' il numero della pagina visualizzata ld c,02h exx vis: push af vis1: push hl call nloc ; calcola in DE l'indirizzo del video nuovo in base alla riga/colonna nella locazione puntata da HL e HL+1 push de pop hl call lf06e ; carica in R18 e R19 l'indirizzo (HL) del carattere da visualizzare pop hl call vloc ; calcola in DE l'indirizzo del video vecchio in base alla riga/colonna nella locazione puntata da HL e HL+1 vis2: ld a,(hl) ; recupera il carattere da scrivere call waitv ; attende la ritraccia del video vecchio ld (de),a ; visualizza il carattere sul video vecchio inc de call writen ; attende la ritraccia e visualizza il carattere sul video nuovo inc hl xor a ; controlla se il prossimo carattere è 00h cp (hl) jr nz,vis2 inc hl cpl ; controlla se il prossimo carattere è 0ffh cp (hl) ; se no, ricarica la successiva prima posizione e looppa jr nz,vis1 ld hl,curs ; calcola in DE l'indirizzo del cursore in base alla riga/colonna nella locazione puntata da HL e HL+1 call nloc push de pop hl call lf060 ; carica in R14, R15, R18 e R19 l'indirizzo (HL) del cursore e del carattere da visualizzare pop af ret ;------------------------------------------------------ ; Subroutines identiche a quelle della eprom 2390 ; lf060: ld a,0eh ; carica da HL l'indirizzo del cursore out (8ch),a ld a,h out (8dh),a ld a,0fh out (8ch),a ld a,l out (8dh),a lf06e: ld a,12h ; carica da HL l'indirizzo del carattere da visualizzare in R18 e R19 out (8ch),a ld a,h out (8dh),a ld a,13h out (8ch),a ld a,l out (8dh),a ; jr lf086 ; (8) ;lf07e: ld a,0ah ; out (8ch),a ; ld a,20h ; out (8dh),a lf086: ld a,1fh ; accesso a R31 del SY6545 per fare l'update out (8ch),a ret ;------------------------------------------------------ ; scrive il carattere presente in A sul video nuovo writen: call waitn ; attende la ritraccia out (80h),a ; scrive il carattere push af ld a,1fh ; imposta gli attributi del carattere out (8eh),a ld a,31 ; update out (8ch),a xor a out (8dh),a pop af ret ;------------------------------------------------------ ; attende la ritraccia del video nuovo waitn: push af waitn1: in a,(8ch) bit 7,a jr z,waitn1 pop af ret ;------------------------------------------------------ ; Calcola la locazione del video in base alla riga/colonna nella locazione puntata da HL e HL+1 ; Chiamare "vloc" per il video vecchio, "nloc" per il video nuovo ; Ritorna DE. HL punterà al primo carattere da visualizzare vloc: push af ld b,00h ld c,(hl) push hl ld hl,0ec00h ld de,00020h jr loc1 nloc: push af ld b,00h ld c,(hl) push hl ld hl,00158h ; offset per centrare la videata sul video nuovo da 80x24 ld de,00050h loc1: ld a,c cp 00h jr z,loc2 add hl,de dec c jr loc1 loc2: ex de,hl pop hl inc hl ld c,(hl) ex de,hl add hl,bc ex de,hl inc hl pop af ret ;------------------------------------------------------ ; Visualizza il messaggio puntato da HL sui display della tastiera esadecimale msg: push af push bc ld bc,08F7h msg1: ld a,(hl) out (c),a inc hl dec c dec b xor a cp b jr nz,msg1 pop bc pop af ret ;------------------------------------------------------ ; ROUTINE PER LA PROVA TASTIERA key: call initv ld bc,0020h iniz: ld hl,0ec00h in a,(0eah) ; input da tastiera vecchia call keyvis in a,(085h) ; input da tastiera nuova call keyvis in a,(085h) ; input da tastiera nuova complementato cpl call keyvis jr iniz keyvis: call key1 ; visualizza il dato come arriva da tastiera add hl,bc ; si posiziona sulla riga successiva and 7fh ; visualizza il dato con lo strobe a 0 call key1 add hl,bc ; si posiziona due righe dopo add hl,bc ret key1: push hl push af push af loop: pop af rlca jr c,uno call waitv ld (hl),'0' jr cont uno: call waitv ld (hl),'1' cont: push af inc hl ld a,l and 0fh cp 08h jr nz,loop pop af call sep ; separatore pop af ; visualizza il byte push af rra rra rra rra and 0fh call lett ; somma l'offset per l'ASCII del numero o della lettera call waitv ld (hl),a inc hl pop af push af and 0fh call lett call waitv ld (hl),a call sep ; separatore pop af ; visualizza il carattere ASCII call waitv ld (hl),a pop hl ret sep: inc hl ; separatore inc hl call waitv ld (hl),'-' inc hl inc hl ret lett: cp 0Ah jr c,lett1 ; salta se minore add a,55 ret lett1: add a,'0' ret ;------------------------------------------------------ menu1: .byte 000h, 006h, "Z80 NUOVA ELETTRONICA", 00h .byte 001h, 00ch, "BOOTSTRAP", 00h .byte 001h, 01dh, "1/2", 00h .byte 003h, 000h, "1 > BOOT BASIC 5.5K SU " .byte "FLOPPY", 00h .byte 004h, 000h, "2 > BOOT NE-DOS 1.5", 00h .byte 005h, 000h, "3 > BOOT NE-DOS GRAFIC 1.0", 00h .byte 006h, 000h, "4 > BOOT S.O.N.E.", 00h .byte 007h, 000h, "5 > BASIC 16K IN RAM", 00h .byte 008h, 000h, "6 > MONITOR ORIGINALE " .byte "NO INTERR.", 00h .byte 009h, 000h, "7 > MONITOR SP RILOC. " .byte "NO INTERR.", 00h .byte 00Ah, 000h, "8 > MONITOR A VIDEO " .byte "(RILOCATO)", 00h .byte 00Bh, 000h, "CR> CAMBIA PAGINA", 00h .byte 00Dh, 00Fh, "> <", 00h .byte 00Fh, 000h, "(C) ROBERTO BAZZANO " .byte "2000-2018", 00h .byte 0ffh menu2: .byte 000h, 006h, "Z80 NUOVA ELETTRONICA", 00h .byte 001h, 00ch, "BOOTSTRAP", 00h .byte 001h, 01dh, "2/2", 00h .byte 003h, 000h, "9 > MONITOR ORIGINALE " .byte "(RILOCATO)", 00h .byte 004h, 000h, "A > BOOT IMMEDIATO NE-DOS", 00h .byte 005h, 000h, "B > LOADER BASIC 5.5K SU " .byte "CASS.", 00h .byte 006h, 000h, "C > PROVA TASTIERA", 00h .byte 007h, 000h, "D > RESTART A 0000H", 00h .byte 008h, 000h, "E > RESTART A 1000H", 00h .byte 009h, 000h, "F > LOAD ROUTINES STAMPA " .byte "A 0070H", 00h .byte 00Bh, 000h, "CR> CAMBIA PAGINA", 00h .byte 00Dh, 00Fh, "> <", 00h .byte 00Fh, 000h, "(C) ROBERTO BAZZANO " .byte "2000-2018", 00h .byte 0ffh curs: .byte 00Dh, 010h ; riga/colonna in cui posizionare il cursore ; Tabelle per visualizzazione su display tastiera esadecimale ; ; ; Valori per l'accensione dei segmenti del display: ; ; 1 ; - bit a 1 spegne il segmento ; 32 | | 2 ; - 64 F0 = display a destra ; 16 | | 4 !! ; - F7 = display a sinistra ; 8 ; 128 = punto decimale out0: .byte 0ffh, 092h, 086h, 0C7h, 086h, 0C6h, 087h, 0ffh ; select out1: .byte 0ABh, 086h, 0A1h, 0C0h, 092h, 0FFh, 079h, 092h ; nedos 1.5 out2: .byte 0ABh, 086h, 0A1h, 0C0h, 092h, 0FFh, 042h, 0F9h ; nedos G.1 out3: .byte 083h, 088h, 092h, 0F9h, 0C6h, 0FFh, 0F9h, 082h ; basic 16 out4: .byte 0C8h, 0C0h, 0ABh, 0F9h, 087h, 0C0h, 0AFh, 0FFh ; monitor out7: .byte 0FFh, 0FFh, 083h, 0C0h, 0C0h, 087h, 0FFh, 0FFh ; boot out8: .byte 0FFh, 0FFh, 087h, 086h, 092h, 087h, 0FFh, 0FFh ; test out9: .byte 0FFh, 0FFh, 0C1h, 092h, 086h, 0AFh, 0FFh, 0FFh ; user out10: .byte 083h, 088h, 092h, 0F9h, 0C6h, 0FFh, 012h, 092h ; basic 5.5 out11: .byte 0FFh, 0FFh, 092h, 0C0h, 0ABh, 086h, 0FFh, 0FFh ; sone ;------------------------------------------------------ ; ; Nuova routine di input tastiera per il monitor esadecimale ; Sostituisce la 80AA e accetta l'input dalla tastiera alfanumerica vecchia o nuova ; o dalla tastiera esadecimale convertendo il valore ricevuto in modo da essere ; compatibile con la 80AA ; ; Dati ricevuti dalla tastiera: ; Numeri da 0 a 9: da 30h a 39h ; Lettere da A ad F: da 61h a 66h ; Shift+numero da 1 a 9: da 21h a 29h ; Shift+lettere da A ad F: da 41h a 46h ; Return: 0dh .org 0FE80h input: push bc push de push hl t1: call chect ; Se non c'è la scheda video vecchia salta il controllo e passa subito alla tastiera nuova jr nz,t2 t1x: in a,(0eah) ; tastiera vecchia bit 7,a jr nz,t1x t2: in a,(085h) ; tastiera nuova bit 7,a jr z,t2 t2es1: ld hl,0456h ; tastiera esadecimale t2es2: in a,(0f0h) bit 7,a jr z,t2es1 t2es3: dec hl ld a,h or l jr nz,t2es2 ; Input da tastiere t2a: call chect ; Se non c'è la scheda video vecchia salta il controllo e passa subito alla tastiera nuova jr nz,t2ax in a,(0eah) ; tastiera vecchia bit 7,a jr nz,t2b t2ax: in a,(085h) ; tastiera nuova cpl bit 7,a jr nz,t2b in a,(0f0h) ; tastiera esadecimale bit 7,a jr z,tes4 jr t2a ; se non ho premuto nulla sulle tre tastiere allora looppa ; Input da tastiera esadecimale tes1: ld hl,0456h tes2: in a,(0f0h) bit 7,a jr z,tes1 tes3: dec hl ld a,h or l jr nz,tes2 tes4: in a,(0f0h) bit 7,a jr nz,tes4 ld b,a ld hl,0005h call rit tes5: in a,(0f0h) ld c,a and 7fh cp b jr nz,tes5 bit 7,c jr nz,tes1 tes6: jr texit ; Conversione dato per tastiere alfanumeriche t2b: and 7fh cp 0dh ; controlla se è stato premuto Return jr nz,t3 ld a,10h ; se si carica il valore di Control+0 jr texit t3: cp 03ah ; controlla se è stato premuto un numero jr nc,t4 cp 030h jr c,t4 sub 030h ; se si sottrae 30h ed esce jr texit t4: cp 67h ; controlla se è stata premuta una lettera tra A ed F jr nc,t5 cp 61h jr c,t5 sub 57h ; se si sottrae 57h ed esce jr texit t5: cp 2ah ; controlla se è stato premuto shift+numero (escluso 0) jr nc,t6 cp 21h jr c,t6 sub 10h ; se si sottrae 10h ed esce jr texit t6: cp 47h ; controlla se è stato premuto shift+lettera da A ad F jr nc,t7 cp 41h jr c,t7 sub 27h ; se si sottrae 27h ed esce jr texit t7: jp t1 texit: pop hl pop de pop bc ret ; Genera un ritardo rit: push hl push af rit1: call rit2 dec hl ld a,h or l jr nz,rit1 pop af pop hl ret rit2: push af push de ld de,0047h rit3: dec de ld a,d or e jr nz,rit3 pop de pop af ret ;------------------------------------------------------ ; ; Nuova routine di output su video per monitor esadecimale ; Sostituisce la 80EC e accetta l'input dalle locazioni da 0000h a 0007h ; convertendo il valore letto in modo da essere compatibile con la 80EC ; .org 0FF50h push af push bc push de push hl call chect ; esce se non esiste la scheda video vecchia jr nz,m3 m1: ld de,0007h ld bc,0ec00h m2: ld hl,tabout push bc ld a,(de) ld b,0h ld c,a add hl,bc pop bc ld a,(hl) call waitv ; attende la ritraccia video ld (bc),a dec e inc c ld a,e cp 0ffh jr nz,m2 m3: pop hl pop de pop bc pop af ret tabout: .byte "0123456789ABCDEF" .byte "-", " ", "M", "R", "#", "H", "L", "P", "C", "G" .byte "NQRTUVJY S" ;------------------------------------------------------ .org 10000h .end