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.
Files changed (254) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -1
  3. data/CLAUDE.md +27 -7
  4. data/CONTRIBUTING.md +4 -3
  5. data/README.md +8 -5
  6. data/doc/media.md +2 -1
  7. data/doc/pinned-behaviour.md +29 -0
  8. data/doc/snapshot-format.md +1047 -0
  9. data/doc/snapshots.md +72 -39
  10. data/lib/badline/audio/bare_player.rb +50 -17
  11. data/lib/badline/audio/machine_player.rb +15 -9
  12. data/lib/badline/audio/renderer.rb +32 -21
  13. data/lib/badline/c128/banks.rb +6 -3
  14. data/lib/badline/c128/bus/keyed_state.rb +45 -0
  15. data/lib/badline/c128/bus.rb +17 -3
  16. data/lib/badline/c128/drives.rb +6 -25
  17. data/lib/badline/c128/keyed_modules.rb +117 -0
  18. data/lib/badline/c128/keyed_state.rb +91 -0
  19. data/lib/badline/c128/keys.rb +9 -0
  20. data/lib/badline/c128/mmu.rb +9 -8
  21. data/lib/badline/c128/mmu_pages.rb +20 -0
  22. data/lib/badline/c128/modes.rb +19 -9
  23. data/lib/badline/c128/z80_turns.rb +1 -1
  24. data/lib/badline/c128.rb +8 -8
  25. data/lib/badline/c64/attachments.rb +0 -44
  26. data/lib/badline/c64/banked_ram/plus256k.rb +18 -10
  27. data/lib/badline/c64/banked_ram/plus60k.rb +8 -6
  28. data/lib/badline/c64/banked_ram/unexpanded.rb +2 -2
  29. data/lib/badline/c64/bus/debug_register.rb +32 -0
  30. data/lib/badline/c64/bus/keyed_state.rb +41 -0
  31. data/lib/badline/c64/bus.rb +2 -1
  32. data/lib/badline/c64/cartridge/action_replay.rb +0 -13
  33. data/lib/badline/c64/cartridge/easy_flash.rb +0 -15
  34. data/lib/badline/c64/cartridge/epyx_fastload.rb +0 -8
  35. data/lib/badline/c64/cartridge/final_cartridge3.rb +0 -12
  36. data/lib/badline/c64/cartridge/flash.rb +3 -3
  37. data/lib/badline/c64/cartridge/g_mod2.rb +0 -12
  38. data/lib/badline/c64/cartridge/geo_ram.rb +0 -16
  39. data/lib/badline/c64/cartridge/kcs_power.rb +0 -8
  40. data/lib/badline/c64/cartridge/keyed_state.rb +393 -0
  41. data/lib/badline/c64/cartridge/pagefox.rb +0 -10
  42. data/lib/badline/c64/cartridge/retro_replay.rb +0 -8
  43. data/lib/badline/c64/cartridge/rgcd.rb +0 -10
  44. data/lib/badline/c64/cartridge/super_games.rb +0 -10
  45. data/lib/badline/c64/cartridge/zaxxon.rb +0 -16
  46. data/lib/badline/c64/cartridge.rb +1 -27
  47. data/lib/badline/c64/kernal_traps.rb +28 -25
  48. data/lib/badline/c64/keyed_modules.rb +111 -0
  49. data/lib/badline/c64/keyed_state.rb +68 -0
  50. data/lib/badline/c64/reu/dma.rb +0 -4
  51. data/lib/badline/c64/reu/keyed_state.rb +140 -0
  52. data/lib/badline/c64/reu/ram.rb +0 -15
  53. data/lib/badline/c64/reu.rb +1 -3
  54. data/lib/badline/c64/true_drives.rb +56 -5
  55. data/lib/badline/c64.rb +7 -3
  56. data/lib/badline/chips/cia/interrupt_register.rb +0 -17
  57. data/lib/badline/chips/cia/keyed_parts.rb +213 -0
  58. data/lib/badline/chips/cia/serial.rb +0 -4
  59. data/lib/badline/chips/cia/time_of_day.rb +0 -22
  60. data/lib/badline/chips/cia/timer.rb +0 -20
  61. data/lib/badline/chips/cia.rb +2 -2
  62. data/lib/badline/chips/cpu/core.rb +18 -2
  63. data/lib/badline/chips/cpu/keyed_state.rb +177 -0
  64. data/lib/badline/chips/cpu/microcode.rb +16 -0
  65. data/lib/badline/chips/cpu/port.rb +20 -3
  66. data/lib/badline/chips/cpu.rb +5 -0
  67. data/lib/badline/chips/sid/decimator.rb +10 -8
  68. data/lib/badline/chips/sid/envelope.rb +1 -6
  69. data/lib/badline/chips/sid/filter.rb +0 -14
  70. data/lib/badline/chips/sid/keyed_parts.rb +286 -0
  71. data/lib/badline/chips/sid/voice.rb +0 -10
  72. data/lib/badline/chips/sid/waveform.rb +0 -2
  73. data/lib/badline/chips/sid.rb +1 -2
  74. data/lib/badline/chips/ted/beam.rb +119 -0
  75. data/lib/badline/chips/ted/timers.rb +66 -0
  76. data/lib/badline/chips/ted.rb +143 -0
  77. data/lib/badline/chips/tia.rb +49 -0
  78. data/lib/badline/chips/vdc/keyed_parts.rb +105 -0
  79. data/lib/badline/chips/vdc/painter.rb +0 -12
  80. data/lib/badline/chips/vdc/raster.rb +0 -16
  81. data/lib/badline/chips/vdc/window.rb +0 -9
  82. data/lib/badline/chips/vdc.rb +1 -2
  83. data/lib/badline/chips/via/control_lines.rb +0 -15
  84. data/lib/badline/chips/via/interrupt_register.rb +0 -9
  85. data/lib/badline/chips/via/keyed_parts.rb +163 -0
  86. data/lib/badline/chips/via/shift_register.rb +0 -14
  87. data/lib/badline/chips/via/timer1.rb +0 -13
  88. data/lib/badline/chips/via/timer2.rb +0 -18
  89. data/lib/badline/chips/via.rb +1 -2
  90. data/lib/badline/chips/vic/border_mask.rb +0 -10
  91. data/lib/badline/chips/vic/collisions.rb +0 -11
  92. data/lib/badline/chips/vic/color_patches.rb +0 -11
  93. data/lib/badline/chips/vic/display_state.rb +0 -19
  94. data/lib/badline/chips/vic/graphics_shifter.rb +0 -4
  95. data/lib/badline/chips/vic/keyed_parts.rb +228 -0
  96. data/lib/badline/chips/vic/keyed_sprites.rb +225 -0
  97. data/lib/badline/chips/vic/keyed_state.rb +102 -0
  98. data/lib/badline/chips/vic/register_log.rb +0 -18
  99. data/lib/badline/chips/vic/registers.rb +0 -9
  100. data/lib/badline/chips/vic/sequencer.rb +0 -2
  101. data/lib/badline/chips/vic/sprite/internal_bus.rb +0 -11
  102. data/lib/badline/chips/vic/sprite.rb +0 -2
  103. data/lib/badline/chips/vic/sprites.rb +0 -3
  104. data/lib/badline/chips/vic.rb +6 -2
  105. data/lib/badline/chips/vic_i/keyed_parts.rb +142 -0
  106. data/lib/badline/chips/vic_i/painter.rb +0 -4
  107. data/lib/badline/chips/vic_i/sound.rb +38 -46
  108. data/lib/badline/chips/vic_i.rb +2 -2
  109. data/lib/badline/chips/z80/core.rb +2 -2
  110. data/lib/badline/chips/z80/keyed_state.rb +73 -0
  111. data/lib/badline/chips.rb +10 -0
  112. data/lib/badline/core.rb +4 -21
  113. data/lib/badline/drives/datasette/keyed_state.rb +38 -0
  114. data/lib/badline/drives/datasette.rb +40 -7
  115. data/lib/badline/drives/engine/core.rb +3 -0
  116. data/lib/badline/drives/engine/serial_lines.rb +4 -7
  117. data/lib/badline/drives/model1541/bus.rb +0 -13
  118. data/lib/badline/drives/model1541/disk.rb +9 -8
  119. data/lib/badline/drives/model1541/keyed_state.rb +251 -0
  120. data/lib/badline/drives/model1541/mechanism.rb +0 -2
  121. data/lib/badline/drives/model1541.rb +1 -2
  122. data/lib/badline/drives/model1571/bus.rb +0 -13
  123. data/lib/badline/drives/model1571/keyed_state.rb +108 -0
  124. data/lib/badline/drives/model1571/wd1770.rb +0 -14
  125. data/lib/badline/drives/model1571.rb +1 -2
  126. data/lib/badline/drives/model1581/bus.rb +0 -13
  127. data/lib/badline/drives/model1581/disk.rb +0 -4
  128. data/lib/badline/drives/model1581/keyed_state.rb +280 -0
  129. data/lib/badline/drives/model1581/mechanism.rb +0 -21
  130. data/lib/badline/drives/model1581/slot.rb +0 -18
  131. data/lib/badline/drives/model1581/wd1772.rb +0 -2
  132. data/lib/badline/drives/model1581.rb +2 -2
  133. data/lib/badline/drives.rb +8 -0
  134. data/lib/badline/frontend/app.rb +3 -3
  135. data/lib/badline/frontend/boot.rb +1 -1
  136. data/lib/badline/frontend/controls.rb +19 -3
  137. data/lib/badline/frontend/drive_led.rb +44 -21
  138. data/lib/badline/frontend/menu/menu_dialogs.rb +2 -2
  139. data/lib/badline/frontend/snapshots.rb +12 -1
  140. data/lib/badline/frontend/timeline.rb +28 -10
  141. data/lib/badline/input/matrix_typist.rb +98 -0
  142. data/lib/badline/input.rb +1 -0
  143. data/lib/badline/kernal_trap/chrout.rb +45 -0
  144. data/lib/badline/kernal_trap/dos/channel.rb +0 -27
  145. data/lib/badline/kernal_trap/dos/channels.rb +0 -25
  146. data/lib/badline/kernal_trap/dos/memory.rb +0 -9
  147. data/lib/badline/kernal_trap/dos/status.rb +0 -8
  148. data/lib/badline/kernal_trap/dos/write_file.rb +0 -18
  149. data/lib/badline/kernal_trap/dos.rb +0 -19
  150. data/lib/badline/kernal_trap/file_routine.rb +4 -4
  151. data/lib/badline/kernal_trap/keyed_state.rb +150 -0
  152. data/lib/badline/kernal_trap/layout.rb +75 -11
  153. data/lib/badline/kernal_trap/load.rb +14 -16
  154. data/lib/badline/kernal_trap/routine.rb +12 -0
  155. data/lib/badline/kernal_trap/save.rb +8 -18
  156. data/lib/badline/kernal_trap/serial.rb +1 -17
  157. data/lib/badline/kernal_trap.rb +2 -0
  158. data/lib/badline/machine/keyboard_buffer.rb +49 -0
  159. data/lib/badline/machine/settling.rb +29 -0
  160. data/lib/badline/machine.rb +5 -2
  161. data/lib/badline/media/boot_disk.rb +14 -2
  162. data/lib/badline/media/extensions.rb +10 -0
  163. data/lib/badline/memory.rb +3 -6
  164. data/lib/badline/options/family.rb +5 -2
  165. data/lib/badline/options/help.rb +42 -16
  166. data/lib/badline/options/table.rb +2 -0
  167. data/lib/badline/options/validation.rb +2 -0
  168. data/lib/badline/options.rb +6 -1
  169. data/lib/badline/plus4/acia.rb +45 -0
  170. data/lib/badline/plus4/bus.rb +312 -0
  171. data/lib/badline/plus4/cpu.rb +10 -0
  172. data/lib/badline/plus4/cpu_port.rb +93 -0
  173. data/lib/badline/plus4/keyboard_port.rb +51 -0
  174. data/lib/badline/plus4/model.rb +38 -0
  175. data/lib/badline/plus4/user_port.rb +31 -0
  176. data/lib/badline/plus4.rb +164 -0
  177. data/lib/badline/roms/README +38 -0
  178. data/lib/badline/roms/plus4/basic.rom +0 -0
  179. data/lib/badline/roms/plus4/function-high.rom +0 -0
  180. data/lib/badline/roms/plus4/function-low.rom +0 -0
  181. data/lib/badline/roms/plus4/kernal-ntsc.rom +0 -0
  182. data/lib/badline/roms/plus4/kernal-pal.rom +0 -0
  183. data/lib/badline/snapshot/c128_setup.rb +9 -20
  184. data/lib/badline/snapshot/c64_setup.rb +28 -24
  185. data/lib/badline/snapshot/container.rb +4 -0
  186. data/lib/badline/snapshot/field_doc/markdown.rb +112 -0
  187. data/lib/badline/snapshot/field_doc.rb +109 -0
  188. data/lib/badline/snapshot/image.rb +134 -28
  189. data/lib/badline/snapshot/keyed/cursor.rb +40 -0
  190. data/lib/badline/snapshot/keyed/modules.rb +66 -0
  191. data/lib/badline/snapshot/keyed/reader.rb +188 -0
  192. data/lib/badline/snapshot/keyed/recorder.rb +88 -0
  193. data/lib/badline/snapshot/keyed/report.rb +26 -0
  194. data/lib/badline/snapshot/keyed/writer.rb +55 -0
  195. data/lib/badline/snapshot/keyed.rb +64 -0
  196. data/lib/badline/snapshot/machine_state.rb +17 -64
  197. data/lib/badline/snapshot/storage_setup.rb +29 -34
  198. data/lib/badline/snapshot/vic20_setup.rb +6 -15
  199. data/lib/badline/snapshot/vice/reu1764.rb +2 -2
  200. data/lib/badline/snapshot/vice.rb +7 -31
  201. data/lib/badline/snapshot.rb +43 -20
  202. data/lib/badline/storage/crt_file.rb +3 -1
  203. data/lib/badline/storage/g64_image.rb +8 -3
  204. data/lib/badline/storage/tap.rb +43 -15
  205. data/lib/badline/version.rb +1 -1
  206. data/lib/badline/vic20/attachments.rb +3 -0
  207. data/lib/badline/vic20/bus/keyed_state.rb +52 -0
  208. data/lib/badline/vic20/bus.rb +1 -2
  209. data/lib/badline/vic20/keyed_modules.rb +73 -0
  210. data/lib/badline/vic20/keyed_state.rb +45 -0
  211. data/lib/badline/vic20.rb +5 -5
  212. data/lib/badline.rb +1 -0
  213. metadata +61 -42
  214. data/lib/badline/c128/bus/saved_state.rb +0 -53
  215. data/lib/badline/c128/saved_state.rb +0 -117
  216. data/lib/badline/c64/bus/saved_state.rb +0 -68
  217. data/lib/badline/c64/cartridge/flash/saved_state.rb +0 -40
  218. data/lib/badline/c64/cartridge/retro_replay/saved_state.rb +0 -47
  219. data/lib/badline/c64/cartridge/saved_state.rb +0 -63
  220. data/lib/badline/c64/reu/dma/saved_state.rb +0 -52
  221. data/lib/badline/c64/reu/saved_state.rb +0 -55
  222. data/lib/badline/c64/saved_state.rb +0 -112
  223. data/lib/badline/chips/cia/saved_state.rb +0 -49
  224. data/lib/badline/chips/cia/serial/saved_state.rb +0 -45
  225. data/lib/badline/chips/cpu/saved_state.rb +0 -117
  226. data/lib/badline/chips/sid/envelope/saved_state.rb +0 -70
  227. data/lib/badline/chips/sid/filter/saved_state.rb +0 -42
  228. data/lib/badline/chips/sid/saved_state.rb +0 -52
  229. data/lib/badline/chips/sid/waveform/saved_state.rb +0 -68
  230. data/lib/badline/chips/vdc/saved_state.rb +0 -36
  231. data/lib/badline/chips/via/saved_state.rb +0 -44
  232. data/lib/badline/chips/vic/graphics_shifter/saved_state.rb +0 -40
  233. data/lib/badline/chips/vic/saved_state.rb +0 -82
  234. data/lib/badline/chips/vic/sequencer/saved_state.rb +0 -91
  235. data/lib/badline/chips/vic/sprite/saved_state.rb +0 -66
  236. data/lib/badline/chips/vic/sprites/saved_state.rb +0 -59
  237. data/lib/badline/chips/vic_i/painter/saved_state.rb +0 -40
  238. data/lib/badline/chips/vic_i/saved_state.rb +0 -55
  239. data/lib/badline/chips/z80/saved_state.rb +0 -71
  240. data/lib/badline/chrout_trap.rb +0 -43
  241. data/lib/badline/debug_register.rb +0 -28
  242. data/lib/badline/drives/datasette/saved_state.rb +0 -37
  243. data/lib/badline/drives/model1541/disk/saved_state.rb +0 -88
  244. data/lib/badline/drives/model1541/mechanism/saved_state.rb +0 -72
  245. data/lib/badline/drives/model1541/saved_state.rb +0 -44
  246. data/lib/badline/drives/model1571/saved_state.rb +0 -47
  247. data/lib/badline/drives/model1581/disk/saved_state.rb +0 -89
  248. data/lib/badline/drives/model1581/saved_state.rb +0 -42
  249. data/lib/badline/drives/model1581/wd1772/saved_state.rb +0 -68
  250. data/lib/badline/keyboard_buffer.rb +0 -33
  251. data/lib/badline/snapshot/setup.rb +0 -31
  252. data/lib/badline/snapshot/state.rb +0 -179
  253. data/lib/badline/vic20/bus/saved_state.rb +0 -35
  254. data/lib/badline/vic20/saved_state.rb +0 -110
