badline 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -0
  3. data/CLAUDE.md +1 -1
  4. data/README.md +130 -17
  5. data/doc/media.md +14 -2
  6. data/doc/pinned-behaviour.md +61 -0
  7. data/doc/snapshot-format.md +379 -70
  8. data/doc/snapshots.md +185 -10
  9. data/lib/badline/cbm2/acia.rb +10 -0
  10. data/lib/badline/cbm2/bus.rb +263 -0
  11. data/lib/badline/cbm2/cpu.rb +58 -0
  12. data/lib/badline/cbm2/crtc_video.rb +133 -0
  13. data/lib/badline/cbm2/ieee_drive.rb +18 -0
  14. data/lib/badline/cbm2/ieee_layout.rb +69 -0
  15. data/lib/badline/cbm2/ieee_ports.rb +104 -0
  16. data/lib/badline/cbm2/ieee_traps.rb +81 -0
  17. data/lib/badline/cbm2/keyboard_ports.rb +60 -0
  18. data/lib/badline/cbm2/keyed_modules.rb +67 -0
  19. data/lib/badline/cbm2/keyed_state.rb +91 -0
  20. data/lib/badline/cbm2/model.rb +44 -0
  21. data/lib/badline/cbm2/p500/control_ports.rb +80 -0
  22. data/lib/badline/cbm2/p500/ieee_layout.rb +41 -0
  23. data/lib/badline/cbm2/p500/keyed_state.rb +85 -0
  24. data/lib/badline/cbm2/p500/model.rb +39 -0
  25. data/lib/badline/cbm2/p500/pages.rb +57 -0
  26. data/lib/badline/cbm2/p500.rb +262 -0
  27. data/lib/badline/cbm2/sid_page.rb +19 -0
  28. data/lib/badline/cbm2.rb +267 -0
  29. data/lib/badline/{plus4 → chips}/acia/frames.rb +1 -1
  30. data/lib/badline/chips/acia/keyed_state.rb +47 -0
  31. data/lib/badline/chips/acia.rb +307 -0
  32. data/lib/badline/chips/crtc.rb +3 -2
  33. data/lib/badline/chips/riot/fast_forward.rb +72 -0
  34. data/lib/badline/chips/riot/keyed_parts.rb +69 -0
  35. data/lib/badline/chips/riot/timer.rb +80 -0
  36. data/lib/badline/chips/riot.rb +162 -0
  37. data/lib/badline/chips/rriot/keyed_state.rb +30 -0
  38. data/lib/badline/chips/rriot.rb +132 -0
  39. data/lib/badline/chips/tpi/keyed_state.rb +38 -0
  40. data/lib/badline/chips/tpi.rb +233 -0
  41. data/lib/badline/chips/vic/bank.rb +60 -5
  42. data/lib/badline/chips/vic/sprite.rb +4 -3
  43. data/lib/badline/drives/datasette/keyed_state.rb +9 -1
  44. data/lib/badline/drives/datasette.rb +27 -3
  45. data/lib/badline/drives/ieee_bus.rb +50 -4
  46. data/lib/badline/drives/model2031/ieee_port.rb +133 -0
  47. data/lib/badline/drives/model2031/keyed_state.rb +66 -0
  48. data/lib/badline/drives/model2031/parts.rb +25 -0
  49. data/lib/badline/drives/model2031.rb +92 -0
  50. data/lib/badline/drives/model8050/disk.rb +163 -0
  51. data/lib/badline/drives/model8050/fdc_bus.rb +102 -0
  52. data/lib/badline/drives/model8050/idle.rb +177 -0
  53. data/lib/badline/drives/model8050/ieee_port.rb +147 -0
  54. data/lib/badline/drives/model8050/ip_bus.rb +93 -0
  55. data/lib/badline/drives/model8050/keyed_state.rb +160 -0
  56. data/lib/badline/drives/model8050/mechanism.rb +230 -0
  57. data/lib/badline/drives/model8050/parts.rb +37 -0
  58. data/lib/badline/drives/model8050.rb +243 -0
  59. data/lib/badline/frontend/app.rb +10 -3
  60. data/lib/badline/frontend/boot.rb +1 -1
  61. data/lib/badline/frontend/controls.rb +51 -15
  62. data/lib/badline/frontend/gamepads.rb +3 -3
  63. data/lib/badline/frontend/keys.rb +61 -2
  64. data/lib/badline/frontend/media_slots.rb +1 -1
  65. data/lib/badline/frontend/menu/menu_media.rb +14 -11
  66. data/lib/badline/frontend/menu/menu_pages.rb +29 -6
  67. data/lib/badline/frontend/menu/menu_ports.rb +40 -4
  68. data/lib/badline/frontend/menu/pause_menu.rb +1 -1
  69. data/lib/badline/frontend/pet_keyboard.rb +23 -7
  70. data/lib/badline/frontend/timeline.rb +19 -10
  71. data/lib/badline/kernal_trap/dos/disk_commands.rb +80 -0
  72. data/lib/badline/kernal_trap/dos/status.rb +3 -0
  73. data/lib/badline/kernal_trap/dos.rb +18 -5
  74. data/lib/badline/kernal_trap/ieee.rb +7 -2
  75. data/lib/badline/kernal_trap/ieee_layout.rb +95 -43
  76. data/lib/badline/machine/ieee_drives.rb +194 -0
  77. data/lib/badline/machine/settling.rb +4 -0
  78. data/lib/badline/machine.rb +26 -8
  79. data/lib/badline/media/cbm2_media.rb +29 -0
  80. data/lib/badline/media/pet_media.rb +5 -5
  81. data/lib/badline/media/program.rb +6 -3
  82. data/lib/badline/media/true_drive.rb +50 -8
  83. data/lib/badline/media.rb +21 -8
  84. data/lib/badline/options/family.rb +15 -3
  85. data/lib/badline/options/help.rb +24 -6
  86. data/lib/badline/options/table.rb +25 -5
  87. data/lib/badline/options/validation.rb +47 -7
  88. data/lib/badline/options.rb +48 -15
  89. data/lib/badline/pet/bus/expansion.rb +99 -5
  90. data/lib/badline/pet/bus.rb +30 -12
  91. data/lib/badline/pet/cassettes.rb +22 -1
  92. data/lib/badline/pet/characters.rb +8 -2
  93. data/lib/badline/pet/crtc_video.rb +20 -7
  94. data/lib/badline/pet/ieee_drive.rb +17 -0
  95. data/lib/badline/pet/ieee_ports.rb +19 -1
  96. data/lib/badline/pet/ieee_traps.rb +10 -5
  97. data/lib/badline/pet/keyed_modules.rb +4 -1
  98. data/lib/badline/pet/keyed_parts.rb +10 -6
  99. data/lib/badline/pet/model.rb +56 -6
  100. data/lib/badline/pet/rom_sets.rb +30 -6
  101. data/lib/badline/pet.rb +45 -16
  102. data/lib/badline/plus4/acia.rb +4 -298
  103. data/lib/badline/plus4/keyed_parts.rb +0 -44
  104. data/lib/badline/plus4.rb +1 -0
  105. data/lib/badline/roms/8050/dos-2.7.rom +0 -0
  106. data/lib/badline/roms/8050/fdc-901869-01.rom +0 -0
  107. data/lib/badline/roms/8050/fdc-901885-04.rom +0 -0
  108. data/lib/badline/roms/README +144 -1
  109. data/lib/badline/roms/cbm2/basic128-02b.rom +0 -0
  110. data/lib/badline/roms/cbm2/basic128.rom +0 -0
  111. data/lib/badline/roms/cbm2/basic256.rom +0 -0
  112. data/lib/badline/roms/cbm2/characters-600.rom +0 -0
  113. data/lib/badline/roms/cbm2/characters-700.rom +0 -0
  114. data/lib/badline/roms/cbm2/kernal-03b.rom +0 -0
  115. data/lib/badline/roms/cbm2/kernal-04a.rom +0 -0
  116. data/lib/badline/roms/cbm2/p500-basic.rom +0 -0
  117. data/lib/badline/roms/cbm2/p500-kernal.rom +0 -0
  118. data/lib/badline/roms/dos2031.rom +0 -0
  119. data/lib/badline/roms/pet/characters-din.rom +0 -0
  120. data/lib/badline/roms/pet/editor4-80-b-50hz-8296.rom +0 -0
  121. data/lib/badline/snapshot/cbm2_setup.rb +53 -0
  122. data/lib/badline/snapshot/container.rb +9 -1
  123. data/lib/badline/snapshot/field_doc/markdown.rb +4 -2
  124. data/lib/badline/snapshot/field_doc.rb +39 -3
  125. data/lib/badline/snapshot/image.rb +79 -15
  126. data/lib/badline/snapshot/pet_setup.rb +30 -13
  127. data/lib/badline/snapshot/vice/cbm2.rb +93 -0
  128. data/lib/badline/snapshot/vice/cbm2_acia.rb +75 -0
  129. data/lib/badline/snapshot/vice/cbm2_crtc.rb +127 -0
  130. data/lib/badline/snapshot/vice/cbm2_mains.rb +49 -0
  131. data/lib/badline/snapshot/vice/cbm2_mem.rb +75 -0
  132. data/lib/badline/snapshot/vice/cbm2_restore.rb +204 -0
  133. data/lib/badline/snapshot/vice/cbm2_tpi.rb +58 -0
  134. data/lib/badline/snapshot/vice/cias.rb +13 -9
  135. data/lib/badline/snapshot/vice/p500.rb +96 -0
  136. data/lib/badline/snapshot/vice/p500_restore.rb +130 -0
  137. data/lib/badline/snapshot/vice/p500_vicii.rb +166 -0
  138. data/lib/badline/snapshot/vice/pet.rb +121 -0
  139. data/lib/badline/snapshot/vice/pet_cpu.rb +70 -0
  140. data/lib/badline/snapshot/vice/pet_crtc.rb +241 -0
  141. data/lib/badline/snapshot/vice/pet_drive.rb +180 -0
  142. data/lib/badline/snapshot/vice/pet_drive8050.rb +216 -0
  143. data/lib/badline/snapshot/vice/pet_mem.rb +93 -0
  144. data/lib/badline/snapshot/vice/pet_pias.rb +56 -0
  145. data/lib/badline/snapshot/vice/pet_restore.rb +214 -0
  146. data/lib/badline/snapshot/vice/pet_via.rb +165 -0
  147. data/lib/badline/snapshot/vice/sid_registers.rb +2 -1
  148. data/lib/badline/snapshot/vice/vicii_import.rb +10 -6
  149. data/lib/badline/snapshot/vice.rb +4 -0
  150. data/lib/badline/snapshot.rb +11 -3
  151. data/lib/badline/storage/crt_file.rb +7 -1
  152. data/lib/badline/storage/d64_image.rb +7 -0
  153. data/lib/badline/storage/d80_image.rb +17 -1
  154. data/lib/badline/storage/d81_image.rb +14 -0
  155. data/lib/badline/storage/disk_image/bam.rb +18 -3
  156. data/lib/badline/storage/disk_image/formatting.rb +69 -0
  157. data/lib/badline/storage/disk_image/writing.rb +35 -0
  158. data/lib/badline/storage/disk_image.rb +2 -0
  159. data/lib/badline/storage.rb +1 -0
  160. data/lib/badline/support/cbm2_checkpoint.rb +48 -0
  161. data/lib/badline/support/p500_checkpoint.rb +35 -0
  162. data/lib/badline/version.rb +1 -1
  163. data/lib/badline.rb +1 -0
  164. metadata +87 -2
