Merge pull request #30 from FeralChild64/master
IEC fixes, BRK handling, other small improvements
This commit is contained in:
55 files changed
+406
-262
No files matched your search
@@ -6,7 +6,8 @@ Here are the features of the Open ROMs not found in the original ROMs from the 8
|
||||
* improved keyboard scanning, supports multi-key roll-over and rejection of spurious joystick input
|
||||
* joystick (port 1) can be used to move text cursor
|
||||
* uses RAM under ROM and I/O: 61436 bytes free
|
||||
* cold/warm start silences 4 SID chips - assumes addresses $D400, $D420, $D440, $D460
|
||||
* cold/warm start silences multiple SID chips - all $D4xx and $D5xx addresses
|
||||
* wark start due to BRK prints out the instruction address
|
||||
* extended `LOAD` command
|
||||
* start/end addresses are displayed, in the Final cartridge style
|
||||
* command with just the file name tries to use the last device if it's number seems sane; otherwise uses 8
|
||||
@@ -15,6 +16,7 @@ Here are the features of the Open ROMs not found in the original ROMs from the 8
|
||||
|
||||
NOTE: extra features and their syntax can change in the future!
|
||||
|
||||
|
||||
# Features missing
|
||||
|
||||
|
||||
@@ -27,11 +29,8 @@ The following ROM features are currently missing:
|
||||
* tape support
|
||||
* RS-232 support
|
||||
* breaking Kernal routines with RUN/STOP key
|
||||
* BRK handling; NMI/IRQ handling is incomplete
|
||||
* NMI andling is incomplete
|
||||
|
||||
Features currently being worked on:
|
||||
|
||||
* IEC support needs more work; alternative drive ROMs (JiffyDOS, DolphinDOS, etc) usually don't work with current implementation, SAVE / VERIFY are not implemented, etc.
|
||||
|
||||
# API status
|
||||
|
||||
@@ -101,14 +100,14 @@ NOTE: Even the 'DONE' routines won't support features described as missing in on
|
||||
| `$FFD2` | `CHROUT` | PARTIAL | |
|
||||
| `$FFD5` | `LOAD` | PARTIAL | no VERIFY support yet, no STOP key support |
|
||||
| `$FFD8` | `SAVE` | NOT DONE | |
|
||||
| `$FFDB` | `SETTIM` | NOT DONE | |
|
||||
| `$FFDE` | `RDTIM` | NOT DONE | |
|
||||
| `$FFDB` | `SETTIM` | DONE | |
|
||||
| `$FFDE` | `RDTIM` | DONE | |
|
||||
| `$FFE1` | `STOP` | DONE | |
|
||||
| `$FFE4` | `GETIN` | PARTIAL | only some devices supported |
|
||||
| `$FFE7` | `CLALL` | DONE | |
|
||||
| `$FFEA` | `UDTIM` | NOT DONE | checking for STOP key present in SCNKEY instead |
|
||||
| `$FFEA` | `UDTIM` | DONE | |
|
||||
| `$FFED` | `SCREEN` | DONE | |
|
||||
| `$FFF0` | `PLOT` | NOT DONE | |
|
||||
| `$FFF0` | `PLOT` | DONE | |
|
||||
| `$FFF3` | `IOBASE` | DONE | |
|
||||
|
||||
<br />
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -34,11 +34,7 @@
|
||||
.alias IEC_TMP1 $A3 ; temporary variable for tape and IEC
|
||||
.alias IEC_TMP2 $A4 ; temporary variable for tape and IEC
|
||||
|
||||
;; 2-byte location below seems to be a good place for temporary storage,
|
||||
;; it seems used for timing during tape reads only - see:
|
||||
;; - 'C64 Programmer's Reference Guide', page 314
|
||||
;; - 'Compute's Mapping the Commodore 64', page 32
|
||||
.alias CMP0 $B0 ; $B0-$B1
|
||||
.alias CMP0 $B0 ; $B0-$B1, temporary tape storage, we use it too for BRK instruction address
|
||||
|
||||
.alias FNLEN $B7 ; current file name length
|
||||
|
||||
|
||||
@@ -30,8 +30,9 @@ basic_execute_statement:
|
||||
|
||||
;; Check for RUN/STOP
|
||||
lda STKEY
|
||||
bpl basic_do_break
|
||||
|
||||
bmi +
|
||||
jmp basic_do_break
|
||||
*
|
||||
;; Skip over any white space and :
|
||||
ldy #0
|
||||
ldx #<basic_current_statement_ptr
|
||||
|
||||
@@ -2,6 +2,22 @@
|
||||
|
||||
basic_warm_start:
|
||||
jsr install_ram_routines
|
||||
|
||||
|
||||
;; If warm start caused by BRK, print it address
|
||||
lda CMP0
|
||||
ora CMP0+1
|
||||
beq +
|
||||
|
||||
ldx #32
|
||||
jsr print_packed_message
|
||||
|
||||
lda CMP0+1
|
||||
jsr printf_printhexbyte
|
||||
lda CMP0+0
|
||||
jsr printf_printhexbyte
|
||||
lda #$0D
|
||||
jsr JCHROUT
|
||||
|
||||
*
|
||||
jmp basic_main_loop
|
||||
|
||||
|
||||
@@ -66,7 +66,9 @@ got_filename:
|
||||
|
||||
jsr basic_parse_line_number
|
||||
lda basic_line_number+1
|
||||
bne do_ILLEGAL_QUANTITY_error
|
||||
beq +
|
||||
jmp do_ILLEGAL_QUANTITY_error
|
||||
*
|
||||
lda basic_line_number+0
|
||||
sta current_device_number
|
||||
|
||||
|
||||
+17
-9
@@ -17,11 +17,13 @@ wedge_dos:
|
||||
;; Check if user asked for a status
|
||||
ldy #$00
|
||||
lda (basic_current_statement_ptr), y
|
||||
beq wedge_dos_status
|
||||
|
||||
bne +
|
||||
jmp wedge_dos_status ; XXX try to optimize this, perhaps move 'wedge_dos_status' above?
|
||||
*
|
||||
;; Check if asked for a directory
|
||||
cmp #$24
|
||||
beq wedge_dos_directory
|
||||
bne +
|
||||
jmp wedge_dos_directory
|
||||
*
|
||||
;; Check if asked to change drive number, or if it is a regular command
|
||||
cmp #$30
|
||||
@@ -42,8 +44,9 @@ wedge_dos_command:
|
||||
|
||||
jsr JSETNAM
|
||||
jsr JOPEN
|
||||
bcs wedge_dos_basic_error
|
||||
|
||||
bcc +
|
||||
jmp wedge_dos_basic_error ; XXX combine with other such jumps
|
||||
*
|
||||
;; Retrieve status, print it if not OK
|
||||
jsr JCLALL
|
||||
jsr wedge_dos_status_get
|
||||
@@ -83,12 +86,16 @@ wedge_dos_status_get:
|
||||
lda #$00 ; empty file name
|
||||
jsr JSETNAM
|
||||
jsr JOPEN
|
||||
bcs wedge_dos_basic_error
|
||||
bcc +
|
||||
jmp wedge_dos_basic_error ; XXX combine with other such jumps
|
||||
*
|
||||
|
||||
;; Set channel for input
|
||||
ldx #$0F
|
||||
jsr JCHKIN
|
||||
bcs wedge_dos_basic_error
|
||||
bcc +
|
||||
jmp wedge_dos_basic_error ; XXX combine with other such jumps
|
||||
*
|
||||
|
||||
ldy #$00
|
||||
*
|
||||
@@ -99,7 +106,9 @@ wedge_dos_status_get:
|
||||
;; Print out everything retrieved from the drive
|
||||
bne +
|
||||
jsr JCHRIN
|
||||
bcs wedge_dos_basic_error
|
||||
bcc wedge_dos_x1
|
||||
jmp wedge_dos_basic_error ; XXX try to optimize this
|
||||
wedge_dos_x1:
|
||||
sta BUF, y
|
||||
iny
|
||||
jmp -
|
||||
@@ -129,7 +138,6 @@ wedge_dos_directory:
|
||||
|
||||
;; First change the secondary address to the one suitable for
|
||||
;; directory loading
|
||||
;; XXX
|
||||
lda #$00 ; logical device number
|
||||
ldx current_device_number
|
||||
ldy #$60
|
||||
|
||||
@@ -448,8 +448,9 @@ screen_grow_logical_line:
|
||||
ldy current_screen_y
|
||||
;; Don't grow line if it is already grown
|
||||
lda screen_line_link_table,y
|
||||
bmi done_grow_line
|
||||
|
||||
bpl +
|
||||
jmp done_grow_line
|
||||
*
|
||||
lda #$80
|
||||
sta screen_line_link_table,y
|
||||
|
||||
|
||||
@@ -9,16 +9,57 @@
|
||||
;;
|
||||
|
||||
|
||||
cint:
|
||||
cint_real:
|
||||
|
||||
;; According to [CM64], this routine checks for PAL/NTSC. It's definitely not done
|
||||
;; within the 'BRK' part, this can be easily checked - POKE something
|
||||
;; to address 678 on a real C64, press STOP+RESTORE, the value won't change
|
||||
|
||||
;; Detect video system (PAL/NTSC), use Graham's method, as it's short and reliable
|
||||
;; see here: https://codebase64.org/doku.php?id=base:detect_pal_ntsc
|
||||
|
||||
lda #$C8 ; preparation, as the VIC might be uninitialized
|
||||
sta VIC_SCROLX
|
||||
|
||||
cint_w0:
|
||||
lda VIC_RASTER
|
||||
cint_w1:
|
||||
cmp VIC_RASTER
|
||||
beq cint_w1
|
||||
bmi cint_w0
|
||||
|
||||
;; Result in A, if no interrupt happened during the test:
|
||||
;; #$37 -> 312 rasterlines, PAL, VIC 6569
|
||||
;; #$06 -> 263 rasterlines, NTSC, VIC 6567R8
|
||||
;; #$05 -> 262 rasterlines, NTSC, VIC 6567R56A
|
||||
|
||||
cmp #$07
|
||||
bcs cint_pal
|
||||
|
||||
cint_ntsc:
|
||||
|
||||
;; NTSC C64 (https://codebase64.org/doku.php?id=base:cpu_clocking),
|
||||
;; is clocked at 1.022727 MHz, so that 1/60s is 17045 CPU cycles
|
||||
|
||||
ldy #<17045
|
||||
ldx #>17045
|
||||
|
||||
sty CIA1_TIMALO
|
||||
stx CIA1_TIMAHI
|
||||
|
||||
lda #$00
|
||||
beq +
|
||||
|
||||
cint_pal:
|
||||
|
||||
lda #$01
|
||||
*
|
||||
sta PALNTSC
|
||||
|
||||
cint_brk: ; entry for BRK and STOP+RESTORE - XXX, where should it start?
|
||||
|
||||
jsr setup_vicii
|
||||
|
||||
;; According to [CM64], this routine also checks for PAL/NTSC - this must be a mistake,
|
||||
;; it's too late (IOINIT already needs this information), besides - POKE something
|
||||
;; to address 678 on a real C64, press STOP+RESTORE - the value won't change
|
||||
|
||||
;; Initialise cursor blink flags (Compute's Mapping the 64 p215)
|
||||
lda #$00
|
||||
sta cursor_blink_disable
|
||||
@@ -76,7 +76,7 @@ open_iec:
|
||||
lda current_secondary_address
|
||||
jsr iec_cmd_open
|
||||
bcc +
|
||||
jmp kernalerror_DEVICE_NOT_FOUND ; XXX find a better error message for wrong channel (create new one?)
|
||||
jmp kernalerror_DEVICE_NOT_FOUND
|
||||
*
|
||||
|
||||
;; We need our helpers to get to filenames under ROMs or IO area
|
||||
|
||||
+36
-22
@@ -41,8 +41,9 @@ load:
|
||||
;; Check whether we support the requested device
|
||||
lda current_device_number
|
||||
and #$FC
|
||||
beq lvs_illegal_device_number ; device number below 4, not an IEC device
|
||||
|
||||
bne +
|
||||
jmp lvs_illegal_device_number ; device number below 4, not an IEC device
|
||||
*
|
||||
;; Device numbers above 30 are also illegal (see https://www.pagetable.com/?p=1031),
|
||||
;; as the protocol combines device number with command code int one byte,
|
||||
;; above 30 it is no longer possible (UNLISTEN and UNTALK codes prevent using
|
||||
@@ -60,41 +61,51 @@ load:
|
||||
;; Call device to LISTEN (p16)
|
||||
lda current_device_number
|
||||
jsr listen
|
||||
bcs lvs_device_not_found_error
|
||||
|
||||
bcc +
|
||||
jmp lvs_device_not_found_error ; XXX deduplicate with other jumps in this routine
|
||||
*
|
||||
;; Open channel 0 (reserved for file reading)
|
||||
lda #$00
|
||||
jsr iec_cmd_open
|
||||
bcs lvs_load_verify_error
|
||||
|
||||
bcc +
|
||||
jmp lvs_device_not_found_error ; XXX deduplicate with other jumps in this routine
|
||||
*
|
||||
;; Send file name
|
||||
jsr lvs_send_file_name
|
||||
bcs lvs_load_verify_error
|
||||
|
||||
bcc +
|
||||
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine
|
||||
*
|
||||
;; Now command device to talk (p16)
|
||||
lda current_device_number
|
||||
jsr talk
|
||||
bcs lvs_load_verify_error
|
||||
|
||||
bcc +
|
||||
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine
|
||||
*
|
||||
lda #$60 ; open channel / data (p3) , required according to p13
|
||||
sta IEC_TMP2
|
||||
jsr iec_tx_command
|
||||
bcs lvs_load_verify_error
|
||||
|
||||
bcc +
|
||||
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine
|
||||
*
|
||||
;; We are currently talker, so do the IEC turn around so that we
|
||||
;; are the listener (p16)
|
||||
jsr iec_turnaround_to_listen
|
||||
bcs lvs_load_verify_error
|
||||
|
||||
bcc +
|
||||
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine
|
||||
*
|
||||
;; Get load address and store it if secondary address is zero
|
||||
jsr iec_rx_byte
|
||||
bcs lvs_file_not_found_error
|
||||
bcc +
|
||||
jmp lvs_file_not_found_error ; XXX deduplicate with other jumps in this routine
|
||||
*
|
||||
ldx current_secondary_address
|
||||
beq +
|
||||
sta STAL+0
|
||||
*
|
||||
jsr iec_rx_byte
|
||||
bcs lvs_file_not_found_error
|
||||
bcc +
|
||||
jmp lvs_file_not_found_error ; XXX deduplicate with other jumps in this routine
|
||||
*
|
||||
ldx current_secondary_address
|
||||
beq +
|
||||
sta STAL+1
|
||||
@@ -105,16 +116,19 @@ load:
|
||||
load_loop:
|
||||
;; We are now ready to receive bytes
|
||||
jsr iec_rx_byte
|
||||
bcs lvs_load_verify_error
|
||||
|
||||
bcc +
|
||||
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine
|
||||
*
|
||||
;; Handle the byte (store in memory / verify)
|
||||
jsr lvs_handle_byte_load_verify
|
||||
bcs lvs_load_verify_error
|
||||
|
||||
bcc +
|
||||
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine
|
||||
*
|
||||
;; Advance pointer to data
|
||||
jsr lvs_advance_pointer
|
||||
bcs lvs_wrap_around_error
|
||||
|
||||
bcc +
|
||||
jmp lvs_wrap_around_error
|
||||
*
|
||||
;; Check for EOI - if so, this was the last byte
|
||||
lda IOSTATUS
|
||||
and #K_STS_EOI
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
Original Kernal location of the RESTOR routine.
|
||||
|
||||
Routine moved to original location due to game 'Duotris' calling it instead of using the Kernal jumptable.
|
||||
Starting the game without this patch caused warm reset with 'BRK AT $FD15' message.
|
||||
File renamed without changes.
@@ -20,47 +20,24 @@ ioinit:
|
||||
sta CPU_R6510
|
||||
stx CPU_D6510
|
||||
|
||||
;; Silence the SID chips
|
||||
;; Silence the SID chips under common addresses
|
||||
|
||||
ldy #$00
|
||||
*
|
||||
;; SIDs under $D4xx
|
||||
lda SID_SIGVOL, Y
|
||||
and #$F0
|
||||
sta SID_SIGVOL, Y
|
||||
;; SIDs under $D5xx
|
||||
lda SID_SIGVOL + $100, Y
|
||||
and #$F0
|
||||
sta SID_SIGVOL + $100, Y
|
||||
tya
|
||||
clc
|
||||
adc #$20
|
||||
tay
|
||||
cpy #$80 ; $20 * amount of chips to silence, $80 to silence 4 chips
|
||||
bne -
|
||||
|
||||
;; Detect video system (PAL/NTSC), use Graham's method, as it's short and reliable
|
||||
;; see here: https://codebase64.org/doku.php?id=base:detect_pal_ntsc
|
||||
|
||||
ioinit_w0:
|
||||
lda VIC_RASTER
|
||||
ioinit_w1:
|
||||
cmp VIC_RASTER
|
||||
beq ioinit_w1
|
||||
bmi ioinit_w0
|
||||
|
||||
;; Result in A, if no interrupt happened during the test:
|
||||
;; #$37 -> 312 rasterlines, PAL, VIC 6569
|
||||
;; #$06 -> 263 rasterlines, NTSC, VIC 6567R8
|
||||
;; #$05 -> 262 rasterlines, NTSC, VIC 6567R56A
|
||||
|
||||
cmp #$07
|
||||
bcs ioinit_pal
|
||||
|
||||
ioinit_ntsc:
|
||||
lda #$00
|
||||
beq +
|
||||
|
||||
ioinit_pal:
|
||||
lda #$01
|
||||
*
|
||||
sta PALNTSC
|
||||
|
||||
;; XXX: calibrate TOD for both CIA's, see here: https://codebase64.org/doku.php?id=base:efficient_tod_initialisation
|
||||
|
||||
;; Enable CIA1 IRQ and ~50Hz timer (https://csdb.dk/forums/?roomid=11&topicid=69037)
|
||||
@@ -81,17 +58,6 @@ ioinit_pal:
|
||||
ldy #<16421
|
||||
ldx #>16421
|
||||
|
||||
lda PALNTSC
|
||||
bne +
|
||||
|
||||
;; NTSC C64 (https://codebase64.org/doku.php?id=base:cpu_clocking),
|
||||
;; is clocked at 1.022727 MHz, so that 1/60s is 17045 CPU cycles
|
||||
|
||||
ldy #<17045
|
||||
ldx #>17045
|
||||
|
||||
;; Store the IRQ timing constant to CIA chip
|
||||
*
|
||||
sty CIA1_TIMALO
|
||||
stx CIA1_TIMAHI
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
;; Our implementation is longer than the original one,
|
||||
;; placing it here would cause a collision with OPEN
|
||||
|
||||
cint:
|
||||
jmp cint_real
|
||||
@@ -0,0 +1,4 @@
|
||||
Original Kernal location of the CINT routine.
|
||||
|
||||
Routine moved to original location due to game 'Duotris' calling it instead of using the Kernal jumptable.
|
||||
Starting the game without this patch caused warm reset with 'BRK AT $FF5B' message.
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
iec_pull_clk_release_data_oneshot:
|
||||
|
||||
lda CIA2_PRA
|
||||
ora #BIT_CIA2_PRA_CLK_OUT ; pull
|
||||
and #$FF - BIT_CIA2_PRA_DAT_OUT ; release
|
||||
sta CIA2_PRA
|
||||
rts
|
||||
@@ -19,11 +19,66 @@ iec_tx_byte:
|
||||
;; and it is going to be a data byte (released ATN)
|
||||
jsr iec_release_atn_clk_data
|
||||
|
||||
;; Common part of iec_txbyte and iec_tx_common - waits for devices
|
||||
;; and transmits a byte
|
||||
;; Common part of iec_tx_byte and iec_tx_command
|
||||
;; Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
|
||||
;; and http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
|
||||
|
||||
jsr iec_tx_common
|
||||
iec_tx_common:
|
||||
|
||||
;; Timing is critical here - execute on disabled IRQs
|
||||
php
|
||||
sei
|
||||
|
||||
;; Wait till all receivers are ready, they should all release DATA
|
||||
jsr iec_wait_for_data_release
|
||||
|
||||
;; At this point a delay 256 usec or more is considered EOI,
|
||||
;; receiver should now acknowledge it by pulling data for at least 60 usec
|
||||
;; Keep the implementation as simple as possible: data should be released now
|
||||
;; so wait until it's pushed and released again
|
||||
|
||||
jsr iec_wait_for_data_pull
|
||||
jsr iec_wait_for_data_release
|
||||
*
|
||||
;; Pull CLK back to indicate that DATA is not valid, keep it for 60us
|
||||
;; We can use this routine as we don't hold DATA anyway (and its state doesn't even matter)
|
||||
|
||||
jsr iec_pull_clk_release_data_oneshot
|
||||
jsr iec_wait60us
|
||||
|
||||
;; Now, we can start transmission of 8 bits of data
|
||||
ldx #7
|
||||
|
||||
iec_tx_common_sendbit:
|
||||
;; Is next bit 0 or 1?
|
||||
lda IEC_TMP2
|
||||
lsr
|
||||
sta IEC_TMP2
|
||||
bcs +
|
||||
|
||||
;; Bit is 0
|
||||
jsr iec_release_clk_pull_data
|
||||
jmp iec_tx_common_bit_is_sent
|
||||
*
|
||||
;; Bit is 1
|
||||
jsr iec_release_clk_data
|
||||
|
||||
iec_tx_common_bit_is_sent:
|
||||
|
||||
;; Wait 20us, so that device(s) can pick DATA
|
||||
jsr iec_wait20us
|
||||
|
||||
;; Pull CLK for 20us again, before sending the next bit
|
||||
;; or performing any other action
|
||||
jsr iec_pull_clk_release_data_oneshot
|
||||
jsr iec_wait20us
|
||||
|
||||
;; More bits to send?
|
||||
dex
|
||||
bpl iec_tx_common_sendbit
|
||||
|
||||
plp
|
||||
|
||||
;; Give device time to tell if they are busy by pulling DATA
|
||||
;; They should do it within 1ms
|
||||
ldx #$FF
|
||||
@@ -36,5 +91,3 @@ iec_tx_byte:
|
||||
bpl iec_return_DEVICE_NOT_FOUND
|
||||
*
|
||||
jmp iec_return_success
|
||||
|
||||
|
||||
@@ -19,15 +19,10 @@ iec_tx_command:
|
||||
;; and it is going to be a command (pulled ATN)
|
||||
jsr iec_pull_atn_clk_release_data
|
||||
|
||||
;; Give devices time to respond (response is mandatory!)
|
||||
;; Give devices time to respond (response is mandatory!) by pulling DATA
|
||||
jsr iec_wait1ms
|
||||
|
||||
;; Did at least one device respond by pulling DATA?
|
||||
lda CIA2_PRA
|
||||
and #BIT_CIA2_PRA_DAT_IN ; XXX try to optimize this, move to separate routine
|
||||
beq +
|
||||
|
||||
;; No devices present on the bus, so we can immediately return with device not found
|
||||
lda CIA2_PRA ; pulled DATA = highest bit 0 = 'plus'
|
||||
bpl +
|
||||
jmp iec_return_DEVICE_NOT_FOUND
|
||||
*
|
||||
;; At least one device responded, but they are still allowed to stall
|
||||
@@ -41,22 +36,5 @@ iec_tx_command:
|
||||
;; and transmits a byte
|
||||
|
||||
clc ; Carry flag set is used for EOI mark
|
||||
jsr iec_tx_common
|
||||
jmp iec_tx_common
|
||||
|
||||
;; According to https://www.pagetable.com/?p=1135 there is some complicated and dangerous
|
||||
;; flow here, but http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf (page 6)
|
||||
;; advices to just wait 1ms and check the DATA status
|
||||
jsr iec_wait1ms
|
||||
lda CIA2_PRA
|
||||
and #BIT_CIA2_PRA_DAT_IN ; XXX try to optimize this, move to separate routine
|
||||
beq +
|
||||
|
||||
;; XXX possible optimization of the flow above: for many commands it is enough
|
||||
;; to wait for the DATA being pulled, as confirmation is expected from
|
||||
;; a single device only - but not sure if it's worth the trouble
|
||||
|
||||
jmp iec_return_DEVICE_NOT_FOUND
|
||||
*
|
||||
;; Done
|
||||
|
||||
jmp iec_return_success
|
||||
@@ -1,72 +0,0 @@
|
||||
|
||||
;; This is a common part of iec_tx_byte and iec_tx_command
|
||||
;; Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
|
||||
;; and http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
|
||||
|
||||
;; Expects byte to send in IEC_TMP2 ($A4 is a byte buffer according to http://sta.c64.org/cbm64mem.html)
|
||||
;; Carry flag set = signal EOI
|
||||
|
||||
iec_tx_common:
|
||||
|
||||
;; Timing is critical here - execute on disabled IRQs
|
||||
php
|
||||
sei
|
||||
|
||||
;; Wait till all receivers are ready, they should all release DATA
|
||||
jsr iec_wait_for_data_release
|
||||
|
||||
;; At this point a delay 256 usec or more is considered EOI - add waits if necessary
|
||||
bcc +
|
||||
jsr iec_wait100us
|
||||
jsr iec_wait100us
|
||||
jsr iec_wait60us
|
||||
|
||||
;; XXX waits above should be enough - why do we need more waits???
|
||||
jsr iec_wait100us
|
||||
jsr iec_wait100us
|
||||
jsr iec_wait100us
|
||||
|
||||
;; Receiver should now acknowledge EOI by pulling data for at least 60 usec
|
||||
jsr iec_wait60us
|
||||
jsr iec_wait_for_data_release
|
||||
*
|
||||
;; Pull CLK back to indicate that DATA is not valid, keep it for 60us
|
||||
;; We can use this routine as we don't hold DATA anyway (and its state doesn't even matter)
|
||||
|
||||
jsr iec_pull_clk_release_data
|
||||
jsr iec_wait60us
|
||||
|
||||
;; Now, we can start transmission of 8 bits of data
|
||||
ldx #7
|
||||
|
||||
iec_tx_common_sendbit:
|
||||
;; Is next bit 0 or 1?
|
||||
lda IEC_TMP2
|
||||
lsr
|
||||
sta IEC_TMP2
|
||||
bcs +
|
||||
|
||||
;; Bit is 0
|
||||
jsr iec_release_clk_pull_data
|
||||
jmp iec_tx_common_bit_is_sent
|
||||
*
|
||||
;; Bit is 1
|
||||
jsr iec_release_clk_data
|
||||
|
||||
iec_tx_common_bit_is_sent:
|
||||
|
||||
;; Wait 20us, so that device(s) can pick DATA
|
||||
jsr iec_wait20us
|
||||
|
||||
;; Pull CLK for 20us again, before sending the next bit
|
||||
;; or performing any other action
|
||||
jsr iec_pull_clk_release_data
|
||||
jsr iec_wait20us ; XXX this might be an overkill, there is a lot of code besides this wait here - few NOPs might be enough
|
||||
|
||||
;; More bits to send?
|
||||
dex
|
||||
bpl iec_tx_common_sendbit
|
||||
|
||||
plp
|
||||
rts ; Flow continues differently for data/command
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
|
||||
iec_wait100us:
|
||||
|
||||
;; Wait 100usec
|
||||
|
||||
;; PAL:
|
||||
;; - CPU frequency 0.985248 MHz, we need to waste at least 99 cycles
|
||||
;; NTSC:
|
||||
;; - CPU frequency 1.022727 MHZ, we need to waste at least 103 cycles
|
||||
|
||||
;; Waste cycles in a loop
|
||||
|
||||
ldy #$12 ; 2 cycles
|
||||
* dey ; 2 cycles * 18
|
||||
bpl - ; 3 cycles * 17 + 2 cycles
|
||||
rts ; 6 cycles
|
||||
|
||||
;; 6 cycles JSR to routine,
|
||||
;; 97 cycles routine with RTS
|
||||
;; 1 cycle to fetch next instruction
|
||||
;; ---
|
||||
;; 104 cycles
|
||||
@@ -17,4 +17,5 @@ iec_wait1ms:
|
||||
lda VIC_RASTER
|
||||
dex
|
||||
bne -
|
||||
|
||||
rts
|
||||
@@ -26,5 +26,9 @@ default_nmi_handler:
|
||||
bcs +
|
||||
jmp return_from_interrupt ; no STOP pressed
|
||||
*
|
||||
jmp (CBINV) ; STOP + RESTORE
|
||||
;; STOP + RESTORE - clean the address of the BRK instruction (it's not BRK) first
|
||||
lda #$00
|
||||
sta CMP0+0
|
||||
sta CMP0+1
|
||||
jmp (CBINV)
|
||||
|
||||
@@ -16,12 +16,10 @@ irq_handler:
|
||||
pha
|
||||
|
||||
;; Check if caused by BRK
|
||||
|
||||
;; XXX disabled for now - resets Duotris game, unknown why
|
||||
; tsx
|
||||
; lda $0104, x ; get the pre-interrupt processor state
|
||||
; and #$10
|
||||
; bne irq_handler_brk
|
||||
tsx
|
||||
lda $0104, x ; get the pre-interrupt processor state
|
||||
and #$10
|
||||
bne irq_handler_brk
|
||||
|
||||
;; Not caused by BRK - call interrupt routine (only if initialised)
|
||||
lda CINV
|
||||
@@ -34,6 +32,15 @@ irq_handler:
|
||||
|
||||
irq_handler_brk:
|
||||
|
||||
;; Store BRK adddress, to be displayed
|
||||
sec
|
||||
lda $0105, x
|
||||
sbc #$02
|
||||
sta CMP0+0
|
||||
lda $0106, x
|
||||
sbc #$00
|
||||
sta CMP0+1
|
||||
|
||||
;; Interrupt caused by BRK
|
||||
jmp (CBINV)
|
||||
|
||||
@@ -51,10 +51,13 @@ lvs_handle_byte_load_verify:
|
||||
lvs_advance_pointer:
|
||||
;; Advance pointer
|
||||
inc STAL
|
||||
bne lvs_success_end
|
||||
beq +
|
||||
jmp lvs_success_end
|
||||
*
|
||||
inc STAL+1
|
||||
;; If we wrap around to $0000, then this is bad.
|
||||
beq lvs_error_end
|
||||
bne +
|
||||
jmp lvs_error_end
|
||||
*
|
||||
clc
|
||||
rts
|
||||
@@ -146,7 +149,7 @@ lvs_illegal_device_number:
|
||||
lvs_load_verify_error:
|
||||
;; XXX should we really return BASIC error code here?
|
||||
lda VERCK
|
||||
beq lvs_verify_error
|
||||
bne lvs_verify_error
|
||||
lda #B_ERR_LOAD
|
||||
bne lvs_error_end
|
||||
;; FALLTHROUGH
|
||||
|
||||
@@ -9,4 +9,19 @@
|
||||
;;
|
||||
|
||||
plot:
|
||||
bcs plot_get
|
||||
|
||||
plot_set:
|
||||
sty current_screen_y
|
||||
stx current_screen_x
|
||||
|
||||
;; Our implementation has different screen editor, updating any
|
||||
;; other variables (see [CM64]) seems to be unnecessary
|
||||
|
||||
;; FALLTROUGH to save one byte on RTS
|
||||
|
||||
plot_get:
|
||||
ldy current_screen_y
|
||||
ldx current_screen_x
|
||||
rts
|
||||
|
||||
@@ -9,4 +9,19 @@
|
||||
;;
|
||||
|
||||
rdtim:
|
||||
|
||||
;; Disable interrupts for the duration of the routine, to prevent
|
||||
;; jiffy clock update while reeading it's values
|
||||
sei
|
||||
|
||||
;; Store the jiffy clock state
|
||||
ldy TIME + 0
|
||||
ldx TIME + 1
|
||||
lda TIME + 2
|
||||
|
||||
;; Enable interrupts. More elegant solution would be pha + sei + ... + pla,
|
||||
;; but (checked by running a test program) original ROM routine always
|
||||
;; leaves IRQs enabled.
|
||||
cli
|
||||
rts
|
||||
|
||||
@@ -13,14 +13,8 @@ reset_entry:
|
||||
|
||||
; The following routine is based on reading the public KERNAL jumptable routine
|
||||
; list, and making unimaginative assumptions about what should be done on reset.
|
||||
|
||||
; According to example here: https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image
|
||||
; the cartridge does not call RAMTAS - despite it's obviously required. So, call RAMTAS
|
||||
; before the cartridge check/takeover
|
||||
|
||||
; Setting up the screen and testing ram is obviously required
|
||||
; also affirmed by p269 of c64 prg
|
||||
jsr RAMTAS
|
||||
; Also, https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image was used
|
||||
; as it shows example startup sequence, to be followe by cartridge creators
|
||||
|
||||
; C64 PRG p269
|
||||
jsr cartridge_check
|
||||
@@ -28,16 +22,18 @@ reset_entry:
|
||||
jmp (ICART_COLD_START)
|
||||
*
|
||||
; Initialising IO is obviously required. Also indicated by c64 prg p269.
|
||||
; Has to be after ther RAMTAS, as it clears memory, including the PAL/NTSC flag,
|
||||
; which is set by IOINIT
|
||||
jsr IOINIT
|
||||
jsr JIOINIT
|
||||
|
||||
; Setting up the screen and testing ram is obviously required
|
||||
; also affirmed by p269 of c64 prg
|
||||
jsr JRAMTAS ; called RANTAM on Codebase64 wiki
|
||||
|
||||
; Resetting IO vectors is obviously required, if we want interrupts to run
|
||||
; also affirmed by c64 prg p269
|
||||
jsr RESTOR
|
||||
jsr JRESTOR
|
||||
|
||||
;; "Compute's Mapping the 64" p236
|
||||
jsr CINT
|
||||
jsr JCINT
|
||||
|
||||
; What do we do when finished? A C64 jumps into the BASIC ROM
|
||||
cli ; Allow interrupts to happen
|
||||
|
||||
+6
-13
@@ -204,10 +204,6 @@ ReturnNoKeys:
|
||||
|
||||
NoActivityDetected:
|
||||
|
||||
;; Cancel STKEY status
|
||||
lda #$FF
|
||||
sta STKEY ; XXX this variable should be set by UDTIM
|
||||
|
||||
;; So cancel all bucky keys
|
||||
lda key_bucky_state
|
||||
sta key_last_bucky_state
|
||||
@@ -326,20 +322,15 @@ next_row:
|
||||
|
||||
stx $dc00 ;// Disconnect all Keyboard Rows
|
||||
cpx $dc01 ;// Only Control Port activity will be detected
|
||||
bne ReturnNoKeys
|
||||
|
||||
beq +
|
||||
jmp ReturnNoKeys
|
||||
*
|
||||
;; Make X = $00, assumed below
|
||||
inx
|
||||
|
||||
;; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
;; // Check and flag Non Alphanumeric Keys
|
||||
|
||||
;; Store last row of keyboard scan result,
|
||||
;; so that RUN/STOP etc can be checked easily
|
||||
;; (Compute's Mapping the 64, p27)
|
||||
lda ScanResult+0
|
||||
sta STKEY ; XXX this variable should be set by UDTIM
|
||||
|
||||
;; Store de-bounce data for bucky keys
|
||||
;; (Compute's Mapping the 64, p58-59)
|
||||
lda key_bucky_state
|
||||
@@ -472,7 +463,9 @@ RecordKeypress:
|
||||
;; // New Key Detected
|
||||
ldy BufferQuantity
|
||||
cpy #MaxKeyRollover
|
||||
bcs TooManyNewKeys
|
||||
bcc +
|
||||
jmp TooManyNewKeys
|
||||
*
|
||||
AcceptKeyEvent:
|
||||
sta Buffer,y
|
||||
iny
|
||||
|
||||
@@ -9,4 +9,19 @@
|
||||
;;
|
||||
|
||||
settim:
|
||||
|
||||
;; Disable interrupts for the duration of the routine, to prevent
|
||||
;; jiffy clock update while changing it's values
|
||||
sei
|
||||
|
||||
;; Store the jiffy clock state
|
||||
sty TIME + 0
|
||||
stx TIME + 1
|
||||
sta TIME + 2
|
||||
|
||||
;; Enable interrupts. More elegant solution would be pha + sei + ... + pla,
|
||||
;; but (checked by running a test program) original ROM routine always
|
||||
;; leaves IRQs enabled.
|
||||
cli
|
||||
rts
|
||||
|
||||
@@ -9,4 +9,46 @@
|
||||
;;
|
||||
|
||||
udtim:
|
||||
|
||||
;; Update jiffy clock. The whole day is $4F1A00 jiffies (24 hours * 60 minutes * 60 seconds * 60 jiffies),
|
||||
;; after this time we have to reset the clock.
|
||||
|
||||
inc TIME+0
|
||||
bne udtim_clock_done
|
||||
inc TIME+1
|
||||
bne udtim_clock_rollover
|
||||
inc TIME+2
|
||||
|
||||
;; FALLTROUGH
|
||||
|
||||
udtim_clock_done:
|
||||
udtim_update_stkey: ; entry to be used when interrupts are disabled
|
||||
|
||||
;; Another action we have to perform is to copy the last row of keyboard to RAM,
|
||||
;; so that various routines can detect the STOP key press
|
||||
;; XXX scnkey contains similar sequence - deduplicate this!
|
||||
lda #$FF
|
||||
sta CIA1_DDRA ; output
|
||||
lda #$00
|
||||
sta CIA1_DDRB ; input
|
||||
|
||||
lda #$7F
|
||||
sta CIA1_PRA ; select the last row (bit to 0)
|
||||
|
||||
lda CIA1_PRB ; read the row
|
||||
sta STKEY
|
||||
rts
|
||||
|
||||
udtim_clock_rollover:
|
||||
|
||||
;; At this point TIME+0 has to contain 0,
|
||||
lda TIME+1
|
||||
cmp #$1A
|
||||
bne udtim_clock_done
|
||||
lda TIME+2
|
||||
cmp #$4F
|
||||
bne udtim_clock_done
|
||||
lda #$00
|
||||
sta TIME+2
|
||||
sta TIME+1
|
||||
beq udtim_clock_done ; will always jump
|
||||
+1
-1
@@ -161,7 +161,7 @@ char *error_list[]={
|
||||
"READY.\r", // #29 // https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.zconcepts/zconc_whatistsonative.htm https://github.com/stefanhaustein/expressionparser
|
||||
"NTSC, ", // #30
|
||||
"PAL, ", // #31
|
||||
"", // unused for now
|
||||
"BRK AT $", // #32
|
||||
"ERROR", // #33 // Simply the word error that is attached to the other parts of messages https://fjkraan.home.xs4all.nl/comp/apple2faq/app2asoftfaq.html
|
||||
"BYTES FREE\r\r", // #34 // https://github.com/stefanhaustein/expressionparser
|
||||
"MEMORY CORRUPT", // #35
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
$DD00 + AND #$DF
|
||||
|
||||
Instruction and a half (well known hardware register address) - not copyrightable.
|
||||
@@ -0,0 +1,5 @@
|
||||
$DD00 + AND #$DF + STA $DD00 + RTS
|
||||
|
||||
$DD00 is a hardware register, where one typically set/unset/read individual bits.
|
||||
Having a set of trivial helper subroutines to set/clear individual bits (or groups of bits) is an obvious solution (thus not copyrightable), some similarities are unevitable.
|
||||
Besides, in this case (since the similarity does not even cover a single subroutine from start to end) it is clear that the similar code actually performs slightly different actions.
|
||||
@@ -0,0 +1,3 @@
|
||||
JSR $EE06 + LDA (argument does not match)
|
||||
|
||||
Instruction and a half - not copyrightable.
|
||||
@@ -0,0 +1 @@
|
||||
This is a part of Kernal jumptable - series of jumps, sometimes to the well known addreses (or through documented vectors). No business logic, part of the Kernal API itself (has to be as it is to maintain compatibility) - not copyrightable.
|
||||
@@ -0,0 +1 @@
|
||||
This is a part of Kernal jumptable - series of jumps, sometimes to the well known addreses (or through documented vectors). No business logic, part of the Kernal API itself (has to be as it is to maintain compatibility) - not copyrightable.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
RTS (from previous routine) + a list of vectors to be copied starting from $0314
|
||||
RTS (from previous routine) + a list of vectors to be copied starting from $0314 + LDA #$00
|
||||
|
||||
Values of the vectors are already present in many autostart software - as it often overrides them,
|
||||
sometimes changing one to trigger autostart (one of the possible techniques). We have to use the same
|
||||
@@ -1 +1 @@
|
||||
This is a part of Kernal jumptable - series of jumps, sometimes to the well known addreses (or through documented vectors). No business logic, part of the Kernal API itself - not copyrightable.
|
||||
This is a part of Kernal jumptable - series of jumps, sometimes to the well known addreses (or through documented vectors). No business logic, part of the Kernal API itself (has to be as it is to maintain compatibility) - not copyrightable.
|
||||
@@ -0,0 +1,3 @@
|
||||
$7F + STA $DC0D
|
||||
|
||||
Instruction (access to a docummented hardware register) and some part - not copyrightable.
|
||||
@@ -0,0 +1,3 @@
|
||||
TYA + PHA + TSX + LDA $0104,X + AND #$10
|
||||
|
||||
Beginning of IRQ handler - checks whether it is caused by BRK instruction or some other reason. Since IRQ handling for BRK/non-BRK caused interrupts are totally different, there is no other way but to start with such a check. Not creative - not copyrightable.
|
||||
@@ -0,0 +1,3 @@
|
||||
LDA $9D + BPL (address match)
|
||||
|
||||
Checking a well-known zeropage flag - not creative, not copyrightable.
|
||||
@@ -0,0 +1,3 @@
|
||||
LDA #$7F + STA $DC00 + LDA $DC01
|
||||
|
||||
Part of keyboard scanning code in UDTIM routine - to get the last row (not even complete code, as there is also some code to set the port directions). This is probably the only sane way to read the rom. Not creative - not copyrightable.
|
||||
@@ -0,0 +1,3 @@
|
||||
BNE (offset match) + INC $A1 + BNE (offset does not match)
|
||||
|
||||
Part of the routine to increment a well-known 24-bit counter. There are not many ways to do this in a sane way, some similarity is unavoidable, 2 instructions and a half is not much in this case. Not copyrightable.
|
||||
@@ -0,0 +1,5 @@
|
||||
$DD + ORA #$08 + STA $DD00
|
||||
|
||||
$DD00 is a hardware register, where one typically set/unset/read individual bits.
|
||||
Having a set of trivial helper subroutines to set/clear individual bits (or groups of bits) is an obvious solution (thus not copyrightable), some similarities are unevitable.
|
||||
Besides, in this case (since the similarity does not even cover a single subroutine from start to end) it is clear that the similar code actually performs slightly different actions.
|
||||
@@ -0,0 +1,5 @@
|
||||
$DD + RTS + LDA $DD00 + ORA #$10
|
||||
|
||||
$DD00 is a hardware register, where one typically set/unset/read individual bits.
|
||||
Having a set of trivial helper subroutines to set/clear individual bits (or groups of bits) is an obvious solution (thus not copyrightable), some similarities are unevitable.
|
||||
Besides, in this case (since the similarity does not even cover a single subroutine from start to end) it is clear that the similar code actually performs slightly different actions.
|
||||
@@ -0,0 +1,5 @@
|
||||
$DF + STA $DD00 + RTS + LDA $DD00 + ORA (argument does not match)
|
||||
|
||||
$DD00 is a hardware register, where one typically set/unset/read individual bits.
|
||||
Having a set of trivial helper subroutines to set/clear individual bits (or groups of bits) is an obvious solution (thus not copyrightable), some similarities are unevitable.
|
||||
Besides, in this case (since the similarity does not even cover a single subroutine from start to end) it is clear that the similar code actually performs slightly different actions.
|
||||
@@ -0,0 +1,3 @@
|
||||
$EE + LDA $DD00
|
||||
|
||||
Instruction (access to a well known hardware register address) and a half - not copyrightable.
|
||||
@@ -0,0 +1 @@
|
||||
This is a part of Kernal jumptable - series of jumps, sometimes to the well known addreses (or through documented vectors). No business logic, part of the Kernal API itself (has to be as it is to maintain compatibility) - not copyrightable.
|
||||
@@ -0,0 +1,3 @@
|
||||
$FF + CLI + JMP ($A000)
|
||||
|
||||
Part of the address, reenabling interrupts, jump through a documented vector - part of the initialization/reset sequence. Not creative - not copyrightable.
|
||||
Reference in new issue
Block a user