ULM 3
ULM 3 is a tool, totaly written in machine language that add about 40 new functions to the BASIC.
|
ULM 3 est une collection de programme, entierement programmé en langage machine, qui ajoute un quarantaine de fonctions au basic.
La documentation est en anglais car je n'ai pas le temps d'en faire 2.
|
With few characters redefined, it could be used on an unexpanded PC-1350 (5 KB of RAM) but only few memory remains for the user and it isn't fully protected agains NEW
, CLEAR
or such ... In fact, it was designed to be secure with a memory card under MEM "C"
memory mode.
WARNING : ULM3 is not movable (it can't be moved on memory without recompilation), and some functions needs a ROM 1. As I haven't ROM 0 machine, I can't port it to this ROM. As you have the full source code, it's up to you ... I think, this task is mainly to find out addresses of all function used in the UPPER ROM.
Anyway, some function like OLD can be used without ULM3.
This page was made using reverse engineering on the binary dump. All known important bugs were corrected. Anyway, the design of this code should be better and one day, I should write a better version ... but I have other thing to do ;-D
Download
|
ULM3
|
ULM2
|
- ULM3.bin - Binary dump of ULM3, including some some redefined characters data (the same as POKE listing),
- ULM3.s - Raw source code as generated by (should be useful to have the numeric value of labels, until labels definition files will be online)
- ULM3.bas - Well, normally this BASIC program can configure ULM3. Unfortunately, I can't recover this progy from my tape. Until I made a recovery tool, this link is dead.
|
ULM2 is the previous version of this tool. Without documentation, without source code and without some ULM3 functions. It is there because it can be useful for machine without memory extension.
- ULM2.bin - Binary dump of ULM2, including some some redefined characters data,
- ULM2.bas - Configuration tool for ULM2, in BASIC.
|
The dispatcher
The root of ULM3 is a dispatcher called using the following syntax
CALL &68B5,command[;arg...][,command ...]
|
Some explanations :
The dispatcher by itself is basically a CASE1 / CASE2 jump table. Each new function, which is a simple ASCII code, is associated with a machine language function.
As usual, the X register point to the following character to read, but, as this register should be modified by the called function, this pointer in backup in [CALL Rtn @dr] : so a call to [CALL Rtn @dr <- X] is needed after reading something on the command line.
Like 'normal' basic command, the CARRY is set if an error occur. To avoid heavy cleaning in each function code, the stack pointer is reset to $58.
|
Commodity functions
Here after, some functions used by many others.
A "..." is meaning the function continue in the next one.
[Last Result<-Xreg]
Store Xreg in [Last Result]
|
&6BAF LIDP [Last Result]
&6BB2 LP $10 (Xreg)
&6BB3 LII &07
&6BB5 EXWD
...
|
[Xreg<-Last Result]
Recall Xreg stored in [Last Result]
|
&6BB6 LIDP [Last Result]
&6BB9 LP $10 (Xreg)
&6BBA LII &07
&6BBC MVWD
&6BBD RTN
|
[U3 find variable]
Glue code to call [find variable]
|
&6BBE LP $33 ; We are looking for every kind of variable
&6BBF ANIM &9F
&6BC1 ORIM &02
&6BC3 CAL [find variable]
&6BC5 CAL [CALL Rtn @dr <- X]
&6BC7 JPC [exit ULM3]
&6BCA RTN
|
[U3 Store {B,A} in variable]
Store a 16 bits value in a variable.
- {B,A} hold the 16 bits value
- X point to the beginning of the variable name
|
&6B68 DX ; to compensate DX in beginning of [U3 Store Xreg in variable, X++]
...
|
[U3 Store {B,A} in variable, X++]
Idem but X point to the separator before the variable name
|
&6B69 LIQ $02 (A)
&6B6B LP $18 (Yreg)
&6B6C MVB ;{$19,$18} <- {B,A}]
&6B6D CAL [BCD<-BIN unsigned]
...
|
|
[U3 Store Xreg in variable, X++]
Same as the next function but X point to the separator before the variable name
|
&6B6F IX
...
|
[U3 Store Xreg in variable]
|
&6B70 CALL [Last Result<-Xreg] ; save the value to store
&6B73 CALL [U3 find variable] ; find the target variable
&6B76 CALL [Xreg<-Last Result] ; restore the value
&6B79 CAL [Tst string] ; Is it a string ?
&6B7B JRNCP &6B8A
{storing a number}
&6B7D LP $33 ; check if the variable is numeric
&6B7E TSIM &04
&6B80 JPNZ [ERROR 9]
&6B83 IY ; DP = address of the variable
&6B84 LP $10 (Xreg)
&6B85 LII &07
&6B87 EXWD ; Store the number
&6B88 RC
&6B89 RTN
{storing a string}
&6B8A LP $33 ; check if the variable is not numeric
&6B8B TSIM &04
&6B8D JPZ [ERROR 9]
&6B90 TSIM &90 ; check if it's a fixed variable
&6B92 JRZP &6B99
&6B94 LIA &F5
&6B96 IYS
&6B97 LIA &07
&6B99 DECA ; push the length of the variable
&6B9A PUSH
&6B9B LIQ $15 ; X <- address of the string
&6B9D LP $04 (Xl)
&6B9E MVB
&6B9F DX
&6BA0 LP $17 ; B <- length of the string
&6BA1 LDM
&6BA2 EXAB
&6BA3 NOPT ; ??? Bug fix ???
&6BA4 IXL ; Read the string
&6BA5 DECB ; check if the string is not finished
&6BA6 JRNCP &6BAA
&6BA8 LEAVE ; if yes, exiting the loop
&6BA9 CLA
&6BAA IYS ; store the value in the variable
&6BAB LOOP &6BA4
&6BAD RC
&6BAE RTN
|
|
Following functions read a binary number which is stored in {$19,$18}
[U3 arg string position, X++]
0 -> 79
|
&6B18 IX
...
|
[U3 arg string position]
0 -> 79
|
&6B19 LIA &01
&6B1B JRP &6B38
|
[U3 arg string position not null, X++]
1 -> 79
|
&6B1D IX
...
|
[U3 arg string position not null]
1 -> 79
|
&6B1E LIA &02
&6B20 JRP &6B38
|
|
[U3 arg BIN unsigned, X++]
0 -> 65535
&0000 -> &FFFF
|
&6B22 IX
...
|
[U3 arg BIN unsigned]
0 -> 65535
&0000 -> &FFFF
|
&6B23 LIA &03
&6B25 JRP &6B38
|
[U3 arg BYTE, X++]
0 -> 255
|
&6B27 IX
...
|
[U3 arg BYTE]
0 -> 255
|
&6B28 LIA &04
&6B2A JRP &6B38
|
[U3 arg BYTE not null, X++]
1 -> 255
|
&6B2C IX
...
|
|
[U3 arg BYTE not null]
1 -> 255
|
&6B2D LIA &05
&6B2F JRP &6B38
|
[U3 arg line number, X++]
1 -> 65279
|
&6B31 IX
...
|
[U3 arg line number]
1 -> 65279
|
&6B32 LIA &06
&6B34 JRP &6B38
|
[U3 arg BIN signed, X++]
??? -> ???
|
&6B36 IX
...
|
[U3 arg BIN signed]
??? -> ???
|
&6B37 CLA
&6B38 PUSH
&6B39 CAL [Int read argument]
&6B3B CAL [CALL Rtn @dr <- X]
&6B3D POP
&6B3E JRCP &6BC7
&6B40 CASE1 6 TESTS RETURN &6BC7
&6B44 CASE2
&01 [String Position<-BCD]
&02 [String Position<-BCD not null]
&03 [BIN unsigned<-BCD]
&04 [Byte<-BCD]
&05 [Byte<-BCD not null]
&06 [Line Number<-BCD]
DEFAULT [BIN signed<-BCD]
|
|
[U3 arg string, X++]
|
&6BCB IX
...
|
[U3 arg string]
- X point to the beginning of the string,
- Y point to the end of the string.
|
&6BCC CAL [Int read argument]
&6BCE CAL [CALL Rtn @dr <- X]
&6BD0 JRCP &6BE6 ; should be a JPC [ERROR 9]
&6BD2 CAL [Tst string]
&6BD4 JRCP &6BE7
&6BD6 LIQ $15 ; X=beginning of the string
&6BD8 LP $04 (Xl)
&6BD9 MVB
&6BDA DX
&6BDB CAL [Y <- X]
&6BDD LP $17 ; Add the length -> Y
&6BDE LDM
&6BDF LIB &00
&6BE1 LP $06 (Yl)
&6BE2 ADB
&6BE3 CLA
&6BE4 IYS ; Clear the last character
&6BE5 RC
&6BE6 RTN
&6BE7 JP [ERROR 9]
|
|
Hexa
[U3 Hexa]
|
&6A85 CALL [U3 arg BIN unsigned] ;Read the value
&6A88 CAL [Xreg <- 0] ;build Xreg
&6A8A LIB &6D ; data are stored on the string buffer
&6A8C LIA &60
&6A8E LIQ $02 ;(A)
&6A90 LP $15
&6A91 MVB
&6A92 CAL [Y <- BA-1]
&6A94 LP $14
&6A95 ORIM &D0 ;it's a string
&6A97 LP $17
&6A98 ORIM &04 ; 4 bytes long
&6A9A LP $19
&6A9B LDM
&6A9C SWP
&6A9D CALL [Hexa DIGIT]
&6AA0 LDM
&6AA1 CALL [Hexa DIGIT]
&6AA4 LP $18 (Yreg)
&6AA5 LDM
&6AA6 SWP
&6AA7 CALL [Hexa DIGIT]
&6AAA LDM
&6AAB CALL [Hexa DIGIT]
&6AAE JP [U3 Store Xref in variable, X++]
|
|
CALL &68B5,Hnumber;variable$
This function converts a 16 bits unsigned integer to an HEXADECIMAL string.
CALL &68B5,H255;K$ => K$ =FF
PORTABILITY : ROM 1 only
[Hexa DIGIT] is a function in the external ROM. It's
converting the lower 4 bits of A and store them at (Y) as Hexa digit. It's part
of OPEN$ function.
[Hexa DIGIT]
|
&F163 ANIA &0F
&F165 CPIA &0A
&F167 JRCP &F16B
&F169 ADIA &07
&F16B ADIA &30
&F16D IYS
&F16E RTN
|
|
Character repeat
[ULM3 Char repeat]
|
&675C CALL [U3 arg BYTE] ; the char to repeat
&675F LP $18 (Yreg)
&6760 LDM ;Fill the string buffer
&6761 LIDP &6E60
&6764 LII &4F
&6766 FILD
&6767 CALL [U3 arg string position not null, X++] ; length of the string
&676A CAL [Xreg <- 0] ; build the result
&676C LP $18 (Yreg)
&676D LDM
&676E LP $17
&676F EXAM
&6770 LIB &6E
&6772 LIA &60
&6774 LIQ $02 (A)
&6776 LP $15
&6777 MVB
&6778 LP $14
&6779 ORIM &D0
&677B JP [U3 Store Xreg in variable, X++]
|
|
CALL &68B5,*code;number;variable$
Repeat number times the character of code code and store this string in variable$.
CALL &68B5,*$41;5;K$ => K$ =AAAAA
PORTABILITY : Portable
|
find a character in a string
CALL &68B5,pcode;exp$;var
find out in string2$ the character whose ASCII code is number (first form) or the first character of string1$.
The result is the position of this character in string2$ or 0
if it can't be found.
PORTABILITY : Portable
[ULM3 STRPOS]
|
&6680 CAL [Int read argument]
&6682 CAL [CALL Rtn @dr <- X]
&6684 JRCP &66A6 ; error ?
&6686 CAL [Tst string]
&6688 JRCP &6697
&668A LIQ $15 ; it's a string ...
&668C LP $04 (Xl)
&668D MVB
&668E DX
&668F IXL ; read the 1st char
&6690 CPIA &FE ; shifted char ?
&6692 JRZM &668F
&6694 CAL [X <- CALL Rtn @dr]
&6696 JRP &669E
&6698 CAL [Byte<-BCD] ; read the ASCII code
&669A JRCP &66A7
&669C LP $18 (Yreg)
&669D LDM
&669E PUSH ; save the char
&669F CALL [U3 arg string, X++] ; now we read the string
&66A2 POP ; restore the char
&66A3 JRNCP &66A8
&66A5 CAL [X <- CALL Rtn @dr]
&66A7 RTN
...
|
|
...
&66A8 EXAB
&66A9 LP $17 ; reading the length of the string
&66AA LDM
&66AB DECA
&66AC JRCP &66C5 ; string empty
&66AE PUSH
&66AF LII &00
&66B1 INCI
&66B2 IXL
&66B3 CPIA &FE ; shifted char ?
&66B5 JRZM &66B2 ; should be JRZP &66BE
&66B7 LP $03 (B)
&66B8 CPMA
&66B9 JRNZP &66BE ; exiting : char found
&66BB LEAVE
&66BC LIJ &00
&66BE LOOP &66B1
&66C0 LP $01 (J)
&66C1 CPIM &01 ; char found ?
&66C3 JRCP &66C7
&66C5 LII &00 ; No ... result is 0
&66C7 LIJ &01
&66C9 LP $00 (I)
&66CA LDM
&66CB LIB &00
&66CD CAL [X <- CALL Rtn @dr]
&66CF JP [U3 Store {B,A} in variable, X++]
|
|
Printing on CE-126P
[ULM3 Imprime]
|
{print a line}
&6BEA CALL [Test printer on]
&6BED CAL [Wait 6 ms]
&6BEF LIA &17 ; 24 characters to print
&6BF1 PUSH
&6BF2 IXL
&6BF3 CPIA &FE ; it's a SHIFT : skipped
&6BF5 JRNZP &6BF8
&6BF7 IXL
&6BF8 CPIA &00 ; end of this line ?
&6BFA JRZP &6C0D
&6BFC CALL [Print {A}]
&6BFF LOOP &6BF2
&6C01 LIA &0D ; Print end of line
&6C03 CALL [Print {A}]
&6C06 LIA &0E
&6C08 CALL [Print {A}]
&6C0B RC
&6C0C RTN
&6C0D CLA ; Fill until 24 char with space
&6C0E CALL [Print {A}]
&6C11 LOOP &6C0D
&6C13 CALL &6C01
&6C16 SC
&6C17 RTN
[ULM3 Imprime]
&6C18 CALL [U3 arg string] ; Read the string to print
&6C1B JRCP &6C2F
&6C1D LIA &03 ; The maximum length is 3x24 characters
&6C1F PUSH
&6C20 CALL {print a line}
&6C23 JRCP &6C2B ; finished ?
&6C25 IXL
&6C26 DX
&6C27 CPIA &00 ; it's finished ?
&6C29 JRNZP &6C2C
&6C2B LEAVE
&6C2C LOOP &6C20
&6C2E RC
&6C2F RTN
|
|
CALL &68B5,Istring
Print on CE-126P a characters string without any modification, unlink LPRINT basic function where some characters are converted.
PORTABILITY : ROM 1 Only (call some printing function of the upper ROM).
|
Music
[U3 Music]
|
&6AF6 CALL [U3 arg BIN unsigned]
&6AF9 LIQ $18 (Yreg) ;store parameter
&6AFB LP $02 (A)
&6AFC MVB
&6AFD PUSH ;push length of this note
&6AFE LIA &21 ;Sound ON
&6B00 CAL [Out C <- {A}]
&6B02 EXAB
&6B03 PUSH ;push the 'frequency'
&6B04 EXAB
&6B05 LOOP &6B05
&6B07 CAL [Display ON] ;Sound OFF
&6B09 EXAB
&6B0A PUSH ;push the 'frequency'
&6B0B EXAB
&6B0C LOOP &6B0C
&6B0E LOOP &6AFE
&6B10 IXL ;another note
&6B11 CPIA ';'
&6B13 JRZM [ULM3 Music]
&6B15 DX
&6B16 RC
&6B17 RTN
|
|
CALL &68B5,Mfrequency*256 + length;...
Beep with difference frequencies
CALL &68B5,M25*256+15;150*256+30
PORTABILITY : Portable
|
Memorize screen
CALL &68B5,maddress
CALL &68B5,raddress
Store the current screen in memory starting at address. 600 Bytes are needed to store screen data.
PORTABILITY : Portable
[U3 Memorize screen]
|
&69A2 CALL [U3 arg BIN unsigned] ;where to store the screen
&69A5 LIQ $18 (Yreg)
&69A7 LP $04 (Xl)
&69A8 MVB
&69A9 DX
&69AA LIA &03
&69AC PUSH
&69AD POP
&69AE PUSH
&69AF CAL [Y<-@dr line video]
&69B1 LIA &04
&69B3 PUSH
&69B4 LIA &1D
&69B6 PUSH
&69B7 IY
&69B8 LDD
&69B9 IX
&69BA STD
&69BB LOOP &69B7
&69BD LIA &E2
&69BF LIB &01
&69C1 LP $06 (Yl)
&69C2 ADB
&69C3 LOOP &69B4
&69C5 LOOP &69AD
&69C7 RC
&69C8 RTN
|
|
[U3 Restore screen]
|
&6980 CALL [U3 arg BIN unsigned] ;where the screen is stored
&6983 LIQ $18 (Yreg)
&6985 LP $04 (Xl)
&6986 MVB
&6987 DX
&6988 LIA &03
&698A PUSH
&698B POP
&698C PUSH
&698D CAL [Y<-@dr line video]
&698F LIA &04
&6991 PUSH
&6992 LIB &1E
&6994 CAL [{IXL - IYS}*B]
&6996 LIA &E2
&6998 LIB &01
&699A LP $06 (Yl)
&699B ADB
&699C LOOP &6992
&699E LOOP &698B
&69A0 RC
&69A1 RTN
|
|
Memory protection
[ULM3 Protect memory]
|
&6ABD CAL [LIDP Mem flags]
&6ABF ORID &01
&6AC1 RTN
|
|
[ULM3 Unprotect memory]
|
&6ABD CAL [LIDP Mem flags]
&6ABF ANID &FE
&6AC1 RTN
|
|
CALL &68B5,B
CALL &68B5,b
Protect (B) or Unprotect (b) the memory.
If the memory is protected, some function like NEW , CLEAR , LOAD , CLOAD , ... fails. It's mainly use to avoid user mistake or with commercial memory modules.
PORTABILITY : Portable
|
ANDing or ORing memory
[ULM3 OR]
|
&681A LIA &47 ;ORMA
&681C JRP &6820
...
|
[ULM3 AND]
|
&681E LIA &46 ;ANMA
&6820 LIDP &683B ; auto-modify the code
&6823 STD ; to set the operation to make
&6824 CALL [U3 arg BIN unsigned]
&6827 LIQ $18 (Yreg) ; read the address
&6829 LP $04 (Xl) ; and store it in X
&682A MVB
&682B DX
&682C CAL [push X] ; push the address to modify
&682E CAL [X <- CALL Rtn @dr]
&6830 CALL [U3 arg BYTE, X++]
&6833 IXL ; read the next character
&6834 LP $10 (Xreg)
&6835 EXAM
&6836 CAL [pop X]
&6838 IXL
&6839 LP $18 (Yreg)
&683A EXAM
&683B ORMA
&683C MVDM
&683D LP $10 (Xreg)
&683E LDM
&683F CPIA &3B ; another value ?
&6841 JRZM &682C
&6843 RC
&6844 RTN
|
|
CALL &68B5, AND @dr;val1[;val2...]
CALL &68B5, OR @dr;val1[;val2...]
These commands are doing massive AND or OR actions in memory.
For example,
CALL &68B5, AND &6C30;1;2;3
is exactly the same as
POKE &6C30, PEEK &6C30 AND 1, PEEK &6C31 AND 2, PEEK &6C32 AND 3
|
CLEAR
CALL &68B5,C[;var]
Like CLEAR
basic command but keep ULM3 memory allocated.
If the memory is protected nothing is cleared.
The optional var is set with the start address of ULM3.
PORTABILITY : ROM 1 only due to call of &BCE1.
[ULM3 Clear]
|
&6706 CAL [Protected memory ?] ; if the memory is protected
&6708 JRNZP &6712 ; we'll not CLEAR variables
&670A CALL [{B,A} <- U3 Stored Start Variable pointer]
&670D CAL [LIDP Mem flags]
&670F CALL &BCE1 ; Call end of CLEAR basic code
&6712 IXL
&6713 CPIA &3B ; ';' ?
&6715 JRNZP &67E6
&6717 LIAB [Start ULM3]
&671B JP [U3 Store {B,A} in variable]
|
|
[{B,A} <- U3 Stored Start Variable pointer]
|
&64C5 LIDP [U3 Stored Start Variable pointer]
&64C8 LP $02 (A)
&64C9 MVBD
&64CA RTN
|
ROM 1 - end of CLEAR code
|
&BCE1 TSID &10
&BCE3 JRZP &BCE9
&BCE5 LIA &00
&BCE7 LIB &60
&BCE9 LIDP [Start Variable pointer]
&BCEC LP $02 (A)
&BCED EXBD
&BCEE LIDL &13
&BCF0 ANID &36
&BCF2 RC
&BCF3 RTN
|
|
|
Set Clear
[ULM3 SetClear]
|
&6724 CAL [Protected memory ?]
&6726 JPNZ [ERROR 1]
&6729 CALL [U3 arg BIN unsigned]
&672C LP $18 (Yreg)
&672D LIDP [Start Variable pointer]
&6730 EXBD
&6731 RTN
|
|
CALL &68B5,caddress
Force the value of [Start Variable pointer].
Notez-bien : nothing but the memory protection is checked, so playing with this function without care is the better way to trash the memory and loose data.
PORTABILITY : Portable and Relogeable
SetClear can be used also as standalone because it doesn't need other ULM3 functions.
|
Old
[ULM3 OLD]
|
&6A70 CAL [X <- Start BASIC]
&6A72 IX
&6A73 ANID &00
&6A75 IX
&6A76 IXL
&6A77 LIB &00
&6A79 LP $04 (Xl)
&6A7A ADB
&6A7B IXL
&6A7C CPIA &FF
&6A7E JRNZM &6A75
&6A80 CAL &14CB
&6A82 LP $04 (Xl)
&6A83 EXBD
&6A84 RTN
|
|
CALL &68B5,O
Old will recover a program erased by a NEW command, by a reset or if the Start Basic pointer has been modified.
PORTABILITY : Portable and Relogeable
Old can be used also as standalone because it doesn't need other ULM3 functions.
|
Internal PEEK
[ULM3 Internal Peek]
|
&6B59 CALL [U3 arg BYTE] ; read the register address
&6B5C LP $18 (Yreg)
&6B5D LDM
&6B5E CPIA &60 ; check if it's in internal memory range
&6B60 JPNC [ERROR 3]
&6B63 STP
&6B64 LDM
&6B65 LIB &00 ; {B,A} <- (p)
&6B67 IX ; to compensate DX in beginning of [U3 Store {B,A} in variable]
... followed by [U3 Store {B,A} in variable] code ...
|
|
CALL &68B5,Paddress;var
Store in var the content of a register.
PORTABILITY : Portable
Obviously, many registers are modified by this function, so to use with care.
|
Extended functions
[ULM3 functions]
|
&6A34 CALL [U3 arg string position] ; Read the function number
&6A37 LP $18 (Yreg)
&6A38 LDM
&6A39 CASE1 16 TESTS RETURN &6BCA ; call function
&6A3D CASE2
&01 &6BCA
&02 &6BCA
&03 &6BCA
&04 &6BCA
&05 &6BCA
&06 &6BCA
&07 &6BCA
&08 &6BCA
&09 &6BCA
&0A &6BCA
&0B &6BCA
&0C &6BCA
&0D &6BCA
&0E &6BCA
&0F &6BCA
&10 &6BCA
DEFAULT [ERROR 3]
|
|
CALL &68B5,@num[;...]
@ is used to add new function to ULM3 for example to extend its functionality.
By default, it call &6BCA which is only a RTN
PORTABILITY : Portable (but called function should not be).
|
Set RESERVE
[UML3 set RESERVE]
|
&6845 CALL [U3 arg string position]
&6848 LP $18 (Yreg)
&6849 LDM
&684A CASE1 9 TESTS RETURN &689C
&684E CASE2
&01 &686C
&02 &6871
&03 &6876
&04 &687B
&05 &6880
&06 &6885
&07 &688A
&08 &688F
&09 &6894
DEFAULT [ERROR 3]
&686C LIB &6F
&686E LIA &6E
&6870 RTN
&6871 LIB &6F
&6873 LIA &82
&6875 RTN
&6876 LIB &6E
&6878 LIA &6F
&687A RTN
...
|
|
...
&687B LIB &6F
&687D LIA &6E
&687F RTN
&6880 LIB &6E
&6882 LIA &6F
&6884 RTN
&6885 LIB &6F
&6887 LIA &6E
&6889 RTN
&688A LIB &6F
&688C LIA &6E
&688E RTN
&688F LIB &6F
&6891 LIA &6E
&6893 RTN
&6894 CALL [U3 arg BIN unsigned, X++]
&6897 LIQ $18 (Yreg)
&6899 LP $02 (A)
&689A MVB
&689B RTN
&689C JRCP &68A3
&689E LIDP [Reserve pointer]
&68A1 LP $02 (A)
&68A2 EXBD
&68A3 RTN
|
|
CALL &68B5,Rnum
CALL &68B5,R9;address
Switch between different RESERVE data. Up to 8 different reserve bank informations can be stored into ULM3, but using R9 , you can specify your own RESERVE bank.
PORTABILITY : Portable
|
STATUS
[ULM3 Status]
|
&69C9 CALL [U3 arg string position]
&69CC LP $18 (Yreg)
&69CD LDM
&69CE CASE1 10 TESTS RETURN &6A19
&69D2 CASE2
&00 &6A15
&01 [LIDP Start BASIC pointer]
&02 [LIDP End BASIC pointer]
&03 &6A11
&04 &6A0D
&05 &6A09
&06 &6A05
&07 &6A01
&08 &69FD
&09 &69F3
DEFAULT [ERROR 3]
&69F3 CALL [U3 arg BIN unsigned, X++]
&69F6 LIQ $18 (Yreg)
&69F8 LP $06 (Yl)
&69F9 MVB
&69FA DY
&69FB IY
&69FC RTN
...
|
|
...
&69FD LIDP [Reserve pointer]
&6A00 RTN
&6A01 LIDP [Start Last MERGEd pointer]
&6A04 RTN
&6A05 LIDP [Error @ddr]
&6A08 RTN
&6A09 LIDP [Break @ddr]
&6A0C RTN
&6A0D LIDP [CALL Return @ddr]
&6A10 RTN
&6A11 LIDP [READ pointer]
&6A14 RTN
&6A15 LIDP [Start Variable pointer]
&6A18 RTN
&6A19 LP $02 (A)
&6A1A MVBD
&6A1B JP [U3 Store {B,A} in variable, X++]
|
|
CALL &68B5,Snum;var
CALL &68B5,S9;address;var
STATUS, return the value of a system pointer.
There is the value for num:
0 | Start Variable
|
---|
1 | Start BASIC
|
---|
2 | End BASIC
|
---|
3 | READ
|
---|
4 | CALL Return @ddr
|
---|
5 | Break @ddr
|
---|
6 | Error @ddr
|
---|
7 | Start Last MERGEd
|
---|
8 | Reserve
|
---|
9 | Specify the address of the pointer to see.
|
---|
PORTABILITY : Portable
|
Variable address
[ULM3 var address]
|
&680F CALL [U3 find variable]
&6812 IY
&6813 LIQ $06 (Yl) ; {B,A} <- Y
&6815 LP $02 (A)
&6816 MVB
&6817 JP [U3 Store {B,A} in variable, X++]
|
|
CALL &68B5,Avar1;var2
var2 = address of var1
PORTABILITY : Portable
|
Unit
[ULM3 Unit]
|
&6732 LIDP &787C
&6735 LIA &C1 ;DEGREE
&6737 TSID &02
&6739 JRZP &673C
&673B INCA ;RADIAN
&673C TSID &04
&673E JRZP &6742
&6740 LIA &C3 ;GRAD
&6742 LIDP [OldKey]
&6745 STD
&6746 JP &6AD7 ;end of GET to store the result
|
|
CALL &68B5,Uvar$
var$ = current trigonometric unit.
PORTABILITY : Portable
|
Get cursor position
[ULM3 CURSOR]
|
&67A1 LIDP [CSR Y position]
&67A4 LDD
&67A5 PUSH
&67A6 LIDL &8B ; [CSR X position]
&67A8 LDD
&67A9 LIB &00
&67AB CALL [U3 Store {B,A} in variable]
&67AE POP
&67AF LIB &00
&67B1 JP [U3 Store {B,A} in variable, X++]
|
|
CALL &68B5,CURSOR Xpos;Ypos
Store in Xpos and Ypos the actual position of the text cursor.
PORTABILITY : Portable
|
Tokenize
[ULM3 BASIC]
|
&6947 CAL [Clear input buffer]
&6949 LIDP [String buffer] ; clear the string buffer
&694C LIA &0D
&694E LII &4F
&6950 FILD
&6951 CALL [U3 Read string if not in interactive mode]
&6954 JRCP &69A1
&6956 ORID &0D ; the string is Zero ended : now it's a &0d
&6958 CAL [Y <- Input Buffer]
&695A CALL [Tockenize]
&695D CAL [X <- CALL Rtn @dr]
&695F JRCP &69A1
&6961 CAL [Xreg <- 0] ; create the result
&6963 LIB &6E
&6965 LIA &B0
&6967 LP $15
&6968 LIQ $02 (A)
&696A MVB
&696B LP $14
&696C ORIM &D0
&696E CAL [X <- BA-1] ; compute the length of the string
&6970 LIB &FF
&6972 IXL
&6973 INCB
&6974 CPIA &0D
&6976 JRNZM &6972
&6978 EXAB
&6979 LP $17
&697A EXAM
&697B CAL [X <- CALL Rtn @dr]
&697D JP [U3 Store Xreg in variable, X++]
|
|
CALL &68B5,BASIC;string;var$
Tokenize a string. It's needed before using CALC or you will get a syntax error on Basic functions.
PORTABILITY : ROM 1 only because of call to [Tockenize]
[U3 Read string if not in interactive mode]
|
&68A4 CALL [U3 Fail if in Interactive mode]
&68A7 JP [U3 arg string]
|
[U3 Fail if in Interactive mode]
|
&68AA LP $36 ; check if we are in interactive mode
&68AB TSIM &02
&68AD JRZP &68B2
&68AF CLA
&68B0 CAL [ERROR (accu)]
&68B2 JP &6BC7
|
|
Evaluating an expression
[ULM3 Eval]
|
&6749 CALL [U3 arg string] ; read the string
&674C JRCP &67E7 ; exit on error
&674E CAL [Int read argument]
&6750 JRNCP &6757
&6752 CAL [Xreg <- 0] ;Clear the result on error
&6754 LP $17
&6755 ORIM &55
&6757 CAL [X <- CALL Rtn @dr]
&6759 JP [U3 Store Xreg in variable, X++]
|
|
CALL &68B5,Fstring;var
Evaluate an expression.
e.g :
CALL &68B5,F"X^2";Y
PORTABILITY : Portable
WARNING : if the string contains BASIC function, it could be tokenized before calling Eval or you will got some syntaxe error
CALL &68B5,BASIC "SIN X";K$,FK$;Y
Obviously, if Eval is used in a loop, the tokenization should be done only once.
|
Exiting stacks
[ULM3 FOR]
|
&66D2 IXL
&66D3 CPIA 'A'
&66D5 JRZP &66E3 ; exit all FOR ?
&66D7 LIDP [FOR stack pointer]
&66DA LDD
&66DB CPIA &18 ; check if the stack is not empty
&66DD JRCP &66E3
&66DF SBIA &12
&66E1 STD
&66E2 RTN
&66E3 CAL [CALL Rtn @dr <- X]
&66E5 LIA &06 ; reset the pointer
&66E7 LIDL &2B
&66E9 STD
&66EA RC
&66EB RTN
|
|
[ULM3 GOSUB]
|
&66EC IXL
&66ED CPIA 'A'
&66EF JRZP &66FD ; exit all GOSUB ?
&66F1 LIDP [GOSUB stack pointer]
&66F4 LDD
&66F5 SBIA &02
&66F7 CPIA &90 ; check if the stack is not empty
&66F9 JRCP &66FF
&66FB STD
&66FC RTN
&66FD CAL [CALL Rtn @dr <- X]
&66FF LIA &90
&6701 LIDL &2C
&6703 STD
&6704 RC
&6705 RTN
|
|
CALL &68B5,FOR [A]
CALL &68B5,GOSUB [A]
Unstack one FOR (or GOSUB ) : it's usefull to exit easily from FOR /NEXT or GOSUB/RETURN . With A, we are existing from all pending FOR or GOSUB .
PORTABILITY : Portable
|
Video commodities
These functions are low level tools used by others video functions.
PORTABILITY : Portable
[U3 Inc text cusor]
- M text cursor X
- N text cursor Y
|
&6AB1 INCM ; Inc X pos
&6AB2 LP $0A (M)
&6AB3 CPIM &18 ; Next line ?
&6AB5 JRCP &6ABA
&6AB7 ANIM &00
&6AB9 INCN
&6ABA RTN
|
[U3 Calc @dr video]
- input : {N,M} = pos text cursor
- output : Y = video @ddresse.
|
&67E8 LP $0B (N)
&67E9 LDM
&67EA CAL [Y<-@dr line video]
&67EC LP $0A (M)
&67ED LDM
&67EE JP &1CF9 ; end of [Y<-video @dr of Working CSR]
|
|
[U3 Calc message beginning]
We only have the current cursor position. To got the beginning of the message, we need to decrease this position by the length of the string.
- output: M text cursor X
- output: N text cursor Y
- output: I length of the message
|
&67F1 LIDP [CSR X position]
&67F4 LII &FF
&67F6 LP $0A (M)
&67F7 MVBD
&67F8 LIB &6D ; Beginning of the string buffer
&67FA LIA &5F
&67FC CAL [X <- BA]
&67FE IXL
&67FF CPIA &00 ; it's the end of this string ?
&6801 JRNZP &6804
&6803 RTN
&6804 INCI ; inc string length
&6805 DECM ; dec cursor position
&6806 JRNCM &67FE
&6808 DECN
&6809 LIA &17
&680B LP $0A (M)
&680C EXAM
&680D JRM &67FE
|
|
Video manipulations
-
CALL &68B5,V
-
Video inverse of the last displayed message
-
CALL &68B5,vnum
-
Video inverse starting from the actual CURSOR position and on num characters
-
CALL &68B5,s
-
Underline the last displayed message
-
CALL &68B5,wnum
-
Underline starting from the actual CURSOR position and on num characters
The last displayed message is the last message displayed by PRINT
or PAUSE
commands if the output is not redirected to the printer (PRINT = PRINT
). Give unpredicted result with INPUT
.
Notez bien : There is no clean way to access informations about the last displayed messages. So these functions use [U3 Calc message beginning] to retrieve those informations, but it's only a big dirty hack : so you MUST use them JUST AFTER the PRINT
or the PAUSE
command. Otherwise, the string buffer should be modified and the result is unpredicted.
PORTABILITY : Portable
[ULM3 Undeline length]
|
&677E LIDP &67D9 ; modify the code ...
&6781 ANID &80 ; for setting the last digit
&6783 LIA &47 ; ORMA
&6785 JRP &678E
|
[ULM3 VideoInverse length]
|
&6787 LIDP &67D9 ; modify the code ...
&678A ORID &FF ; for reversing the video data
&678C LIA &45 ; SBM
&678E LIDL &DC
&6790 STD
&6791 CALL [U3 Fail if in Interactive mode]
&6794 CALL [U3 arg BYTE not null]
&6797 LP $18 (Yreg) ; read the length of the message
&6798 LDM
&6799 DECA
&679A LIDP [CSR X position] ; read cursor position
&679D LP $0A (M) ; M=X, N=Y
&679E MVBD
&679F JRP &67CF
|
|
[ULM3 underline]
|
&67B4 LIDP &67D9 ; modify the code ...
&67B7 ANID &80 ; for setting the last digit
&67B9 LIA &47 ; ORMA
&67BB JRP &67C4
|
[ULM3 VideoInverse]
|
&67BD LIDP &67D9 ; modify the code ...
&67C0 ORID &FF ; for reversing the video data
&67C2 LIA &45 ; SBM
&67C4 LIDL &DC
&67C6 STD
&67C7 CALL [U3 Fail if in Interactive mode]
&67CA CALL [U3 Calc message beginning]
&67CD LP $00 (I) ; Read the length of the string
&67CE LDM
&67CF PUSH
&67D0 CALL [U3 Calc @dr video]
&67D3 CAL [X <- Y]
&67D5 LIA &05 ; size of a char
&67D7 PUSH
&67D8 LIB &80 ;Auto-modified code
&67DA IXL
&67DB LP $03 (B)
&67DC ORMA ;Auto-modified code
&67DD EXAB
&67DE STD
&67DF LOOP &67D8
&67E1 CALL [U3 Inc text cusor]
&67E4 LOOP &67D0
&67E6 RC
&67E7 RTN
|
|
Characters redefinition
-
CALL &68B5,D
-
Redefine characters of the last displayed message
-
CALL &68B5,d
-
Redefine characters on the the whole display
The last displayed message is the last message displayed by PRINT
or PAUSE
commands if the output is not redirected to the printer (PRINT = PRINT
). Give unpredicted result with INPUT
.
Notez bien : There is no clean way to access informations about the last displayed messages. So these functions use [U3 Calc message beginning] to retrieve those informations, but it's only a big dirty hack : so you MUST use them JUST AFTER the PRINT
or the PAUSE
command. Otherwise, the string buffer should be modified and the result is unpredicted.
PORTABILITY : Portable
[U3 Calc @dr buffer]
- input : {N,M} = pos text cursor
- output : Y = @dr. of the character in the screen buffer.
|
&6552 LP $0B (N)
&6553 LDM
&6554 CAL [Y<-@dr line screen buffer]
&6556 LP $0A (M)
&6557 LDM
&6558 LP $06 (Yl)
&6559 ADM
&655A DY
&655B RTN
|
[U3 {B;A}<-(Defchar bank pointer)]
|
&671E LIDP [U3 Defchar bank pointer]
&6721 LP $02 (A)
&6722 MVBD
&6723 RTN
|
[ULM3 defchar length]
|
&64F4 LIB &00 ; start position is {0,0}
&64F6 CLA
&64F7 LP $0A (M)
&64F8 LIQ $02 (A)
&64FA MVB
&64FB LII &5F ; Redefining the whole display
&64FD JRP &6505
|
|
[ULM3 defchar]
|
&64FF CALL [U3 Calc message beginning]
&6502 CALL [U3 Fail if in Interactive mode]
&6505 LP $00 (I) ; Read the length of the string
&6506 LDM
&6507 PUSH
&6508 CALL [U3 Calc @dr buffer]
&650B IY ; Read the character
&650C LDD
&650D LP $03 (B)
&650E EXAB
&650F LDM
&6510 ANIA &F0 ; Check if it's a redefined char
&6512 CPIA &10
&6514 JRNZP &651A
&6516 SBIM &10 ; and calcul the char number
&6518 JRP &652C
&651A CPIA &80
&651C JRZP &6522
&651E CPIA &90
&6520 JRNZP &6526
&6522 SBIM &70
&6524 JRP &652C
&6526 CPIA &E0
&6528 JRNZP &654B
&652A SBIM &B0
&652C LDM
&652D PUSH
&652E CALL [U3 Calc @dr video]
&6531 CALL [U3 {B;A}<-(Defchar bank pointer)]
&6534 CAL [X <- BA-1]
&6536 POP
&6537 LIB &00 ; compute the beginning of data
&6539 RC ; offset = char number * 6
&653A SL
&653B JRNCP &653E
&653D INCB
&653E LP $04 (Xl)
&653F ADB
&6540 RC
&6541 SL
&6542 JRNCP &6545
&6544 INCB
&6545 LP $04 (Xl)
&6546 ADB ; X = start back + offset
&6547 LIB &06 ; a char is 6 bytes long
&6549 CAL [{IXL - IYS}*B]
&654B CALL [U3 Inc text cusor]
&654E LOOP &6508
&6550 RC
&6551 RTN
|
|
Switch characters bank
[ULM3 Switch bank]
|
&64CD CALL [U3 arg string position]
&64D0 LP $18 (Yreg)
&64D1 LDM ; read the bank number
&64D2 CPIA &09
&64D4 JRZP &64EE
&64D6 JPNC [ERROR 3]
&64D9 SL ; offset of this pointer
&64DA LIB &00
&64DC CAL [X <- BA-1]
&64DE LIAB [U3 Start defcar banks]
&64E2 LP $04 (Xl)
&64E3 ADB ; add the offset
&64E4 IX
&64E5 LP $02 (A)
&64E6 MVBD
&64E7 LP $02 (A)
&64E8 LIDP [U3 Defchar bank pointer]
&64EB EXBD
&64EC RC
&64ED RTN
&64EE CALL [U3 arg BIN unsigned, X++]
&64F1 LP $18 (Yreg)
&64F2 JRM &64E8
|
|
CALL &68B5,$num
CALL &68B5,$9;address
Set redefinition table number num as the active table
If num=9, you can specify the table address as the second argument.
PORTABILITY : Portable
|
RAW keyboard test
[ULM3 RAW keyboard test]
|
&6A1E CALL [U3 arg BIN unsigned]
&6A21 LIQ $18 (Yreg)
&6A23 LP $02 (A)
&6A24 MVB
&6A25 LIP $5C (Port A)
&6A27 EXAM
&6A28 EXAB
&6A29 LIDP &7E00
&6A2C STD
&6A2D OUTA
&6A2E INA
&6A2F LIB &00
&6A31 JP [U3 Store {B,A} in variable, X++]
|
|
CALL &68B5,T{&7E00}*256 + {portA};var
Test if is some key are pressed, in RAW mode. The input value of portA is stored in var.
PORTABILITY : Portable
|
GET
[ULM3 GET]
|
&6AC7 CAL [LIDP indicators]
&6AC9 ANID &EF ; remove 'RUN' (see note 1)
&6ACB LIA &23 ; see note 2
&6ACD CAL &1206 ; [GET + 2], after LIA 03
&6ACF CAL [LIDP indicators]
&6AD1 TSID &28 ; set 'RUN' if 'PRO' and 'RSV' are unset
&6AD3 JRNZP &6AD7
&6AD5 ORID &10
&6AD7 CAL [Xreg <- 0] ; set the result
&6AD9 LIB &6F ;the character is in &6F57
&6ADB LIA &57 ; [OldKey]
&6ADD LP $15
&6ADE LIQ $02 (A)
&6AE0 MVB
&6AE1 LP $14 ; it's a string ...
&6AE2 ORIM &D0
&6AE4 LP $17 ; only 1 character long
&6AE5 ORIM &01
&6AE7 CAL [X <- CALL Rtn @dr]
&6AE9 JP [U3 Store Xreg in variable]
|
|
CALL &68B5,Gvar$
Like INKEY$ but wait until a key is pressed.
PORTABILITY : Portable
NOTE 1 : [GET] will crash the system if a program is launched by [DEF]+key. To avoid this, the 'RUN' indicator is unset while we are waiting for an input.
NOTE 2 : This LIA will product a 'beep' at each key pressed. See BEEP command
|
Japanese mode
[ULM3 Enable japanese]
|
&6AF1 CAL [LIDP &6F16]
&6AF3 ORID &80
&6AF5 RTN
|
|
[ULM3 Disable japanese]
|
&6AEC CAL [LIDP &6F16]
&6AEE ANID &7F
&6AF0 RTN
|
|
CALL &68B5,J
CALL &68B5,j
Enable (J) or disable (j) Japanese mode.
PORTABILITY : Portable
|
BEEP
[ULM3 BEEP]
|
&655C IXL ; read the argument
&655D CAL [CALL Rtn @dr <- X]
&655F EXAB
&6560 LIA &03
&6562 LP $03 (B)
&6563 CPIM &DA ; STOP
&6565 JRZP &656E
&6567 CPIM &D3 ; ON
&6569 JPNZ [ERROR 1]
&656C ORIA &20 ; we need a beep
&656E LIDP &65AE ; in the keyboard driver
&6571 STD
&6572 LIDL &8B ; in the keyboard driver
&6574 STD
&6575 LIDP &663B ; in the keyboard driver
&6578 STD
&6579 LIDP &6ACC ; in GET
&657C STD
&657D RC
&657E RTN
|
|
CALL &68B5,BEEP ON
CALL &68B5,BEEP STOP
Activate or stop beep on each key hit.
Works only if the keyboard driver is installed and on GET.
Notez-bien : if the keyboard driver is installed, a beep is ALWAYS emitted if the input buffer is full.
PORTABILITY : Portable
|
Install the keyboard driver
[ULM3 install keyboard driver]
|
&658F LDR ; save the stack pointer
&6590 EXAB
&6591 LIA &5C ; set [ULM3 Keyboard driver]
&6593 STR ; as keyboard interpretation function
&6594 LIA &65
&6596 PUSH
&6597 LIA &9D
&6599 PUSH
&659A EXAB ; restore the stack pointer
&659B STR
&659C RTN
|
|
[ULM3 force keyboard driver]
|
&657F LIA &5C
&6581 STR
&6582 CAL &0901 ; make some cleaning
&6584 JRP [ULM3 Keyboard driver]
|
|
-
CALL &68B5,k
- Smoothly install the keyboard driver. It's totally transparent whatever the current status of the machine is.
-
CALL &68B5,K
- Force the install of the keyboard driver. The current CPU stack is cleared and the machine is reset to an interactive use in RUN MODE.
Caution :
- only use it if another keyboard driver is loaded and you want to remove it.
- K shouldn't be use in a program or your program will stop.
PORTABILITY : ROM 1 only (in fact these functions by themselve are portable but it's not the case of the driver)
Keyboard driver
[ULM3 Keyboard driver]
|
&659D CAL [LIDP indicators]
&659F ANID &EF ; unset RUN
&65A1 LIDP &6EFF ; check if the input buffer is full
&65A4 LDD
&65A5 CPIA &0D
&65A7 JRZP &65AD
&65A9 LIA &33
&65AB JRP &65AF
&65AD LIA &23 ; warning : auto-modified by BEEP
&65AF CAL &1206 ; [GET]+2
&65B1 CAL [LIDP indicators]
&65B3 TSID &28
&65B5 JRNZP &65B9
&65B7 ORID &10 ; reactivate RUN
&65B9 TSID &03 ; SHIFT or DEF
&65BB JRNZP &65F7
&65BD EXAB
&65BE LP $03 (B)
&65BF LDM
&65C0 CASE1 16 TESTS RETURN [ULM3 Keyboard driver]
&65C4 CASE2 ; normal key dispatcher (from &8021)
&02 &E301 ; [CLS]
&03 &0901 ; [CA]
&04 &E6AA ; [Up]
&05 &D84C ; [Down]
&06 &AEC0 ; [P=NP]
&07 &D15B ; [BRK]
&08 &AE25 ; [MODE]
&0A &AED7 ; [OFF]
&0B &E801 ; [INS]
&0C &E8A0 ; [DEL]
&0D &B250 ; [ENTER]
&0E &E490 ; [left]
&0F &E4E6 ; [right]
&13 &E5B4 ; [Shift left]
&14 &E5A7 ; [Shift right]
&16 &AED5 ; [Lock]
DEFAULT &AA48
;
; processing SHIFT or DEF
;
&65F7 TSID &01 ; SHIFT
&65F9 JRZP &6603
&65FB CPIA &08 ; [MODE] : switch to reserve mode
&65FD JRZP &6601
&65FF ANID &FC ; turn off SHIFT and DEF
&6601 JRM &65BD
&6603 ANID &FC ; turn off SHIFT and DEF
&6605 EXAB
&6606 LIA &65 ; the return address is the driver
&6608 PUSH
&6609 LIA &9D
&660B PUSH
&660C EXAB
&660D SBIA &30
&660F JRCP &6618
&6611 CPIA &09
&6613 JPC &684A ; jump to [ULM3 set RESERVE]
&6616 JRZP &662E
&6618 ADIA &30
&661A CPIA &0A ;OFF ?
&661C JRNZP &6623
&661E CAL [Save system memory]
&6620 JP [Auto power OFF]
...
|
|
...
;
; processing DEF
;
&6623 PUSH
&6624 CALL &D512
&6627 POP
&6628 ORIA &80
&662A EXAB
&662B JP &AC51
;
; entering a character by its code
;
&662E CALL [U3 internal bug fix get]
&6631 NOPW
&6632 CALL [U3 conv kbd digit]
&6635 JRCM &662E ; unwanted character
&6637 SWP
&6638 LP $0F
&6639 EXAM
&663A LIA &23
&663C CAL &1206
&663E CALL [U3 conv kbd digit]
&6641 JRCM &663A ; unwanted character
&6643 LP $0F
&6644 ORMA
&6645 LDM
&6646 JP &AA66 ; add a new character
|
[U3 internal bug fix get]
|
&6586 CAL [LIDP indicators]
&6588 ANID &EF
&658A LIA &23
&658C JP &1206
|
[U3 conv kbd digit]
|
&6649 SBIA &28 ; convert the char to an offset
&664B JRCP &6659
&664D CPIA &12
&664F JRCP &665B
&6651 SBIA &07
&6653 JRCP &6659
&6655 CPIA &18
&6657 JRCP &665B
&6659 SC
&665A RTN
&665B LIB &00 ; read the number associated w/ this key
&665D CAL [X <- BA-1]
&665F LIAB [U3 conversion table]
&6663 LP $04 (Xl)
&6664 ADB
&6665 IXL
&6666 RC
&6667 RTN
|
[U3 conversion table]
|
&6668 DC &0A, &0A, &0C, &0C, &0D, &0D, &0F, &0B
&6670 DC &00, &01, &02, &03, &04, &05, &06, &07
&6678 DC &08, &09, &0A, &0B, &0C, &0D, &0E, &0F
|
|
This driver add following new feature to the keyboard :
- Beep at each keypress (see BEEP)
- Beep higher if the input buffer is full
- [DEF] + num switch to reserve bank number num (see R function)
- [DEF] + 9 : enter a character by its ASCII code. This code must be entered in HEXADECIMAL. As short-cut [(] and [)] act as A, [/] and [:] as B,[*] and [;] as C, [-] and [,] as E and [.] and [+] as F.
- All other key can be used as label called by [DEF] including small characters or katana !
- [DEF][OFF] shut-down the machine like the 'AutoPowerOff'. Please not, when the system is powered up again, the keyboard is not any more active.
PORTABILITY : ROM 1 only, many calls to upper ROM