badline 0.16.1 → 0.18.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +213 -0
- data/CLAUDE.md +11 -7
- data/CONTRIBUTING.md +7 -1
- data/README.md +265 -26
- data/doc/media.md +5 -2
- data/doc/pinned-behaviour.md +189 -0
- data/doc/snapshot-format.md +616 -74
- data/doc/snapshots.md +192 -24
- data/exe/badline-ruby +5 -0
- data/lib/badline/audio/terminal.rb +34 -2
- data/lib/badline/c128/keyed_state.rb +2 -0
- data/lib/badline/c128.rb +1 -0
- data/lib/badline/c64/keyed_state.rb +2 -0
- data/lib/badline/c64.rb +1 -0
- data/lib/badline/cbm2/acia.rb +10 -0
- data/lib/badline/cbm2/bus.rb +263 -0
- data/lib/badline/cbm2/cpu.rb +58 -0
- data/lib/badline/cbm2/crtc_video.rb +133 -0
- data/lib/badline/cbm2/ieee_drive.rb +18 -0
- data/lib/badline/cbm2/ieee_layout.rb +69 -0
- data/lib/badline/cbm2/ieee_ports.rb +104 -0
- data/lib/badline/cbm2/ieee_traps.rb +81 -0
- data/lib/badline/cbm2/keyboard_ports.rb +60 -0
- data/lib/badline/cbm2/keyed_modules.rb +67 -0
- data/lib/badline/cbm2/keyed_state.rb +95 -0
- data/lib/badline/cbm2/model.rb +44 -0
- data/lib/badline/cbm2/p500/control_ports.rb +80 -0
- data/lib/badline/cbm2/p500/ieee_layout.rb +41 -0
- data/lib/badline/cbm2/p500/keyed_state.rb +85 -0
- data/lib/badline/cbm2/p500/model.rb +39 -0
- data/lib/badline/cbm2/p500/pages.rb +57 -0
- data/lib/badline/cbm2/p500.rb +264 -0
- data/lib/badline/cbm2/sid_page.rb +19 -0
- data/lib/badline/cbm2.rb +270 -0
- data/lib/badline/{plus4 → chips}/acia/frames.rb +1 -1
- data/lib/badline/chips/acia/keyed_state.rb +47 -0
- data/lib/badline/chips/acia.rb +307 -0
- data/lib/badline/chips/cia/timer.rb +2 -2
- data/lib/badline/chips/cpu/instruction_set.rb +1 -1
- data/lib/badline/chips/crtc.rb +3 -2
- data/lib/badline/chips/m6809/arithmetic.rb +140 -0
- data/lib/badline/chips/m6809/bus_steps.rb +223 -0
- data/lib/badline/chips/m6809/core.rb +149 -0
- data/lib/badline/chips/m6809/indexed.rb +82 -0
- data/lib/badline/chips/m6809/interrupts.rb +159 -0
- data/lib/badline/chips/m6809/keyed_state.rb +147 -0
- data/lib/badline/chips/m6809/opcodes.rb +159 -0
- data/lib/badline/chips/m6809/operations.rb +258 -0
- data/lib/badline/chips/m6809/plans.rb +143 -0
- data/lib/badline/chips/m6809/registers.rb +82 -0
- data/lib/badline/chips/m6809/stack.rb +140 -0
- data/lib/badline/chips/m6809.rb +13 -0
- data/lib/badline/chips/riot/fast_forward.rb +72 -0
- data/lib/badline/chips/riot/keyed_parts.rb +69 -0
- data/lib/badline/chips/riot/timer.rb +91 -0
- data/lib/badline/chips/riot.rb +162 -0
- data/lib/badline/chips/rriot/keyed_state.rb +30 -0
- data/lib/badline/chips/rriot.rb +134 -0
- data/lib/badline/chips/sid/filter.rb +4 -4
- data/lib/badline/chips/sid/waveform.rb +6 -6
- data/lib/badline/chips/tpi/keyed_state.rb +38 -0
- data/lib/badline/chips/tpi.rb +233 -0
- data/lib/badline/chips/vic/bank.rb +60 -5
- data/lib/badline/chips/vic/sprite.rb +4 -3
- data/lib/badline/chips/vic_i/keyed_parts.rb +7 -2
- data/lib/badline/chips/vic_i.rb +84 -21
- data/lib/badline/data_path.rb +3 -3
- data/lib/badline/drives/datasette/keyed_state.rb +9 -1
- data/lib/badline/drives/datasette.rb +27 -3
- data/lib/badline/drives/ieee_models.rb +54 -0
- data/lib/badline/drives/model1001.rb +37 -0
- data/lib/badline/drives/model2031.rb +6 -0
- data/lib/badline/drives/model4040/disk.rb +62 -0
- data/lib/badline/drives/model4040/ip_bus.rb +46 -0
- data/lib/badline/drives/model4040/keyed_state.rb +57 -0
- data/lib/badline/drives/model4040/mechanism.rb +192 -0
- data/lib/badline/drives/model4040/parts.rb +20 -0
- data/lib/badline/drives/model4040.rb +179 -0
- data/lib/badline/drives/model8050/board.rb +77 -0
- data/lib/badline/drives/model8050/disk.rb +163 -0
- data/lib/badline/drives/model8050/dos_board.rb +91 -0
- data/lib/badline/drives/model8050/fdc_bus.rb +102 -0
- data/lib/badline/drives/model8050/idle.rb +181 -0
- data/lib/badline/drives/model8050/ieee_port.rb +147 -0
- data/lib/badline/drives/model8050/ip_bus.rb +93 -0
- data/lib/badline/drives/model8050/keyed_state.rb +163 -0
- data/lib/badline/drives/model8050/mechanism.rb +230 -0
- data/lib/badline/drives/model8050/parts.rb +37 -0
- data/lib/badline/drives/model8050.rb +131 -0
- data/lib/badline/drives/model9060/idle.rb +149 -0
- data/lib/badline/drives/model9060/keyed_state.rb +123 -0
- data/lib/badline/drives/model9060/parts.rb +98 -0
- data/lib/badline/drives/model9060/sasi_bus.rb +88 -0
- data/lib/badline/drives/model9060/sasi_commands.rb +168 -0
- data/lib/badline/drives/model9060/sasi_target.rb +161 -0
- data/lib/badline/drives/model9060.rb +195 -0
- data/lib/badline/frontend/app.rb +18 -3
- data/lib/badline/frontend/boot.rb +4 -3
- data/lib/badline/frontend/controls.rb +107 -15
- data/lib/badline/frontend/gamepads.rb +3 -3
- data/lib/badline/frontend/keys.rb +97 -2
- data/lib/badline/frontend/kim1_panel.rb +208 -0
- data/lib/badline/frontend/media_slots.rb +8 -1
- data/lib/badline/frontend/menu/drive_types.rb +56 -0
- data/lib/badline/frontend/menu/menu_dialogs.rb +61 -14
- data/lib/badline/frontend/menu/menu_media.rb +47 -14
- data/lib/badline/frontend/menu/menu_pages.rb +113 -4
- data/lib/badline/frontend/menu/menu_ports.rb +77 -4
- data/lib/badline/frontend/menu/pause_menu.rb +6 -2
- data/lib/badline/frontend/pet_keyboard.rb +45 -7
- data/lib/badline/frontend/screen.rb +1 -1
- data/lib/badline/frontend/screens.rb +40 -2
- data/lib/badline/frontend/teletype_pane.rb +152 -0
- data/lib/badline/frontend/timeline.rb +49 -11
- data/lib/badline/frontend.rb +3 -0
- data/lib/badline/kernal_trap/dos/disk_commands.rb +80 -0
- data/lib/badline/kernal_trap/dos/status.rb +3 -0
- data/lib/badline/kernal_trap/dos.rb +18 -5
- data/lib/badline/kernal_trap/ieee.rb +4 -2
- data/lib/badline/kernal_trap/ieee_layout.rb +95 -43
- data/lib/badline/kim1/bus.rb +117 -0
- data/lib/badline/kim1/cpu.rb +25 -0
- data/lib/badline/kim1/host_terminal.rb +74 -0
- data/lib/badline/kim1/key_entry.rb +74 -0
- data/lib/badline/kim1/keyed_modules.rb +53 -0
- data/lib/badline/kim1/keyed_state.rb +133 -0
- data/lib/badline/kim1/panel.rb +176 -0
- data/lib/badline/kim1/rriots.rb +28 -0
- data/lib/badline/kim1/sound.rb +29 -0
- data/lib/badline/kim1/tape.rb +116 -0
- data/lib/badline/kim1/teletype.rb +193 -0
- data/lib/badline/kim1.rb +190 -0
- data/lib/badline/machine/ieee_drives.rb +171 -0
- data/lib/badline/machine/keyboard_buffer.rb +20 -3
- data/lib/badline/machine/line_sound.rb +122 -0
- data/lib/badline/machine/settling.rb +4 -0
- data/lib/badline/machine.rb +62 -14
- data/lib/badline/media/cbm2_media.rb +29 -0
- data/lib/badline/media/extensions.rb +8 -4
- data/lib/badline/media/kim1_media.rb +150 -0
- data/lib/badline/media/pet_media.rb +3 -1
- data/lib/badline/media/program.rb +6 -3
- data/lib/badline/media/true_drive.rb +51 -25
- data/lib/badline/media.rb +23 -8
- data/lib/badline/options/family.rb +108 -6
- data/lib/badline/options/help.rb +58 -12
- data/lib/badline/options/table.rb +60 -14
- data/lib/badline/options/validation.rb +71 -11
- data/lib/badline/options.rb +46 -13
- data/lib/badline/pet/bus.rb +16 -2
- data/lib/badline/pet/cassettes.rb +22 -1
- data/lib/badline/pet/ieee_drive.rb +5 -64
- data/lib/badline/pet/ieee_ports.rb +7 -0
- data/lib/badline/pet/keyboard_ports.rb +9 -2
- data/lib/badline/pet/keyed_state.rb +4 -0
- data/lib/badline/pet/model.rb +11 -2
- data/lib/badline/pet/rom_sets.rb +1 -0
- data/lib/badline/pet/sound.rb +5 -105
- data/lib/badline/pet/superpet/acia.rb +12 -0
- data/lib/badline/pet/superpet/board.rb +221 -0
- data/lib/badline/pet/superpet/dongle.rb +81 -0
- data/lib/badline/pet/superpet/keyed_modules.rb +63 -0
- data/lib/badline/pet/superpet/keyed_parts.rb +76 -0
- data/lib/badline/pet/superpet/m6809.rb +32 -0
- data/lib/badline/pet/superpet/waterloo_traps.rb +199 -0
- data/lib/badline/pet/superpet.rb +216 -0
- data/lib/badline/pet.rb +33 -6
- data/lib/badline/plus4/acia.rb +4 -298
- data/lib/badline/plus4/keyed_parts.rb +0 -44
- data/lib/badline/plus4/keyed_state.rb +2 -0
- data/lib/badline/plus4.rb +2 -0
- data/lib/badline/roms/1001/fdc-251257-02a.rom +0 -0
- data/lib/badline/roms/4040/dos-1.2.rom +0 -0
- data/lib/badline/roms/4040/dos-2.1-rev.rom +0 -0
- data/lib/badline/roms/4040/dos-2.1.rom +0 -0
- data/lib/badline/roms/4040/fdc-901466-02.rom +0 -0
- data/lib/badline/roms/4040/fdc-901466-04.rom +0 -0
- data/lib/badline/roms/8050/dos-2.7.rom +0 -0
- data/lib/badline/roms/8050/fdc-901869-01.rom +0 -0
- data/lib/badline/roms/8050/fdc-901885-04.rom +0 -0
- data/lib/badline/roms/9060/dos-3.0.rom +0 -0
- data/lib/badline/roms/9060/sasi-300515-revb.rom +0 -0
- data/lib/badline/roms/README +277 -0
- data/lib/badline/roms/cbm2/basic128-02b.rom +0 -0
- data/lib/badline/roms/cbm2/basic128.rom +0 -0
- data/lib/badline/roms/cbm2/basic256.rom +0 -0
- data/lib/badline/roms/cbm2/characters-600.rom +0 -0
- data/lib/badline/roms/cbm2/characters-700.rom +0 -0
- data/lib/badline/roms/cbm2/kernal-03b.rom +0 -0
- data/lib/badline/roms/cbm2/kernal-04a.rom +0 -0
- data/lib/badline/roms/cbm2/p500-basic.rom +0 -0
- data/lib/badline/roms/cbm2/p500-kernal.rom +0 -0
- data/lib/badline/roms/kim1/6530-002.rom +0 -0
- data/lib/badline/roms/kim1/6530-003.rom +0 -0
- data/lib/badline/roms/pet/characters-superpet.rom +0 -0
- data/lib/badline/roms/pet/superpet-a000.rom +0 -0
- data/lib/badline/roms/pet/superpet-c000.rom +0 -0
- data/lib/badline/roms/pet/superpet-e000-50hz.rom +0 -0
- data/lib/badline/roms/pet/superpet-e000.rom +0 -0
- data/lib/badline/snapshot/cbm2_setup.rb +53 -0
- data/lib/badline/snapshot/container.rb +9 -2
- data/lib/badline/snapshot/field_doc/markdown.rb +4 -2
- data/lib/badline/snapshot/field_doc.rb +59 -3
- data/lib/badline/snapshot/image.rb +65 -9
- data/lib/badline/snapshot/kim1_setup.rb +28 -0
- data/lib/badline/snapshot/pet_setup.rb +27 -11
- data/lib/badline/snapshot/storage_setup.rb +4 -1
- data/lib/badline/snapshot/vic20_setup.rb +11 -7
- data/lib/badline/snapshot/vice/cbm2.rb +93 -0
- data/lib/badline/snapshot/vice/cbm2_acia.rb +75 -0
- data/lib/badline/snapshot/vice/cbm2_crtc.rb +127 -0
- data/lib/badline/snapshot/vice/cbm2_mains.rb +49 -0
- data/lib/badline/snapshot/vice/cbm2_mem.rb +75 -0
- data/lib/badline/snapshot/vice/cbm2_restore.rb +204 -0
- data/lib/badline/snapshot/vice/cbm2_tpi.rb +58 -0
- data/lib/badline/snapshot/vice/cias.rb +13 -9
- data/lib/badline/snapshot/vice/p500.rb +96 -0
- data/lib/badline/snapshot/vice/p500_restore.rb +130 -0
- data/lib/badline/snapshot/vice/p500_vicii.rb +166 -0
- data/lib/badline/snapshot/vice/pet.rb +20 -10
- data/lib/badline/snapshot/vice/pet_cpu.rb +42 -5
- data/lib/badline/snapshot/vice/pet_crtc.rb +25 -17
- data/lib/badline/snapshot/vice/pet_drive.rb +180 -0
- data/lib/badline/snapshot/vice/pet_drive8050.rb +336 -0
- data/lib/badline/snapshot/vice/pet_mem.rb +49 -5
- data/lib/badline/snapshot/vice/pet_restore.rb +100 -7
- data/lib/badline/snapshot/vice/pet_via.rb +6 -5
- data/lib/badline/snapshot/vice/sid_registers.rb +2 -1
- data/lib/badline/snapshot/vice/vicii_import.rb +10 -6
- data/lib/badline/snapshot/vice.rb +3 -0
- data/lib/badline/snapshot.rb +15 -3
- data/lib/badline/status.rb +30 -30
- data/lib/badline/storage/crt_file.rb +7 -1
- data/lib/badline/storage/d64_image.rb +7 -0
- data/lib/badline/storage/d67_image.rb +55 -0
- data/lib/badline/storage/d80_image.rb +17 -1
- data/lib/badline/storage/d81_image.rb +14 -0
- data/lib/badline/storage/d90_image.rb +180 -0
- data/lib/badline/storage/disk_image/bam.rb +18 -3
- data/lib/badline/storage/disk_image/formatting.rb +69 -0
- data/lib/badline/storage/disk_image/writing.rb +37 -2
- data/lib/badline/storage/disk_image.rb +2 -0
- data/lib/badline/storage/kim_tape.rb +254 -0
- data/lib/badline/storage/papertape.rb +90 -0
- data/lib/badline/storage.rb +5 -0
- data/lib/badline/support/cbm2_checkpoint.rb +48 -0
- data/lib/badline/support/kim1_checkpoint.rb +41 -0
- data/lib/badline/support/p500_checkpoint.rb +35 -0
- data/lib/badline/support/superpet_checkpoint.rb +35 -0
- data/lib/badline/version.rb +1 -1
- data/lib/badline/vic20/keyed_modules.rb +6 -3
- data/lib/badline/vic20/keyed_state.rb +6 -4
- data/lib/badline/vic20.rb +26 -12
- data/lib/badline.rb +2 -0
- metadata +148 -2
data/doc/snapshots.md
CHANGED
|
@@ -17,7 +17,7 @@ autosave that fails warns once and stops autosaving.
|
|
|
17
17
|
|
|
18
18
|
The pause menu's Snapshots page quicksaves, saves under a name in the
|
|
19
19
|
`saves` folder and loads a named save. The name starts as the game's,
|
|
20
|
-
from its cartridge, disk or tape, or BASIC, with the next free number,
|
|
20
|
+
from its cartridge, disk or tape, or BASIC, or KIM-1 on a KIM-1, with the next free number,
|
|
21
21
|
and saving over a name already taken asks first. Below those, the
|
|
22
22
|
newest quicksaves and autosaves, with the time each was saved, load
|
|
23
23
|
with a press.
|
|
@@ -149,9 +149,14 @@ port lines the 8296's RAM follows, both PIAs, the VIA, the CPU, the
|
|
|
149
149
|
CRTC on the boards that have one, the picture with where the video is
|
|
150
150
|
in its frame, the tapes in both datasettes with their places on them,
|
|
151
151
|
and the disk or directory device 8 serves through the IEEE-488 traps.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
152
|
+
A SuperPET's also holds its board's latches and 64K of bank RAM, the
|
|
153
|
+
6702, the ACIA, the 6809 and the traps on the Waterloo ROM's IEEE-488
|
|
154
|
+
routines, in 6502 mode and in 6809 mode alike, and saves once the CPU
|
|
155
|
+
that has the bus is between instructions. It restores into a machine of
|
|
156
|
+
the same model with the same RAM, the same editor frame rate, the same
|
|
157
|
+
ROMs, which come with the model, an 8296's same jumpers and a SuperPET's
|
|
158
|
+
CPU and RAM switches at the same positions. Its file names its machine
|
|
159
|
+
`PET`, as xpet's do,
|
|
155
160
|
and holds only badline's modules, so xpet doesn't open it unless it is
|
|
156
161
|
saved with `--vice` (see [xpet](#xpet)).
|
|
157
162
|
|
|
@@ -160,40 +165,203 @@ saved with `--vice` (see [xpet](#xpet)).
|
|
|
160
165
|
A PET snapshot saved with `--vice`, or `computer.export_snapshot(path)`,
|
|
161
166
|
also holds xpet's modules for the CPU, the RAM with the screen RAM, or
|
|
162
167
|
an 8296's 32K from `$8000`, an 8096's or 8296's board and its control
|
|
163
|
-
register,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
+
register, a SuperPET's board, its bank and its `$EFFE` bit, the CRTC
|
|
169
|
+
with the character set VIA CA2 picks, both PIAs and the VIA, a
|
|
170
|
+
SuperPET's 6809 and ACIA, a true 2031's CPU, RAM, VIAs and head, or the
|
|
171
|
+
interface processor of a true 8050, 8250, SFD-1001, 4040, 3040, 2040,
|
|
172
|
+
D9060 or D9090, with its RAM and 6532s and the heads' tracks, and the
|
|
173
|
+
ones xpet 3.10 needs to open
|
|
174
|
+
the file, with nothing open on the file system drive and nothing on the
|
|
175
|
+
user port. The CRTC module carries the discrete boards' video too, in
|
|
176
|
+
xpet's terms. The file says it is in VICE's snapshot format 1.0, the
|
|
177
|
+
only one xpet reads.
|
|
168
178
|
|
|
169
179
|
xpet 3.10 opens those snapshots as long as its model and editor match:
|
|
170
|
-
`-model 2001`, `3032`, `3032B`, `4032`, `8032`, `8096
|
|
171
|
-
for a badline editor other than xpet's own, `-editor`
|
|
172
|
-
ROM. xpet
|
|
180
|
+
`-model 2001`, `3032`, `3032B`, `4032`, `8032`, `8096`, `8296` or
|
|
181
|
+
`SuperPET`, and for a badline editor other than xpet's own, `-editor`
|
|
182
|
+
naming badline's ROM. xpet runs a SuperPET's 6809 when the snapshot
|
|
183
|
+
says it has the bus, whatever its own CPU switch, and has no system
|
|
184
|
+
latch, write protect or 6702 to take from it. xpet's 8296 runs the 8032's editor, 901474-04 dated 0283, so an
|
|
173
185
|
8296 saved for it has to run that editor (`--editor 4-80-b-50hz-0283`),
|
|
174
186
|
and xpet takes the 8296's jumpers from its own settings. It keeps its
|
|
175
|
-
own
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
187
|
+
own datasettes and leaves out badline's tapes and disks. A true drive
|
|
188
|
+
needs `-drive8type 2031`, `8050`, `8250`, `1001`, `4040`, `3040`,
|
|
189
|
+
`2040`, or `9000` for either hard disk, with `-drive8truedrive` and the
|
|
190
|
+
disk attached as `-8`. Its snapshot is settled with the 2031's CPU
|
|
191
|
+
between instructions too, and one saved while the 2031 talks on the bus
|
|
192
|
+
can stall there in xpet, as xpet's own snapshots saved while it searches
|
|
193
|
+
for a file do. xpet runs an 8050's floppy controller, and a hard disk's
|
|
194
|
+
SASI host, at a high level, so a snapshot for it is settled until
|
|
195
|
+
badline's controller, or host, sits in its idle loop with both
|
|
196
|
+
processors between instructions, and xpet's controller
|
|
197
|
+
starts from idle there, taking up any job the interface processor has
|
|
198
|
+
left it. A unit that doesn't reach its idle loop within about 262,000
|
|
199
|
+
cycles, such as one still starting up, is left out of xpet's modules,
|
|
200
|
+
and badline's own modules keep it. Its CRTC loses a few lines on
|
|
201
|
+
opening any snapshot, its own too, so a program it runs on from one
|
|
202
|
+
finds the vertical sync a few hundred cycles later than one it ran
|
|
203
|
+
without stopping.
|
|
179
204
|
|
|
180
205
|
Snapshots xpet saves open in badline through the same modules: the CPU
|
|
181
206
|
at its instruction boundary, the RAM, the screen RAM, an 8096's or
|
|
182
207
|
8296's board, the CRTC's registers and beam, both PIAs' registers and
|
|
183
|
-
flags,
|
|
208
|
+
flags, the VIA's registers, timers and shift register, a true 2031's
|
|
209
|
+
CPU, RAM, VIAs and head, which go on the bus with the disk badline's
|
|
210
|
+
2031 had in it, and the interface processor of a true 8050, 8250,
|
|
211
|
+
SFD-1001, 4040, 3040, 2040, D9060 or D9090, its RAM and both 6532s,
|
|
212
|
+
which go on the bus with the disks badline's unit of the same model had
|
|
213
|
+
in it. xpet's type 9000 stands for both hard disks, and the hard disk
|
|
214
|
+
badline's had in it, of either, makes it a D9090 for an image of six
|
|
215
|
+
heads and otherwise a D9060. Its floppy controller comes back as a unit
|
|
216
|
+
switched on has it, in its idle loop with the heads on track 1: its next
|
|
217
|
+
job steps them out to the track, and a job xpet's controller had under
|
|
218
|
+
way starts again from there. A hard disk's SASI host comes back in its
|
|
219
|
+
job loop the same way. A program
|
|
184
220
|
badline runs on from xpet's snapshot finds the vertical sync on the
|
|
185
221
|
cycle xpet does, so the two run on alike, cycle for cycle. The picture
|
|
186
222
|
starts again with the next frame. xpet doesn't save its ROMs, which
|
|
187
223
|
keyboard it has or an 8296's jumpers, so the board, the RAM and the
|
|
188
224
|
CRTC's frame build the machine: a 2001, a 3032 for any other discrete
|
|
189
225
|
board, a 4032, an 8032, an 8096 or an 8296 with none of its jumpers
|
|
190
|
-
fitted, at 50 or 60 Hz, and an 8032, 8096 or 8296 whose
|
|
191
|
-
64 cycles long runs xpet's own 50 Hz editor, 901474-04
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
226
|
+
fitted, or a SuperPET, at 50 or 60 Hz, and an 8032, 8096 or 8296 whose
|
|
227
|
+
CRTC lines are 64 cycles long runs xpet's own 50 Hz editor, 901474-04
|
|
228
|
+
dated 0283. A SuperPET comes with its bank RAM, its bank, its `$EFFE`
|
|
229
|
+
bit and its ACIA, its CPU switch at the CPU that had the bus, and while
|
|
230
|
+
that is the 6809, the 6809's registers. Its RAM switch is at R/W, the
|
|
231
|
+
only position xpet has, its system latch is clear and its 6702 is as the
|
|
232
|
+
RES line leaves it, since xpet saves none of them, and in 6809 mode its
|
|
233
|
+
frame rate is the one the Waterloo ROM's CRTC table sets. It reports the modules it leaves out, such
|
|
234
|
+
as the drives past device 8, the datasettes and the keyboard, and
|
|
235
|
+
carries on without them, and a snapshot without a true drive takes
|
|
236
|
+
badline's off the bus and says so.
|
|
237
|
+
Restored into a running PET, an xpet snapshot fails for a PET built
|
|
238
|
+
another way, such as a 3032B, and otherwise switches the machine off
|
|
239
|
+
and on, keeping its tapes and the disk device 8 serves.
|
|
240
|
+
|
|
241
|
+
## The CBM-II
|
|
242
|
+
|
|
243
|
+
The B series, the 610, 620, 710 and 720, saves and restores the same
|
|
244
|
+
way. A snapshot of one holds segment 15's RAM, the screen RAM, the RAM
|
|
245
|
+
board's segments, both segment registers, a cartridge's ROMs, the CPU,
|
|
246
|
+
the CRTC with the picture, the SID, the CIA, the ACIA, both TPIs with
|
|
247
|
+
their priority stacks, the mains' place in its period, and the disk or
|
|
248
|
+
directory device 8 serves through the IEEE-488 traps. It restores into
|
|
249
|
+
a machine of the same model with the same KERNAL and mains. Its file
|
|
250
|
+
names its machine `CBM-II`, as xcbm2's do, and holds only badline's
|
|
251
|
+
modules, so xcbm2 doesn't open it unless it is saved with `--vice` (see
|
|
252
|
+
[xcbm2](#xcbm2)).
|
|
253
|
+
|
|
254
|
+
### xcbm2
|
|
255
|
+
|
|
256
|
+
A CBM-II snapshot saved with `--vice`, or `computer.export_snapshot(path)`, also holds
|
|
257
|
+
xcbm2's modules for the CPU, the RAM with both segment registers, the
|
|
258
|
+
CRTC, the CIA, both TPIs, the ACIA and the SID, a true 2031, 8050 or
|
|
259
|
+
8250 as xpet's are written (see [xpet](#xpet)), or with no true drive,
|
|
260
|
+
none on any device, and the ones xcbm2 3.10 needs to open the file, with
|
|
261
|
+
no cartridge, nothing open on the file system drive and nothing on the
|
|
262
|
+
user port. The file says it is in
|
|
263
|
+
VICE's snapshot format 1.0, the only one xcbm2 reads.
|
|
264
|
+
|
|
265
|
+
xcbm2 3.10 opens those snapshots as long as its model matches: `-model
|
|
266
|
+
610`, `620`, `710` or `720`. It takes a 600's 60 Hz from the snapshot
|
|
267
|
+
and leaves out badline's cartridge and disks. A true drive needs
|
|
268
|
+
`-drive8type 2031`, `8050` or `8250` with `-drive8truedrive` and the
|
|
269
|
+
disk attached as `-8`, and with no true drive in the snapshot xcbm2
|
|
270
|
+
takes its own off the bus. It
|
|
271
|
+
runs on from badline's snapshot just as it runs on from one it saved
|
|
272
|
+
itself, cycle for cycle. Opening any snapshot, its own too, costs it a
|
|
273
|
+
couple of hundred cycles of its CRTC, so the mains ticks that much later
|
|
274
|
+
than in a run that didn't stop.
|
|
275
|
+
|
|
276
|
+
xcbm2 saves no mains. It ticks the mains once a frame of its CRTC, as
|
|
277
|
+
vertical sync ends, whatever its mains is set to, so its ticks come a
|
|
278
|
+
frame apart: 40,064 cycles on a 600 at 50 Hz, where badline's come
|
|
279
|
+
40,000 apart, and its 700 has no 60 Hz. A snapshot saved for xcbm2 ticks
|
|
280
|
+
where xcbm2's CRTC says, not where badline's mains had it. Neither
|
|
281
|
+
does xcbm2 save a TPI's priority stack, so the interrupts in service are
|
|
282
|
+
lost both ways. Its cursor blinks 32 fields on and 32 off, where the
|
|
283
|
+
6845 blinks 16 and 16, so it comes back showing or hidden as it was,
|
|
284
|
+
with its place in the blink scaled.
|
|
285
|
+
|
|
286
|
+
Snapshots xcbm2 saves open in badline through the same modules: the CPU
|
|
287
|
+
at its instruction boundary, the RAM and both segment registers, the
|
|
288
|
+
CRTC's registers and beam, the CIA's registers, timers and clock, both
|
|
289
|
+
TPIs' registers, latches, mask, AIR, CA and CB, the ACIA's registers and
|
|
290
|
+
the byte it waits to send, and the SID's registers and reSID voice
|
|
291
|
+
state. The mains' next falling edge comes where xcbm2 would tick it, and
|
|
292
|
+
the ones after at badline's 50 or 60 Hz, so the two part from the
|
|
293
|
+
second tick on. xcbm2 has no DRAM refresh, so a program badline runs
|
|
294
|
+
on from xcbm2's snapshot runs about 5% slower than in xcbm2, as the
|
|
295
|
+
refresh takes a cycle from the CPU about every 21. On a machine built
|
|
296
|
+
with `refresh: false` it reads the mains, the CIA and the rest as xcbm2
|
|
297
|
+
does until that second tick, cycle for cycle. The picture starts again with the next frame. xcbm2 doesn't
|
|
298
|
+
save its ROMs, so the RAM board and the model line build the machine:
|
|
299
|
+
a 610, 620, 710 or 720 with xcbm2's KERNAL, 901244-04a, at 60 Hz for a
|
|
300
|
+
600 whose model line says so and at 50 Hz otherwise. A board of 512K or
|
|
301
|
+
more, or RAM mapped into segment 15, fails. A true 2031, 8050 or 8250
|
|
302
|
+
goes on the bus as xpet's does, with the disks badline's drive of that
|
|
303
|
+
model had, and xcbm2 runs a true 2031 on device 8 unless told otherwise,
|
|
304
|
+
so its snapshots mostly put one there. One saved part way into a `LOAD`
|
|
305
|
+
from xcbm2's true drive goes on with it in badline. A snapshot without
|
|
306
|
+
a true drive takes badline's off the bus and says so. It reports the
|
|
307
|
+
modules it leaves out, such as the datasette and the keyboard, and
|
|
308
|
+
carries on without them. Restored into a running CBM-II, an xcbm2
|
|
309
|
+
snapshot fails for a CBM-II built another way, and otherwise switches
|
|
310
|
+
the machine off and on, keeping the disk device 8 serves through the
|
|
311
|
+
traps.
|
|
312
|
+
|
|
313
|
+
### xcbm5x0
|
|
314
|
+
|
|
315
|
+
The P500, the 510 on PAL and NTSC, saves and restores as the B series
|
|
316
|
+
does, with the VIC-II and its colour RAM in place of the CRTC. Its file
|
|
317
|
+
names its machine `CBM-II-5x0`, as xcbm5x0's do. Saved with `--vice`,
|
|
318
|
+
or `computer.export_snapshot(path)`, it also holds xcbm5x0's modules
|
|
319
|
+
for the CPU, the RAM with the video matrix, the colour RAM and both
|
|
320
|
+
segment registers, the CIA, both TPIs, the ACIA, the SID, a true drive
|
|
321
|
+
or none as for the B series, the VIC-II and the mains, and the ones
|
|
322
|
+
xcbm5x0 3.10 needs to open the file, with
|
|
323
|
+
no cartridge, nothing open on the file system drive and the joysticks
|
|
324
|
+
released. The file says it is in VICE's snapshot format 0.0, as
|
|
325
|
+
xcbm5x0 writes it.
|
|
326
|
+
|
|
327
|
+
xcbm5x0 3.10 opens those snapshots with `-model 510`, and `-ntsc` for
|
|
328
|
+
an NTSC 510, takes the true drive as xcbm2 does and leaves out badline's
|
|
329
|
+
cartridge and disks. It runs on from badline's snapshot as it runs on from its own,
|
|
330
|
+
cycle for cycle. xcbm5x0 runs VICE's line-based VIC-II, not x64sc's, and
|
|
331
|
+
its module is laid out otherwise: it carries the registers, colour RAM,
|
|
332
|
+
the beam, VC, VCBASE, whether the sequencer is idle, the buffers and
|
|
333
|
+
the sprites' DMA, and badline writes the rest as xcbm5x0 leaves it.
|
|
334
|
+
xcbm5x0 saves the cycles to the mains' next tick, which badline reads
|
|
335
|
+
and writes. It ticks the mains every 19,656 cycles, a PAL frame, on
|
|
336
|
+
NTSC too, about 52 Hz there, where badline's NTSC 510 runs at 60 Hz, so
|
|
337
|
+
a tick more than a 60 Hz period away comes back sooner.
|
|
338
|
+
|
|
339
|
+
Snapshots xcbm5x0 saves open in badline through the same modules, as
|
|
340
|
+
xcbm2's do, with the VIC-II's registers, beam, counters and colour RAM,
|
|
341
|
+
and the mains' next tick on xcbm5x0's cycle. The row counter follows
|
|
342
|
+
from the line, and the sprites' counters, the borders' flip-flops and
|
|
343
|
+
the pixel pipeline start afresh. xcbm5x0's VIC isn't cycle exact as
|
|
344
|
+
x64sc's is, so a program badline runs on from its snapshot reads the
|
|
345
|
+
raster a cycle off now and then, and its cycles drift from xcbm5x0's by
|
|
346
|
+
a few over a second. The picture starts again with the next frame. The
|
|
347
|
+
RAM's size and the VIC's picture build the machine: a 510, on NTSC for
|
|
348
|
+
NTSC's picture. More RAM fails. A true drive goes on the bus as from
|
|
349
|
+
xcbm2's snapshots. Restored into a running P500, an
|
|
350
|
+
xcbm5x0 snapshot fails for a P500 built another way, and otherwise
|
|
351
|
+
switches the machine off and on, keeping the disk device 8 serves.
|
|
352
|
+
|
|
353
|
+
## The KIM-1
|
|
354
|
+
|
|
355
|
+
A KIM-1 saves and restores as the others do. A snapshot of one holds
|
|
356
|
+
its RAM, the expansion's too, the CPU, both 6530s with their 64 bytes,
|
|
357
|
+
ports and timers, the timer's interrupt flag among them, the panel with
|
|
358
|
+
the TTY/KB jumper, the key held down and how long each LED segment has
|
|
359
|
+
been lit, the teletype with the character on its way in or out, what
|
|
360
|
+
it has queued and all it has printed, the SST switch, U3's wiring to
|
|
361
|
+
IRQ and the speaker, and the keys `type_keys` has still to press. It
|
|
362
|
+
restores into a KIM-1 with the same RAM. Its file names its machine
|
|
363
|
+
`KIM1`, since VICE has no KIM-1, so no VICE emulator opens it, and
|
|
364
|
+
`--vice` fails for it.
|
|
197
365
|
|
|
198
366
|
## VICE
|
|
199
367
|
|
data/exe/badline-ruby
CHANGED
|
@@ -34,6 +34,11 @@ def load_sdl
|
|
|
34
34
|
require "badline/frontend"
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
if options.kim1_terminal?
|
|
38
|
+
require "badline/audio/console"
|
|
39
|
+
exit Badline::KIM1::HostTerminal.start(options, Badline::Audio::Console.new(input: $stdin, output: $stdout))
|
|
40
|
+
end
|
|
41
|
+
|
|
37
42
|
if options.headless?
|
|
38
43
|
require "badline/audio/console"
|
|
39
44
|
console = if options.player_window?
|
|
@@ -4,8 +4,9 @@ module Badline
|
|
|
4
4
|
module Audio
|
|
5
5
|
# The terminal face of `--headless`: the tune's header, a status line
|
|
6
6
|
# redrawn in place, and single keypresses read without waiting for
|
|
7
|
-
# Return
|
|
8
|
-
#
|
|
7
|
+
# Return, or for the KIM-1, the text typed and printed (#typing).
|
|
8
|
+
# Ctrl-C still interrupts. A subclass puts the terminal in raw mode
|
|
9
|
+
# with #raw! and #restore and waits for keys with #readable?:
|
|
9
10
|
# Console with io/console for badline-ruby, and Native::Console with
|
|
10
11
|
# stty and poll(2) for the native badline.
|
|
11
12
|
class Terminal
|
|
@@ -50,6 +51,37 @@ module Badline
|
|
|
50
51
|
end
|
|
51
52
|
end
|
|
52
53
|
|
|
54
|
+
# Raw input for the length of the block, the cursor showing, for a
|
|
55
|
+
# session that types and prints text, as the KIM-1's teletype does.
|
|
56
|
+
def typing
|
|
57
|
+
mode = raw! if @input.tty?
|
|
58
|
+
yield
|
|
59
|
+
ensure
|
|
60
|
+
restore(mode) if mode
|
|
61
|
+
@output.print "\r\n"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Waits up to `seconds` for keys and returns what they typed, as raw
|
|
65
|
+
# mode reads it, or an empty string.
|
|
66
|
+
def read_text(seconds)
|
|
67
|
+
if @closed
|
|
68
|
+
sleep(seconds)
|
|
69
|
+
return ""
|
|
70
|
+
end
|
|
71
|
+
return "" unless readable?(seconds)
|
|
72
|
+
|
|
73
|
+
text = @input.read_nonblock(64, exception: false)
|
|
74
|
+
return "" if text == :wait_readable
|
|
75
|
+
|
|
76
|
+
@closed = true if text.nil?
|
|
77
|
+
text.nil? ? "" : text
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def print_text(text)
|
|
81
|
+
@output.print(text)
|
|
82
|
+
@output.flush
|
|
83
|
+
end
|
|
84
|
+
|
|
53
85
|
def header(lines)
|
|
54
86
|
lines.each { |line| @output.print "#{line}\r\n" }
|
|
55
87
|
@output.print "←/→ subtune n/p tune ,/. seek space pause s shuffle l loop a all subtunes q quit\r\n"
|
|
@@ -39,6 +39,7 @@ module Badline
|
|
|
39
39
|
pending = @pending_keys
|
|
40
40
|
out.ints("host.pending_keys", pending) if pending
|
|
41
41
|
out.bool("host.typing", !pending.nil?)
|
|
42
|
+
save_init_keys(out)
|
|
42
43
|
out.int("host.init_pending", @cycles <= init_threshold ? @init_handlers.length : 0)
|
|
43
44
|
out.bool("host.holding_commodore", @holding_commodore)
|
|
44
45
|
@typist.save_fields(out, "host.typist.")
|
|
@@ -55,6 +56,7 @@ module Badline
|
|
|
55
56
|
@cpu_reset_pending = input.bool("cpu_reset_pending", @cpu_reset_pending)
|
|
56
57
|
pending = input.ints("host.pending_keys", [])
|
|
57
58
|
@pending_keys = input.bool("host.typing", !pending.empty?) ? pending.dup : nil
|
|
59
|
+
load_init_keys(input)
|
|
58
60
|
@init_handlers_lost = [input.int("host.init_pending", 0) - @init_handlers.length, 0].max
|
|
59
61
|
load_holding_fields(input)
|
|
60
62
|
@typist.load_fields(input, "host.typist.")
|
data/lib/badline/c128.rb
CHANGED
|
@@ -39,6 +39,7 @@ module Badline
|
|
|
39
39
|
out.bool("dma", @dma)
|
|
40
40
|
pending = @pending_keys
|
|
41
41
|
out.ints("host.pending_keys", pending) if pending
|
|
42
|
+
save_init_keys(out)
|
|
42
43
|
out.int("host.init_pending", booting? ? @init_handlers.length : 0)
|
|
43
44
|
end
|
|
44
45
|
|
|
@@ -52,6 +53,7 @@ module Badline
|
|
|
52
53
|
@dma = input.bool("dma", @dma)
|
|
53
54
|
pending = input.ints("host.pending_keys", [])
|
|
54
55
|
@pending_keys = pending.empty? ? nil : pending.dup
|
|
56
|
+
load_init_keys(input)
|
|
55
57
|
@init_handlers_lost = [input.int("host.init_pending", 0) - @init_handlers.length, 0].max
|
|
56
58
|
end
|
|
57
59
|
|
data/lib/badline/c64.rb
CHANGED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
class CBM2
|
|
5
|
+
# The 6509's bus: sixteen segments of 64K, which the CPU's four extra
|
|
6
|
+
# address lines pick from the execution register at $0000 or, for the
|
|
7
|
+
# data of LDA (zp),Y and STA (zp),Y, the indirection register at $0001
|
|
8
|
+
# (CPU). Both registers answer at $0000 and $0001 in every segment.
|
|
9
|
+
#
|
|
10
|
+
# Segment 15 is the system's:
|
|
11
|
+
#
|
|
12
|
+
# $0000-$07FF - 2K of static RAM
|
|
13
|
+
# $0800-$0FFF - nothing: the buffer RAM socket
|
|
14
|
+
# $1000-$7FFF - the disk ROM's socket and the cartridge's three 8K
|
|
15
|
+
# selects, nothing until a ROM is in (#attach_cartridge)
|
|
16
|
+
# $8000-$BFFF - BASIC
|
|
17
|
+
# $C000-$CFFF - nothing
|
|
18
|
+
# $D000-$D7FF - the screen RAM
|
|
19
|
+
# $D800-$DFFF - I/O, a chip a page (#map_io), nothing where none is
|
|
20
|
+
# $E000-$FFFF - the KERNAL
|
|
21
|
+
#
|
|
22
|
+
# The RAM board fills the segments +ram_segments+ names, and the rest
|
|
23
|
+
# hold nothing. The data lines hold the last byte they carried, which
|
|
24
|
+
# a read from nothing finds, and a write to ROM or to nothing goes
|
|
25
|
+
# nowhere.
|
|
26
|
+
#
|
|
27
|
+
# Each segment is a pair of page tables, one read and one write. The
|
|
28
|
+
# CPU reads and writes through the execution segment's (#peek and
|
|
29
|
+
# #poke), and a write to $0000 switches them, so an access pays
|
|
30
|
+
# nothing for the banking. For an indirect access the CPU switches to
|
|
31
|
+
# the indirection segment's tables and back (#select_indirect! and
|
|
32
|
+
# #select_execute!).
|
|
33
|
+
class Bus
|
|
34
|
+
include Addressable
|
|
35
|
+
|
|
36
|
+
SEGMENTS = 16
|
|
37
|
+
SYSTEM = 15
|
|
38
|
+
|
|
39
|
+
# The last byte the CPU moved, which nothing reads back.
|
|
40
|
+
class OpenBus
|
|
41
|
+
def initialize(bus)
|
|
42
|
+
@bus = bus
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def peek(_addr) = @bus.data
|
|
46
|
+
def poke(_addr, _value); end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# A segment's page 0: the execution register at $0000 and the
|
|
50
|
+
# indirection register at $0001, whose reads return the register in
|
|
51
|
+
# the low four bits and 0 in the high four, over what the page holds.
|
|
52
|
+
class Registers
|
|
53
|
+
def initialize(bus, under)
|
|
54
|
+
@bus = bus
|
|
55
|
+
@under = under
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def peek(addr)
|
|
59
|
+
case addr
|
|
60
|
+
when 0 then @bus.execution_segment
|
|
61
|
+
when 1 then @bus.indirect_segment
|
|
62
|
+
else @under.peek(addr)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def poke(addr, value)
|
|
67
|
+
case addr
|
|
68
|
+
when 0 then @bus.execution_segment = value & 0x0f
|
|
69
|
+
when 1 then @bus.indirect_segment = value & 0x0f
|
|
70
|
+
else @under.poke(addr, value)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# VICE's debug cartridge register at $DAFF in segment 15, which a
|
|
76
|
+
# write calls the handler with, the exit code the VICE testprogs
|
|
77
|
+
# report. Every other write to its page passes to the chip there.
|
|
78
|
+
class DebugRegister
|
|
79
|
+
ADDRESS = 0xdaff
|
|
80
|
+
|
|
81
|
+
attr_accessor :under
|
|
82
|
+
|
|
83
|
+
def initialize(&handler)
|
|
84
|
+
@handler = handler
|
|
85
|
+
@under = nil
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def poke(addr, value)
|
|
89
|
+
return @handler.call(value) if addr == ADDRESS
|
|
90
|
+
|
|
91
|
+
@under.poke(addr, value)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
attr_reader :ram, :screen, :segment_ram, :execution_segment
|
|
96
|
+
attr_accessor :indirect_segment
|
|
97
|
+
|
|
98
|
+
# The last byte the CPU read or wrote.
|
|
99
|
+
attr_reader :data
|
|
100
|
+
|
|
101
|
+
# +basic+ and +kernal+ are ROM files for $8000-$BFFF and
|
|
102
|
+
# $E000-$FFFF, +ram_segments+ the segments the RAM board fills, and
|
|
103
|
+
# +screen_length+ the bytes of screen RAM from $D000 on.
|
|
104
|
+
def initialize(basic:, kernal:, ram_segments:, screen_length: 0x800)
|
|
105
|
+
addressable_at(0, length: 2**16)
|
|
106
|
+
@ram = Memory.new([], length: 0x800, start: 0)
|
|
107
|
+
@screen = Memory.new([], length: screen_length, start: 0xd000)
|
|
108
|
+
@screen_pages = screen_length >> 8
|
|
109
|
+
@basic_rom = ROM.load(basic, 0x8000)
|
|
110
|
+
@kernal_rom = ROM.load(kernal, 0xe000)
|
|
111
|
+
@open_bus = OpenBus.new(self)
|
|
112
|
+
@data = 0
|
|
113
|
+
@segment_ram = Array.new(SEGMENTS) do |segment|
|
|
114
|
+
ram_segments.include?(segment) ? Memory.new([], length: 0x10000, start: 0) : nil
|
|
115
|
+
end
|
|
116
|
+
@io = Array.new(8, @open_bus)
|
|
117
|
+
@cartridge = []
|
|
118
|
+
@video = Array.new(0x18, nil)
|
|
119
|
+
@video_writable = Array.new(0x18, false)
|
|
120
|
+
@debug_register = nil
|
|
121
|
+
@reads = Array.new(SEGMENTS) { Array.new(256, @open_bus) }
|
|
122
|
+
@writes = Array.new(SEGMENTS) { Array.new(256, @open_bus) }
|
|
123
|
+
reset!
|
|
124
|
+
map_pages
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# The RES line sets both registers to 15.
|
|
128
|
+
def reset!
|
|
129
|
+
self.execution_segment = SYSTEM
|
|
130
|
+
@indirect_segment = SYSTEM
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def power_on!
|
|
134
|
+
@ram.clear!
|
|
135
|
+
@screen.clear!
|
|
136
|
+
@segment_ram.each { |memory| memory&.clear! }
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def execution_segment=(segment)
|
|
140
|
+
@execution_segment = segment
|
|
141
|
+
select_execute!
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Switches the CPU's accesses to the indirection segment, for the one
|
|
145
|
+
# access LDA (zp),Y or STA (zp),Y moves its data with.
|
|
146
|
+
def select_indirect!
|
|
147
|
+
@read_pages = @reads[@indirect_segment]
|
|
148
|
+
@write_pages = @writes[@indirect_segment]
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Switches them back to the execution segment.
|
|
152
|
+
def select_execute!
|
|
153
|
+
@read_pages = @reads[@execution_segment]
|
|
154
|
+
@write_pages = @writes[@execution_segment]
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def peek(addr)
|
|
158
|
+
@data = @read_pages[addr >> 8].peek(addr)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def poke(addr, value)
|
|
162
|
+
@data = value
|
|
163
|
+
@write_pages[addr >> 8].poke(addr, value)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Reads and writes +segment+ as the CPU would, wherever it executes.
|
|
167
|
+
def peek_bank(segment, addr) = @reads[segment][addr >> 8].peek(addr)
|
|
168
|
+
|
|
169
|
+
def poke_bank(segment, addr, value)
|
|
170
|
+
@writes[segment][addr >> 8].poke(addr, value)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Whether the CPU runs the KERNAL: it executes in segment 15.
|
|
174
|
+
def kernal_mapped? = @execution_segment == SYSTEM
|
|
175
|
+
|
|
176
|
+
# Puts +chip+ at I/O page +page+, $D8 to $DF of segment 15. The chip
|
|
177
|
+
# hears the whole address.
|
|
178
|
+
def map_io(page, chip)
|
|
179
|
+
@io[page - 0xd8] = chip
|
|
180
|
+
map_pages
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Puts +chip+ at +count+ pages of segment 15 from +page+ on, between
|
|
184
|
+
# $C000 and $D7FF, over what was there: the P500's character ROM, and
|
|
185
|
+
# its colour RAM, which takes writes as well (+writable+). The chip
|
|
186
|
+
# hears the whole address.
|
|
187
|
+
def map_video(chip, page, count, writable: false)
|
|
188
|
+
count.times do |i|
|
|
189
|
+
@video[page + i - 0xc0] = chip
|
|
190
|
+
@video_writable[page + i - 0xc0] = writable
|
|
191
|
+
end
|
|
192
|
+
map_pages
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Puts the cartridge's ROM chips, Storage::CRTFile::Chips, at their
|
|
196
|
+
# load addresses in segment 15, from $1000 to $7FFF, in place of what
|
|
197
|
+
# was there.
|
|
198
|
+
def attach_cartridge(chips)
|
|
199
|
+
@cartridge = chips.map { |chip| ROM.new(chip.data, length: chip.data.length, start: chip.address) }
|
|
200
|
+
map_pages
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def detach_cartridge
|
|
204
|
+
@cartridge = []
|
|
205
|
+
map_pages
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Calls the block with each byte written to $DAFF (DebugRegister).
|
|
209
|
+
def install_debug_register(&)
|
|
210
|
+
@debug_register = DebugRegister.new(&)
|
|
211
|
+
map_pages
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
private
|
|
215
|
+
|
|
216
|
+
def map_pages
|
|
217
|
+
SEGMENTS.times do |segment|
|
|
218
|
+
memory = @segment_ram[segment]
|
|
219
|
+
if memory
|
|
220
|
+
map(segment, memory, 0x00, 0x100)
|
|
221
|
+
else
|
|
222
|
+
map(segment, @open_bus, 0x00, 0x100)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
map_system
|
|
226
|
+
SEGMENTS.times { |segment| map_registers(segment) }
|
|
227
|
+
select_execute!
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def map_system
|
|
231
|
+
map(SYSTEM, @open_bus, 0x00, 0x100)
|
|
232
|
+
map(SYSTEM, @ram, 0x00, 0x08)
|
|
233
|
+
@cartridge.each { |rom| @reads[SYSTEM].fill(rom, rom.start >> 8, rom.length >> 8) }
|
|
234
|
+
@reads[SYSTEM].fill(@basic_rom, 0x80, 0x40)
|
|
235
|
+
map(SYSTEM, @screen, 0xd0, @screen_pages)
|
|
236
|
+
@video.each_with_index { |chip, i| map_video_page(chip, 0xc0 + i, @video_writable[i]) if chip }
|
|
237
|
+
@io.each_with_index { |chip, i| map(SYSTEM, chip, 0xd8 + i, 1) }
|
|
238
|
+
@reads[SYSTEM].fill(@kernal_rom, 0xe0, 0x20)
|
|
239
|
+
map_debug_register if @debug_register
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def map_video_page(chip, page, writable)
|
|
243
|
+
@reads[SYSTEM][page] = chip
|
|
244
|
+
@writes[SYSTEM][page] = writable ? chip : @open_bus
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def map_registers(segment)
|
|
248
|
+
@reads[segment][0] = Registers.new(self, @reads[segment][0])
|
|
249
|
+
@writes[segment][0] = Registers.new(self, @writes[segment][0])
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def map_debug_register
|
|
253
|
+
@debug_register.under = @writes[SYSTEM][0xda]
|
|
254
|
+
@writes[SYSTEM][0xda] = @debug_register
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def map(segment, chip, first, count)
|
|
258
|
+
@reads[segment].fill(chip, first, count)
|
|
259
|
+
@writes[segment].fill(chip, first, count)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|