Keyboard layout

Martin A
Posts: 508
Joined: 09 Nov 2013 21:03

Re: Keyboard layout

Post by Martin A »

Dave's pointed me to a copy of the "Piggyback" language roms for Finnish and Danish in Andy's Memo package. Do I've disassembled both for a quick look at what they do.

They both work the same way, they're auto boot roms. The keyboard handler in Basic is intercepted and pointed to the code in the piggyback rom. That appears to ignore the language switches and use the langage rom regardless.

They also re-define a number of, language dependant, character definitions in VDP memory so that the keyboard and screen representations match. Because the ROMs auto start this is all set up before the BASIC "Ready" prompt appears and the MTX presents a unified keyboard and display.

I can see 2 reasons why this wasn't extended to CPM:
The language rom is mapped to slot 7, which means if CPM is runnng the language rom won't be booted. CPM is in slot 4 and takes over the whole machine from there, rom slots 5, 6 and 7 don't get examined or run.

The other is the rom itself is tied in tightly to BASIC and the way the VDP is handled by BASIC. The alterations that are made to the character set to make the keyboard and screen match don't translate to any of the CPM disc systems.

Which is probably why the original Memotech "fix" applied to Basic only. To make the FDX character display match any non UK keyboard would have required the character rom on the 80 column card to be swapped.

So, the COM utility Bill wrote can be tweaked to provide a modified CPM keyboard layout, but the screen representation might not match.
User avatar
gunrock
Posts: 67
Joined: 28 Oct 2020 21:17

Re: Keyboard layout

Post by gunrock »

Way ahead of me there, Martin.

Saved me the job of dumping and disassembling my Danish piggy back ROM, at least! Actually, providing a modified character set in CPM iss way beyond where I want to go, which is to remap the colon and such to the matching keys on the keyboard. Which is what I'll have a go at.

Many thanks.
Steve
Martin A
Posts: 508
Joined: 09 Nov 2013 21:03

Re: Keyboard layout

Post by Martin A »

For completeness, the full source to the Danish rom:

Code: Select all

