Skip to content

Commit 1be9ca6

Browse files
authored
Merge pull request #244 from davidgiven/c64
Add a fastloader for the C64 and VIC20 ports.
2 parents d6cbed4 + 2b1d1a9 commit 1be9ca6

File tree

25 files changed

+2089
-761
lines changed

25 files changed

+2089
-761
lines changed

.github/workflows/ccpp.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
repository: 'davidgiven/cpm65'
1212

1313
- name: apt
14-
run: sudo apt update && sudo apt install cc1541 cpmtools libfmt-dev fp-compiler moreutils mame srecord 64tass libreadline-dev
14+
run: sudo apt update && sudo apt install cc1541 cpmtools libfmt-dev fp-compiler moreutils mame srecord 64tass libreadline-dev libelf-dev
1515

1616
- name: install llvm-mos
1717
run: |

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
path: 'cpm65'
1616

1717
- name: apt
18-
run: sudo apt update && sudo apt install cc1541 cpmtools libfmt-dev fp-compiler moreutils srecord 64tass libreadline-dev
18+
run: sudo apt update && sudo apt install cc1541 cpmtools libfmt-dev fp-compiler moreutils srecord 64tass libreadline-dev libelf-dev
1919

2020
- name: install llvm-mos
2121
run: |

README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -163,17 +163,20 @@ the same time.
163163
164164
- Load and run the `CPM` program to start.
165165
166-
- It's excruciatingly slow as it uses normal 1541 disk accesses at 300 bytes
167-
per second. Everything works, but you won't enjoy it. At some point I want
168-
to add a fastloader.
166+
- It has its own built-in fastloader, which has been lightly tested but seems
167+
to work on both NTSC and PAL C64s. It needs tuning but currently seems to get
168+
about 1100 bytes per second, which is 4x the normal 1541 speed. (It's the same
169+
one as for the VIC-20.)
169170
170171
- The disk image produced is a hybrid of a CP/M file system and a CBMDOS file
171172
system, which can be accessed as either. The disk structures used by the
172173
other file system are hidden. You get about 170kB on a normal disk.
173174
174-
- Disk accesses are done using direct block access, so it _won't_ work on
175-
anything other than a 1541 (but it should be straightforward to add
176-
support for other drives). Sorry.
175+
- It'll only work on a 1541, and probably only a 1541-II. Because of the
176+
fastloader. Sorry. Porting it to other drives is perfectly possible, I
177+
just haven't done it.
178+
179+
- This won't work on MAME. You'll need VICE to emulate it.
177180
178181
### VIC-20 notes
179182
@@ -186,9 +189,6 @@ the same time.
186189
doesn't look great but is surprisingly readable, and is vastly better than
187190
the VIC-20's default 22x24 screen mode.
188191
189-
- Disk accesses are slightly faster than the Commodore 64, but only just.
190-
It's still a miserable experience.
191-
192192
### Commodore PET notes
193193
194194
- You need a PET 4032, 8032 or 8096 and either a 4040 disk drive or something

build.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
package(name="libreadline", package="readline")
55
package(name="libfmt", package="fmt")
6+
package(name="libelf", package="libelf")
67

78
export(
89
name="all",
@@ -63,18 +64,28 @@
6364
name="mametest",
6465
deps=[
6566
"src/arch/bbcmicro+mametest",
66-
"src/arch/commodore+c64_mametest",
67+
68+
# Isn't accurate enough to support the fastloader.
69+
#"src/arch/commodore+c64_mametest",
70+
71+
# As above, and also doesn't support enough memory expansions.
72+
#"src/arch/commodore+vic20_mametest",
73+
6774
# MAME's ROM configuration is for the graphics keyboard, but MAME's
6875
# hardware emulates the business keyboard, so we can't interact with the
6976
# system.
7077
# "src/arch/commodore+pet4032_mametest",
78+
7179
# MAME's ROM configuration is for the business keyboard, but MAME's
7280
# hardware emulates the graphics keyboard...
7381
# "src/arch/commodore+pet8032_mametest",
82+
7483
# Works locally, but not on github CI.
7584
# "src/arch/apple2e+mametest",
85+
7686
# Fails everywhere.
7787
# "src/arch/atari800+mametest",
88+
7889
"src/arch/oric+mametest",
7990
],
8091
)

include/zif.inc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,22 @@
1010
.set zloopsp, 0
1111
.set zifsp, 0
1212

13+
.macro blt label
14+
bcc \label
15+
.endm
16+
17+
.macro bge label
18+
bcs \label
19+
.endm
20+
1321
.macro zproc name, sect=.text, binding=global
1422
.section \sect, "ax"
1523
.\binding \name
1624
\name:
1725
.endm
1826

19-
.macro zlproc name, sect=.text, binding=global
20-
zproc \name, .text, local
27+
.macro zlproc name, sect=.text
28+
zproc \name, \sect, local
2129
.endm
2230

2331
.macro zendproc