@@ -1,117 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Chips
5
- class CPU
6
- # The CPU's state for a snapshot: the registers, the interrupt lines and
7
- # their pipeline, and the step of the instruction in flight, named by
8
- # where its plan comes from.
9
- module SavedState
10
- # Writes everything the CPU holds, down to the step of the instruction
11
- # it is in, for load_state to put back. The interrupt lines, BA stalls
12
- # and SO are state too; the traps and the debug flag belong to the host.
13
- def save_state(out)
14
- out.marker("CPU")
15
- out.int(@program_counter).int(@stack_pointer).int(@a).int(@x).int(@y).int(@status.value)
16
- [@irq, @nmi, @irq_sample, @irq_pending, @nmi_sample, @nmi_pending, @skip_poll, @boundary_irq,
17
- @boundary_nmi, @boundary_crossed, @brk, @pending_write, @so_high, @optional_dummy,
18
- @branch_taken].each { |flag| out.boolean(flag) }
19
- out.optional_int(@interrupt).optional_int(@stalled_at).int(@cycles).int(@instructions)
20
- out.int(plan_source).int(@index).int(OPERATIONS.index(@operation) || -1)
21
- [@address, @dummy_address, @value, @rmw_result, @pointer].each { |register| out.optional_int(register) }
22
- end
23
-
24
- def load_state(input)
25
- input.marker("CPU")
26
- @program_counter = input.int
27
- @stack_pointer = input.int
28
- @a = input.int
29
- @x = input.int
30
- @y = input.int
31
- @status.value = input.int
32
- load_flags(input)
33
- @interrupt = input.optional_int
34
- @stalled_at = input.optional_int
35
- @cycles = input.int
36
- @instructions = input.int
37
- load_plan(input.int)
38
- @index = input.int
39
- operation = input.int
40
- @operation = operation.negative? ? nil : OPERATIONS.fetch(operation)
41
- load_working_registers(input)
42
- end
43
-
44
- # Drops the instruction or interrupt sequence in flight and the
45
- # interrupt lines' pipeline, so the next cycle fetches an opcode at the
46
- # program counter, and sets the cycle count. A snapshot taken between
47
- # instructions, as VICE's are, restores through here.
48
- def resume(cycles)
49
- @irq_sample = @irq_pending = false
50
- @nmi_sample = @nmi_pending = false
51
- @skip_poll = false
52
- @interrupt = nil
53
- @brk = false
54
- @stalled_at = nil
55
- @cycles = cycles
56
- end_sequence
57
- @pending_write = false
58
- end
59
-
60
- private
61
-
62
- # Where the plan running comes from: an opcode's microcode, or FETCH,
63
- # INTERRUPT or JAMMED below it.
64
- def plan_source
65
- return FETCH if @plan.equal?(FETCH_PLAN)
66
- return INTERRUPT if @plan.equal?(INTERRUPT_PLAN)
67
- return JAMMED if @plan.equal?(JAMMED_PLAN)
68
-
69
- MICROCODE.index { |micro| micro.plan.equal?(@plan) && micro.operation == @operation } ||
70
- MICROCODE.index { |micro| micro.plan.equal?(@plan) }
71
- end
72
-
73
- def load_plan(source)
74
- case source
75
- when FETCH then use_plan(FETCH_PLAN, FETCH_WRITES)
76
- when INTERRUPT then use_plan(INTERRUPT_PLAN, INTERRUPT_WRITES)
77
- when JAMMED then use_plan(JAMMED_PLAN, JAMMED_WRITES)
78
- else
79
- micro = MICROCODE.fetch(source)
80
- use_plan(micro.plan, micro.writes)
81
- end
82
- end
83
-
84
- def use_plan(plan, writes)
85
- @plan = plan
86
- @writes = writes
87
- end
88
-
89
- def load_flags(input)
90
- @irq = input.boolean?
91
- @nmi = input.boolean?
92
- @irq_sample = input.boolean?
93
- @irq_pending = input.boolean?
94
- @nmi_sample = input.boolean?
95
- @nmi_pending = input.boolean?
96
- @skip_poll = input.boolean?
97
- @boundary_irq = input.boolean?
98
- @boundary_nmi = input.boolean?
99
- @boundary_crossed = input.boolean?
100
- @brk = input.boolean?
101
- @pending_write = input.boolean?
102
- @so_high = input.boolean?
103
- @optional_dummy = input.boolean?
104
- @branch_taken = input.boolean?
105
- end
106
-
107
- def load_working_registers(input)
108
- @address = input.optional_int
109
- @dummy_address = input.optional_int
110
- @value = input.optional_int
111
- @rmw_result = input.optional_int
112
- @pointer = input.optional_int
113
- end
114
- end
115
- end
116
- end
117
- end
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Chips
5
- class SID
6
- class Envelope
7
- # A snapshot of an envelope: its rates, the gate, the state and the
8
- # counters and pipelines between them, and the same fields as reSID
9
- # keeps them, for VICE's SIDEXTENDED module.
10
- module SavedState
11
- # The fields reSID keeps for an envelope between cycles: the rate and
12
- # exponential counters, the level, the state as an index into STATES,
13
- # whether it holds at zero, the two periods and the pipeline.
14
- def resid_fields
15
- [@rate_counter, @exponential_counter, @counter, STATES.index(@state).to_i, @hold_zero ? 1 : 0,
16
- @rate_period, @exponential_period, @envelope_pipeline]
17
- end
18
-
19
- # Takes the fields resid_fields gives from `fields`, from `at` on.
20
- def restore_resid_fields(fields, at)
21
- @rate_counter = fields[at]
22
- @exponential_counter = fields[at + 1]
23
- @counter = @env3 = fields[at + 2]
24
- state = fields[at + 3]
25
- @state = @next_state = STATES.fetch(state.clamp(0, STATES.length - 1)).to_sym
26
- @hold_zero = fields[at + 4] != 0
27
- @rate_period = fields[at + 5]
28
- @exponential_period = fields[at + 6]
29
- @envelope_pipeline = fields[at + 7]
30
- end
31
-
32
- def save_state(out)
33
- [@attack, @decay, @sustain, @release].each { |rate| out.int(rate) }
34
- out.boolean(@gate).int(STATES.index(@state)).int(STATES.index(@next_state))
35
- out.int(@counter).int(@env3).int(@rate_counter).int(@rate_period).boolean(@reset_rate_counter)
36
- out.int(@exponential_counter).int(@exponential_period)
37
- out.int(@state_pipeline).int(@envelope_pipeline).int(@exponential_pipeline).boolean(@hold_zero)
38
- end
39
-
40
- def load_state(input)
41
- @attack = input.int
42
- @decay = input.int
43
- @sustain = input.int
44
- @release = input.int
45
- @gate = input.boolean?
46
- @state = STATES.fetch(input.int).to_sym
47
- @next_state = STATES.fetch(input.int).to_sym
48
- load_counters(input)
49
- end
50
-
51
- private
52
-
53
- def load_counters(input)
54
- @counter = input.int
55
- @env3 = input.int
56
- @rate_counter = input.int
57
- @rate_period = input.int
58
- @reset_rate_counter = input.boolean?
59
- @exponential_counter = input.int
60
- @exponential_period = input.int
61
- @state_pipeline = input.int
62
- @envelope_pipeline = input.int
63
- @exponential_pipeline = input.int
64
- @hold_zero = input.boolean?
65
- end
66
- end
67
- end
68
- end
69
- end
70
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Chips
5
- class SID
6
- class Filter
7
- # The filter's state for a snapshot.
8
- module SavedState
9
- # The registers as the filter decoded them and its integrators. The
10
- # W0 table is the model's.
11
- def save_state(out)
12
- out.int(@cutoff).int(@routing).int(@mode).int(@volume).boolean(@voice3_off).int(@w0).int(@resonance)
13
- [@highpass, @bandpass, @lowpass, @unfiltered, @input].each { |value| out.int(value) }
14
- @external.save_state(out)
15
- end
16
-
17
- def load_state(input)
18
- @cutoff = input.int
19
- @routing = input.int
20
- @mode = input.int
21
- @volume = input.int
22
- @voice3_off = input.boolean?
23
- @w0 = input.int
24
- @resonance = input.int
25
- load_integrators(input)
26
- end
27
-
28
- private
29
-
30
- def load_integrators(input)
31
- @highpass = input.int
32
- @bandpass = input.int
33
- @lowpass = input.int
34
- @unfiltered = input.int
35
- @input = input.int
36
- @external.load_state(input)
37
- end
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Chips
5
- class SID
6
- # The SID's state for a snapshot.
7
- module SavedState
8
- # How far the recording has got into the sample it is averaging, for
9
- # a host that carries on recording from a saved state: it calls
10
- # #record, then #load_recording.
11
- def save_recording(out)
12
- decimator = @decimator
13
- raise ArgumentError, "the SID isn't recording" if decimator.nil?
14
-
15
- out.marker("RECORDING")
16
- decimator.save_state(out)
17
- end
18
-
19
- def load_recording(input)
20
- decimator = @decimator
21
- raise ArgumentError, "the SID isn't recording" if decimator.nil?
22
-
23
- input.marker("RECORDING")
24
- decimator.load_state(input)
25
- end
26
-
27
- # The registers, the data bus, the voices and the filter, and the span
28
- # the DSP has yet to catch up on, as it stands: saving leaves the SID
29
- # as it was. Whether it synthesizes or records is the host's.
30
- def save_state(out)
31
- out.marker("SID")
32
- @registers.save_state(out)
33
- out.int(@bus_value).int(@bus_ttl).int(@pending_cycles).ints(@deferred_writes)
34
- @voices.each { |voice| voice.save_state(out) }
35
- @filter.save_state(out)
36
- end
37
-
38
- def load_state(input)
39
- input.marker("SID")
40
- @registers.load_state(input)
41
- @bus_value = input.int
42
- @bus_ttl = input.int
43
- @pending_cycles = input.int
44
- input.ints_into(@deferred_writes)
45
- @voices.each { |voice| voice.load_state(input) }
46
- @filter.load_state(input)
47
- update_span_rules
48
- end
49
- end
50
- end
51
- end
52
- end
@@ -1,68 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Chips
5
- class SID
6
- class Waveform
7
- # A snapshot of an oscillator: its phase, the noise register and the
8
- # output latch, and the same fields as reSID keeps them, for VICE's
9
- # SIDEXTENDED module. The model's tables and the voices it syncs with
10
- # are the SID's wiring.
11
- module SavedState
12
- # The fields reSID keeps for an oscillator between cycles: the phase,
13
- # the noise register, its shift pipeline and reset countdown, the
14
- # floating output's countdown and the pulse level.
15
- def resid_fields
16
- [@accumulator, @shift_register, @shift_pipeline, @shift_register_reset, @floating_ttl, @pulse]
17
- end
18
-
19
- # Takes the fields resid_fields gives from `fields`, from `at` on.
20
- def restore_resid_fields(fields, at)
21
- @accumulator = fields[at]
22
- @shift_register = fields[at + 1]
23
- @shift_pipeline = fields[at + 2]
24
- @shift_register_reset = fields[at + 3]
25
- @floating_ttl = fields[at + 4]
26
- @pulse = fields[at + 5]
27
- @stale = true
28
- end
29
-
30
- def save_state(out)
31
- out.int(@accumulator).int(@delayed_triangle).int(@delayed_sawtooth)
32
- out.int(@shift_register).int(@shift_register_reset).int(@shift_pipeline)
33
- out.int(@frequency).int(@pulse_width).int(@selected)
34
- [@test, @ring, @sync, @msb_rising].each { |flag| out.boolean(flag) }
35
- out.int(@floating).int(@floating_ttl).int(@pulse).int(@output).boolean(@stale)
36
- end
37
-
38
- def load_state(input)
39
- @accumulator = input.int
40
- @delayed_triangle = input.int
41
- @delayed_sawtooth = input.int
42
- @shift_register = input.int
43
- @shift_register_reset = input.int
44
- @shift_pipeline = input.int
45
- @frequency = input.int
46
- @pulse_width = input.int
47
- @selected = input.int
48
- load_latches(input)
49
- end
50
-
51
- private
52
-
53
- def load_latches(input)
54
- @test = input.boolean?
55
- @ring = input.boolean?
56
- @sync = input.boolean?
57
- @msb_rising = input.boolean?
58
- @floating = input.int
59
- @floating_ttl = input.int
60
- @pulse = input.int
61
- @output = input.int
62
- @stale = input.boolean?
63
- end
64
- end
65
- end
66
- end
67
- end
68
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Chips
5
- class VDC
6
- # The VDC's state for a snapshot.
7
- module SavedState
8
- # Everything the VDC holds but its display, which it paints again
9
- # while it renders: the registers, the RAM, the data port and the
10
- # raster. Whether it renders is the host's.
11
- def save_state(out)
12
- out.marker("VDC")
13
- out.ints(@registers).blob(@memory.ram)
14
- out.int(@selected).int(@read_latch).int(@write_data).int(@busy_until).int(@phase).int(@line_units)
15
- @raster.save_state(out)
16
- @painter.save_state(out)
17
- end
18
-
19
- def load_state(input)
20
- input.marker("VDC")
21
- input.ints_into(@registers)
22
- input.blob_into(@memory.ram)
23
- @memory.mode64 = @registers[28].anybits?(0x10)
24
- @selected = input.int
25
- @read_latch = input.int
26
- @write_data = input.int
27
- @busy_until = input.int
28
- @phase = input.int
29
- @line_units = input.int
30
- @raster.load_state(input)
31
- @painter.load_state(input)
32
- end
33
- end
34
- end
35
- end
36
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Chips
5
- class VIA
6
- # Saving and restoring a VIA for a snapshot.
7
- module SavedState
8
- # The registers, the timers, the shift register, the interrupt flags
9
- # and the control lines. The peripheral is the drive's wiring.
10
- def save_state(out)
11
- out.int(@ora).int(@orb).int(@ddra).int(@ddrb).int(@latch_a).int(@latch_b).int(@acr).int(@pcr)
12
- out.boolean(@pb6_high).boolean(@sr_uses_t2)
13
- @t1.save_state(out)
14
- @t2.save_state(out)
15
- @shift_register.save_state(out)
16
- @ifr.save_state(out)
17
- @ca.save_state(out)
18
- @cb.save_state(out)
19
- end
20
-
21
- # Puts the state back without telling the peripheral, which restores
22
- # its own.
23
- def load_state(input)
24
- @ora = input.int
25
- @orb = input.int
26
- @ddra = input.int
27
- @ddrb = input.int
28
- @latch_a = input.int
29
- @latch_b = input.int
30
- @acr = input.int
31
- @pcr = input.int
32
- @pb6_high = input.boolean?
33
- @sr_uses_t2 = input.boolean?
34
- @t1.load_state(input)
35
- @t2.load_state(input)
36
- @shift_register.load_state(input)
37
- @ifr.load_state(input)
38
- @ca.load_state(input)
39
- @cb.load_state(input)
40
- end
41
- end
42
- end
43
- end
44
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Chips
5
- class VIC
6
- class GraphicsShifter
7
- # The shifter's state for a snapshot.
8
- module SavedState
9
- def save_state(out)
10
- out.int(@next_ecm_bmm).int(@black_below).ints(@colors).booleans(@fg)
11
- out.int(@gbuf).int(@vbuf).int(@cbuf).int(@flop).int(@pixel)
12
- out.int(@mode_lookup).int(@mode_read).boolean(@late_mcm).boolean(@late_read)
13
- end
14
-
15
- def load_state(input)
16
- @next_ecm_bmm = input.int
17
- @black_below = input.int
18
- input.ints_into(@colors)
19
- input.booleans_into(@fg)
20
- load_buffers(input)
21
- @mode_lookup = input.int
22
- @mode_read = input.int
23
- @late_mcm = input.boolean?
24
- @late_read = input.boolean?
25
- end
26
-
27
- private
28
-
29
- def load_buffers(input)
30
- @gbuf = input.int
31
- @vbuf = input.int
32
- @cbuf = input.int
33
- @flop = input.int
34
- @pixel = input.int
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Chips
5
- class VIC
6
- # The VIC's state for a snapshot.
7
- module SavedState
8
- # Everything the VIC holds between cycles: the beam, the fetch and
9
- # g-access pipeline, the light pen and raster latches, the finished
10
- # lines, on the VIC-IIe the display line and the TEST bit's wrap, the
11
- # registers and the display, sequencer and sprite logic.
12
- # Whether it renders is the host's, and every line comes back dirty so
13
- # a front end repaints.
14
- def save_state(out)
15
- out.marker("VIC")
16
- out.int(@column).int(@rasterline)
17
- out.int(@g_tick).ints(@g_kind).int(@g_kept_char).int(@g_kept_color).boolean(@g_display)
18
- out.int(@fetch_d011).boolean(@lp_triggered).boolean(@lp_low).boolean(@raster_match)
19
- out.int(@vic_bank.lines)
20
- out.blob(@character_buffer).blob(@color_buffer).booleans(@sprite_ba)
21
- @lines.each { |line| out.blob(line) }
22
- out.int(@output_line).boolean(@test_wrap) if @iie
23
- @registers.save_state(out)
24
- @display_state.save_state(out)
25
- @sequencer.save_state(out)
26
- @sprites.save_state(out)
27
- end
28
-
29
- def load_state(input)
30
- input.marker("VIC")
31
- load_beam(input)
32
- load_buffers(input)
33
- load_lines(input)
34
- load_test_state(input) if @iie
35
- @registers.load_state(input)
36
- @display_state.load_state(input)
37
- @sequencer.load_state(input)
38
- @sprites.load_state(input)
39
- end
40
-
41
- private
42
-
43
- def load_beam(input)
44
- @column = input.int
45
- @rasterline = @output_line = input.int
46
- @g_tick = input.int
47
- input.ints_into(@g_kind)
48
- @g_kept_char = input.int
49
- @g_kept_color = input.int
50
- @g_display = input.boolean?
51
- @fetch_d011 = input.int
52
- @lp_triggered = input.boolean?
53
- @lp_low = input.boolean?
54
- @raster_match = input.boolean?
55
- @vic_bank.lines = input.int
56
- end
57
-
58
- def load_buffers(input)
59
- input.blob_into(@character_buffer)
60
- input.blob_into(@color_buffer)
61
- input.booleans_into(@sprite_ba)
62
- end
63
-
64
- # The VIC-IIe's display line and TEST wrap, which only its TEST bit
65
- # moves off the raster line.
66
- def load_test_state(input)
67
- @output_line = input.int
68
- @test_wrap = input.boolean?
69
- end
70
-
71
- # The display is the finished lines one after another.
72
- def load_lines(input)
73
- @lines.each_with_index do |line, number|
74
- input.blob_into(line)
75
- @display[number * @width, @width] = line
76
- end
77
- @dirty_lines.fill(true)
78
- end
79
- end
80
- end
81
- end
82
- end
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Badline
4
- module Chips
5
- class VIC
6
- class Sequencer
7
- # The sequencer's save_state and load_state.
8
- module SavedState
9
- FG_SHIFTER = -1
10
- PAIR_CODES = 256
11
-
12
- # The line buffers, the border flip-flops, the g-access ring and the
13
- # pixel pipeline. The foreground masks the groups point at go as
14
- # FG_SHIFTER for the shift register's, or their data byte in
15
- # GraphicsMode's HIRES_FG, or that plus 256 in its PAIR_FG. The left
16
- # vertical border compare goes as -1 before it has run.
17
- def save_state(out)
18
- out.int(@line).boolean(@first_csel).int(@left_vertical_border.nil? ? -1 : bit(@left_vertical_border))
19
- out.blob(@colors).booleans(@fg)
20
- @border_mask.save_state(out)
21
- out.ints(@cur_colors).int(fg_code(@cur_fg)).ints(@prev_colors).int(fg_code(@prev_fg))
22
- out.boolean(@vertical_border).boolean(@vertical_armed).boolean(@main_border)
23
- @color_patches.save_state(out)
24
- @shifter.save_state(out)
25
- out.int(@xscroll).int(@last_shift).int(@last_mode).boolean(@settling).boolean(@prev_fresh).boolean(@check)
26
- out.ints(@ring_data).ints(@ring_char).ints(@ring_color)
27
- end
28
-
29
- def load_state(input)
30
- load_line(input)
31
- @border_mask.load_state(input)
32
- input.ints_into(@cur_colors)
33
- @cur_fg = fg_pattern(input.int)
34
- input.ints_into(@prev_colors)
35
- @prev_fg = fg_pattern(input.int)
36
- @vertical_border = input.boolean?
37
- @vertical_armed = input.boolean?
38
- @main_border = input.boolean?
39
- @color_patches.load_state(input)
40
- @shifter.load_state(input)
41
- load_pipeline(input)
42
- end
43
-
44
- private
45
-
46
- def bit(flag) = flag ? 1 : 0
47
-
48
- def load_line(input)
49
- @line = input.int
50
- @first_csel = input.boolean?
51
- left = input.int
52
- @left_vertical_border = left.negative? ? nil : left == 1
53
- input.blob_into(@colors)
54
- input.booleans_into(@fg)
55
- end
56
-
57
- def load_pipeline(input)
58
- @xscroll = input.int
59
- @last_shift = input.int
60
- @last_mode = input.int
61
- @settling = input.boolean?
62
- @prev_fresh = input.boolean?
63
- @check = input.boolean?
64
- input.ints_into(@ring_data)
65
- input.ints_into(@ring_char)
66
- input.ints_into(@ring_color)
67
- end
68
-
69
- def fg_code(pattern)
70
- return FG_SHIFTER if pattern.equal?(@shifter.fg)
71
-
72
- hires = GraphicsMode::HIRES_FG.index { |fg| fg.equal?(pattern) }
73
- return hires if hires
74
-
75
- pair = GraphicsMode::PAIR_FG.index { |fg| fg.equal?(pattern) }
76
- raise ArgumentError, "a foreground mask the sequencer doesn't know" unless pair
77
-
78
- PAIR_CODES + pair
79
- end
80
-
81
- def fg_pattern(code)
82
- return @shifter.fg if code == FG_SHIFTER
83
- return GraphicsMode::HIRES_FG.fetch(code) if code < PAIR_CODES
84
-
85
- GraphicsMode::PAIR_FG.fetch(code - PAIR_CODES)
86
- end
87
- end
88
- end
89
- end
90
- end
91
- end