; Disassembler generated equates.
CTRBADR EQU &FA52
LSTPG EQU &FA7A
VARNAM EQU &FA7B
VALBOT EQU &FA7D
CALCBOT EQU &FA7F
CALCST EQU &FA81
KBDBUF EQU &FA83
USYNT EQU &FA85
USER EQU &FA89
spare_var EQU &FA8C
IOPL EQU &FA8F
REALBY EQU &FA90
KBFLAG EQU &FA91
STKLIM EQU &FA92
SYSTOP EQU &FA94
SSTACK EQU &FA96
USERINT EQU &FA98
NODLOC EQU &FA9B
FEXPAND EQU &FA9E
USERNOD EQU &FAA1
NBTOP EQU &FAA4
NBTPG EQU &FAA6
BASTOP EQU &FAA7
BASTPG EQU &FAA9
BASBOT EQU &FAAA
BASTPO EQU &FAAC
ARRTOP EQU &FACC
BASELIN EQU &FACF
BASLNP EQU &FAD1
PAGE EQU &FAD2
CRNTPG EQU &FAD3
PGN1 EQU &FAD4
PGN2 EQU &FAD5
PGTOP EQU &FAD6
GOSTACK EQU &FAD8
GOPTR EQU &FB41
GOSNUM EQU &FB43
FORCOUNT EQU &FB44
CTYSLT EQU &FB45
DATAAD EQU &FB46
DATAPG EQU &FB48
DESAVE EQU &FB49
START EQU &FB4B
SETCALL EQU &FD48
RICHJL EQU &FD4B
USRRST EQU &FD4E
USERIO EQU &FD51
USERROR EQU &FD54
CLOCK EQU &FD57
INTFFF EQU &FD5E
CASBAUD EQU &FD5F
MIDVAL EQU &FD60
RETSAVE EQU &FD61
VAZERO EQU &FD65
VERIF EQU &FD67
TYPE EQU &FD68
CONTFLG EQU &FD69
CONTAD EQU &FD6A
CONTPG EQU &FD6C
ASTACK EQU &FD6D
TMPHL EQU &FD6F
TMPA EQU &FD71
STACCT EQU &FD73
PRORPL EQU &FD75
IOPR EQU &FD76
AUTOIN EQU &FD77
AUTOST EQU &FD79
AUTOCT EQU &FD7B
LASTKY EQU &FD7C
LASTASC EQU &FD7D
LASTDR EQU &FD7E
RNSEED EQU &FD7F
BREAK EQU &FD81
COMMAND EQU &FD82
ERRPOS EQU &FD84
FLAGS1 EQU &FD86
ITYPE EQU &FD87
MAFD EQU &FD89
MBCD EQU &FD8B
MDED EQU &FD8D
MHLD EQU &FD8F
MAF EQU &FD91
MBC EQU &FD93
MDE EQU &FD95
MHL EQU &FD97
MIX EQU &FD99
MIY EQU &FD9B
MSP EQU &FD9D
MPC EQU &FD9F
MEMPOINT EQU &FDA1
WCHJUMP EQU &FDA3
POINTERR EQU &FDA5
DADD EQU &FDA6
INDEX EQU &FDA8
DBYTE EQU &FDAA
LINKER EQU &FDAC
EDIT EQU &FDAD
LENGTH EQU &FDAE
DETYPE EQU &FDAF
DTYPE EQU &FDB0
DISAD EQU &FDB1
DPROG EQU &FDB3
LABTABL EQU &FDB5
APROG EQU &FDB7
ENDTAB EQU &FDB9
COMMENT EQU &FDBB
COMAD EQU &FDBC
ADLABEL EQU &FDBE
INDEXLAB EQU &FDC1
DATALAB EQU &FDC3
DBLABEL EQU &FDC6
BASEM EQU &FDC7
CURLAB EQU &FDC9
SPARE_VAR2 EQU &FDC8
ACC1 EQU &FDCC
OP1 EQU &FDD1
OP11 EQU &FDD2
YORN EQU &FDD7
SIGN EQU &FDD8
MEM1 EQU &FDD9
COPY EQU &FDDE
INTTAB EQU &FDF2
GASH EQU &FE02
TEMP EQU &FE04
CHAN EQU &FE14
FREQ EQU &FE16
VOL EQU &FE18
WKAREA EQU &FE1A
BSSTR EQU &FE3F
SPEED EQU &FE4B
SPBASE EQU &FE4C
MVDIST EQU &FE4D
NOSPR EQU &FE4E
DLSPNO EQU &FE4F
PLSPNO EQU &FE50
MVNO EQU &FE51
DELSPR EQU &FE52
VCOUNT EQU &FE53
VDPSTS EQU &FE54
SPRTBL EQU &FE55
SMBYTE EQU &FF55
LENLO EQU &FF56
LENHI EQU &FF57
VINTFLG EQU &FF58
CHPTR EQU &FF59
CURSCR EQU &FF5B
SCRN0 EQU &FF5D
SCRN1 EQU &FF6C
SCRN2 EQU &FF7B
SCRN3 EQU &FF8A
SCRN4 EQU &FF99
SCRN5 EQU &FFA8
SCRN6 EQU &FFB7
SCRN7 EQU &FFC6
TYPBL EQU &FFD5
OVRLAY EQU &FFED
IJTABLE EQU &FFF0
memory_limit EQU &10000
;
; ROM routines referenced in the code
shif   equ &00AD      ;test the shift keys
scent0 equ &00D3      ; set page A and return
key1   equ &3622      ; default keyboard handler
; keyboard handler
drive  equ &05        ; keyboard has 8 drive lines
sense1 equ &05        ; main keyboard sense lines
sense2 equ &06        ; remainder of sense lines + keyboard ID bits 

org &2000
;autostart header
DB   &08,&07,&06,&05,&04,&03,&02,&01
; pointer to ROM identifier
DW   romID
DW   startRom
; ROM 7 entry point
JR   startRom

DW   keytable
; Autorun entry point
.startRom
LD   HL,wedge
LD   DE,INTTAB
LD   B,&00
LD   C,endWedge-Wedge
LDIR                   ; copy the ram resident cose into place
LD   DE,(USERIO+1)     ; address of the current handler 
                       ; as byte at USERIO is JP instruction