@@ -1,305 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "badline/plus4/acia/frames"
4
-
5
3
  module Badline
6
4
  class Plus4
7
- # The Plus/4's 6551 ACIA at $FD00-$FD0F, its four registers repeated:
8
- #
9
- # $FD00 - read the receiver's data, write the transmitter's
10
- # $FD01 - read the status, write a programmed reset
11
- # $FD02 - the command register
12
- # $FD03 - the control register
13
- #
14
- # Status: bit 0 a parity error, 1 a framing error, 2 an overrun, 3 the
15
- # receiver full, 4 the transmitter empty, 5 DCD and 6 DSR as their pins
16
- # read (1 high, not asserted), 7 an interrupt. Reading it clears bit 7.
17
- #
18
- # Command: bit 0 DTR, which also enables the receiver and every
19
- # interrupt, bit 1 set disables the receiver's interrupt, bits 2-3 the
20
- # transmitter (00 off with RTS high, 01 on with its interrupt, 10 on
21
- # without, 11 sending a break), bit 4 echoes what is received, bits 5-7
22
- # the parity.
23
- #
24
- # Control: bits 0-3 the baud rate from the 1.8432 MHz crystal (0, the
25
- # 16x external clock, runs straight from the crystal, 115,200 baud),
26
- # bit 4 the receiver's clock (0 the RxC pin, which nothing drives on the
27
- # Plus/4, so the receiver hears nothing), bits 5-6 the word length (8
28
- # down to 5 bits) and bit 7 the stop bits (Frames).
29
- #
30
- # The transmitter runs in whole characters while it is on: at the end
31
- # of each it hands the character it shifted out to the line, moves a
32
- # waiting byte from the data register into the shift register and sets
33
- # the transmitter empty, and with its interrupt on interrupts while the
34
- # register is empty, every character until a byte comes. The first
35
- # character ends a character's time after the transmitter comes on.
36
- # The receiver takes a character's time for each byte the line sends,
37
- # and a byte that arrives while the last is unread is lost to an
38
- # overrun. The receiver full, and DCD or DSR changing, interrupt unless
39
- # bit 1 disables it.
40
- #
41
- # The user port carries no CTS, so the transmitter is always clear to
42
- # send; the KERNAL takes the user port's 6529 P1 as its handshake.
43
- #
44
- # What is on the other end of the user port (#plug): nothing, where
45
- # DCD and DSR read high and what is sent goes nowhere; a terminal,
46
- # which asserts DCD and DSR, sends what the host feeds it (#feed) while
47
- # DTR is asserted and keeps what it receives for the host to drain
48
- # (#drain); or a loopback plug, which returns TxD to RxD and DTR to DSR
49
- # and DCD.
50
- #
51
- # The machine runs the ACIA at the cycle it next has something to do
52
- # (#due) through #run!, and learns its IRQ line and that cycle from
53
- # `clock`'s #acia_changed, whose #cycles is the time.
54
- class ACIA
55
- include Frames
56
-
57
- PARITY_ERROR = 0x01
58
- FRAMING_ERROR = 0x02
59
- OVERRUN = 0x04
60
- RECEIVER_FULL = 0x08
61
- TRANSMITTER_EMPTY = 0x10
62
- DCD = 0x20
63
- DSR = 0x40
64
- IRQ = 0x80
65
-
66
- NOTHING = 0
67
- TERMINAL = 1
68
- LOOPBACK = 2
69
-
70
- # No shift in progress.
71
- IDLE = -1
72
-
73
- # Far enough ahead that it never comes.
74
- NEVER = 1 << 60
75
-
76
- attr_reader :command, :control, :device, :due
77
-
78
- def initialize(clock, clock_hz)
79
- @clock = clock
80
- @clock_hz = clock_hz
81
- @device = NOTHING
82
- @incoming = []
83
- @received = []
84
- reset!
85
- end
86
-
87
- # The RES line: every register cleared, the transmitter empty and
88
- # both shift registers stopped.
89
- def reset!
90
- @command = 0
91
- @control = 0
92
- @errors = 0
93
- @receiver_full = false
94
- @transmitter_empty = true
95
- @irq = false
96
- @receive_data = 0
97
- @transmit_data = 0
98
- @shifting = IDLE
99
- @transmit_at = NEVER
100
- @transmit_remainder = 0
101
- @receive_at = NEVER
102
- @receive_remainder = 0
103
- @clock_lost = false
104
- @lines = modem_lines
105
- changed
106
- end
107
-
108
- def irq? = @irq
109
-
110
- # DTR and RTS as asserted, low on the pins.
111
- def dtr? = @command.anybits?(0x01)
112
-
113
- def rts? = @command.anybits?(0x0c)
114
-
115
- # Whether the transmitter sends a break, holding TxD low.
116
- def break? = @command & 0x0c == 0x0c
117
-
118
- # Plugs NOTHING, a TERMINAL or a LOOPBACK plug into the user port.
119
- def plug(device)
120
- @device = device
121
- @incoming.clear
122
- lines_changed
123
- start_receiving
124
- changed
125
- end
126
-
127
- # Bytes the terminal sends, one a character's time while DTR is
128
- # asserted.
129
- def feed(bytes)
130
- return unless @device == TERMINAL
131
-
132
- @incoming.concat(bytes)
133
- start_receiving
134
- changed
135
- end
136
-
137
- # What the terminal has received since the last drain.
138
- def drain
139
- received = @received
140
- @received = []
141
- received
142
- end
143
-
144
- # Runs what falls due up to cycle `now`: the transmitter's character
145
- # ends, then the receiver's.
146
- def run!(now)
147
- end_character while @transmit_at <= now
148
- receive_character while @receive_at <= now
149
- changed
150
- end
151
-
152
- def peek(addr)
153
- case addr & 0x03
154
- when 0
155
- @receiver_full = false
156
- @receive_data
157
- when 1 then read_status
158
- when 2 then @command
159
- else @control
160
- end
161
- end
162
-
163
- def poke(addr, value)
164
- case addr & 0x03
165
- when 0 then write_data(value)
166
- when 1 then write_command(@command & 0xe0, clear_overrun: true)
167
- when 2 then write_command(value)
168
- else @control = value
169
- end
170
- changed
171
- end
172
-
173
- # The status as a read finds it, without clearing the interrupt.
174
- def status
175
- status = @errors | (@lines & (DCD | DSR))
176
- status |= RECEIVER_FULL if @receiver_full
177
- status |= TRANSMITTER_EMPTY if @transmitter_empty
178
- @irq ? status | IRQ : status
179
- end
180
-
181
- private
182
-
183
- def read_status
184
- value = status
185
- @irq = false
186
- changed
187
- value
188
- end
189
-
190
- def write_data(value)
191
- @transmit_data = value
192
- @transmitter_empty = false
193
- end
194
-
195
- def write_command(value, clear_overrun: false)
196
- was_on = transmitter_on?
197
- @command = value
198
- @errors &= ~OVERRUN if clear_overrun
199
- start_transmitting if transmitter_on? && !was_on
200
- stop_transmitting unless transmitter_on? || @shifting != IDLE
201
- lines_changed
202
- start_receiving
203
- end
204
-
205
- def transmitter_on?
206
- control = @command & 0x0c
207
- control != 0 && control != 0x0c
208
- end
209
-
210
- def interrupts? = @command.anybits?(0x01)
211
-
212
- def receiver_interrupts? = @command & 0x03 == 0x01
213
-
214
- def transmitter_interrupts? = @command & 0x0d == 0x05
215
-
216
- def receiving? = dtr? && @control.anybits?(0x10)
217
-
218
- def start_transmitting
219
- @transmit_remainder = 0
220
- @transmit_at = after(@clock.cycles, true)
221
- end
222
-
223
- def stop_transmitting
224
- @transmit_at = NEVER
225
- end
226
-
227
- # A character's end: the character shifted out goes to the line, and
228
- # the transmitter takes the next byte or interrupts while it has none.
229
- def end_character
230
- sent = @shifting
231
- @shifting = IDLE
232
- deliver(sent) unless sent == IDLE
233
- on = transmitter_on?
234
- if on && !@transmitter_empty
235
- @shifting = @transmit_data & word_mask
236
- @transmitter_empty = true
237
- end
238
- @irq = true if on && @transmitter_empty && transmitter_interrupts?
239
- if on || @shifting != IDLE
240
- @transmit_at = after(@transmit_at, true)
241
- else
242
- stop_transmitting
243
- end
244
- end
245
-
246
- def deliver(byte)
247
- case @device
248
- when TERMINAL then @received << byte
249
- when LOOPBACK then take(byte) if receiving?
250
- end
251
- end
252
-
253
- def start_receiving
254
- return unless @receive_at == NEVER && !@incoming.empty? && receiving?
255
-
256
- @receive_remainder = 0
257
- @receive_at = after(@clock.cycles, false)
258
- end
259
-
260
- def receive_character
261
- byte = @incoming[0]
262
- @incoming.delete_at(0)
263
- take(byte)
264
- @receive_at = !@incoming.empty? && receiving? ? after(@receive_at, false) : NEVER
265
- end
266
-
267
- # A whole character in from RxD: into the data register, or lost to
268
- # an overrun while the last is unread. In echo mode it goes back out
269
- # to the terminal.
270
- def take(byte)
271
- if @receiver_full
272
- @errors |= OVERRUN
273
- else
274
- @receive_data = byte & word_mask
275
- @receiver_full = true
276
- @errors = 0
277
- end
278
- @received << byte if @device == TERMINAL && @command & 0x1c == 0x10
279
- @irq = true if receiver_interrupts?
280
- end
281
-
282
- # DCD and DSR as the device drives them, interrupting on a change.
283
- def lines_changed
284
- lines = modem_lines
285
- return if lines == @lines
286
-
287
- @lines = lines
288
- @irq = true if receiver_interrupts?
289
- end
290
-
291
- def modem_lines
292
- case @device
293
- when TERMINAL then 0
294
- when LOOPBACK then dtr? ? 0 : DCD | DSR
295
- else DCD | DSR
296
- end
297
- end
298
-
299
- def changed
300
- @due = [@transmit_at, @receive_at].min
301
- @clock.acia_changed(@irq && interrupts?, @due)
302
- end
5
+ # The Plus/4's 6551 at $FD00-$FD0F, on the user port. Nothing drives
6
+ # its RxC pin, and the user port carries no CTS; the KERNAL takes the
7
+ # user port's 6529 P1 as its handshake.
8
+ class ACIA < Chips::ACIA
303
9
  end
