Elenco blog personale

venerdì 18 maggio 2018

File di configurazione SETKEYS per alcuni editor a tutto schermo (Amstrad CPC 6128 - CP/M Plus)



File di configurazione per l'editor a tutto schermo ED80.COM dell'Hisoft Devpac80

ED80 è l'editor a tutto schermo del pacchetto Hisoft Devpac80 (versione 2) e può essere utilizzato anche indipendentemente da quest'ultimo. Infatti basta copiare il file ED80.COM in un altro disco ed utilizzarlo come editor stand alone.
L'unica cosa da fare è creare un file di configurazione per SETKEYS così da poter utilizzare correttamente la tastiera.
Ecco il contenuto del file che ho creato per questo editor:

 8   "↑S"        Freccia Sinistra => cursore a sinistra
 8 S "↑A"        SHIFT + Freccia Sinistra => parola a sinistra
 8 C "↑'#8F'"    CTRL + Freccia Sinistra => Inizio riga

 1   "↑D"        Freccia Destra => cursore a destra
 1 S "↑F"        SHIFT + Freccia Destra => parola a destra
 1 C "↑'#90'"    CTRL + Freccia Destra => Fine riga

 0   "↑E"        Freccia Su => Cursore in alto
 0 S "↑R"        SHIFT + Freccia Su => Pagina precedente
 0 C "↑'#91'"    CTRL + Freccia Su => Inizio documento

 2   "↑X"        Freccia Giu => cursore in basso
 2 S "↑C"        SHIFT + Freccia Giu => Pagina successiva
 2 C "↑'#92'"    CTRL + Freccia Giu => Fine documento

68   "↑'#8D'"    TAB => tab a destra
68 S "↑'#8E'"    SHIFT + TAB => tab a sinistra

16   "↑G"        CLR => elimina carattere sotto il cursore
16 C "↑'#93'"    CTRL + CLR => elimina caratteri a destra
16 S "↑'#94'"    SHIFT + CLR => elimina caratteri a sinistra

66   "↑'#95'"    ESC => salva ed esce

9    "↑'#96'"    COPY => copia il blocco selezionato
9 S  "↑'#97'"    SHIFT + COPY => muove il blocco selezionato
9 C  "↑'#98'"    CTRL + COPY => elimina il blocco selezionato

E #8D "↑OD"      Token per Tab a destra
E #8E "↑OS"      Token per Tab a sinistra
E #8F "↑QS"      Token per Inizio riga
E #90 "↑QD"      Token per Fine riga
E #91 "↑QR"      Token per Inizio documento
E #92 "↑QC"      Token per Fine documento
E #93 "↑QY"      Token per Elimina car. a destra
E #94 "↑Q↑'127'" Token per Elimina car. a sinistra
E #95 "↑OQ"      Token per Salva ed esce
E #96 "↑KC"      Token per Copia blocco selezionato
E #97 "↑KV"      Token per Muove blocco selezionato
E #98 "↑KY"      Token per Elimina blocco selezionato

E #81 "↑KB"      F1 => Marca inizio del blocco
E #82 "↑KK"      F2 => Marca fine del blocco

Questo è il link github del file:

Occorre notare che il carattere ↑ in questo articolo è l'Unicode U+2191, mentre sul CPC deve essere l'ASCII 0x5E per cui, se si edita il file su Windows dovrà essere sostituito dal simbolo ^ (accento circonflesso). 


File di configurazione per l'editor a tutto schermo Nevada Edit 3

Nevada Edit è un altro editor a tutto schermo. Prima del suo utilizzo va configurato eseguendo il comando NVEDIT.COM e dal menu selezionando il terminale "HEATH Hl9/H89 OR ZENITH Zl9/Z89" (opzione I), che è quello più adatto al CPC.

A questo punto verrà prodotto il file "EDIT.COM" che è l'unico necessario per eseguire l'editor, gli altri posso essere eliminati (NVEDIT.COM, NVEDIT.ERR, NVEDIT.PRN e anche EDTKEY.COM).
Questo è il file di configurazione SETKEYS che utilizzo per questo editor:

 0    "↑E"     Freccia Su => muove il cursore su
 0 C  "↑W"     CTRL + Freccia Su => scorre il documento giu
 0 S  "↑R"     SHIFT + Freccia Su => Pagina precedente

 2    "↑X"     Freccia Giu => muove il cursore giu
 2 C  "↑Z"     CTRL + Freccia Giu => scorre il documento su
 2 S  "↑C"     SHIFT + Freccia Giu => Pagina successiva

 8    "↑S"     Freccia Sinistra => muove il cursore a sinistra

 1    "↑D"     Freccia Destra => muove il cursore a destra

 5    "↑L"     F3 => continua ricerca stringa

68    "↑I"     TAB => tab a destra

16    "↑G"     CLR => rimuove carattere sotto il cursore
16 C  "↑T"     CTRL + CLR => elimina caratteri a destra

66    "↑K"     ESC => esce dall'editor
66 C  "↑'#8D'" CTRL + ESC => Abort (annulla mod. ed esci)

E #8D "↑BAB↑M" Token per Abort

Questo è il link github del file:


Nevada Edit risulta più veloce di ED80, tuttavia lo scrolling è meno intuitivo perché necessita di una combinazione di tasti separata (lo scrolling non avviene spostando il cursore).