LD   HL,key1
AND  A                 ; zero the carry
SBC  HL,DE             ; default keyboard handler in use ?
JR   Z,insertHandler   ; yes replace with the wedge code

; code entered when the default keyboard is already replaced
; looks like it's checking for an alternate patch to modify
; that to use the language rom
LD   HL,&0007       
ADD  HL,DE             ; current handler+7
PUSH HL
LD   E,(HL)            ; extract an address
INC  HL
LD   D,(HL)
LD   HL,key1           ; again compare with the default handler
AND  A
SBC  HL,DE
POP  HL
JR   Z,insertHandler1  ; and poke in the new one


.insertHandler
LD   HL,USERIO+1
.insertHandler1
LD   (HL),INTTAB       ; low byte of the address 
INC  HL
LD   (HL),INTTAB>8     ; high byte
RET

; code to be poked into space left for this purpose
; in the system variables
.wedge
LD   HL,PAGE
LD   A,(HL)
PUSH AF                ; save the current memory map on the stack
LD   A,&70             ; select rom 7
LD   (HL),A            ; update shadow copy
OUT  (&00),A           ; update the hardware
JP   main              ; jump intothe code in the rom 
.endWedge

.main
CALL newkey1
POP  HL                ; get the old meory map
PUSH AF                ; save return value and flags
LD   A,H               ; get the memory map details ready for 
JP   scent0            ; ROM routine to set page A and return to main code


.newkey1
LD   A,(OVRLAY)
CP   &C9               ; is the overlay the default immediate return
CALL Z,vramPatch       ; if yes then redefine the characters

.keyStart
LD   A,&FB             ; drive line for the control key
LD   (LASTDR),A
out  (drive),A
IN   A,(sense1)
BIT  0,A               ; test the control key
JR   Z,control         ; down use modified handler
CALL normal            ; call main handler
RET                    ; all done

; use when the control key tests as down
; the man code exclused both shifts and control key
; when scanning the keyboard matrix
.control
CALL normal            ; scan the keys as usual
RET  Z                 ; nothing pressed
AND  &1F               ; restrict the return value to 0-31
LD   (LASTASC),A       ; re-save 
RET                    ; and done

.normal
CALL shif
JR   Z,shift
CALL scan
RET  Z
LD   D,A
LD   BC,base
CALL look
LD   B,A
CP   &7F
JR   Z,kb8
CP   &20
CCF
.kb8
LD   A,(KBFLAG)
JR   C,kbn999
BIT  2,A
JR   NZ,nsh1
.kbn999
BIT  7,A
LD   A,B
JR   Z,ncont
LD   HL,alpha
LD   E,D
LD   D,&00
ADD  HL,DE
LD   A,(HL)
LD   D,E
AND  A
LD   A,B
JR   NZ,norm1          ; RETURN WITH LOWER-CASE IF ALPHA=1
                       ; (CHECK FOR CHARS 160 AND 29)
.nsh1
LD   A,D
JR   nsh2

.shift
CALL scan
RET  Z
.nsh2
LD   BC,upper
CALL look
.ncont
LD   B,A
.norm1
CP   &A0
JR   NZ,norm2
LD   A,(KBFLAG)
XOR  &80
LD   (KBFLAG),A
XOR  A
RET

.norm2
CP   &1D               ; 28 =SCROLL/PAGE
RET  NZ                ; NORMAL CHAR
LD   E,A               ; save 28
LD   A,(KBFLAG)
BIT  5,A
JR   Z,norm3
DEC  E
.norm3
XOR  &20
LD   (KBFLAG),A
.norm4
LD   A,E
LD   (LASTASC),A
AND  A
RET