304
10
  end
305
11
  end
@@ -52,50 +52,6 @@ module Badline
52
52
  include KeyedState
53
53
  end
54
54
 
55
- class ACIA
56
- # The registers, the status, the shift register and when the
57
- # transmitter's character ends, in a keyed snapshot module (BL-ACIA).
58
- # What the device on the user port has still to send stays with the
59
- # host, and the receiver starts on it again once loaded (#restored!).
60
- # A snapshot from before the transmitter's timing was saved starts
61
- # its character clock on load.
62
- module KeyedState
63
- def save_fields(out)
64
- out.int("command", @command).int("control", @control).int("errors", @errors)
65
- out.bool("receiver_full", @receiver_full).bool("transmitter_empty", @transmitter_empty).bool("irq", @irq)
66
- out.int("receive_data", @receive_data).int("transmit_data", @transmit_data).int("shifting", @shifting)
67
- out.int("transmit_at", @transmit_at).int("transmit_remainder", @transmit_remainder)
68
- end
69
-
70
- def load_fields(input)
71
- @command = input.byte("command", @command)
72
- @control = input.byte("control", @control)
73
- @errors = input.masked("errors", 0, PARITY_ERROR | FRAMING_ERROR | OVERRUN)
74
- @receiver_full = input.bool("receiver_full", false)
75
- @transmitter_empty = input.bool("transmitter_empty", true)
76
- @irq = input.bool("irq", false)
77
- @receive_data = input.byte("receive_data", 0)
78
- @transmit_data = input.byte("transmit_data", 0)
79
- @shifting = input.int("shifting", IDLE)
80
- @transmit_remainder = input.int("transmit_remainder", 0)
81
- transmit_at = input.optional_int("transmit_at")
82
- @transmit_at = transmit_at || NEVER
83
- @clock_lost = transmit_at.nil?
84
- end
85
-
86
- def restored!
87
- @receive_at = NEVER
88
- @lines = modem_lines
89
- start_transmitting if @clock_lost && transmitter_on?
90
- @clock_lost = false
91
- start_receiving
92
- changed
93
- end
94
- end
95
-
96
- include KeyedState
97
- end
98
-
99
55
  class Bus
