; Utility.asm. Assembly language utility routines ; undid change January 6, 1985 4:28 PM by Bill van Melle ; changed SmallPosP/Neg December 14, 1984 2:11 PM by Bill van Melle ; added 2 args to DspRate July 20, 1983 2:09 PM by Bill van Melle ; added SDP December 9, 1982 6:11 PM by Bill van Melle ; removed DoBitBlt July 21, 1982 6:55 PM by Bill van Melle ; added DspRate June 25, 1982 2:50 PM by Bill van Melle ; 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, EmUnbox .ENT MkSmallPos, MkSmallNeg, Smallp, SmallUnbox, SmallNegUnbox .ENT UCase, ReadClock, TimeSince .ENT MachineType, Version, Serial, DspRateInstr, DskPartInstr ; procedures used .EXTN RAIDCode ; statics used .EXTD RMSK, lvVPtr, VPtr0, VPtr1 .EXTN EmulatorSpace ; new opcodes defined .DUSR SWAT = #77400 ; For where one shouldnt go .DUSR DSPRT = #61027 ; changes display rate .DUSR SDP = #61037 ; sets/returns default partition .SREL VP: .vp VP2: .vp2 Bytes2: .by2 EqNIL: .eqn EmAddr: .ea EmUnbox: .emunb MkSmallPos: .msp MkSmallNeg: .msn Smallp: .smp SmallUnbox: .smunb SmallNegUnbox: .smnunb UCase: .uc ReadClock: .rclk TimeSince: .tme MachineType: .mt Version: .vers Serial: .ser DspRateInstr: .dpr DskPartInstr: .dskp .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 ; EmUnbox(lvN) unbox if emulator pointer, otherwise error .emunb: sta 3,1,2 mov 0,3 ; ac3 ← arg lda 0,0,3 ; ac0 ← hiloc(arg) lda 1,@.es ; ac1 ← Emulator hi sub# 0,1,szr ; test ac1=ac2 jmp .notem lda 0,1,3 ; ac0 ← loloc(arg) lda 3,1,2 jmp 1,3 .notem: mov 3, 1 ; original arg .notem2: jsr .emerr ; get addr of error msg into ac3 .TXTM B .TXT "Not a short pointer" .emerr: mov 3, 0 ; addr of error msg jsrii .raid 2 lda 1, .smallp ; random safe garbage jmp .notem2 ; 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 .smerr2: 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 lda 1, .smallp ; random safe garbage jmp .smerr2 ; 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 ; DspRateInstr(ac0, ac1, ac2) returns old rate .dpr: sta 2, dspsaveac2 lda 2, 3,2 ; load correct ac2 DSPRT lda 2, dspsaveac2 jmp 1,3 dspsaveac2: 0 ; DskPartInstr(newpart) returns old part .dskp: SDP jmp 1,3 ; 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