File di configurazione per l'editor a tutto schermo VDE 2.66


VDE (Video Display Editor) è un editor full screen ottimizzato per lo Z80 e per questo molto più veloce dei precedenti.
L'installazione va fatta per mezzo del comando VI.COM che modifica l'eseguibile specificato come parametro (per esempio VDE.COM). Tramite VI.COM si può indicare il tipo di terminale e altre opzioni:

VI VDE.COM

Come terminale (opzione T) selezionare "Amstrad / Heath", poi salvare ed uscire. E' consigliabile usare KEYS.CCP all'interno dell'installer VI. Dopo il salvataggio l'unico eseguibile necessario è VDE.COM.

Questo è il file di configurazione SETKEYS che utilizzo per questo editor (molto simile a quello del DevPac80):

 0    "↑E"      Freccia Su => muove il cursore su

 0 S  "↑R"      SHIFT + Freccia Su => Pagina precedente
 0 C  "↑'#8F'"  CTRL + Freccia Su => Inizio documento

 1    "↑D"      Freccia Destra => muove il cursore a destra

 1 C  "↑'#8D'"  CTRL + Freccia Destra => Fine riga
 1 S  "↑F"      SHIFT + Freccia Destra => parola a destra

 2    "↑X"      Freccia Giu => muove il cursore giu
 2 S  "↑C"      SHIFT + Freccia Giu => Pagina successiva
 2 C  "↑'#90'"  CTRL + Freccia Giu => Fine documento

 8    "↑S"      Freccia Sinistra => muove il cursore a sinistra
 8 C  "↑'#8E'"  CTRL + Freccia Sinistra => Inizio riga
 8 S  "↑A"      SHIFT + Freccia Sinistra => parola a sinistra

16    "↑G"      CLR => elimina carattere sotto il cursore
16 C  "↑'#91'"  CTRL + CLR => elimina caratteri a destra


 9    "↑'#92'"  COPY => copia il blocco selezionato
 9 S  "↑'#93'"  SHIFT + COPY => muove il blocco selezionato
 9 C  "↑'#94'"  CTRL + COPY => elimina il blocco selezionato


 5    "↑L"      F3 => continua ricerca

37 C  "↑'ESC'"  CTRL + K => ESC

E #8D "↑Q↑D"    Token per Fine riga
E #8E "↑Q↑S"    Token per Inizio riga
E #8F "↑Q↑R"    Token per Inizio documento
E #90 "↑Q↑C"    Token per Inizio documento 
E #91 "↑Q↑Y"    Token per Elimina caratteri a destra
E #92 "↑'ESC'C" Token per Copia blocco selezionato
E #93 "↑'ESC'V" Token per Muove blocco selezionato
E #94 "↑'ESC'Y" Token per Elimina blocco selezionato

E #81 "'ESC'B" F1 => Marca inizio del blocco
E #82 "'ESC'K" F2 => Marca fine del blocco
E #84 "↑PZ"     F4 => Setta placemarker
E #85 "↑QP"     F5 => Cicla tra i placemarkers

mercoledì 16 maggio 2018

Configurare la tastiera con SETKEYS (Amstrad PCW 8256/8512 e PCW 9512)


Questo post fa riferimento al contenuto dell'articolo su SETKEYS con il CPC 6128 ed evidenzia solo le differenze che ci sono rispetto ai PCW 8256, 8512 e 9512.
Nella serie PCW il CONTROL (CTRL) è sostituito dall'ALT. Oltre a questo è presente un altro tasto di shift (modificatore come CTRL o SHIFT) denominato EXTRA.
Le tastiere della serie 8000 e 9000 hanno gli stessi tasti e gli stessi codici, cambia soltanto la loro disposizione.

Questo è il layout ed i codici per la tastiera del PCW 8256/8512:





Il seguente invece è il layout ed i codici per il PCW 9512:



Gli stati di shift sono S per SHIFT, A per ALT, E per EXTRA e SA per SHIFT + ALT. Ecco alcuni esempi:

10    "↑C"  COPY genera CTRL+C
10 S  "↑C"  SHIFT + COPY genera CTRL+C
10 A  "↑C"  ALT + COPY genera CTRL+C
10 E  "↑C"  EXTRA + COPY genera CTRL+C
10 SA "↑C"  SHIFT + ALT + COPY genera CTRL+C

I tasti funzione vengono vengono assegnati ai token #81 a #88 (F1..F8).




venerdì 11 maggio 2018

Configurare la tastiera con SETKEYS (Amstrad CPC 6128 - CP/M Plus)


In questo articolo descriverò il comando SETKEYS.COM, presente nel primo disco di sistema del CP/M Plus fornito con il CPC 6128.

Il comando serve a riconfigurare la tastiera in base alle informazioni contenute nel file di testo specificato come primo ed unico parametro:

SETKEYS CONF.TXT

SETKEYS è necessario perché il CP/M, ed in particolare il BIOS scritto per il CPC, non assegna una funzione specifica ad alcuni tasti, come le frecce, i tasti funzione, etc, per cui occorre assegnare a questi un codice di controllo (per esempio come CTRL-A che sposta a sinistra il cursore).
SETKEYS legge il file di configurazione ed installa un RSX (estensione residente al BDOS) che intercetta le chiamate di sistema dedicate all'input dalla console.