src/arch/commodore/bios1541.S

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
; CP/M-65 Copyright © 2022 David Given
2+
; This file is licensed under the terms of the 2-clause BSD license. Please
3+
; see the COPYING file in the root project directory for the full text.
4+
5+
#include "zif.inc"
6+
#include "cpm65.inc"
7+
8+
ZEROPAGE
9+
10+
.zeropage ptr
11+
.zeropage ptr1
12+
13+
dma: .fill 2
14+
15+
sector_num: .fill 3 ; current absolute sector number
16+
buffered_sector: .fill 3 ; sector currently in disk buffer
17+
18+
; Initialises the disk library.
19+
20+
zproc bios1541_init, ".init"
21+
lda #0
22+
sta buffer_dirty
23+
24+
ldy #3
25+
zrepeat
26+
lda #0
27+
sta sector_num-1, y
28+
lda #0xff
29+
sta buffered_sector-1, y
30+
dey
31+
zuntil eq
32+
33+
rts
34+
zendproc
35+
36+
; Sets the current DMA address.
37+
38+
zproc bios_SETDMA
39+
sta dma+0
40+
stx dma+1
41+
clc
42+
rts
43+
zendproc
44+
45+
; Select a disk.
46+
; A is the disk number.
47+
; Returns the DPH in XA.
48+
; Sets carry on error.
49+
50+
zproc bios_SELDSK
51+
cmp #0
52+
zif ne
53+
sec ; invalid drive
54+
rts
55+
zendif
56+
57+
lda #<dph
58+
ldx #>dph
59+
clc
60+
rts
61+
zendproc
62+
63+
; Set the current absolute sector number.
64+
; XA is a pointer to a three-byte number.
65+
66+
zproc bios_SETSEC
67+
sta ptr+0
68+
stx ptr+1
69+
ldy #2
70+
zrepeat
71+
lda (ptr), y
72+
sta sector_num, y
73+
dey
74+
zuntil mi
75+
clc
76+
rts
77+
zendproc
78+
79+
zproc bios_READ
80+
jsr change_sectors
81+
zif cc
82+
lda sector_num+0
83+
ror a ; bottom bit -> C
84+
lda #0
85+
ror a ; C -> top bit, producing $00 or $80
86+
tax
87+
88+
ldy #0
89+
zrepeat
90+
lda disk_buffer, x
91+
sta (dma), y
92+
iny
93+
inx
94+
cpy #$80
95+
zuntil eq
96+
97+
clc
98+
zendif
99+
rts
100+
zendproc
101+
102+
; On entry, A=0 for a normal write; A=1 to always flush to disk.
103+
104+
zproc bios_WRITE
105+
pha
106+
jsr change_sectors
107+
zif cs
108+
pla
109+
sec
110+
rts
111+
zendif
112+
113+
lda sector_num+0
114+
ror a ; bottom bit -> C
115+
lda #0
116+
ror a ; C -> top bit, producing $00 or $80
117+
tax
118+
119+
ldy #0
120+
zrepeat
121+
lda (dma), y
122+
sta disk_buffer, x
123+
iny
124+
inx
125+
cpy #$80
126+
zuntil eq
127+
128+
lda #$80
129+
sta buffer_dirty
130+
131+
pla
132+
zif ne
133+
jmp flush_buffered_sector
134+
zendif
135+
136+
clc
137+
rts
138+
zendproc
139+
140+
; Returns C on error.
141+
142+
zproc change_sectors
143+
; If the buffered sector is the one we want, just return.
144+
145+
lda sector_num+0
146+
and #$fe
147+
cmp buffered_sector+0
148+
zif eq
149+
lda sector_num+1
150+
cmp buffered_sector+1
151+
zif eq
152+
lda sector_num+2
153+
cmp buffered_sector+2
154+
zif eq
155+
clc
156+
rts
157+
zendif
158+
zendif
159+
zendif
160+
161+
; We need to change sectors. Flush the current one?
162+
163+
jsr flush_buffered_sector
164+
165+
; Now read the new one.
166+
167+
lda sector_num+0
168+
and #$fe
169+
sta buffered_sector+0
170+
lda sector_num+1
171+
sta buffered_sector+1
172+
lda sector_num+2
173+
sta buffered_sector+2
174+
175+
jsr buffered_sector_to_lba
176+
jmp read_sector
177+
zendproc
178+
179+
; Compute the current LBA sector number in XA for the buffered sector.
180+
181+
zproc buffered_sector_to_lba
182+
lda buffered_sector+1
183+
lsr a
184+
tax
185+
lda buffered_sector+0
186+
ror
187+
rts
188+
zendproc
189+
190+
zproc flush_buffered_sector
191+
bit buffer_dirty
192+
zif mi
193+
jsr buffered_sector_to_lba
194+
jsr write_sector
195+
196+
lda #0
197+
sta buffer_dirty
198+
zendif
199+
rts
200+
zendproc
201+
202+
.bss
203+
204+
.global directory_buffer, disk_buffer
205+
directory_buffer: .fill 128
206+
disk_buffer: .fill 256
207+
buffer_dirty: .fill 1 ; non-zero if sector needs flushing
208+
209+
; DPH and DPB for drive 0 (our only drive)
210+
211+
define_dpb dpb_1541, 136*10, 1024, 64, 0
212+
define_dph dph, dpb_1541

0 commit comments

Comments
 (0)