badline 0.13.0 → 0.14.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 +49 -1
- data/CLAUDE.md +27 -7
- data/CONTRIBUTING.md +4 -3
- data/README.md +8 -5
- data/doc/media.md +2 -1
- data/doc/pinned-behaviour.md +29 -0
- data/doc/snapshot-format.md +1047 -0
- data/doc/snapshots.md +72 -39
- data/lib/badline/audio/bare_player.rb +50 -17
- data/lib/badline/audio/machine_player.rb +15 -9
- data/lib/badline/audio/renderer.rb +32 -21
- data/lib/badline/c128/banks.rb +6 -3
- data/lib/badline/c128/bus/keyed_state.rb +45 -0
- data/lib/badline/c128/bus.rb +17 -3
- data/lib/badline/c128/drives.rb +6 -25
- data/lib/badline/c128/keyed_modules.rb +117 -0
- data/lib/badline/c128/keyed_state.rb +91 -0
- data/lib/badline/c128/keys.rb +9 -0
- data/lib/badline/c128/mmu.rb +9 -8
- data/lib/badline/c128/mmu_pages.rb +20 -0
- data/lib/badline/c128/modes.rb +19 -9
- data/lib/badline/c128/z80_turns.rb +1 -1
- data/lib/badline/c128.rb +8 -8
- data/lib/badline/c64/attachments.rb +0 -44
- data/lib/badline/c64/banked_ram/plus256k.rb +18 -10
- data/lib/badline/c64/banked_ram/plus60k.rb +8 -6
- data/lib/badline/c64/banked_ram/unexpanded.rb +2 -2
- data/lib/badline/c64/bus/debug_register.rb +32 -0
- data/lib/badline/c64/bus/keyed_state.rb +41 -0
- data/lib/badline/c64/bus.rb +2 -1
- data/lib/badline/c64/cartridge/action_replay.rb +0 -13
- data/lib/badline/c64/cartridge/easy_flash.rb +0 -15
- data/lib/badline/c64/cartridge/epyx_fastload.rb +0 -8
- data/lib/badline/c64/cartridge/final_cartridge3.rb +0 -12
- data/lib/badline/c64/cartridge/flash.rb +3 -3
- data/lib/badline/c64/cartridge/g_mod2.rb +0 -12
- data/lib/badline/c64/cartridge/geo_ram.rb +0 -16
- data/lib/badline/c64/cartridge/kcs_power.rb +0 -8
- data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
- data/lib/badline/c64/cartridge/pagefox.rb +0 -10
- data/lib/badline/c64/cartridge/retro_replay.rb +0 -8
- data/lib/badline/c64/cartridge/rgcd.rb +0 -10
- data/lib/badline/c64/cartridge/super_games.rb +0 -10
- data/lib/badline/c64/cartridge/zaxxon.rb +0 -16
- data/lib/badline/c64/cartridge.rb +1 -27
- data/lib/badline/c64/kernal_traps.rb +28 -25
- data/lib/badline/c64/keyed_modules.rb +111 -0
- data/lib/badline/c64/keyed_state.rb +68 -0
- data/lib/badline/c64/reu/dma.rb +0 -4
- data/lib/badline/c64/reu/keyed_state.rb +140 -0
- data/lib/badline/c64/reu/ram.rb +0 -15
- data/lib/badline/c64/reu.rb +1 -3
- data/lib/badline/c64/true_drives.rb +56 -5
- data/lib/badline/c64.rb +7 -3
- data/lib/badline/chips/cia/interrupt_register.rb +0 -17
- data/lib/badline/chips/cia/keyed_parts.rb +213 -0
- data/lib/badline/chips/cia/serial.rb +0 -4
- data/lib/badline/chips/cia/time_of_day.rb +0 -22
- data/lib/badline/chips/cia/timer.rb +0 -20
- data/lib/badline/chips/cia.rb +2 -2
- data/lib/badline/chips/cpu/core.rb +18 -2
- data/lib/badline/chips/cpu/keyed_state.rb +177 -0
- data/lib/badline/chips/cpu/microcode.rb +16 -0
- data/lib/badline/chips/cpu/port.rb +20 -3
- data/lib/badline/chips/cpu.rb +5 -0
- data/lib/badline/chips/sid/decimator.rb +10 -8
- data/lib/badline/chips/sid/envelope.rb +1 -6
- data/lib/badline/chips/sid/filter.rb +0 -14
- data/lib/badline/chips/sid/keyed_parts.rb +286 -0
- data/lib/badline/chips/sid/voice.rb +0 -10
- data/lib/badline/chips/sid/waveform.rb +0 -2
- data/lib/badline/chips/sid.rb +1 -2
- data/lib/badline/chips/ted/beam.rb +119 -0
- data/lib/badline/chips/ted/timers.rb +66 -0
- data/lib/badline/chips/ted.rb +143 -0
- data/lib/badline/chips/tia.rb +49 -0
- data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
- data/lib/badline/chips/vdc/painter.rb +0 -12
- data/lib/badline/chips/vdc/raster.rb +0 -16
- data/lib/badline/chips/vdc/window.rb +0 -9
- data/lib/badline/chips/vdc.rb +1 -2
- data/lib/badline/chips/via/control_lines.rb +0 -15
- data/lib/badline/chips/via/interrupt_register.rb +0 -9
- data/lib/badline/chips/via/keyed_parts.rb +163 -0
- data/lib/badline/chips/via/shift_register.rb +0 -14
- data/lib/badline/chips/via/timer1.rb +0 -13
- data/lib/badline/chips/via/timer2.rb +0 -18
- data/lib/badline/chips/via.rb +1 -2
- data/lib/badline/chips/vic/border_mask.rb +0 -10
- data/lib/badline/chips/vic/collisions.rb +0 -11
- data/lib/badline/chips/vic/color_patches.rb +0 -11
- data/lib/badline/chips/vic/display_state.rb +0 -19
- data/lib/badline/chips/vic/graphics_shifter.rb +0 -4
- data/lib/badline/chips/vic/keyed_parts.rb +228 -0
- data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
- data/lib/badline/chips/vic/keyed_state.rb +102 -0
- data/lib/badline/chips/vic/register_log.rb +0 -18
- data/lib/badline/chips/vic/registers.rb +0 -9
- data/lib/badline/chips/vic/sequencer.rb +0 -2
- data/lib/badline/chips/vic/sprite/internal_bus.rb +0 -11
- data/lib/badline/chips/vic/sprite.rb +0 -2
- data/lib/badline/chips/vic/sprites.rb +0 -3
- data/lib/badline/chips/vic.rb +6 -2
- data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
- data/lib/badline/chips/vic_i/painter.rb +0 -4
- data/lib/badline/chips/vic_i/sound.rb +38 -46
- data/lib/badline/chips/vic_i.rb +2 -2
- data/lib/badline/chips/z80/core.rb +2 -2
- data/lib/badline/chips/z80/keyed_state.rb +73 -0
- data/lib/badline/chips.rb +10 -0
- data/lib/badline/core.rb +4 -21
- data/lib/badline/drives/datasette/keyed_state.rb +38 -0
- data/lib/badline/drives/datasette.rb +40 -7
- data/lib/badline/drives/engine/core.rb +3 -0
- data/lib/badline/drives/engine/serial_lines.rb +4 -7
- data/lib/badline/drives/model1541/bus.rb +0 -13
- data/lib/badline/drives/model1541/disk.rb +9 -8
- data/lib/badline/drives/model1541/keyed_state.rb +251 -0
- data/lib/badline/drives/model1541/mechanism.rb +0 -2
- data/lib/badline/drives/model1541.rb +1 -2
- data/lib/badline/drives/model1571/bus.rb +0 -13
- data/lib/badline/drives/model1571/keyed_state.rb +108 -0
- data/lib/badline/drives/model1571/wd1770.rb +0 -14
- data/lib/badline/drives/model1571.rb +1 -2
- data/lib/badline/drives/model1581/bus.rb +0 -13
- data/lib/badline/drives/model1581/disk.rb +0 -4
- data/lib/badline/drives/model1581/keyed_state.rb +280 -0
- data/lib/badline/drives/model1581/mechanism.rb +0 -21
- data/lib/badline/drives/model1581/slot.rb +0 -18
- data/lib/badline/drives/model1581/wd1772.rb +0 -2
- data/lib/badline/drives/model1581.rb +2 -2
- data/lib/badline/drives.rb +8 -0
- data/lib/badline/frontend/app.rb +3 -3
- data/lib/badline/frontend/boot.rb +1 -1
- data/lib/badline/frontend/controls.rb +19 -3
- data/lib/badline/frontend/drive_led.rb +44 -21
- data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
- data/lib/badline/frontend/snapshots.rb +12 -1
- data/lib/badline/frontend/timeline.rb +28 -10
- data/lib/badline/input/matrix_typist.rb +98 -0
- data/lib/badline/input.rb +1 -0
- data/lib/badline/kernal_trap/chrout.rb +45 -0
- data/lib/badline/kernal_trap/dos/channel.rb +0 -27
- data/lib/badline/kernal_trap/dos/channels.rb +0 -25
- data/lib/badline/kernal_trap/dos/memory.rb +0 -9
- data/lib/badline/kernal_trap/dos/status.rb +0 -8
- data/lib/badline/kernal_trap/dos/write_file.rb +0 -18
- data/lib/badline/kernal_trap/dos.rb +0 -19
- data/lib/badline/kernal_trap/file_routine.rb +4 -4
- data/lib/badline/kernal_trap/keyed_state.rb +150 -0
- data/lib/badline/kernal_trap/layout.rb +75 -11
- data/lib/badline/kernal_trap/load.rb +14 -16
- data/lib/badline/kernal_trap/routine.rb +12 -0
- data/lib/badline/kernal_trap/save.rb +8 -18
- data/lib/badline/kernal_trap/serial.rb +1 -17
- data/lib/badline/kernal_trap.rb +2 -0
- data/lib/badline/machine/keyboard_buffer.rb +49 -0
- data/lib/badline/machine/settling.rb +29 -0
- data/lib/badline/machine.rb +5 -2
- data/lib/badline/media/boot_disk.rb +14 -2
- data/lib/badline/media/extensions.rb +10 -0
- data/lib/badline/memory.rb +3 -6
- data/lib/badline/options/family.rb +5 -2
- data/lib/badline/options/help.rb +42 -16
- data/lib/badline/options/table.rb +2 -0
- data/lib/badline/options/validation.rb +2 -0
- data/lib/badline/options.rb +6 -1
- data/lib/badline/plus4/acia.rb +45 -0
- data/lib/badline/plus4/bus.rb +312 -0
- data/lib/badline/plus4/cpu.rb +10 -0
- data/lib/badline/plus4/cpu_port.rb +93 -0
- data/lib/badline/plus4/keyboard_port.rb +51 -0
- data/lib/badline/plus4/model.rb +38 -0
- data/lib/badline/plus4/user_port.rb +31 -0
- data/lib/badline/plus4.rb +164 -0
- data/lib/badline/roms/README +38 -0
- data/lib/badline/roms/plus4/basic.rom +0 -0
- data/lib/badline/roms/plus4/function-high.rom +0 -0
- data/lib/badline/roms/plus4/function-low.rom +0 -0
- data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
- data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
- data/lib/badline/snapshot/c128_setup.rb +9 -20
- data/lib/badline/snapshot/c64_setup.rb +28 -24
- data/lib/badline/snapshot/container.rb +4 -0
- data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
- data/lib/badline/snapshot/field_doc.rb +109 -0
- data/lib/badline/snapshot/image.rb +134 -28
- data/lib/badline/snapshot/keyed/cursor.rb +40 -0
- data/lib/badline/snapshot/keyed/modules.rb +66 -0
- data/lib/badline/snapshot/keyed/reader.rb +188 -0
- data/lib/badline/snapshot/keyed/recorder.rb +88 -0
- data/lib/badline/snapshot/keyed/report.rb +26 -0
- data/lib/badline/snapshot/keyed/writer.rb +55 -0
- data/lib/badline/snapshot/keyed.rb +64 -0
- data/lib/badline/snapshot/machine_state.rb +17 -64
- data/lib/badline/snapshot/storage_setup.rb +29 -34
- data/lib/badline/snapshot/vic20_setup.rb +6 -15
- data/lib/badline/snapshot/vice/reu1764.rb +2 -2
- data/lib/badline/snapshot/vice.rb +7 -31
- data/lib/badline/snapshot.rb +43 -20
- data/lib/badline/storage/crt_file.rb +3 -1
- data/lib/badline/storage/g64_image.rb +8 -3
- data/lib/badline/storage/tap.rb +43 -15
- data/lib/badline/version.rb +1 -1
- data/lib/badline/vic20/attachments.rb +3 -0
- data/lib/badline/vic20/bus/keyed_state.rb +52 -0
- data/lib/badline/vic20/bus.rb +1 -2
- data/lib/badline/vic20/keyed_modules.rb +73 -0
- data/lib/badline/vic20/keyed_state.rb +45 -0
- data/lib/badline/vic20.rb +5 -5
- data/lib/badline.rb +1 -0
- metadata +61 -42
- data/lib/badline/c128/bus/saved_state.rb +0 -53
- data/lib/badline/c128/saved_state.rb +0 -117
- data/lib/badline/c64/bus/saved_state.rb +0 -68
- data/lib/badline/c64/cartridge/flash/saved_state.rb +0 -40
- data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +0 -47
- data/lib/badline/c64/cartridge/saved_state.rb +0 -63
- data/lib/badline/c64/reu/dma/saved_state.rb +0 -52
- data/lib/badline/c64/reu/saved_state.rb +0 -55
- data/lib/badline/c64/saved_state.rb +0 -112
- data/lib/badline/chips/cia/saved_state.rb +0 -49
- data/lib/badline/chips/cia/serial/saved_state.rb +0 -45
- data/lib/badline/chips/cpu/saved_state.rb +0 -117
- data/lib/badline/chips/sid/envelope/saved_state.rb +0 -70
- data/lib/badline/chips/sid/filter/saved_state.rb +0 -42
- data/lib/badline/chips/sid/saved_state.rb +0 -52
- data/lib/badline/chips/sid/waveform/saved_state.rb +0 -68
- data/lib/badline/chips/vdc/saved_state.rb +0 -36
- data/lib/badline/chips/via/saved_state.rb +0 -44
- data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +0 -40
- data/lib/badline/chips/vic/saved_state.rb +0 -82
- data/lib/badline/chips/vic/sequencer/saved_state.rb +0 -91
- data/lib/badline/chips/vic/sprite/saved_state.rb +0 -66
- data/lib/badline/chips/vic/sprites/saved_state.rb +0 -59
- data/lib/badline/chips/vic_i/painter/saved_state.rb +0 -40
- data/lib/badline/chips/vic_i/saved_state.rb +0 -55
- data/lib/badline/chips/z80/saved_state.rb +0 -71
- data/lib/badline/chrout_trap.rb +0 -43
- data/lib/badline/debug_register.rb +0 -28
- data/lib/badline/drives/datasette/saved_state.rb +0 -37
- data/lib/badline/drives/model1541/disk/saved_state.rb +0 -88
- data/lib/badline/drives/model1541/mechanism/saved_state.rb +0 -72
- data/lib/badline/drives/model1541/saved_state.rb +0 -44
- data/lib/badline/drives/model1571/saved_state.rb +0 -47
- data/lib/badline/drives/model1581/disk/saved_state.rb +0 -89
- data/lib/badline/drives/model1581/saved_state.rb +0 -42
- data/lib/badline/drives/model1581/wd1772/saved_state.rb +0 -68
- data/lib/badline/keyboard_buffer.rb +0 -33
- data/lib/badline/snapshot/setup.rb +0 -31
- data/lib/badline/snapshot/state.rb +0 -179
- data/lib/badline/vic20/bus/saved_state.rb +0 -35
- data/lib/badline/vic20/saved_state.rb +0 -110
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "badline/chips/ted/timers"
|
|
4
|
+
require "badline/chips/ted/beam"
|
|
5
|
+
|
|
6
|
+
module Badline
|
|
7
|
+
module Chips
|
|
8
|
+
# The TED of the Commodore 264 series, the 7360 and 8360: its registers
|
|
9
|
+
# at $FF00-$FF1F, the raster, the three timers, the interrupt, the
|
|
10
|
+
# keyboard latch and the clock it gives the CPU (Beam). It paints no
|
|
11
|
+
# picture and plays no sound yet: those registers keep what is written
|
|
12
|
+
# to them.
|
|
13
|
+
#
|
|
14
|
+
# The machine clocks it once a single clock cycle, 57 to a line, and
|
|
15
|
+
# asks it then how many cycles the CPU runs in that one (#cpu_slots)
|
|
16
|
+
# and whether BA is low (#ba_low?).
|
|
17
|
+
#
|
|
18
|
+
# $FF08 is the keyboard latch: a write latches the K0-K7 inputs, which
|
|
19
|
+
# the keyboard port answers for the byte written (KeyboardPort#latch),
|
|
20
|
+
# and a read returns them. $FF09 holds the interrupt flags, each
|
|
21
|
+
# cleared by writing a 1 to it, with bit 7 set while the interrupt
|
|
22
|
+
# line is pulled. $FF0A holds the mask and bit 8 of the raster compare,
|
|
23
|
+
# and $FF0B the compare's low byte. $FF13 bit 0 reads whether the CPU
|
|
24
|
+
# sees ROM at $8000-$FFFF (#rom_selected=). $FF1C and $FF1D read and
|
|
25
|
+
# set the raster line, and $FF1E reads the horizontal position's top 8
|
|
26
|
+
# bits.
|
|
27
|
+
class TED
|
|
28
|
+
include Timers
|
|
29
|
+
include Beam
|
|
30
|
+
|
|
31
|
+
# The clock a TED is fed, its single clock: the crystal divided by 20
|
|
32
|
+
# on PAL machines and by 16 on NTSC ones (the Plus/4 hardware manual's
|
|
33
|
+
# TED datasheet).
|
|
34
|
+
Profile = Data.define(:name, :clock_hz)
|
|
35
|
+
|
|
36
|
+
PAL = Profile.new(name: :pal, clock_hz: 886_724)
|
|
37
|
+
NTSC = Profile.new(name: :ntsc, clock_hz: 894_886)
|
|
38
|
+
|
|
39
|
+
RASTER_FLAG = 0x02
|
|
40
|
+
|
|
41
|
+
# The interrupt sources a mask bit can enable: the raster, the light
|
|
42
|
+
# pen and the three timers.
|
|
43
|
+
SOURCES = 0x5e
|
|
44
|
+
|
|
45
|
+
attr_reader :profile, :interrupt_flags, :interrupt_mask
|
|
46
|
+
|
|
47
|
+
# What answers the keyboard latch: an object with #latch(value).
|
|
48
|
+
attr_writer :keyboard_port
|
|
49
|
+
|
|
50
|
+
# Whether the CPU sees ROM at $8000-$FFFF, which $FF13 bit 0 reads.
|
|
51
|
+
attr_writer :rom_selected
|
|
52
|
+
|
|
53
|
+
def initialize(profile = PAL)
|
|
54
|
+
@profile = profile
|
|
55
|
+
@keyboard_port = nil
|
|
56
|
+
@rom_selected = true
|
|
57
|
+
power_on!
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def power_on!
|
|
61
|
+
@registers = Array.new(0x20, 0)
|
|
62
|
+
@interrupt_flags = 0
|
|
63
|
+
@interrupt_mask = 0
|
|
64
|
+
@raster_compare = 0
|
|
65
|
+
@key_latch = 0xff
|
|
66
|
+
reset_timers
|
|
67
|
+
reset_beam
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Counts the timers and moves the beam on a cycle, unless $FF07's
|
|
71
|
+
# freeze bit holds them, then decides the CPU's clock for the cycle.
|
|
72
|
+
def cycle!
|
|
73
|
+
unless frozen?
|
|
74
|
+
count_timers
|
|
75
|
+
move_beam
|
|
76
|
+
end
|
|
77
|
+
decide_clock
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Whether the interrupt line is pulled: a flag raised whose mask bit
|
|
81
|
+
# is set.
|
|
82
|
+
def irq? = @interrupt_flags.anybits?(@interrupt_mask & SOURCES)
|
|
83
|
+
|
|
84
|
+
def peek(addr)
|
|
85
|
+
register = addr & 0x3f
|
|
86
|
+
return 0xff if register >= 0x20
|
|
87
|
+
|
|
88
|
+
case register
|
|
89
|
+
when 0x00..0x05 then read_timer(register)
|
|
90
|
+
when 0x08 then @key_latch
|
|
91
|
+
when 0x09 then read_interrupt_flags
|
|
92
|
+
when 0x0a then @interrupt_mask | 0xa0
|
|
93
|
+
when 0x0b then @raster_compare & 0xff
|
|
94
|
+
when 0x13 then (@registers[0x13] & 0xfe) | (@rom_selected ? 1 : 0)
|
|
95
|
+
when 0x1c then 0xfe | (@line >> 8)
|
|
96
|
+
when 0x1d then @line & 0xff
|
|
97
|
+
when 0x1e then @column << 2
|
|
98
|
+
else @registers[register]
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def poke(addr, value)
|
|
103
|
+
register = addr & 0x3f
|
|
104
|
+
return if register >= 0x20
|
|
105
|
+
|
|
106
|
+
@registers[register] = value
|
|
107
|
+
case register
|
|
108
|
+
when 0x00..0x05 then write_timer(register, value)
|
|
109
|
+
when 0x08 then @key_latch = @keyboard_port ? @keyboard_port.latch(value) : 0xff
|
|
110
|
+
when 0x09 then @interrupt_flags &= ~value
|
|
111
|
+
when 0x0a then write_interrupt_mask(value)
|
|
112
|
+
when 0x0b then @raster_compare = (@raster_compare & 0x100) | value
|
|
113
|
+
when 0x1c then self.line = (@line & 0xff) | ((value & 0x01) << 8)
|
|
114
|
+
when 0x1d then self.line = (@line & 0x100) | value
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
|
|
120
|
+
# $FF07 bit 5 stops the beam and the timers.
|
|
121
|
+
def frozen? = @registers[0x07].anybits?(0x20)
|
|
122
|
+
|
|
123
|
+
def read_interrupt_flags
|
|
124
|
+
value = @interrupt_flags | 0x21
|
|
125
|
+
irq? ? value | 0x80 : value
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def write_interrupt_mask(value)
|
|
129
|
+
@interrupt_mask = value & 0x5f
|
|
130
|
+
@raster_compare = (@raster_compare & 0xff) | ((value & 0x01) << 8)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def line=(value)
|
|
134
|
+
@line = value
|
|
135
|
+
raster_reached
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def raster_reached
|
|
139
|
+
@interrupt_flags |= RASTER_FLAG if @line == @raster_compare
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
# The 6523 TIA, a tri-port interface adapter: three 8-bit ports, A, B
|
|
6
|
+
# and C at registers 0-2, each with its direction register at 3-5, a 1
|
|
7
|
+
# making the pin an output. Its three address lines repeat the
|
|
8
|
+
# registers every 8 bytes, and registers 6 and 7 read $FF.
|
|
9
|
+
#
|
|
10
|
+
# A pin read as an output returns what the port drives, and one read as
|
|
11
|
+
# an input returns what the other side drives, #inputs, per port.
|
|
12
|
+
class TIA
|
|
13
|
+
attr_reader :ports, :directions
|
|
14
|
+
|
|
15
|
+
# What the other side drives onto each port's pins.
|
|
16
|
+
attr_reader :inputs
|
|
17
|
+
|
|
18
|
+
def initialize
|
|
19
|
+
@inputs = [0, 0, 0]
|
|
20
|
+
reset!
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def reset!
|
|
24
|
+
@ports = [0, 0, 0]
|
|
25
|
+
@directions = [0, 0, 0]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def peek(addr)
|
|
29
|
+
register = addr & 0x07
|
|
30
|
+
return 0xff if register > 5
|
|
31
|
+
return @directions[register - 3] if register >= 3
|
|
32
|
+
|
|
33
|
+
direction = @directions[register]
|
|
34
|
+
(@ports[register] & direction) | (@inputs[register] & ~direction & 0xff)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def poke(addr, value)
|
|
38
|
+
register = addr & 0x07
|
|
39
|
+
return if register > 5
|
|
40
|
+
|
|
41
|
+
if register >= 3
|
|
42
|
+
@directions[register - 3] = value
|
|
43
|
+
else
|
|
44
|
+
@ports[register] = value
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VDC
|
|
6
|
+
class Raster
|
|
7
|
+
# The raster's fields in a keyed snapshot module, under `prefix`:
|
|
8
|
+
# the frame count, where the beam is in the character rows and the
|
|
9
|
+
# frame, and the frame's size and sync as it latched them.
|
|
10
|
+
module KeyedState
|
|
11
|
+
def save_fields(out, prefix)
|
|
12
|
+
out.int("#{prefix}frame", @frame).int("#{prefix}row", @row).int("#{prefix}row_line", @row_line)
|
|
13
|
+
out.bool("#{prefix}adjusting", @adjusting).int("#{prefix}frame_line", @frame_line)
|
|
14
|
+
out.int("#{prefix}frame_lines", @frame_lines).int("#{prefix}sync_start", @sync_start)
|
|
15
|
+
out.int("#{prefix}sync_lines", @sync_lines)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def load_fields(input, prefix)
|
|
19
|
+
@frame = input.int("#{prefix}frame", @frame)
|
|
20
|
+
@row = input.int("#{prefix}row", @row)
|
|
21
|
+
@row_line = input.int("#{prefix}row_line", @row_line)
|
|
22
|
+
@adjusting = input.bool("#{prefix}adjusting", @adjusting)
|
|
23
|
+
@frame_line = input.int("#{prefix}frame_line", @frame_line)
|
|
24
|
+
@frame_lines = input.int("#{prefix}frame_lines", @frame_lines)
|
|
25
|
+
@sync_start = input.int("#{prefix}sync_start", @sync_start)
|
|
26
|
+
@sync_lines = input.int("#{prefix}sync_lines", @sync_lines)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
include KeyedState
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class Window
|
|
34
|
+
# The start addresses the frame latched, under `prefix`.
|
|
35
|
+
module KeyedState
|
|
36
|
+
def save_fields(out, prefix)
|
|
37
|
+
out.int("#{prefix}display_start", @display_start).int("#{prefix}attribute_start", @attribute_start)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def load_fields(input, prefix)
|
|
41
|
+
@display_start = input.word("#{prefix}display_start", @display_start)
|
|
42
|
+
@attribute_start = input.word("#{prefix}attribute_start", @attribute_start)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
include KeyedState
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class Painter
|
|
50
|
+
# The display's size, as the frame latched it, and the window's
|
|
51
|
+
# start addresses. The picture is painted again.
|
|
52
|
+
module KeyedState
|
|
53
|
+
def save_fields(out)
|
|
54
|
+
out.int("display.width", @width).int("display.height", @height)
|
|
55
|
+
@window.save_fields(out, "window.")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def load_fields(input)
|
|
59
|
+
resize(input.int("display.width", @width), input.int("display.height", @height))
|
|
60
|
+
@window.load_fields(input, "window.")
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
include KeyedState
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# The VDC's fields in a keyed snapshot module (Snapshot::Keyed): the
|
|
68
|
+
# registers, the RAM, the register selected, the data latches, the
|
|
69
|
+
# dot clock's phase and the line's length in the same units
|
|
70
|
+
# (dots·Hz, the line latched at its start), how long an access or
|
|
71
|
+
# block operation stays busy from now, the raster under raster.* and
|
|
72
|
+
# the display's size and window under display.* and window.*. The
|
|
73
|
+
# RAM's layout comes from R28 on load.
|
|
74
|
+
module KeyedState
|
|
75
|
+
def save_fields(out)
|
|
76
|
+
out.bytes("registers", @registers).bytes("ram", @memory.ram).int("selected", @selected)
|
|
77
|
+
out.int("read_latch", @read_latch).int("write_data", @write_data).int("phase", @phase)
|
|
78
|
+
out.int("line_units", @line_units).int("busy_for", @busy_until - @phase)
|
|
79
|
+
@raster.save_fields(out, "raster.")
|
|
80
|
+
@painter.save_fields(out)
|
|
81
|
+
out
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def load_fields(input)
|
|
85
|
+
input.bytes_into("registers", @registers)
|
|
86
|
+
input.bytes_into("ram", @memory.ram)
|
|
87
|
+
@selected = input.masked("selected", @selected, 0x3f)
|
|
88
|
+
@read_latch = input.byte("read_latch", @read_latch)
|
|
89
|
+
@write_data = input.byte("write_data", @write_data)
|
|
90
|
+
@phase = input.int("phase", @phase)
|
|
91
|
+
@line_units = input.int("line_units", @line_units)
|
|
92
|
+
@busy_until = @phase + input.int("busy_for", @busy_until - @phase)
|
|
93
|
+
@raster.load_fields(input, "raster.")
|
|
94
|
+
@painter.load_fields(input)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def restored!
|
|
98
|
+
@memory.mode64 = @registers[28].anybits?(0x10)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
include KeyedState
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -56,18 +56,6 @@ module Badline
|
|
|
56
56
|
[0, 0, shown.clamp(1, @width), (frame_lines - sync_lines).clamp(1, @height)]
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
# The display's size and the window's start addresses. The display
|
|
60
|
-
# starts again cleared, to be painted while the VDC renders.
|
|
61
|
-
def save_state(out)
|
|
62
|
-
out.int(@width).int(@height)
|
|
63
|
-
@window.save_state(out)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def load_state(input)
|
|
67
|
-
resize(input.int, input.int)
|
|
68
|
-
@window.load_state(input)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
59
|
def clear_dirty_lines!
|
|
72
60
|
@dirty_lines.fill(false)
|
|
73
61
|
end
|
|
@@ -30,22 +30,6 @@ module Badline
|
|
|
30
30
|
# Outside the displayed rows, as status bit 5 reads.
|
|
31
31
|
def vertical_blank? = @adjusting || @row >= @registers[6]
|
|
32
32
|
|
|
33
|
-
def save_state(out)
|
|
34
|
-
out.int(@frame).int(@row).int(@row_line).boolean(@adjusting).int(@frame_line).int(@frame_lines)
|
|
35
|
-
out.int(@sync_start).int(@sync_lines)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def load_state(input)
|
|
39
|
-
@frame = input.int
|
|
40
|
-
@row = input.int
|
|
41
|
-
@row_line = input.int
|
|
42
|
-
@adjusting = input.boolean?
|
|
43
|
-
@frame_line = input.int
|
|
44
|
-
@frame_lines = input.int
|
|
45
|
-
@sync_start = input.int
|
|
46
|
-
@sync_lines = input.int
|
|
47
|
-
end
|
|
48
|
-
|
|
49
33
|
def end_line(render)
|
|
50
34
|
paint_line if render
|
|
51
35
|
@frame_line += 1
|
|
@@ -57,15 +57,6 @@ module Badline
|
|
|
57
57
|
@attribute_start = (regs[20] << 8) | regs[21]
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
def save_state(out)
|
|
61
|
-
out.int(@display_start).int(@attribute_start)
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def load_state(input)
|
|
65
|
-
@display_start = input.int
|
|
66
|
-
@attribute_start = input.int
|
|
67
|
-
end
|
|
68
|
-
|
|
69
60
|
def paint(line, row, row_line, frame)
|
|
70
61
|
regs = @registers
|
|
71
62
|
lay_out_cell
|
data/lib/badline/chips/vdc.rb
CHANGED
|
@@ -4,7 +4,7 @@ require "badline/chips/vdc/memory"
|
|
|
4
4
|
require "badline/chips/vdc/window"
|
|
5
5
|
require "badline/chips/vdc/painter"
|
|
6
6
|
require "badline/chips/vdc/raster"
|
|
7
|
-
require "badline/chips/vdc/
|
|
7
|
+
require "badline/chips/vdc/keyed_parts"
|
|
8
8
|
|
|
9
9
|
module Badline
|
|
10
10
|
module Chips
|
|
@@ -34,7 +34,6 @@ module Badline
|
|
|
34
34
|
# fills or two per byte it copies.
|
|
35
35
|
class VDC
|
|
36
36
|
include Addressable
|
|
37
|
-
include SavedState
|
|
38
37
|
|
|
39
38
|
STATUS_READY = 0x80
|
|
40
39
|
STATUS_VBLANK = 0x20
|
|
@@ -56,21 +56,6 @@ module Badline
|
|
|
56
56
|
|
|
57
57
|
def active_c1_edge?(high) = high == @control.anybits?(0x01)
|
|
58
58
|
|
|
59
|
-
# The lines' levels and mode. Which flags they set, and whether reads
|
|
60
|
-
# handshake, are the port's wiring.
|
|
61
|
-
def save_state(out)
|
|
62
|
-
out.int(@control).boolean(@c1_high).boolean(@c2_high).boolean(@handshake_low).int(@pulse).boolean(@c2_output)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def load_state(input)
|
|
66
|
-
@control = input.int
|
|
67
|
-
@c1_high = input.boolean?
|
|
68
|
-
@c2_high = input.boolean?
|
|
69
|
-
@handshake_low = input.boolean?
|
|
70
|
-
@pulse = input.int
|
|
71
|
-
@c2_output = input.boolean?
|
|
72
|
-
end
|
|
73
|
-
|
|
74
59
|
# Everything the lines hold, for comparing them at two points.
|
|
75
60
|
def state = [@control, @c1_high, @c2_high, @handshake_low, @pulse, @c2_output]
|
|
76
61
|
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Badline
|
|
4
|
+
module Chips
|
|
5
|
+
class VIA
|
|
6
|
+
class Timer1
|
|
7
|
+
# Timer 1's fields in a keyed snapshot module, under `prefix`.
|
|
8
|
+
module KeyedState
|
|
9
|
+
def save_fields(out, prefix)
|
|
10
|
+
out.int("#{prefix}counter", @counter).int("#{prefix}latch", @latch).bool("#{prefix}hold", @hold)
|
|
11
|
+
out.bool("#{prefix}reload", @reload).bool("#{prefix}armed", @armed).bool("#{prefix}pb7", @pb7)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def load_fields(input, prefix)
|
|
15
|
+
@counter = input.word("#{prefix}counter", @counter)
|
|
16
|
+
@latch = input.word("#{prefix}latch", @latch)
|
|
17
|
+
@hold = input.bool("#{prefix}hold", @hold)
|
|
18
|
+
@reload = input.bool("#{prefix}reload", @reload)
|
|
19
|
+
@armed = input.bool("#{prefix}armed", @armed)
|
|
20
|
+
@pb7 = input.bool("#{prefix}pb7", @pb7)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
include KeyedState
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class Timer2
|
|
28
|
+
# Timer 2's fields in a keyed snapshot module, under `prefix`.
|
|
29
|
+
module KeyedState
|
|
30
|
+
def save_fields(out, prefix)
|
|
31
|
+
out.int("#{prefix}counter", @counter).int("#{prefix}latch_low", @latch_low).bool("#{prefix}hold", @hold)
|
|
32
|
+
out.bool("#{prefix}low_reload", @low_reload).bool("#{prefix}armed", @armed)
|
|
33
|
+
out.bool("#{prefix}low_underflowed", @low_underflowed).bool("#{prefix}count_pulses", @count_pulses)
|
|
34
|
+
out.bool("#{prefix}counting_pulses", @counting_pulses)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def load_fields(input, prefix)
|
|
38
|
+
@counter = input.word("#{prefix}counter", @counter)
|
|
39
|
+
@latch_low = input.byte("#{prefix}latch_low", @latch_low)
|
|
40
|
+
@hold = input.bool("#{prefix}hold", @hold)
|
|
41
|
+
@low_reload = input.bool("#{prefix}low_reload", @low_reload)
|
|
42
|
+
@armed = input.bool("#{prefix}armed", @armed)
|
|
43
|
+
@low_underflowed = input.bool("#{prefix}low_underflowed", @low_underflowed)
|
|
44
|
+
@count_pulses = input.bool("#{prefix}count_pulses", @count_pulses)
|
|
45
|
+
@counting_pulses = input.bool("#{prefix}counting_pulses", @counting_pulses)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
include KeyedState
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class ShiftRegister
|
|
53
|
+
# The shift register's fields in a keyed snapshot module, under
|
|
54
|
+
# `prefix`.
|
|
55
|
+
module KeyedState
|
|
56
|
+
def save_fields(out, prefix)
|
|
57
|
+
out.int("#{prefix}mode", @mode).int("#{prefix}data", @data).int("#{prefix}bits", @bits)
|
|
58
|
+
out.int("#{prefix}delay", @delay).bool("#{prefix}clock", @clock).bool("#{prefix}cb2", @cb2)
|
|
59
|
+
out.bool("#{prefix}cb2_input", @cb2_input)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def load_fields(input, prefix)
|
|
63
|
+
@mode = input.masked("#{prefix}mode", @mode, 0x07)
|
|
64
|
+
@data = input.byte("#{prefix}data", @data)
|
|
65
|
+
@bits = input.int("#{prefix}bits", @bits)
|
|
66
|
+
@delay = input.int("#{prefix}delay", @delay)
|
|
67
|
+
@clock = input.bool("#{prefix}clock", @clock)
|
|
68
|
+
@cb2 = input.bool("#{prefix}cb2", @cb2)
|
|
69
|
+
@cb2_input = input.bool("#{prefix}cb2_input", @cb2_input)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
include KeyedState
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class InterruptRegister
|
|
77
|
+
# The flags and the enable mask, under `prefix`.
|
|
78
|
+
module KeyedState
|
|
79
|
+
def save_fields(out, prefix)
|
|
80
|
+
out.int("#{prefix}flags", @flags).int("#{prefix}enable", @enable)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def load_fields(input, prefix)
|
|
84
|
+
@flags = input.masked("#{prefix}flags", @flags, 0x7f)
|
|
85
|
+
@enable = input.masked("#{prefix}enable", @enable, 0x7f)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
include KeyedState
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
class ControlLines
|
|
93
|
+
# A pair of control lines' fields, under `prefix`.
|
|
94
|
+
module KeyedState
|
|
95
|
+
def save_fields(out, prefix)
|
|
96
|
+
out.int("#{prefix}control", @control).bool("#{prefix}c1_high", @c1_high).bool("#{prefix}c2_high", @c2_high)
|
|
97
|
+
out.bool("#{prefix}handshake_low", @handshake_low).int("#{prefix}pulse", @pulse)
|
|
98
|
+
out.bool("#{prefix}c2_output", @c2_output)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def load_fields(input, prefix)
|
|
102
|
+
@control = input.masked("#{prefix}control", @control, 0x0f)
|
|
103
|
+
@c1_high = input.bool("#{prefix}c1_high", @c1_high)
|
|
104
|
+
@c2_high = input.bool("#{prefix}c2_high", @c2_high)
|
|
105
|
+
@handshake_low = input.bool("#{prefix}handshake_low", @handshake_low)
|
|
106
|
+
@pulse = input.int("#{prefix}pulse", @pulse)
|
|
107
|
+
@c2_output = input.bool("#{prefix}c2_output", @c2_output)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
include KeyedState
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# The VIA's fields in a keyed snapshot module (Snapshot::Keyed): the
|
|
115
|
+
# registers and PB6, and its parts under t1., t2., sr., ifr., ca. and
|
|
116
|
+
# cb. Whether the shift register clocks off timer 2 comes from the
|
|
117
|
+
# ACR on load. The peripheral restores its own state.
|
|
118
|
+
module KeyedState
|
|
119
|
+
def save_fields(out)
|
|
120
|
+
out.int("ora", @ora).int("orb", @orb).int("ddra", @ddra).int("ddrb", @ddrb).int("latch_a", @latch_a)
|
|
121
|
+
out.int("latch_b", @latch_b).int("acr", @acr).int("pcr", @pcr).bool("pb6_high", @pb6_high)
|
|
122
|
+
@t1.save_fields(out, "t1.")
|
|
123
|
+
@t2.save_fields(out, "t2.")
|
|
124
|
+
@shift_register.save_fields(out, "sr.")
|
|
125
|
+
@ifr.save_fields(out, "ifr.")
|
|
126
|
+
@ca.save_fields(out, "ca.")
|
|
127
|
+
@cb.save_fields(out, "cb.")
|
|
128
|
+
out
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def load_fields(input)
|
|
132
|
+
@ora = input.byte("ora", @ora)
|
|
133
|
+
@orb = input.byte("orb", @orb)
|
|
134
|
+
@ddra = input.byte("ddra", @ddra)
|
|
135
|
+
@ddrb = input.byte("ddrb", @ddrb)
|
|
136
|
+
@latch_a = input.byte("latch_a", @latch_a)
|
|
137
|
+
@latch_b = input.byte("latch_b", @latch_b)
|
|
138
|
+
@acr = input.byte("acr", @acr)
|
|
139
|
+
@pcr = input.byte("pcr", @pcr)
|
|
140
|
+
@pb6_high = input.bool("pb6_high", @pb6_high)
|
|
141
|
+
load_part_fields(input)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def restored!
|
|
145
|
+
@sr_uses_t2 = [1, 4, 5].include?((@acr >> 2) & 0x07)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
private
|
|
149
|
+
|
|
150
|
+
def load_part_fields(input)
|
|
151
|
+
@t1.load_fields(input, "t1.")
|
|
152
|
+
@t2.load_fields(input, "t2.")
|
|
153
|
+
@shift_register.load_fields(input, "sr.")
|
|
154
|
+
@ifr.load_fields(input, "ifr.")
|
|
155
|
+
@ca.load_fields(input, "ca.")
|
|
156
|
+
@cb.load_fields(input, "cb.")
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
include KeyedState
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
@@ -81,20 +81,6 @@ module Badline
|
|
|
81
81
|
# changes it from cycle to cycle.
|
|
82
82
|
def clocking? = @bits.nonzero? && internal_clock?
|
|
83
83
|
|
|
84
|
-
def save_state(out)
|
|
85
|
-
out.int(@mode).int(@data).int(@bits).int(@delay).boolean(@clock).boolean(@cb2).boolean(@cb2_input)
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def load_state(input)
|
|
89
|
-
@mode = input.int
|
|
90
|
-
@data = input.int
|
|
91
|
-
@bits = input.int
|
|
92
|
-
@delay = input.int
|
|
93
|
-
@clock = input.boolean?
|
|
94
|
-
@cb2 = input.boolean?
|
|
95
|
-
@cb2_input = input.boolean?
|
|
96
|
-
end
|
|
97
|
-
|
|
98
84
|
# Everything the register holds, for comparing it at two points.
|
|
99
85
|
def state = [@mode, @data, @bits, @delay, @clock, @cb2, @cb2_input]
|
|
100
86
|
|
|
@@ -93,19 +93,6 @@ module Badline
|
|
|
93
93
|
@counter = @reload ? 0xffff : @latch - phase + 1
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
-
def save_state(out)
|
|
97
|
-
out.int(@counter).int(@latch).boolean(@hold).boolean(@reload).boolean(@armed).boolean(@pb7)
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def load_state(input)
|
|
101
|
-
@counter = input.int
|
|
102
|
-
@latch = input.int
|
|
103
|
-
@hold = input.boolean?
|
|
104
|
-
@reload = input.boolean?
|
|
105
|
-
@armed = input.boolean?
|
|
106
|
-
@pb7 = input.boolean?
|
|
107
|
-
end
|
|
108
|
-
|
|
109
96
|
# What the counter and PB7 don't hold, for comparing the timer at two
|
|
110
97
|
# points.
|
|
111
98
|
def state = [@latch, @armed]
|
|
@@ -85,24 +85,6 @@ module Badline
|
|
|
85
85
|
@low_underflowed = @counter.allbits?(0xff)
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
-
def save_state(out)
|
|
89
|
-
out.int(@counter).int(@latch_low)
|
|
90
|
-
[@hold, @low_reload, @armed, @low_underflowed, @count_pulses, @counting_pulses].each do |flag|
|
|
91
|
-
out.boolean(flag)
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def load_state(input)
|
|
96
|
-
@counter = input.int
|
|
97
|
-
@latch_low = input.int
|
|
98
|
-
@hold = input.boolean?
|
|
99
|
-
@low_reload = input.boolean?
|
|
100
|
-
@armed = input.boolean?
|
|
101
|
-
@low_underflowed = input.boolean?
|
|
102
|
-
@count_pulses = input.boolean?
|
|
103
|
-
@counting_pulses = input.boolean?
|
|
104
|
-
end
|
|
105
|
-
|
|
106
88
|
# What the counter and the low byte's underflow don't hold, for
|
|
107
89
|
# comparing the timer at two points.
|
|
108
90
|
def state = [@latch_low, @armed, @hold, @low_reload, @count_pulses, @counting_pulses]
|
data/lib/badline/chips/via.rb
CHANGED
|
@@ -4,9 +4,9 @@ require "badline/chips/via/control_lines"
|
|
|
4
4
|
require "badline/chips/via/fast_forward"
|
|
5
5
|
require "badline/chips/via/interrupt_register"
|
|
6
6
|
require "badline/chips/via/shift_register"
|
|
7
|
-
require "badline/chips/via/saved_state"
|
|
8
7
|
require "badline/chips/via/timer1"
|
|
9
8
|
require "badline/chips/via/timer2"
|
|
9
|
+
require "badline/chips/via/keyed_parts"
|
|
10
10
|
|
|
11
11
|
module Badline
|
|
12
12
|
module Chips
|
|
@@ -20,7 +20,6 @@ module Badline
|
|
|
20
20
|
class VIA
|
|
21
21
|
include Addressable
|
|
22
22
|
include FastForward
|
|
23
|
-
include SavedState
|
|
24
23
|
|
|
25
24
|
attr_reader :start, :peripheral, :shift_register, :acr, :pcr
|
|
26
25
|
|
|
@@ -28,16 +28,6 @@ module Badline
|
|
|
28
28
|
@groups.fill(FULL)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
def save_state(out)
|
|
32
|
-
out.ints(@groups).booleans(@mask).blob(@snapshot)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def load_state(input)
|
|
36
|
-
input.ints_into(@groups)
|
|
37
|
-
input.booleans_into(@mask)
|
|
38
|
-
input.blob_into(@snapshot)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
31
|
def at?(pixel_x)
|
|
42
32
|
case @groups[pixel_x >> 3]
|
|
43
33
|
when FULL then true
|