La sintassi del file di configurazione

Il file di configurazione è diviso in righe ed ogni riga definisce una diversa combinazione di tasti ed il codice che questa genera quando viene eseguita.
Una riga è composta da due parti, la chiave ed il valore associato. La chiave rappresenta il codice (decimale) del tasto premuto e se questo è stato premuto in combinazione con lo SHIFT o il CTRL. Il valore associato viene specificato tra doppi apici e può indicare un singolo carattere, un codice di controllo o un token. Alla fine può essere aggiunto un commento.

Le successive due figure mostrano il layout della tastiera e i codici decimali dei relativi tasti:




Lo SHIFT è specificato con la lettera S, il CTRL con la C, mente la N oppure la mancanza di S o C indica nessuno SHIFT o CTRL premuto.
Per esempio 69 oppure 69 N S C indica il solo tasto A, mentre 69 S, indica SHIFT+A.
Da notare che la N disabilita sia S che C, per cui queste sequenze sono equivalenti: 69, 69 N, 69 N S, 69 N S C.
La presenza di più di uno shift, per esempio SHIFT e CTRL (S C), non indica la necessità di premere entrambi i tasti, ma solamente che la definizione vale sia che venga premuto solo SHIFT sia che venga premuto solo CTRL.

Il valore da generare può essere specificato direttamente (cioè tutti i caratteri ASCII da 0x20 a 0xFF), ad eccezione del ↑ (il tasto del &) che ha un significato speciale e dei doppi apici che vanno preceduti da un ↑ (esempio: ↑").
Per specificare ↑ ne occorrono due (↑↑).
La combinazione di ↑ con un carattere produce CTRL-carattere. Per esempio ↑H produce CTRL-H.
La sequenza ↑'#xx', dove xx è un codice esadecimale, produce il carattere con il codice ASCII specificato. Per esempio ↑'#A' produce un ritorno a capo. Se il # non è presente allora il codice è decimale anziché esadecimale, così ↑'10' equivale a ↑'#A'.
Infine la sequenza ↑'codice', produce il codice ASCII di controllo relativo. Per esempio ↑'ESC' produce ESC. I codici di controllo sono i seguenti:
NUL, SOH, STX, EXT, EOT, ENQ, ACK, BEL, BS, HT, LF, VT, FF, CR, SO, SI, DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, CAN, EM, SUB, ESC, FS, GS, RS, US, SP, DEL, XON e XOFF.
Così ↑'10' equivale a ↑'#A' che equivale a ↑'LF'.

Per esempio si può utilizzare la seguente riga per spostare il cursore a sinistra premendo il tasto freccia relativo:

8 "↑A"

La definizione specifica che premendo il tasto 8 (freccia a sinistra, senza SHIFT e senza CTRL) venga generato un CTRL-A, che nella console del CP/M serve proprio a spostare il cursore a sinistra di una posizione.

E' possibile anche "espandere" i "token" in sequenze di caratteri. La combinazione da specificare nella riga è: E #xx "stringa"
xx è il codice esadecimale del token. Ci sono alcuni token che sono già stati assegnati ai tasti funzione, all'ENTER, al punto e al CTRL+ENTER del tastierino numerico:
0x80 = tasto funzione F0
0x81 = tasto funzione F1
0x82 = tasto funzione F2
0x83 = tasto funzione F3
0x84 = tasto funzione F4
0x85 = tasto funzione F5
0x86 = tasto funzione F6
0x87 = tasto funzione F7
0x88 = tasto funzione F8
0x89 = tasto funzione F9
0x8A = punto nel tastierino numerico
0x8B = ENTER a destra dello spazio
0x8C = CTRL + ENTER a destra dello spazio

I token non assegnati invece vanno da 0x8D a 0x9F.

Per esempio se si vuol visualizzare (espandere) "Ciao Mondo!" ogni volta che si preme il tasto funzione F0 occorre aggiungere questa riga:

E #80 "Ciao Mondo!"

Un token può essere generato da una definizione precedente. Per esempio le seguenti due definizioni visualizzano "Ciao Mondo!" quando si preme CTRL-A. La prima genera il token 0x8D alla pressione di CTRL-A e la seconda genera "Ciao Mondo!" alla presenza del token 0x8D:

69 C "↑'#8D'"         genera 0x8D quando si preme CTRL-A
E #8D "Ciao Mondo!"   espande 0x8D in "Ciao Mondo!"

All'interno della stringa da espandere ci possono essere dei caratteri di controllo che saranno preceduti sempre da ↑. Per esempio la riga seguente espande il tasto funzione F0 con il comando dir ed invio (CTRL-M):

E #80 "dir↑M"


File di configurazione predefinito keys.cpp

Nel primo disco di sistema del CPC 6128 sono presenti due file di configurazione predefiniti. Il primo ha il nome keys.ccp ed è anche quello caricato di default dal profile.sub (profile.eng) perché configura la tastiera nel modo ottimale per la linea di comando (CCP). Questo è il suo contenuto originale:

 0 N S C "↑'#1F'" CCP cursor up
 1 N S   "↑F"     cursor right
 1 C     "↑'#9F'"
 2 N S C "'#1E'" cursor down
 8 N S   "↑A"     cursor left
 8 C     "'#9E'"
 9 N S C "W"     copy
16 N S   "↑G"     clr
16 C     "↑K"
18 C     "↑E"     enter 
66 N S   "↑'27'"  esc
66 C     "↑C"
79 C     "↑X"     del
E #8C    "↑R"     ctrl enter
E #9E    "↑F↑B"
E #9F    "↑F↑B↑B"

Date le definizioni del file la tastiera viene configurata in questo modo:

Freccia Su (0 N S C)
Genera il carattere di controllo 0x1F (US - ASCII Unit Separator). Forse è utilizzato da qualche applicazione o estensione ma in realtà non ha alcun utilizzo nella linea di comando.

Freccia Destra (1 N S )
Genera CTRL-F che muove il cursore di un carattere a destra.

CTRL + Freccia Destra (1 C)
Genera il token 0x9F, che a sua volta genera la sequenza CTRL-F CTRL-B CTRL-B, cioè muovi il cursore a destra, muovi il cursore all'inizio della riga, muovi il cursore alla fine della riga. Come risultato finale muove il cursore alla fine della riga.

Freccia Giu (2 N S C)
Genera il carattere di controllo 0x1E (RS - ASCII Record Separator). Come per Freccia SU, non sembra avere utilità per la linea di comando.

Freccia Sinistra (8 N S)
Genera CTRL-A che muove il cursore di un carattere a sinistra.

CTRL + Freccia Sinistra (8 C)
Genera il token 0x9E, che a sua volta genera la sequenza CTRL-F CTRL-B, cioè muovi il cursore a destra e muovi il cursore all'inizio della riga. Come risultato finale muove il cursore all'inizio della riga.

COPY (9 N S C)
Genera CTRL-W che richiama l'ultimo comando inserito.

CLR (16 N S)
Genera CTRL-G  che elimina il carattere dov'è posizionato il cursore.

CTRL + CLR (16 C)
Genera CTRL-K che elimina tutti i caratteri compresi tra la posizione del cursore e la fine della riga.

CTRL + RETURN (18 C)
Genera CTRL-E che manda a capo il cursore ma non invia il comando al CP/M.

ESC (66 N S)
Genera il codice di controllo 0x1B (ESC - escape).

CTRL + ESC (66 C)
Genera CTRL-C, cioè un warm start.

CTRL + DEL (79 C)
Genera CTRL-X che elimina tutti i caratteri alla sinistra del cursore, mantenendo tutti quelli compresi tra la posizione del cursore e la fine della riga.

CTRL + ENTER (E #8C)
Genera CTRL-R che va a capo e riscrive la riga corrente fino a dov'era il cursore.


File di configurazione predefinito keys.wp

L'altro file di configurazione presente nel primo disco ha il nome keys.wp ed ha una configurazione ottimizzato per programmi di word processing, come WordStar o Tasword. Questo è il suo contenuto originale:

 0 N     "E"     cursor up
 0 S     "R"
 0 C     "'#9E'"
 1 N     "D"     cursor right
 1 S     "F"
 1 C     "'#9C'"
 2 N     "X"     cursor down
 2 S     "C"
 2 C     "'#9F'"
 8 N S   "S"     cursor left
 8 S     "A"
 8 C     "'#9D'"
16 N     "G"     clr
16 S     "T"
16 C     "'#9A'"
66 N S C "'27'"  esc
68 C     "V"     tab
79 C     "'#9B'"
E #9A    "QY"
E #9B    "Q'127'"
E #9C    "QD"
E #9D    "QS"
E #9E    "QE"
E #9F    "QX"

Date le definizioni del file la tastiera viene configurata in questo modo:

Freccia SU (0 N)
Genera CTRL-E che in Wordstar muove il cursore di una riga in alto.

SHIFT + Freccia Su (0 S)
Genera CTRL-R che in Wordstar muove di una pagina verso l'alto.

CTRL + Freccia Su (0 C)
Genera il token 0x9E che a sua volta genera la sequenza CTRL-Q E, che in Wordsar muove il cursore nella posizione più in alto dello schermo.

Freccia Destra (1 N)
Genera CTRL-D che in Wordstar muove il cursore di un carattere a destra.

SHIFT + Freccia Destra (1 S)
Genera CTRL-F che in Wordwar muove il cursore di una parola a destra.

CTRL + Freccia Destra (1 C)
Genera il token 0x9C che a sua volta genera la sequenza CTRL-Q D, che in Wordstar muove il cursore alla fine della riga.

Freccia Giu (2 N)
Genera CTRL-X che in Wordstar muove il cursore di una riga in basso.

SHIFT + Freccia Giu (2 S)
Genera CTRL-C che in Wordstar muove di una pagina verso il basso.

CTRL + Freccia Giu (2 C)
Genera il token 0x9F che a sua volta genera la sequenza CTRL-Q X, che in Wordstar muove il cursore nella posizione più in basso dello schermo.

Freccia Sinistra (8 N S)
Genera CTRL-S che in Wordstar muove il cursore di un carattere a sinistra.

SHIFT + Freccia Sinistra (8 S)
Genera CTRL-A che in Wordstar muove il cursore di una parola a sinistra.

CTRL + Freccia Sinistra (8 C)
Genera il token 0x9D che a sua volta genera la sequenza CTRL-Q S, che in Wordstar muove il cursore all'inizio della riga.

CLR (16 N)
Genera CTRL-G che in Wordstar (ma anche in CCP) elimina il carattere dov'è posizionato il cursore.

SHIFT + CLR (16 S)
Genera CTRL-T che in Wordstar elimina la parola a destra del cursore.

CTRL + CLR (16 C)
Genera il token 0x9A che a sua volta genera la sequenza CTRL-Q Y, che in Wordstar elimina tutti i caratteri alla destra del cursore.

ESC (66 N S C)
Genera il codice di controllo 0x1B (ESC - escape).

CTRL + TAB (68 C)
Genera CTRL-V che in Wordstar abilita o disabilita la modalità "inserimento".

CTRL + DEL (79 C)
Genera il token 0x9B che a sua volta genera la sequenza CTRL-Q DEL, che in Wordstar elimina tutti i caratteri alla sinistra del cursore.


File di configurazione predefinito keys.drl

L'ultimo file delle definizioni presente nei dischi di sistema si trova nel terzo disco ed è denominato keys.drl, proprio perché specifico per l'editor del linguaggio di programmazione DR Logo. Questo è il contenuto originale del file:

 0 N S   "↑P" DR LOGO cursor up
 0 C     "↑U" 
 1 N S   "↑F" cursor right 
 1 C     "↑E" 
 2 N S   "↑N" cursor down
 2 C     "↑V"
 8 N S   "↑B" cursor left
 8 C     "↑A"
 9 N S C "↑C" copy
16 N S C "↑D" clr
66 N S C "↑G" escape
79 N S C "↑H" del

La tastiera viene configurata in questo modo:

Freccia Su (0 N S)
Genera CTRL-P che in DR Logo muove il cursore verso l'alto.

CTRL + Freccia Su (0 C)
Genera CTRL-U che in Dr Logo non ha alcun effetto!

Freccia Destra (1 N S)
Genera CTRL-F che in Dr Logo muove il cursore a destra.

CTRL + Freccia Destra (1 C)
Genera CTRL-E che in Dr Logo muove il cursore alla fine della riga.

Freccia Giu (2 N S)
Genera CTRL-N che in Dr Logo muove il cursore verso il basso.

CTRL + Freccia Giu (2 C)
Genera CTRL-V che in Dr Logo visualizza la pagina successiva.

Freccia Sinistra (8 N S)
Genera CTRL-B che in Dr Logo muove il cursore a sinistra.

CTRL + Freccia Sinistra (8 C)
Genera CTRL-A che in Dr Logo muove il cursore all'inizio della riga.

COPY (9 N S C)
Genera CTRL-C che in Dr Logo esce dall'editor ed applica il suo contenuto.

CLR (16 N S C)
Genera CTRL-D che in Dr Logo cancella il carattere dov'è posizionato il cursore.

ESC (66 N S C)
Genera CTRL-G che in Dr Logo esce dall'editor ma annulla il suo contenuto.

DEL (79 N S C)
Genera CTRL-H che in Dr Logo elimina il carattere alla sinistra del cursore.



martedì 17 aprile 2018

Joyce, l'emulatore Amstrad PCW: installazione e modifiche al codice per il supporto alla tastiera italiana del Macbook Pro




Questo post descrive la procedura per compilare ed installare l'emulatore Joyce di Amstrad PCW su MacOS e una mia patch al codice sorgente per utilizzare la tastiera italiana del Macbook Pro.

La documentazione dell'emulatore spiega come personalizzare il layout della tastiera, tuttavia questo va fatto a CP/M già avviato, tramite il comando PCKEY. Ho trovato questo metodo di difficile applicazione, considerando anche che non riuscivo a digitare caratteri basilari come i due punti!

Ho quindi deciso di procedere con la via "facile", modificando direttamente il codice Joyce che gestisce la corrispondenza tra la tastiera del PC e quella del sistema emulato. Le modifiche, che si applicano alla versione 2.2.12, l'ho scritte senza badare molto alla forma e senza cercare alternative meno invasive ad una mappatura dei tasti hardcoded nel codice stesso, per cui non è certo un bel esempio di programmazione!

Joyce permette l'emulazione dei PCW serie 8000, 9000 e PCW10, mentre Anne (che si compila automaticamente con Joyce) emula il PCW16. La patch è stata testata solo con la serie 8000 (PCW 8256 e 8512).

Per compilare Joyce occorre prima di tutto installare alcune librerie. Per fare questo userò brew, un tool che porta moltissime applicazioni e librerie di Linux su MacOS. Incollare questa riga sul terminale e premere Invio per installare brew:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"


Installare ora tramite  brew le librerie necessarie (PNG, SDL e XML):

brew install libpng
brew install sdl
brew install libxml2


Il sito originale di Joyce è https://www.seasip.info/Unix/Joyce/, mentre la versione patchata è scaricabile dal mio profilo github, in questo modo:

git clone https://github.com/fdivitto/joyce-custom.git


Terminato il download procedere alla compilazione e all'installazione:


cd joyce-custom/
./configure
make
sudo make install


A questo punto Joyce è installato e funzionante e si può rimuovere la cartella con i sorgenti.
Per eseguire Joyce basta scrivere:

xjoyce


Se appare una finestra bianca premere Invio. Verrà creata la cartella ~\Joyce\Boot dove andranno inserite le immagini (dsk) di boot.
Al primo avvio Joyce necessita di una piccola configurazione e ci chiede da dove effettuare il boot che può essere effettuato sia dai drive fisici (fd0, fd1...) che da un'immagine di un floppy (Disc file):



La schermata successiva permette la selezione del file immagine. In questo caso sto selezionato il lato B del disco di sistema, dov'è contenuto il CP/M:



Si seleziona OK e quindi CONTINUE:



Ora Joyce ci chiede di dare un nome all'immagine. Io ho scritto 'cpm_plus':



A questo punto appare la schermata principale, che è quella che verrà presentata ogni volta che si avvia Joyce:



E' stata specificata una sola immagine, quella denominata "cpm_plus" ed identificata con "1". L'"1" è il tasto da premere se si vuole avviare dal disco "cpm_plus".
Prima di iniziare il boot occorre specificare il tipo di hardware da emulare. Come detto questa patch è specifica per PCW 8256/8512, quindi si procederà come segue. Premere F9, quindi F6 e selezionare con i tasti freccia la voce "General":



Premere Invio e selezionare 8256/8512:



Selezionare EXIT e quindi "Save Settings":




Uscire da tutte le schermate con Exit o con il tasto ESC. Adesso premendo "1" si effettuerà il boot ed il sistema sarà pronto per l'utilizzo:





Per concludere ecco una breve spiegazione delle modifiche che ho apportato al codice sorgente di Joyce. La classe C++ che gestisce la tastiera è chiamata JoycePcwKeyboard, ed è dichiarata e definita nei file JoycePcwKeyboard.hxx e JoycePcwKeyboard.cxx, entrambi posizionati nella cartella "bin".
Nella dichiarazione della classe ho aggiunto il campo m_fdvAlt che è un flag attivo per tutto il tempo in cui il tasto ALT è premuto. Ho dichiarato anche due metodi, il primo è fdv_handle() che è il gestore della tastiera alternativo a Joyce e fdv_setKeyMap() che ne è di supporto:

    bool m_fdvAlt;
    void fdv_setKeyMap(Uint8 addr, Uint8 bit, bool down);
    bool fdv_handle(SDLKey keysym, Uint8 type);

fdv_handle() intercetta solo le configurazioni di tasti (che chiamerò regole) specificati nell'array fdv_KMAPEX[], definito in JoycePcwKeyboard.cxx. Questo array è composto da una struttura di 11 campi: il primo (keysym) specifica il codice SDL del tasto premuto, mentre i campi shift e alt indicano se SHIFT e/o ALT debbano essere attivi affinché la regola venga applicata.

In alcuni casi è necessario disattivare SHIFT o ALT perché il tasto corrispondente sul PCW non li richiede mentre era necessario sul PC. E' il caso dell'uguale (=) che sul macbook si fa con SHIFT + '0', mentre sul PCW c'è un tasto dedicato. Per questo si utilizzano i campi off_addr_swAlt/off_bit_swAlt (quando l'opzione scambia EXTRA<->ALT è attiva) oppure off_addr_nswAlt/off_bit_nswAlt (quando l'opzione scambia EXTRA<->ALT è disattiva). I campi *_addr_* contengono il primo nibble (primi quattro bit) dell'indirizzo memory mapped della tastiera, mentre i campi *_bit_* il numero del bit relativo al tasto, secondo questa tabella:


Ad esempio, per disattivare lo SHIFT occorre impostare off_addr_swAlt = 2 (indirizzo 3FF2h) e off_bit_swAlt = 5 (bit 5).
I campi on_addr_1/on_bit_1on_addr_2/on_bit_2 specificano l'azione da intraprendere, cioè i tasti che il PCW vedrà premuti.
La regola da impostare per generare l'uguale è quindi questa:

{SDLK_0, true, false,   // tasto SDLK_0 e SHIFT premuto (ALT no)
 0x02, 0x05,     // SHIFT su (nel caso ALT-EXTRA scambiati)
 0x02, 0x05,     // SHIFT su (ALT-EXTRA non scambiati)
 0x03, 0x00,     // '=' giù
 0xFF, 0xFF},    // 0xFF indica "campi non utilizzati"

Il metodo fdv_handle(), oltre ad applicare le regole specificate nell'array fdv_KMAPEX[], si occupa anche di rilevare la pressione del tasto ALT (per impostare il flag m_fdvAlt) e sistemare un problema con il tasto CAPSLOCK.

Questa è la dichiarazione della struttura fdv_KMAPEX_t, utilizzata nell'array fdv_KMAPEX[]:

struct fdv_KMAPEX_t {
    // PC side state
    SDLKey keysym;
    bool shift;
    bool alt;
    // PCW side: switch off if m_swapAlt == true
    Uint8 off_addr_swAlt;        // 0xFF nothing to switch off
    Uint8 off_bit_swAlt;         // 0xFF nothing to switch off
    // PCW side: switch off if m_swapAlt == false
    Uint8 off_addr_nswAlt;        // 0xFF nothing to switch off
    Uint8 off_bit_nswAlt;         // 0xFF nothing to switch off
    // PCW side: switch on
    Uint8 on_addr_1;      // 0xFF nothing to switch on
    Uint8 on_bit_1;       // 0xFF nothing to switch on
    Uint8 on_addr_2;      // 0xFF nothing to switch on
    Uint8 on_bit_2;       // 0xFF nothing to switch on
};

Queste sono le regole:

static const fdv_KMAPEX_t fdv_KMAPEX[] = {
    // ':'      MAC-IT: SHIFT + '.'    PCW: SHIFT + ';'
    {SDLK_PERIOD, true, false,
     0xFF, 0xFF,     //
     0xFF, 0xFF,     //
     0x02, 0x05,     // SHIFT down
     0x03, 0x05},    // ';' down
    // ';'      MAC-IT: SHIFT + ','    PCW: ';'
    {SDLK_COMMA, true, false,
     0x02, 0x05,     // SHIFT up
     0x02, 0x05,     // SHIFT up
     0x03, 0x05,     // ';' down
     0xFF, 0xFF},    //
    // '\'      MAC-IT: '\'            PCW: EXTRA + '1/2'
    {SDLK_BACKSLASH, false, false,
     0xFF, 0xFF,     //
     0xFF, 0xFF,     //
     0x0A, 0x1,      // EXTRA down
     0x02, 0x6},     // '1/2' down
    // '|'      MAC-IT: SHIFT + '\'    PCW: EXTRA + '.'
    {SDLK_BACKSLASH, true, false,
     0x02, 0x05,     // SHIFT up
     0x02, 0x05,     // SHIFT up
     0x0A, 0x01,     // EXTRA down
     0x03, 0x07},    // '.' down
    // '&'      MAC-IT: SHIFT + '6'    PCW: SHIFT + '7'
    {SDLK_6, true, false,
     0x02, 0x05,     // SHIFT up
     0x02, 0x05,     // SHIFT up
     0x02, 0x05,     // SHIFT down
     0x05, 0x01},    // '7' down
    // '/'      MAC-IT: SHIFT + '7'    PCW: '/'
    {SDLK_7, true, false,
     0x02, 0x05,     // SHIFT up
     0x02, 0x05,     // SHIFT up
     0x03, 0x06,     // '/' down
     0xFF, 0xFF},    //
    // '('      MAC-IT: SHIFT + '8'    PCW: SHIFT + '9'
    {SDLK_8, true, false,
     0xFF, 0xFF,     //
     0xFF, 0xFF,     //
     0x02, 0x05,     // SHIFT down
     0x04, 0x01},    // '9' down
    // ')'      MAC-IT: SHIFT + '9'    PCW: SHIFT + '0'
    {SDLK_9, true, false,
     0xFF, 0xFF,     //
     0xFF, 0xFF,     //
     0x02, 0x05,     // SHIFT down
     0x04, 0x00},    // '0' down
    // '='      MAC-IT: SHIFT + '0'    PCW: '='
    {SDLK_0, true, false,
     0x02, 0x05,     // SHIFT up
     0x02, 0x05,     // SHIFT up
     0x03, 0x00,     // '=' down
     0xFF, 0xFF},    //
    // '''      MAC-IT: '''            PCW: SHIFT + '6'
    {SDLK_QUOTE, false, false,
     0xFF, 0xFF,     //
     0xFF, 0xFF,     //
     0x02, 0x05,     // SHIFT down
     0x06, 0x00},    // '6' down
    // '?'      MAC-IT: SHIFT + '''    PCW: SHIFT + '/'
    {SDLK_QUOTE, true, false,
     0xFF, 0xFF,     //
     0xFF, 0xFF,     //
     0x02, 0x05,     // SHIFT down
     0x03, 0x06},    // '/' down
    // '^'      MAC-IT: SHIFT + 'ì'    PCW: EXTRA + '7'
    {(SDLKey)0xA0, true, false,   // In my system 'ì' is 0xA0
     0x02, 0x05,     // SHIFT up
     0x02, 0x05,     // SHIFT up
     0x0A, 0x01,     // EXTRA down
     0x05, 0x01},    // '7' down
    // '['      MAC-IT: ALT + 'è'      PCW: '['
    {(SDLKey)0xA1, false, true,
     0x0A, 0x01,     // EXTRA up (EXTRA<->ALT)
     0x0A, 0x07,     // ALT up
     0x03, 0x02,     // '['
     0xFF, 0xFF},    //
    // ']'      MAC-IT: ALT + '+'      PCW: ']'
    {SDLK_PLUS, false, true,
     0x0A, 0x01,     // EXTRA up (EXTRA<->ALT)
     0x0A, 0x07,     // ALT up
     0x02, 0x01,     // ']'
     0xFF, 0xFF},    //
    // '+'      MAC-IT: '+'            PCW: SHIFT + '='
    {SDLK_PLUS, false, false,
     0xFF, 0xFF,     //
     0xFF, 0xFF,     //
     0x02, 0x05,     // SHIFT down
     0x03, 0x00},    // '=' down
    // '*'      MAC-IT: SHIFT + '+'    PCW: SHIFT + '8'
    {SDLK_PLUS, true, false,
     0xFF, 0xFF,     //
     0xFF, 0xFF,     //
     0x02, 0x05,     // SHIFT down
     0x05, 0x00},    // '8' down
    // '@'      MAC-IT: ALT + 'ò'      PCW: SHIFT + '1/2'
    {(SDLKey)0xA3, false, true,
     0x0A, 0x01,     // EXTRA up (EXTRA<->ALT)
     0x0A, 0x07,     // ALT up
     0x02, 0x05,     // SHIFT down
     0x02, 0x6},     // '1/2' down
    // '#'      MAC-IT: ALT + 'à'      PCW: '#'
    {(SDLKey)0xA2, false, true,
     0x0A, 0x01,     // EXTRA up (EXTRA<->ALT)
     0x0A, 0x07,     // ALT up
     0x02, 0x03,     // '#' down
     0xFF, 0xFF},    //
    // '{'      MAC-IT: SHIFT + ALT + 'è'    PCW: SHIFT + '['
    {(SDLKey)0xA1, true, true,
     0x0A, 0x01,     // EXTRA up (EXTRA<->ALT)
     0x0A, 0x07,     // ALT up
     0x02, 0x05,     // SHIFT down
     0x03, 0x02},    // '['
    // '{'      MAC-IT: SHIFT + ALT + '+'    PCW: SHIFT + '['
    {SDLK_PLUS, true, true,
     0x0A, 0x01,     // EXTRA up (EXTRA<->ALT)
     0x0A, 0x07,     // ALT up
     0x02, 0x05,     // SHIFT down
     0x02, 0x01},    // ']'
    // '°'      MAC-IT: SHIFT + 'à'          PCW: EXTRA + '5'
    {(SDLKey)0xA2, true, false,
     0x02, 0x05,     // SHIFT up
     0x02, 0x05,     // SHIFT up
     0x0A, 0x01,     // EXTRA down
     0x06, 0x01},    // '5'
    // '~'      MAC-IT: ALT + '5'            PCW: EXTRA + '-'
    {SDLK_5, false, true,
     0x0A, 0x01,     // EXTRA up (EXTRA<->ALT)
     0x0A, 0x07,     // ALT up
     0x0A, 0x01,     // EXTRA down
     0x03, 0x01},    // '-'
    // '<'      MAC-IT: '<'                  PCW: SHIFT + '§'
    {SDLK_LESS, false, false,
     0xFF, 0xFF,     //
     0xFF, 0xFF,     //
     0x02, 0x05,     // SHIFT down
     0x03, 0x04},    // '§'
    // '>'      MAC-IT: SHIFT + '<'          PCW: SHIFT + '#'
    {SDLK_LESS, true, false,
     0x02, 0x05,     // SHIFT up
     0x02, 0x05,     // SHIFT up
     0x02, 0x05,     // SHIFT down
     0x02, 0x03},    // '#'
};

Ecco i due metodi fdv_setKeyMap() (di supporto) e fdv_handle() (il gestore vero e proprio):

void JoycePcwKeyboard::fdv_setKeyMap(Uint8 addr, Uint8 bit, bool down)
{
  if (down)
    m_pcwKeyMap[addr] |= 1 << bit;
  else
    m_pcwKeyMap[addr] &= ~(1 << bit);
}

bool JoycePcwKeyboard::fdv_handle(SDLKey keysym, Uint8 type)
{
  if (type == SDL_KEYDOWN || type == SDL_KEYUP)
  {
    // semi-handle ALT
    if (keysym == SDLK_LALT || keysym == SDLK_RALT)
    {
      m_fdvAlt = type == SDL_KEYDOWN;
      return false;   // not handled
    }

    // handle CAPSLOCK
    if (keysym == (SDLKey)0x12D)
    {
      m_shiftLock = type == SDL_KEYDOWN;
      return true;   // handled
    }

    for (int i = 0; i < sizeof(fdv_KMAPEX) / sizeof(fdv_KMAPEX_t); ++i)
      if (fdv_KMAPEX[i].keysym == keysym && fdv_KMAPEX[i].shift == m_trueShift && fdv_KMAPEX[i].alt == m_fdvAlt)
      {
        // switch off (if m_swapAlt == true)
        if (m_swapAlt && fdv_KMAPEX[i].off_addr_swAlt != 0xFF)
          fdv_setKeyMap(fdv_KMAPEX[i].off_addr_swAlt, fdv_KMAPEX[i].off_bit_swAlt, type != SDL_KEYDOWN);
        // switch off (if m_swapAlt == false)
        if (!m_swapAlt && fdv_KMAPEX[i].off_addr_nswAlt != 0xFF)
          fdv_setKeyMap(fdv_KMAPEX[i].off_addr_nswAlt, fdv_KMAPEX[i].off_bit_nswAlt, type != SDL_KEYDOWN);
        // switch on (down)
        if (fdv_KMAPEX[i].on_addr_1 != 0xFF)
          fdv_setKeyMap(fdv_KMAPEX[i].on_addr_1, fdv_KMAPEX[i].on_bit_1, type == SDL_KEYDOWN);
        if (fdv_KMAPEX[i].on_addr_2 != 0xFF)
          fdv_setKeyMap(fdv_KMAPEX[i].on_addr_2, fdv_KMAPEX[i].on_bit_2, type == SDL_KEYDOWN);
        m_keyPress = true;
        return true;
      }
  }
  return false;   // not handled
}

La chiamata a fdv_handle() viene effettuata all'interno di handleEvent(), per cui va modificato così:

int JoycePcwKeyboard::handleEvent(SDL_Event &e)
{
...
  if (keysym == SDLK_LSHIFT || keysym == SDLK_RSHIFT) 
    m_trueShift = b;

  if (fdv_handle(keysym, e.type))
    return 1;
...
}