.scan
LD   B,&08             ; B=8=DRIVE COUNTER 
XOR  A                 ; a=0 reset carry
LD   C,A               ; SENSE COUNTER=0
DEC  A                 ; a=ff
.scan2
RLA                    ; A=FE,FD,FB,F7,EF,DF,BF,7F
PUSH AF                ; SAVE DRIVE
LD   (LASTDR),A
out  (drive),A
IN   A,(sense1)
CP   &FF               ; IF FF THEN NO SENSE.TRY OTHER DRIVE
JR   Z,scan3
,check1
PUSH AF                ; SAVE SENSE
.ch10
LD   A,&02             ; CHECK FOR SHIFT
CP   B                 ; IF B=2 THEN RESET SHIFTS
JR   NZ,ch11
POP  AF
SET  6,A
JR   ch13
.ch11
LD   A,&06             ; CHECK FOR CNTRL
CP   B
JR   Z,ch12
POP  AF
JR   valid
.ch12
POP  AF                ; RESTORE SENSE
.ch13
SET  0,A               ; RESET ALPHA,SHIFT AND CONTROL
.ch14
CP   &FF               ; TRY AGAIN AFTER ELIMINATING ODD KEYS
JR   Z,scan3           ; IF STILL 0 THEN TRY OTHER DRIVE 
;VALID KEY FOUND
.valid
POP  DE                ; REMOVE DRIVE
LD   C,&00
.ch15
RRCA
JR   NC,endScan        ; B=1-8,C=0-7
INC  C
JR   ch15

.scan3
IN   A,(sense2)         ; SECOND DRIVE
AND  &03
CP   &03
JR   Z,Scan4
.check2
AND  A
ADD  A,&07
LD   C,A                ; C=8 OR 9
POP  AF
JR   endScan

.scan4
POP  AF                 ; RESTORE DRIVE
DJNZ scan2              ; MOVE TO NEXT DRIVE
LD   C,&00
.endScan
LD   A,C
ADD  A,A
ADD  A,A
ADD  A,A
ADD  A,B
LD   HL,AUTOCT
JR   NZ,deb1
LD   (HL),&B0
JR   Z,deb2
.deb1
RES  7,(HL)
LD   B,A
LD   A,(LASTKY)
CP   B
LD   A,B
.deb2
LD   (LASTKY),A
RET  Z
PUSH AF
XOR  A
CP   (HL)
JR   NZ,endAuto
SET  2,(HL)
SET  1,(HL)
.endAuto
POP  AF
RET

.look
LD   H,&00
LD   L,A
ADD  HL,BC
LD   A,(HL)
LD   (LASTASC),A
RET


.vramPatch
LD   HL,&C900
LD   (OVRLAY),HL        ; reset the Virtual screen pre-call to
                        ; just return doing nothing but with a
                        ; NOP before the return so that the calling 
                        ; code knows if the patch is run or not
LD   DE,characters
.vramNext
LD   A,(DE)             ; read the character to be defined
CP   &FF                ; check for end of table
RET  Z                  ; and exit
LD   L,A
LD   H,&0B              ; HL = &0B00 + char code
ADD  HL,HL              ; HL = &1600 + 2 x char code
ADD  HL,HL              ; HL = &2C00 + 4 x char code
ADD  HL,HL              ; HL = &5800 + 8 x char code
                        ; VDP write bit + address of char in VDP table 
                        ; in VRAM at 1800 to 1BFF
LD   A,L
OUT  (&02),A
LD   A,H
OUT  (&02),A            ; character address set up for writing to VRAM
INC  DE                 ; step to first data byte
LD   B,&08  
.vramLoop
LD   A,(DE)
OUT  (&01),A            ; write 8 byutes to the VRAM
INC  DE
DJNZ vramLoop
JR   vramNext           ; go back and test for another character

; ROM identifier, 4 byte string folowed by code to print
; the name
.romID
DS   "CK11" 
RST  &10       ; output routine
DB   &8C      ; send 12 bytes to the screen
DS   "  CUSTOM KBD"
RET

; Character re-mapp
; 8 byte entried , character code + 8 data bytes
.characters
DB   &5B
DB   &78,&A0,&A0,&B0,&E0,&A0,&B8,&00
DB   &7B
DB   &00,&E0,&38,&E8,&B8,&A0,&F8,&00
DB   &5D
DB   &20,&00,&20,&50,&88,&F8,&88,&00
DB   &7D
DB   &20,&00,&60,&10,&70,&90,&68,&00
DB   &5C
DB   &28,&50,&50,&70,&50,&50,&A0,&00
DB   &7C
DB   &00,&00,&28,&50,&70,&50,&A0,&00
; end of table marker room for 6 more definitions
DB   &FF
DB   &00,&00,&00,&00,&00,&00,&00,&00
DB   &27
DB   &00,&00,&00,&00,&00,&00,&00,&00
DB   &28
DB   &00,&00,&00,&00,&00,&00,&00,&00
DB   &29
DB   &00,&00,&00,&00,&00,&00,&00,&00
DB   &2A
DB   &00,&00,&00,&00,&00,&00,&00,&00
DB   &2B
DB   &00,&00,&00,&00,&00,&00,&00,&00
DB   &FF