100
56
  # The ROM bank latch, whether ROM is selected and the last byte on the
101
57
  # bus, under `prefix`, and the cartridges' ROMs by slot (#save_slot_fields),
data/lib/badline/plus4.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "badline/chips/ted"
4
4
  require "badline/chips/tia"
5
+ require "badline/chips/acia"
5
6
  require "badline/drives/model1551"
6
7
  require "badline/plus4/model"
7
8
  require "badline/plus4/cpu"
Binary file
@@ -88,6 +88,46 @@ Downloaded from
88
88
  https://www.zimmers.net/anonftp/pub/cbm/firmware/drives/new/1551/1551.318008-01.bin
89
89
  SHA-1 fae3c788ad9a6cc2dbdfbcf6c0264b2ca921d55e.
90
90
 
91
+ dos2031.rom
92
+ -----------
93
+ The 2031 disk drive's DOS 2.6, 16 KB for $C000-$FFFF: 901484-03
94
+ ($C000-$DFFF, SHA-1 54d608f7f07860f24186749f21c96724dd48bc50)
95
+ followed by 901484-05 ($E000-$FFFF, SHA-1
96
+ ec6b75ecfdd4744e5d57979ef6af990444c11ae1). Drives::Model2031 loads it.
97
+
98
+ Both halves downloaded from
99
+ https://www.zimmers.net/anonftp/pub/cbm/firmware/drives/old/2031/
100
+ and concatenated.
101
+ SHA-1 c53e180a96649ceb3f421739e8dc66faba7cba44.
102
+
103
+ 8050/fdc-901869-01.rom
104
+ ----------------------
105
+ The 6530 of the 8050 and 8250's floppy controller with the DOS 2.7
106
+ mask for MPI mechanisms, 901869-01 (6530-48): the 1 KB ROM the
107
+ controller runs from $FC00-$FFFF. Chips::RRIOT holds it.
108
+ SHA-1 3a9a80f72ce76e5f5c72513f8ef7553212912ae3.
109
+
110
+ 8050/fdc-901885-04.rom
111
+ ----------------------
112
+ The same 6530 with the DOS 2.7 mask for Micropolis mechanisms,
113
+ 901885-04 (6530-47). It differs from 901869-01 in 104 bytes.
114
+ SHA-1 0dc9a3b60f1b866c63eebd882403532fc59fe57f.
115
+
116
+ 8050/dos-2.7.rom
117
+ ----------------
118
+ The 8050 and 8250's DOS 2.7, 16 KB for the interface processor's
119
+ $C000-$FFFF: 901887-01 ($C000-$DFFF, SHA-1
120
+ b10603195f240118fe5fb6c6dfe5c5097463d890) followed by 901888-01
121
+ ($E000-$FFFF, SHA-1 2e6c2d7ca934e5c550ad14bd5e9e7749686b7af4). xcbm2
122
+ and xpet with -drive8type 8050 or 8250 run the same 16 KB.
123
+ Drives::Model8050 loads it.
124
+ SHA-1 d50b093828888146596f17ae0df9ef3dfde71b05.
125
+
126
+ Both downloaded from
127
+ https://www.zimmers.net/anonftp/pub/cbm/firmware/drives/old/8050/
128
+ and named by the 8050's parts list
129
+ (https://www.zimmers.net/anonftp/pub/cbm/schematics/drives/old/8050/parts.txt).
130
+
91
131
  Commodore VIC-20 ROMs
92
132
  =====================
93
133
 
@@ -253,7 +293,9 @@ BASIC 4 for $B000-$DFFF, 901465-23, 901465-20 and 901465-21
253
293
  (basic-4-b000.901465-23.bin, basic-4-c000.901465-20.bin,
254
294
  basic-4-d000.901465-21.bin) concatenated. 901465-23 is the patched
255
295
  $B000 chip that replaced 901465-19. The 8296's 324746-01 holds the same
256
- four chips.
296
+ four chips (8296/kernal-basic-324746-01.bin, SHA-1
297
+ e3e1431969bf317c885e47f3790e0bcbdf61fe77, $C000, $D000, $B000 and
298
+ $F000 in that order), so the 8296 runs this file and kernal4.rom.
257
299
  SHA-1 d70bec479e1e3a0d0908a4897066e9959bbc11c8.
258
300
 
259
301
  pet/kernal4.rom
@@ -316,3 +358,104 @@ pet/editor4-80-b-60hz.rom
316
358
  The 8032's 60 Hz editor, 901474-03 (edit-4-80-b-60Hz.901474-03.bin),
317
359
  for $E000-$E7FF.
318
360
  SHA-1 c605fa343fd77c73cbe1e0e9567e2f014f6e7e30.
361
+
362
+ pet/editor4-80-b-50hz-8296.rom
363
+ ------------------------------
364
+ The 8296's 50 Hz editor, 324243-02B, the EPROM marked "8296 UE8" in
365
+ Andre Fachat's working 8296 (8296/edit-50hz-324243-02b.bin), for
366
+ $E000-$E7FF. The 8296 parts list names it the ASCII board's. It is
367
+ 901474-04 with the CRTC's register tables at $E72A changed to lines of
368
+ 59 cycles and frames of 339 lines (8296/edit-50hz-324243-02b.txt).
369
+ SHA-1 b715db83fd26458dfd254bef5c4aae636753f7f5.
370
+
371
+ pet/characters-din.rom
372
+ ----------------------
373
+ The 8296's 4K character generator for the DIN board, 324242-01
374
+ (8296/characters-324242-01.bin), which --characters din fits. Its
375
+ second half is 901447-10 byte for byte, and its first a DIN set, with
376
+ the German letters and the section sign in place of @ [ \ ] and in
377
+ some of the graphics. The CRTC's MA13, bit 5 of R12, picks the half.
378
+ SHA-1 9616f7f18757cccefb702a945f954b644d5b17d1.
379
+
380
+ Commodore CBM-II ROMs
381
+ =====================
382
+
383
+ Downloaded from
384
+ https://www.zimmers.net/anonftp/pub/cbm/firmware/computers/b/
385
+ for the B series (610, 620, 710 and 720) and the P500 (510). Each BASIC
386
+ is its two 8K chips concatenated, $8000-$9FFF followed by $A000-$BFFF,
387
+ as the PET's are. Nothing maps them yet.
388
+
389
+ cbm2/kernal-04a.rom
390
+ -------------------
391
+ The B series KERNAL, 901244-04a (kernal.901244-04a.bin), for
392
+ $E000-$FFFF in segment 15. The default, the one VICE runs on every B
393
+ model.
394
+ SHA-1 abb26418b9e1614a8f52bdeee0822d4a96071439.
395
+
396
+ cbm2/kernal-03b.rom
397
+ -------------------
398
+ The B series KERNAL of the 1983 release, 901244-03b
399
+ (kernal.901244-03b.bin), for $E000-$FFFF in segment 15. Its entry
400
+ points and page 3 vectors are 901244-04a's.
401
+ SHA-1 a624899c236bc4458570144d25aaf0b3be08b2cd.
402
+
403
+ cbm2/basic128.rom
404
+ -----------------
405
+ BASIC 128 for the 610 and 710, 901243-04a and 901242-04a
406
+ (b128-8000.901243-04a.bin, SHA-1
407
+ 08d333208060ee2ce84d4532028d94f71c016b96, and b128-a000.901242-04a.bin,
408
+ SHA-1 7c6de17d46a3343dc597d9b9519cf63037b31908) concatenated, for
409
+ $8000-$BFFF in segment 15. The default, paired with kernal-04a.rom.
410
+ SHA-1 9409f92e167984096fe4d5913714bff6214c3b2d.
411
+
412
+ cbm2/basic128-02b.rom
413
+ ---------------------
414
+ BASIC 128 of the 1983 release, 901243-02b and 901242-02b
415
+ (b128-8000.901243-02b.bin, SHA-1
416
+ 625f7337ea972a8bce2bdf2daababc0ed0b3b69b, and b128-a000.901242-02b.bin,
417
+ SHA-1 56e8d2f86bf73ba36b3d3cb84dd75806b66c530a) concatenated, for
418
+ $8000-$BFFF in segment 15. Paired with kernal-03b.rom.
419
+ SHA-1 0da8311666521a1d5d7c80561550f9037f652989.
420
+
421
+ cbm2/basic256.rom
422
+ -----------------
423
+ BASIC 256 for the 620 and 720, 901241-03 and 901240-03
424
+ (b256-8000.901241-03.bin, SHA-1
425
+ 2d46be2cd89594b718cdd0a86d51b6f628343f42, and b256-a000.901240-03.bin,
426
+ SHA-1 0d7f77746290afba8d0abeb87c9caab9a3ad89ce) concatenated, for
427
+ $8000-$BFFF in segment 15. Both KERNALs run it.
428
+ SHA-1 53314b4d565cc405a67a0936b935e6e08955580d.
429
+
430
+ cbm2/characters-600.rom
431
+ -----------------------
432
+ The 600's character generator, 901237-01 (characters.901237-01.bin),
433
+ 4K: two sets of 128 glyphs, 16 bytes each, an 8x8 matrix in the first
434
+ eight rows.
435
+ SHA-1 e63bf18da48e5a53c99ef127c1ae721333d1d102.
436
+
437
+ cbm2/characters-700.rom
438
+ -----------------------
439
+ The 700's character generator, 901232-01 (characters.901232-01.bin),
440
+ 4K: two sets of 128 glyphs, 16 bytes each, an 8x16 matrix. zimmers.net
441
+ also has 901232-02, from a 710, which differs in 139 bytes. xcbm2 runs
442
+ -01 on its 710, and a 710's boot screen painted with it matches xcbm2's
443
+ dot for dot.
444
+ SHA-1 e7f3cbc8e282f79a00c3e95d75c8d725ee3c6287.
445
+
446
+ cbm2/p500-kernal.rom
447
+ --------------------
448
+ The P500's KERNAL, 901234-02 (kernal.901234-02.bin), for $E000-$FFFF in
449
+ segment 15. The P500's character generator is the C64's,
450
+ character.rom above.
451
+ SHA-1 097197d4d08e0b82e0466a5f1fbd49a24f3d2523.
452
+
453
+ cbm2/p500-basic.rom
454
+ -------------------
455
+ The P500's BASIC 128, 901236-02 and 901235-02
456
+ (p500-basic-lo.901236-02.bin, SHA-1
457
+ f50240407bade901144f7e9f489fa9c607834eca, and
458
+ p500-basic-hi.901235-02.bin, SHA-1
459
+ 1b9a55f12f8cf025754d8029cc5324b474c35841) concatenated, for
460
+ $8000-$BFFF in segment 15.
461
+ SHA-1 e69531d45f5993f8e53c6bd9ab2a7bc10fe2d02f.
Binary file
Binary file
Binary file
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Badline
4
+ module Snapshot
5
+ # How a CBM-II was built: its model's name, one of CBM2::Model::ALL or
6
+ # CBM2::P500::Model::ALL, its KERNAL, one of the model's KERNALS, its
7
+ # mains, 50 or 60 Hz, and whether the DRAM refresh takes its cycles,
8
+ # the arguments CBM2.new or CBM2::P500.new takes.
9
+ CBM2Setup = Data.define(:model, :kernal, :mains_hz, :refresh)
10
+
11
+ class CBM2Setup
12
+ MODELS = (CBM2::Model::ALL + CBM2::P500::Model::ALL).map(&:name).freeze
13
+
14
+ KERNALS = (CBM2::Model::KERNALS.keys + CBM2::P500::Model::KERNALS.keys).freeze
15
+
16
+ MAINS = [50, 60].freeze
17
+
18
+ # The setup of `machine`.
19
+ def self.of(machine)
20
+ new(model: machine.model.name, kernal: machine.kernal, mains_hz: machine.mains_hz, refresh: machine.refresh?)
21
+ end
22
+
23
+ # The model by name, the KERNAL, the mains and the refresh, in a keyed
24
+ # snapshot module.
25
+ def write_fields(out)
26
+ out.text("model", model).text("kernal", kernal).int("mains_hz", mains_hz).bool("dram_refresh", refresh)
27
+ end
28
+
29
+ def self.read_fields(input)
30
+ model = input.choice("model", MODELS, CBM2::Model::DEFAULT)
31
+ kernal = input.choice("kernal", KERNALS, "04a")
32
+ mains_hz = input.int("mains_hz", 50)
33
+ unless MAINS.include?(mains_hz)
34
+ raise FormatError, "the snapshot is of a CBM-II at #{mains_hz} Hz, which badline doesn't build"
35
+ end
36
+
37
+ new(model:, kernal:, mains_hz:, refresh: input.bool("dram_refresh", true))
38
+ end
39
+
40
+ # A machine built this way, at power-on.
41
+ def build
42
+ return CBM2::P500.new(model:, mains_hz:) if CBM2::P500::Model.include?(model)
43
+
44
+ CBM2.new(model:, kernal:, mains_hz:, refresh:)
45
+ end
46
+
47
+ def to_s
48
+ machine = "#{model} with KERNAL #{kernal} at #{mains_hz} Hz"
49
+ refresh || CBM2::P500::Model.include?(model) ? machine : "#{machine} without the DRAM refresh"
50
+ end
51
+ end
52
+ end
53
+ end
@@ -38,6 +38,14 @@ module Badline
38
38
  PLUS4 = "PLUS4"
39
39
  # xpet names its machine PET, for every model.
40
40
  PET = "PET"
41
+ # xcbm2 names its machine CBM-II, for every B series model.
42
+ CBM2 = "CBM-II"
43
+ # xcbm5x0 names its machine CBM-II-5x0, the P500.
44
+ CBM2_5X0 = "CBM-II-5x0"
45
+ # The file format version each machine's VICE emulator reads, where
46
+ # it isn't FORMAT_MAJOR.0: xpet and xcbm2 refuse any other than 1.0, and
47
+ # xcbm5x0 writes 0.0.
48
+ FORMAT_MAJORS = { PET => 1, CBM2 => 1, CBM2_5X0 => 0 }.freeze
41
49
  GZIP_MAGIC = "\x1f\x8b".b
42
50
 
43
51
  # The VICE version block, when VICE wrote the file: four version
@@ -67,7 +75,7 @@ module Badline
67
75
  def [](name) = @sections.find { |section| section.name == name }
68
76
 
69
77
  def to_s
70
- header = MAGIC + [FORMAT_MAJOR, FORMAT_MINOR].pack("CC") + padded(@machine)
78
+ header = MAGIC + [FORMAT_MAJORS.fetch(@machine, FORMAT_MAJOR), FORMAT_MINOR].pack("CC") + padded(@machine)
71
79
  header += VERSION_MAGIC + @vice_version if @vice_version
72
80
  header + @sections.map { |section| encode(section) }.join
73
81
  end
@@ -7,7 +7,8 @@ module Badline
7
7
  # its default, with keys that differ only in a unit's number, such as
8
8
  # voice1 to voice3, on one row.
9
9
  class Markdown
10
- NAMES = { "c64" => "C64", "vic20" => "VIC-20", "c128" => "C128", "plus4" => "Plus/4", "pet" => "PET" }.freeze
10
+ NAMES = { "c64" => "C64", "vic20" => "VIC-20", "c128" => "C128", "plus4" => "Plus/4", "pet" => "PET",
11
+ "cbm2" => "CBM-II" }.freeze
11
12
  TAG_TYPES = { Keyed::INT => "int", Keyed::BOOL => "bool", Keyed::BYTES => "bytes", Keyed::INTS => "ints",
12
13
  Keyed::TEXT => "text" }.freeze
13
14
 
@@ -31,7 +32,8 @@ module Badline
31
32
  `int & 0x..` are ints cut to the latch's width. A text that lists
32
33
  its values takes one of them. An optional int is absent when the
33
34
  latch holds nothing. A true drive's modules are named from its
34
- device number, `BL-D8` to `BL-D11`, and the SIDs past the first
35
+ device number, `BL-D8` to `BL-D11`, or to `BL-D15` for an 8050 or
36
+ an 8250. The SIDs past the first
35
37
  are `BL-SID2` onwards, in the order they were fitted. Keys with
36
38
  `<N>` stand for each numbered unit. A default of "written only" is
37
39
  a key the load doesn't read, or reads only when the snapshot has