mirror of
https://github.com/antoinevignau/source.git
synced 2024-11-19 22:31:52 +00:00
613 lines
14 KiB
ArmAsm
613 lines
14 KiB
ArmAsm
*
|
|
* SpeechLab 20A RAM code
|
|
* (c) 1978, Heuristics
|
|
* (c) 2019, Brutal Deluxe Software
|
|
* Visit http://www.brutaldeluxe.fr/
|
|
*
|
|
* Thank you, Jeremy Apple
|
|
*
|
|
|
|
org $6000
|
|
mx %11
|
|
lst off
|
|
|
|
*---------------------------------------------------------
|
|
* Version
|
|
*
|
|
* v1.0 - 20190120 - Antoine Vignau
|
|
* After a couple of tries, it is now working
|
|
* Thank you for your help, Jeremy Apple
|
|
* It would be cool to have a new version of the card!
|
|
*
|
|
|
|
*--- Equates
|
|
|
|
numWORDS = 32 ; number of words one can record (variable)
|
|
wordSIZE = 64 ; length of a spoken word (fixed)
|
|
|
|
*--- Zero page equates
|
|
|
|
CSWL = $36 ; for output
|
|
CSWH = CSWL+1
|
|
KSWL = CSWH+1 ; for input
|
|
KSWH = KSWL+1
|
|
|
|
A5H = $45 ; ACC
|
|
XREG = A5H+1 ; $46
|
|
YREG = XREG+1 ; $47
|
|
STATUS = YREG+1 ; $48
|
|
|
|
zpF0 = $fc ; Zero page addresses I use
|
|
zpF1 = zpF0+1 ; $FC..$FF
|
|
zpPTR = zpF1+1
|
|
|
|
*--- Firmware/ROM equates
|
|
|
|
BELL1 = $FBDD ; Beep
|
|
COUT1 = $FDF0 ; Output a char
|
|
RESTORE = $FF3F ; Restore A/X/Y/P
|
|
SAVE = $FF4A ; Save A/X/Y/P/S
|
|
IORTS = $FF58 ; The official RTS
|
|
|
|
*---------------------------------------------------------
|
|
* How to use
|
|
*
|
|
* Installation of the driver
|
|
* 10 PRINT CHR$(4);"BLOAD SPEECHLAB20A RAM DRIVER"
|
|
* 20 DP = 24576 : REM $6000 FOR PR#
|
|
* 30 DI = DP + 3 : REM $6003 FOR IN#
|
|
* 40 POKE DP + 8, 5 : REM SLOT OF THE CARD
|
|
* REM NO NEED FOR LOMEM ANYMORE
|
|
*
|
|
* Init the card
|
|
* 10 CALL DP : PRINT : CALL DP
|
|
* ==> simulates PR#slot : PRINT : PR#0
|
|
*
|
|
* Get the buffer address
|
|
* 10 BU = PEEK(DP + 7) * 256 + PEEK(DP + 6)
|
|
*
|
|
* Record a word
|
|
* 10 CALL DP : PRINT "WORD" : CALL DP
|
|
* ==> simulates PR#slot : PRINT "WORD" : PR#0
|
|
*
|
|
* Get a word
|
|
* 10 CALL DI : INPUT V$ : CALL DI
|
|
* ==> simulates IN#slot : INPUT V$ : IN#0
|
|
* ==> If V$ is an empty string, no word was recognized
|
|
*
|
|
|
|
*---------------------------------------------------------
|
|
* Room for improvement
|
|
*
|
|
* Make buffers movable
|
|
* The buffers follow the code. One could add pointers
|
|
* to put them in other areas of memory
|
|
*
|
|
* Change the number of words
|
|
* That one is easy, change numWORDS to the value you want
|
|
*
|
|
* PR# and IN#
|
|
* One could keep the doPR and doIN to simulate the PR#
|
|
* and IN# BASIC calls. PR#0 and IN#0 could be kept
|
|
* That would save one page of code
|
|
*
|
|
|
|
*---------------------------------------------------------
|
|
* Entry point
|
|
|
|
jmp doPR ; CALL $6000
|
|
jmp doIN ; CALL $6003
|
|
da ptrBUFFER ; PEEK($6007)*256 + PEEK($6006)
|
|
L12F2 ds 1 ; POKE($6008),slot
|
|
; later transformed to slot*16
|
|
|
|
*---------------------------------------------------------
|
|
* The card runs with the INT ROM on
|
|
* If the "modern" ROMs are called,
|
|
* then calls to SAVE/RESTORE will be useless
|
|
|
|
LC809 ; our new entry point
|
|
lda L12F2 ; is slot already
|
|
cmp #7+1 ; set to slot*16?
|
|
bcs LC817 ; yes
|
|
asl
|
|
asl
|
|
asl
|
|
asl
|
|
sta L12F2 ; no, do slot*16
|
|
|
|
LC817 JSR SAVE ; save all parms
|
|
|
|
LDA CSWH ; output is already set to our card?
|
|
CMP #>LC900 ; L12F1
|
|
BEQ LC878 ; yes
|
|
|
|
LDA #LC84B
|
|
STA KSWH
|
|
LDA #IORTS
|
|
STA CSWH
|
|
|
|
LDY #$00 ; string index is 0
|
|
STY L12F4
|
|
JSR LC956 ; DO MAGIC
|
|
CMP #numWORDS
|
|
BPL LC875
|
|
TAX ; index
|
|
LDA L12F6,X ; pointer
|
|
STA zpPTR
|
|
LDA L1317,X
|
|
STA zpPTR+1
|
|
JSR RESTORE ; restore
|
|
|
|
LC84B JSR SAVE ; save
|
|
LDY L12F4 ; get index
|
|
LDA (zpPTR),Y ; get char
|
|
INC L12F4 ; y++
|
|
CMP #$8D ; end of string?
|
|
BNE LC864 ; no
|
|
|
|
LC85A LDA #LC817
|
|
STA KSWH
|
|
LDA #$8D ; exit with a RET
|
|
LC864 PHA ; save
|
|
JSR RESTORE ; restore
|
|
PLA ; pull A
|
|
RTS ; return
|
|
|
|
LC86A LDA #COUT1
|
|
STA CSWH
|
|
rts ; exit to RANGE ERR (modified)
|
|
|
|
LC875 JMP LC85A
|
|
|
|
*--- Card is already init'ed
|
|
|
|
LC878 LDA A5H ; get a char
|
|
CMP #$8D ; 8D means reset list of words
|
|
BEQ LC8D8
|
|
|
|
LDA #LC89F
|
|
STA CSWH
|
|
|
|
LDY #$00 ; Y as a counter
|
|
STY L12F4
|
|
LDX L12F3 ; word index
|
|
CPX #numWORDS
|
|
BPL LC86A ; we're full!
|
|
LDA L12F6,X ; get its pointer
|
|
STA zpPTR
|
|
LDA L1317,X
|
|
STA zpPTR+1
|
|
JSR RESTORE ; restore registers
|
|
|
|
LC89F JSR SAVE ; save registers
|
|
LDA A5H ; get A
|
|
LDY L12F4 ; get Y
|
|
STA (zpPTR),Y ; save char
|
|
INC L12F4 ; y++
|
|
CMP #$8D
|
|
BNE LC8D4
|
|
|
|
LDA L12F3 ; we're done, get word index
|
|
JSR LC909 ; DO MAGIC
|
|
INC L12F3 ; next index
|
|
LDX L12F3 ; get it again
|
|
LDA zpPTR ; ptr to char
|
|
CLC
|
|
ADC L12F4 ; +index in string
|
|
STA L12F6,X ; save pointer low
|
|
LDA zpPTR+1
|
|
ADC #$00
|
|
STA L1317,X ; save pointer high
|
|
|
|
LDA #LC817
|
|
STA CSWH
|
|
LC8D4 jmp RESTORE ; restore and exit (JMP)
|
|
|
|
LC8D8 LDA #$00 ; word index
|
|
STA L12F3
|
|
LDA #L1339
|
|
STA L1317
|
|
LDA #$00 ; init table of words
|
|
LDX #numWORDS-1
|
|
LC8EB STA L0820,X
|
|
DEX
|
|
BPL LC8EB
|
|
jmp RESTORE ; restore all and return (JMP)
|
|
|
|
*---------------------------------------------------------
|
|
*--- Buffers and friends
|
|
|
|
L081F ds 1 ; a value
|
|
L12F3 ds 1 ; index in list of words, see L12F6
|
|
L12F4 ds 1 ; Y as an index
|
|
L12F5 ds 1 ; A as an index
|
|
|
|
ds \
|
|
|
|
*---------------------------------------------------------
|
|
* The $Cs00 page
|
|
|
|
LC900 JSR LC809
|
|
|
|
LC909 STA L081F
|
|
TAX
|
|
LDA #$01
|
|
STA L0820,X
|
|
|
|
LC912 JSR LC973
|
|
BEQ LC96D
|
|
JSR LCB2D
|
|
LDA #L0AF1
|
|
STA L0808+2
|
|
LDA #$00
|
|
LSR L081F
|
|
BCC LC92D
|
|
LDA #wordSIZE
|
|
LC92D LSR L081F
|
|
BCC LC934
|
|
ORA #$80
|
|
LC934 CLC
|
|
ADC L0808+1
|
|
STA L0808+1
|
|
LDA L0808+2
|
|
ADC L081F
|
|
STA L0808+2
|
|
LDA #L0AB1
|
|
STA L0805+2
|
|
LDA #wordSIZE-1
|
|
JSR L0804
|
|
LDA #$00
|
|
RTS
|
|
|
|
LC956 JSR LC973
|
|
CMP #$00
|
|
BEQ LC967
|
|
JSR LCB2D
|
|
JSR LCA94
|
|
LDA L0840
|
|
RTS
|
|
|
|
LC967 JSR BELL1
|
|
JMP LC956
|
|
|
|
LC96D JSR BELL1
|
|
JMP LC912
|
|
|
|
*--- CALLED BY $Cs00
|
|
|
|
LC973 LDA #$00
|
|
STA L0840+$1
|
|
STA L0840+$2
|
|
LC97B LDA #L0859
|
|
STA L080F+2
|
|
JSR LC9E9
|
|
BEQ LC97B
|
|
LDA #$08
|
|
STA L0840+$7
|
|
LC98F JSR LC9E9
|
|
BEQ LC973
|
|
DEC L0840+$7
|
|
BNE LC98F
|
|
LDA #$0A
|
|
STA L0840+$8
|
|
LC99E JSR LC9E9
|
|
BEQ LC9B9
|
|
LDA #$0A
|
|
STA L0840+$8
|
|
LC9A8 LDA L080F+2 ; end of buffer?
|
|
CMP #>L0AB1
|
|
BNE LC99E
|
|
LDA L080F+1
|
|
CMP #L0859
|
|
ROR
|
|
ROR L0840+$15
|
|
ROR
|
|
ROR L0840+$15
|
|
LDA L0840+$15
|
|
RTS
|
|
|
|
*---------------------------------------------------------
|
|
|
|
LC9E9 LDY #$00
|
|
LDX L12F2
|
|
STY L0840+$9
|
|
LDA $C080,X
|
|
EOR #$FF
|
|
AND #$01
|
|
BEQ LCA0B
|
|
STA L0840+$9
|
|
JMP LCA09
|
|
|
|
ds \
|
|
|
|
*---------------------------------------------------------
|
|
|
|
LCA09 LDA #$08
|
|
LCA0B JSR L080F
|
|
LDA $C080,X
|
|
EOR #$FF
|
|
AND #$10
|
|
BEQ LCA1A
|
|
STA L0840+$9
|
|
LCA1A LDA #$08
|
|
JSR L080F
|
|
JSR LCA26
|
|
LDA L0840+$9
|
|
RTS
|
|
|
|
LCA26 LDA #$C8 ; counter
|
|
STA L0840+$A
|
|
LDA #$00
|
|
STA L0840+$4
|
|
STA L0840+$5
|
|
LDA L0840+$1
|
|
STA L0840+$B
|
|
LDA L0840+$2
|
|
STA L0840+$C
|
|
LCA3F LDA $C080,X
|
|
AND #$08
|
|
CMP L0840+$B
|
|
BEQ LCA52
|
|
STA L0840+$B
|
|
INC L0840+$4
|
|
LCA4F JMP LCA5B
|
|
|
|
LCA52 LDA L0840+$4
|
|
JMP LCA58
|
|
LCA58 JMP LCA4F
|
|
|
|
LCA5B LDA $C080,X
|
|
AND #$80
|
|
CMP L0840+$C
|
|
BEQ LCA6E
|
|
STA L0840+$C
|
|
INC L0840+$5
|
|
LCA6B JMP LCA77
|
|
|
|
LCA6E LDA L0840+$5
|
|
JMP LCA74
|
|
LCA74 JMP LCA6B
|
|
|
|
LCA77 DEC L0840+$A
|
|
BNE LCA3F
|
|
LDA L0840+$4
|
|
CMP #$20
|
|
BCC LCA86
|
|
STA L0840+$9
|
|
LCA86 JSR L080F
|
|
LDA L0840+$5
|
|
CMP #$50
|
|
BCC LCA90
|
|
LCA90 JSR L080F
|
|
RTS
|
|
|
|
LCA94 LDA #L0AF1
|
|
SBC #$00
|
|
STA L0800+2
|
|
LDA #$F4
|
|
STA L0840+$D
|
|
LDA #$01
|
|
STA L0840+$E
|
|
LDA #$20
|
|
STA L0840
|
|
LDY #$FF
|
|
LCAB4 INY
|
|
CPY #numWORDS
|
|
BMI LCABA
|
|
RTS
|
|
|
|
LCABA LDA #wordSIZE ; next
|
|
CLC
|
|
ADC L0800+1
|
|
STA L0800+1
|
|
LDA #$00
|
|
ADC L0800+2
|
|
STA L0800+2
|
|
LDA L0820,Y
|
|
BEQ LCAB4
|
|
LDA #$00
|
|
STA L0840+$F
|
|
STA L0840+$10
|
|
LDX #wordSIZE-1
|
|
LCADA JSR L0800
|
|
SEC
|
|
SBC L0AB1,X
|
|
BCS LCAE7
|
|
EOR #$FF
|
|
ADC #$01
|
|
LCAE7 CLC
|
|
ADC L0840+$10
|
|
STA L0840+$10
|
|
LDA #$00
|
|
ADC L0840+$F
|
|
STA L0840+$F
|
|
CMP L0840+$D
|
|
JMP LCB09
|
|
|
|
ds \
|
|
|
|
*---------------------------------------------------------
|
|
|
|
LCB09 BCC LCB15
|
|
BNE LCAB4
|
|
LDA L0840+$10
|
|
CMP L0840+$E
|
|
BCS LCAB4
|
|
LCB15 DEX
|
|
BMI LCB1B
|
|
JMP LCADA
|
|
|
|
LCB1B LDA L0840+$F
|
|
STA L0840+$D
|
|
LDA L0840+$10
|
|
STA L0840+$E
|
|
STY L0840
|
|
JMP LCAB4
|
|
|
|
*--- CALLED BY $Cs00
|
|
|
|
LCB2D LDA #L0AB1
|
|
STA L080F+2
|
|
LDA L0840+$15
|
|
STA L0840+$13
|
|
LDA #$00
|
|
STA L0840+$11
|
|
LDA #$10
|
|
STA L0840+$12
|
|
JSR LCBA3
|
|
STA zpF0
|
|
STA zpF1
|
|
LDA L0840+$13
|
|
ASL
|
|
ASL
|
|
STA L0840+$16
|
|
BEQ LCB5B
|
|
SEC
|
|
SBC #$04
|
|
LCB5B CLC
|
|
ADC #L0859
|
|
ADC #$00
|
|
STA L081B+2
|
|
LDA #$10
|
|
STA L12F5
|
|
LCB6D LDY #$00
|
|
LCB6F JSR L081B
|
|
JSR L080F
|
|
INY
|
|
CPY #$04
|
|
BNE LCB6F
|
|
LDA zpF0
|
|
CLC
|
|
ADC zpF1
|
|
STA zpF0
|
|
SEC
|
|
SBC #$10
|
|
BMI LCB8C
|
|
STA zpF0
|
|
LDA #$04
|
|
BPL LCB8E
|
|
LCB8C LDA #$00
|
|
LCB8E CLC
|
|
ADC L0840+$16
|
|
ADC L081B+1
|
|
STA L081B+1
|
|
BCC LCB9D
|
|
INC L081B+2
|
|
LCB9D DEC L12F5
|
|
BNE LCB6D
|
|
RTS
|
|
|
|
LCBA3 CLC
|
|
LDX #$F7
|
|
LDA L0840+$11
|
|
LCBA9 ROL L0840+$13
|
|
INX
|
|
BMI LCBB2
|
|
JMP LCBC7
|
|
|
|
LCBB2 ROL
|
|
BCC LCBBB
|
|
SBC L0840+$12
|
|
SEC
|
|
BCS LCBA9
|
|
LCBBB SEC
|
|
SBC L0840+$12
|
|
BCS LCBA9
|
|
ADC L0840+$12
|
|
CLC
|
|
BCC LCBA9
|
|
LCBC7 STA L0840+$11
|
|
RTS
|
|
|
|
*---------------------------------------------------------
|
|
|
|
L0800 LDA |$0000,X ; CODE AT $0800
|
|
RTS
|
|
|
|
L0804 TAX
|
|
L0805 LDA |$0000,X
|
|
L0808 STA |$0000,X
|
|
DEX
|
|
BPL L0805
|
|
RTS
|
|
|
|
L080F STA |$0000
|
|
INC L080F+1
|
|
BNE L081A
|
|
INC L080F+2
|
|
L081A RTS
|
|
|
|
L081B LDA |$0000,Y
|
|
RTS
|
|
|
|
ds \
|
|
|
|
*---------------------------------------------------------
|
|
* doPR
|
|
* We simulate PR#slot and here
|
|
|
|
doPR lda #0
|
|
bne doPRR ; restore
|
|
|
|
ldx CSWL ; put our hook routine
|
|
stx oldCSWL
|
|
ldy CSWH
|
|
sty oldCSWH
|
|
ldx #LC900
|
|
tya ; A is not 0
|
|
|
|
doPRE stx CSWL ; save values
|
|
sty CSWH
|
|
sta doPR+1 ; flip/flop
|
|
rts
|
|
|
|
doPRR ldx oldCSWL ; restore old values
|
|
ldy oldCSWH
|
|
lda #0
|
|
beq doPRE
|
|
|
|
oldCSWL ds 1
|
|
oldCSWH ds 1
|
|
|
|
*---------------------------------------------------------
|
|
* doIN
|
|
* We simulate IN#slot and here
|
|
|
|
doIN lda #0
|
|
bne doINR ; restore
|
|
|
|
ldx KSWL ; put our hook routine
|
|
stx oldKSWL
|
|
ldy KSWH
|
|
sty oldKSWH
|
|
ldx #LC900
|
|
tya ; A is not 0
|
|
|
|
doINE stx KSWL ; save values
|
|
sty KSWH
|
|
sta doIN+1 ; flip/flop
|
|
rts
|
|
|
|
doINR ldx oldKSWL ; restore old values
|
|
ldy oldKSWH
|
|
lda #0
|
|
beq doINE
|
|
|
|
oldKSWL ds 1
|
|
oldKSWH ds 1
|
|
|
|
*---------------------------------------------------------
|
|
*--- Buffers and friends
|
|
|
|
ptrBUFFER ; address of the buffer
|
|
L0840 ds $19 ; variables
|
|
L0859 ds 600 ; read buffer
|
|
; the buffer is $258 (600d) bytes long
|
|
L0AB1 ds wordSIZE ; a buffer ($40 bytes)
|
|
L0AF1 ds numWORDS*wordSIZE ; a buffer ($800 bytes)
|
|
|
|
L0820 ds numWORDS ; a table of numWORDS bytes (0: no word, 1: a word)
|
|
L12F6 ds numWORDS+1 ; table of pointers low ($21 bytes)
|
|
L1317 ds numWORDS+1 ; table of pointers high ($21 bytes)
|
|
L1339 ds numWORDS*numWORDS ; a buffer for words (the words)
|