; 3 keyboard tables, lower case, upper case
; and capslock map, 81 entries each, zero
; byte then one entry for ach clot in the 8x10 
; matrix including the 3 unused keys in the
; final row
.keyTable
.base
DB   &00
DB   &7A,&00,&61,&A0,&71,&00,&1B,&31
DB   &63,&78,&64,&73,&65,&77,&32,&33
DB   &62,&76,&67,&66,&74,&72,&34,&35
DB   &6D,&6E,&6A,&68,&75,&79,&36,&37
DB   &2E,&2C,&6C,&6B,&6F,&69,&38,&39
DB   &5F,&2F,&7C,&7B,&7D,&70,&30,&3A
DB   &15,&00,&0D,&3B,&0A,&40,&2D,&5E
DB   &0C,&0A,&1A,&19,&08,&0B,&05,&1D
DB   &83,&87,&82,&86,&85,&81,&84,&80
DB   &20,&00,&00,&00,&7F,&09,&08,&03
.upper
DB   &00
DB   &5A,&00,&41,&A0,&51,&00,&1B,&21
DB   &43,&58,&44,&53,&45,&57,&22,&23
DB   &42,&56,&47,&46,&54,&52,&24,&25
DB   &4D,&4E,&4A,&48,&55,&59,&26,&27
DB   &3E,&3C,&4C,&4B,&4F,&49,&28,&29
DB   &5F,&3F,&5C,&5B,&5D,&50,&30,&2A
DB   &30,&00,&0D,&2B,&0A,&60,&3D,&7E
DB   &0D,&2E,&32,&33,&31,&35,&38,&37
DB   &8B,&8F,&8A,&8E,&8D,&89,&8C,&88
DB   &20,&00,&00,&00,&36,&34,&08,&39
.alpha
DB   &00
DB   &00,&01,&00,&01,&00,&01,&01,&01
DB   &00,&00,&00,&00,&00,&00,&01,&01
DB   &00,&00,&00,&00,&00,&00,&01,&01
DB   &00,&00,&00,&00,&00,&00,&01,&01
DB   &01,&01,&00,&00,&00,&00,&01,&01
DB   &01,&01,&00,&00,&00,&00,&01,&01
DB   &01,&01,&01,&01,&01,&01,&01,&01
DB   &01,&01,&01,&01,&01,&01,&01,&01
DB   &01,&01,&01,&01,&01,&01,&01,&01
DB   &01,&01,&01,&01,&01,&01,&01,&01

; un-referenced locations
; looks like a leftover copy of part of the upper
; case table
DS "<LKOI()_?\[]P0*0"
DB 0
END 
it's 3/4 of a K long, the key tables you'd need are at the end.
Last edited by Martin A on 05 Apr 2021 16:10, edited 1 time in total.
User avatar
gunrock
Posts: 67
Joined: 28 Oct 2020 21:17

Re: Keyboard layout

Post by gunrock »

Thank you, will read that a bit later on.
User avatar
gunrock
Posts: 67
Joined: 28 Oct 2020 21:17

Re: Keyboard layout

Post by gunrock »

I can confirm that the piggy back ROM code ignores the keyboard switches. I put my new keyboard cable (Raspberry Pi GPIO) in last night and changed the links from the current setting which was 0, to 2 and then 3 (they were fiddly enough for me not to bother witth setting them to 1) and the keyboard mapping was unchanged, as expected.

BTW, if this is useful, the two links are ordered:
20210409_223031.jpg
20210409_223031.jpg (70.12 KiB) Viewed 57 times
Good news, my crappy code on the previous page works. :D
Steve
Post Reply