; Utility.asm. Assembly language utility routines
; Last change July 21, 1981 12:38 PM by Beau Sheil
; Tone change March 17, 1981 6:35 PM by Beau Sheil
; Last change February 4, 1981 10:46 PM by Beau Sheil
; Chord change November 18, 1980 10:30 AM by Beau Sheil
; Previous last change November 11, 1980 5:36 PM by Beau Sheil
.ENT VP, VP2, Bytes2, EqNIL, EmAddr
.ENT MkSmallPos, MkSmallNeg, Smallp, SmallUnbox, SmallNegUnbox
.ENT UCase, ReadClock, TimeSince
.ENT MachineType, Version, Serial, DoBitBlt
; procedures used
.EXTN RAIDCode
; statics used
.EXTD RMSK, lvVPtr, VPtr0, VPtr1
.EXTN EmulatorSpace
; new opcodes defined
.DUSR SWAT = #77400 ; For where one shouldnt go
.SREL
VP: .vp
VP2: .vp2
Bytes2: .by2
EqNIL: .eqn
EmAddr: .ea
MkSmallPos: .msp
MkSmallNeg: .msn
Smallp: .smp
SmallUnbox: .smunb
SmallNegUnbox: .smnunb
UCase: .uc
ReadClock: .rclk
TimeSince: .tme
MachineType: .mt
Version: .vers
Serial: .ser
DoBitBlt: .dbbt
.NREL
; VP(lvAddr) -> virtual page in ac0
.vp: sta 3,1,2
mov 0,3
lda 0,0,3
lda 1,1,3
jmp vp
; VP2(vahi, valo) -> virtual page in ac0
.vp2: sta 3,1,2
vp: lda 3,RMSK
ands 3,0
lda 3,LMSK
ands 3,1
add 1,0
lda 3,1,2
jmp 1,3
LMSK: 177400
; Bytes2(hibyte, lobyte) -> word {hibyte,lobyte} in ac0
.by2: sta 3,1,2
lda 3,RMSK
ands 3,0
and 3,1
add 1,0
lda 3,1,2
jmp 1,3
; Smallp(lvN) -> whether lvN is a SMALLP
.smp: sta 3,1,2
mov 0,3
lda 0,0,3
lda 1, .smallp
sub# 0,1,snr
jmp .true
lda 1, .smalln
sub# 0,1,snr
jmp .true
jmp .false ; .true and .false restore ac3
; SmallNegUnbox(lvN) unbox if smallnegp, otherwise error
.smnunb: lda 1, .smalln
jmp .smun2
; SmallUnbox(lvN) unbox if smallposp, otherwise error
.smunb: lda 1, .smallp
.smun2: sta 3,1,2
mov 0,3
lda 0,0,3
sub# 0,1,szr
jmp .notsm
lda 0,1,3
lda 3,1,2
jmp 1,3
.notsm: mov 3, 1 ; original arg
jsr .smerr ; get addr of error msg into ac3
.TXTM B
.TXT "Not a small posp"
.smerr: mov 3, 0 ; addr of error msg
jsrii .raid
2
SWAT ; cant return
.raid: RAIDCode
.smallp: 16 ;hi order word of small positive numbers
.smalln: 17 ;hi order word of small negative numbers
.es: EmulatorSpace
; EmAddr(n) ; makes an emulator ptr of n
.ea: lda 1,@.es
jmp .ms
; MkSmallNeg(n) ;n is treated as UNSIGNED
.msn: lda 1,.smalln
jmp .ms
; MkSmallPos(n)
.msp: lda 1,.smallp
.ms: sta 0,VPtr1
sta 1,VPtr0
lda 0,lvVPtr
jmp 1,3
; EqNIL(ptr) - NIL is <0><0> by definition
.eqn: sta 3,1,2
mov 0,3
lda 0,0,3
mov 0,0,szr
jmp .false
lda 0,1,3
mov 0,0,szr
.false: sub 0,0,skp ; false is 0
.true: adc 0,0 ; true is -1
lda 3,1,2
jmp 1,3
; UCase(cc) ;returns Upper Case version of character code
.uc: lda 1,.uca ;range check
adcz# 0,1 szc ;skip if ac0 ge 'a
jmp 1,3 ;other characters are OK
lda 1,.ucz
adcz# 1,0 szc ;skip if ac0 le 'z
jmp 1,3 ;other characters are OK
lda 1,.uc0
and 1,0 ;turn off high bit
jmp 1,3
.uc0: #337 ; select only low order byte, turn off bit 2
.uca: "a
.ucz: "z
; ReadClock(ptr) Reads ucode clock into ptr!0 and ptr!1
.rclk: sta 3,1,2
mov 0,3
RCLK
sta 0,0,3
sta 1,1,3
lda 3,1,2
jmp 1,3
; TimeSince(ptr) -> time in msec since time in ptr!0 and ptr!1
.tme: sta 3,1,2
mov 0,3
RCLK ; AC0/1 ← current time
; sta 0, savAC0 ; *** Strictly for debugging ***
; sta 1, savAC1 ; *** Strictly for debugging ***
sta 2, savAC2
lda 2,0,3 ; AC2/3 ← start time
lda 3,1,3
subz 3,1 szc ;
sub 2,0 skp ; AC0/1 ← AC0/1 - AC2/3
adc 2,0 ;
lda 2, msc1
div ; convert to msec
SWAT ; interval too long
lda 2, msc2
subz# 2,0 szc
inc 1,1 ; round up
mov 1,0
lda 2, savAC2
lda 3,1,2
jmp 1,3
;savAC0: 0 ; *** Strictly for debugging ***
;savAC1: 0 ; *** Strictly for debugging ***
savAC2: 0
msc1: 1681. ; 1msec / .595 usec
msc2: 840. ; half the above
; MachineType() = Version() rshift 12 = Dorado or Dolphin
.mt: VERS
lda 1, hi4
and 1, 0
60004 ; cycle4 - moves [0:3] -> [12:15]
jmp 1,3
hi4: 170000 ; selects bits [0:3]
; Version()
.vers: VERS
jmp 1,3
; Serial() returns the Alto Serial number
.ser: sub 0,0
SIO
lda 1, RMSK ; we want the right 8 bits only
and 1, 0
jmp 1,3
; DoBitBlt(Ebbt)
.dbbt: sta 3,1,2
sta 2, bbtAC2 ; *** Strictly for debugging ***
mov 2,1
mov 0,2 ; AC2← BitBltTable
sta 1,1,2 ; old AC2 into word 1 of BBT
sub 1,1 ; AC1← 0
BITBLT
lda 2,1,2 ; restore stack
sub 1,1 ; *** Strictly for debugging ***
sta 1, bbtAC2 ; *** Strictly for debugging ***
lda 3,1,2
jmp 1,3
bbtAC2: 0 ; *** Strictly for debugging ***
; The lines labelled as debugging save the old stack pointer to help us
; chase an outstanding BitBlt bug. They should be removed when it is found.
; Beau 27/Jun/80
; The following are arithmetic routines used ONLY by RAID number printing
; They are here for convenience as I dont want to use a whole file for them
.ENT Divide, Negate
.SREL
Divide: DIVD
Negate: NEGTE
.NREL
; NEGATE (VEC)
NEGTE: STA 3,1,2
MOV 0,3
LDA 0,0,3
LDA 1,1,3
NEG 1,1,SNR
NEG 0,0,SKP
COM 0,0
STA 0,0,3
STA 1,1,3
MOV 3,0
LDA 3,1,2
JMP 1,3
; DIVIDE(a2, b) -> r, leaves q in a
DIVD: STA 3,1,2
STA 2,TEMP
MOV 0,3
MOV 1,2
SUB 0,0
LDA 1,0,3
DIV
JMP .+1
STA 1,0,3 ; Q0
LDA 1,1,3
DIV
JMP .+1
STA 1,1,3 ; Q1
LDA 2,TEMP
LDA 3,1,2
JMP 1,3
TEMP: 0
.END