BASIC
VERIFY Result
When the VERIFY command completes it should either
- display "VERIFY ERROR" if the program does not match
- display "OK", but only in immediate mode
Code: Select all
LDA TXTPTR ; get BASIC execute pointer low byte
CMP #>BUF ; compare with input buffer high byte
BEQ LAB_E194 ; skip "OK" prompt
The code should have been
Code: Select all
LDA TXTPTR+1 ; get BASIC execute pointer high byte
CMP #>BUF ; compare with input buffer high byte
BNE LAB_E194 ; if program mode skip "OK" prompt
Cassette
The code to handle reading and writing to tape was well tested, being inherited from the PET. One regression did somehow make it into the VIC-20.
Programs can be saved with a logical End of Tape marker by giving a secondary address of 2. This causes a header record with an identifier code of 5 to be written after the program. When loading if the record is reached the operation is terminated. On the PET this reports
Code: Select all
?FILE NOT FOUND ERROR
Code: Select all
?DEVICE NOT PRESENT
ERROR
Another mistake is present in the routine blocks waiting for the interrupt-driven part of a read or write operation to complete. The code tests for the read timer interrupt to fire and then attempts to clear it
Code: Select all
LDA VIA2IFR ; get VIA 2 IFR
AND #%01000000 ; mask T1 interrupt
BEQ LAB_F92F ; loop if not T1 interrupt
; else increment jiffy clock
LDA VIA1T1CL ; get VIA 1 T1 counter low byte, clear T1 interrupt flag
Code: Select all
LDA VIA2T1CL ; get VIA 2 T1 counter low byte, clear T1 interrupt flag
The routines used to convert key scancodes from the keyboard matrix into PETSCII characters have blocks of NOP instructions in them. There are also conversion tables that are not referenced.
These are remnants of the decode logic that was used in the VIC-1001. The processing of katakana characters required six tables (rather than four) and the character set switching using [SHIFT][C=] was more complex.
Jiffy Clock
The jiffy clock (TI/TI$ in BASIC) starts running from 0 when the computer is powered on. It is intended to wrap after 24 hours, however the code that handles the roll over is
Code: Select all
SEC ; set carry for subtract
LDA TIME+2 ; get jiffy clock low byte
SBC #$01 ; subtract $4F1A01 low byte
LDA TIME+1 ; get jiffy clock mid byte
SBC #$1A ; subtract $4F1A01 mid byte
LDA TIME ; get jiffy clock high byte
SBC #$4F ; subtract $4F1A01 high byte
BCC LAB_F755 ; branch if less than $4F1A01 jiffies
The clock is updated every 1/60th of a second from a timer interrupt. The IRQ routine calls the UDTIM routine, along with other tasks. However UDTIM is also called from the NMI routine. This means that frequent NMIs (e.g. the [RESTORE] key) cause the clock to run fast.
RS-232
The history of the RS-232 interface seems littered with problems. It was originally intended that a UART would be used. At some point the decision was made to implement it in software.
Transmission is a matter of shifting each data byte under a timer interrupt to the CB2 line of VIA1 (along with start and stop
bits). Reception is more complex: a start bit triggers an interrupt on the CB1 line and then a timer interrupt samples the value of the DRA port and shifts it into the result.
RINONE ($A9), the flag used to record when a start bit is received is not initialized when an input channel is set up. As a result a framing error occurs when the first byte is received.
The interrupt pin of VIA1 is connected to the CPU's NMI line. This is edge-triggered: the CPU only calls the NMI vector when the line transitions from high to low. All interrupt sources must be cleared before the line returns to a high level. The NMI routine only processes a single source at a time in the following order:
- Tx timer
- Rx timer
- Rx data start
The READST routine which is used to return the status flags for the current I/O device was intended to return the value held in RSSTAT ($0297) when the RS-232 interface is in use. The code is
Code: Select all
LDA FA ; get device number
CMP #$02 ; compare device with RS-232 device
BNE READIOST ; branch if not RS-232 device
; get RS-232 device status
LDA RSSTAT ; read RS-232 status byte
LDA #$00 ; clear .A
STA RSSTAT ; clear RS-232 status byte
The RS-232 interface has two modes of operation: 3-line and x-line. The latter was intended to provide hardware flow control for half-duplex modems. Given the following faults this can never have been actually tested:
When preparing to transmit the DSR and CTS lines should be checked, however the code is
Code: Select all
BIT VIA2PB ; test VIA 2 DRB
BPL RSMISSNG ; if DSR = 0 set DSR signal not present and exit
BVC LAB_F019 ; if CTS = 0 set CTS signal not present and exit
Code: Select all
BIT VIA1PB ; test VIA 1 DRB
Code: Select all
LDA VIA1PB ; get VIA 1 DRB
AND #%00000100 ; mask DTR out
; DTR is an output and always held high so the
; following test will never branch
BEQ LAB_F138 ; loop while DTR low
Code: Select all
AND #%00010000 ; mask DCD in
BEQ LAB_F138 ; loop while DCD low
The Programmers Reference Guide documents this routine as "Set serial bus timeout flag" but the text of the description talks about the DAV signal (which is only present in IEEE-488).
The code is
Code: Select all
FSETTMO
STA TIMOUT ; save serial bus timeout flag
RTS