badline 0.5.1 → 0.6.1
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 +52 -0
- data/CLAUDE.md +10 -9
- data/README.md +82 -10
- data/doc/pinned-behaviour.md +131 -30
- data/exe/badline-ruby +20 -23
- data/lib/badline/address_bus/saved_state.rb +72 -0
- data/lib/badline/address_bus.rb +11 -1
- data/lib/badline/audio/cli.rb +18 -5
- data/lib/badline/audio/console.rb +2 -1
- data/lib/badline/audio.rb +0 -3
- data/lib/badline/cartridge/action_replay.rb +15 -0
- data/lib/badline/cartridge/comal80.rb +8 -0
- data/lib/badline/cartridge/dinamic.rb +8 -0
- data/lib/badline/cartridge/easy_flash.rb +20 -1
- data/lib/badline/cartridge/epyx_fastload.rb +8 -0
- data/lib/badline/cartridge/final_cartridge3.rb +12 -0
- data/lib/badline/cartridge/flash.rb +41 -0
- data/lib/badline/cartridge/fun_play.rb +8 -0
- data/lib/badline/cartridge/g_mod2.rb +12 -0
- data/lib/badline/cartridge/game_system.rb +8 -0
- data/lib/badline/cartridge/geo_ram.rb +16 -0
- data/lib/badline/cartridge/magic_desk.rb +8 -0
- data/lib/badline/cartridge/ocean.rb +8 -0
- data/lib/badline/cartridge/pagefox.rb +12 -0
- data/lib/badline/cartridge/retro_replay.rb +44 -1
- data/lib/badline/cartridge/rgcd.rb +10 -0
- data/lib/badline/cartridge/super_games.rb +10 -0
- data/lib/badline/cartridge/zaxxon.rb +16 -0
- data/lib/badline/cartridge.rb +72 -0
- data/lib/badline/cia/interrupt_register.rb +17 -0
- data/lib/badline/cia/serial.rb +44 -0
- data/lib/badline/cia/state.rb +47 -0
- data/lib/badline/cia/timer.rb +33 -0
- data/lib/badline/cia.rb +8 -0
- data/lib/badline/computer/attachments.rb +132 -0
- data/lib/badline/computer/saved_state.rb +116 -0
- data/lib/badline/computer.rb +13 -33
- data/lib/badline/cpu/boundary.rb +54 -0
- data/lib/badline/cpu/core.rb +165 -0
- data/lib/badline/cpu/microcode.rb +8 -0
- data/lib/badline/cpu/saved_state.rb +115 -0
- data/lib/badline/cpu.rb +3 -212
- data/lib/badline/datasette.rb +27 -0
- data/lib/badline/drive1541/bus.rb +13 -0
- data/lib/badline/drive1541/cpu.rb +29 -0
- data/lib/badline/drive1541/disk.rb +7 -2
- data/lib/badline/drive1541/disk_state.rb +80 -0
- data/lib/badline/drive1541/mechanism.rb +2 -0
- data/lib/badline/drive1541/mechanism_state.rb +67 -0
- data/lib/badline/drive1541/rotation.rb +10 -0
- data/lib/badline/drive1541/serial_port.rb +10 -0
- data/lib/badline/drive1541.rb +35 -0
- data/lib/badline/ffi.rb +157 -0
- data/lib/badline/frontend/app.rb +225 -0
- data/lib/badline/frontend/audio_sink.rb +72 -0
- data/lib/badline/frontend/boot.rb +52 -0
- data/lib/badline/frontend/controls.rb +163 -0
- data/lib/badline/frontend/drive_led.rb +51 -0
- data/lib/badline/frontend/frame_rate.rb +83 -0
- data/lib/badline/frontend/gamepads.rb +76 -0
- data/lib/badline/frontend/keys.rb +48 -0
- data/lib/badline/frontend/pacer.rb +100 -0
- data/lib/badline/frontend/pad_port.rb +61 -0
- data/lib/badline/frontend/screen.rb +65 -0
- data/lib/badline/frontend/screenshot.rb +22 -0
- data/lib/badline/frontend/snapshots.rb +60 -0
- data/lib/badline/frontend/sound.rb +153 -0
- data/lib/badline/frontend/timeline.rb +171 -0
- data/lib/badline/frontend.rb +18 -0
- data/lib/badline/kernal_trap/channel.rb +27 -0
- data/lib/badline/kernal_trap/drive/channels.rb +25 -0
- data/lib/badline/kernal_trap/drive/memory.rb +9 -0
- data/lib/badline/kernal_trap/drive/status.rb +8 -0
- data/lib/badline/kernal_trap/drive/write_file.rb +21 -0
- data/lib/badline/kernal_trap/drive.rb +19 -0
- data/lib/badline/kernal_trap/save.rb +8 -0
- data/lib/badline/kernal_trap/serial.rb +16 -0
- data/lib/badline/memory.rb +8 -0
- data/lib/badline/options/event.rb +94 -0
- data/lib/badline/options/help.rb +78 -0
- data/lib/badline/options/option.rb +29 -0
- data/lib/badline/options/table.rb +62 -0
- data/lib/badline/options.rb +181 -144
- data/lib/badline/ram_expansion/plus256k.rb +16 -0
- data/lib/badline/ram_expansion/plus60k.rb +12 -0
- data/lib/badline/ram_expansion/unexpanded.rb +6 -0
- data/lib/badline/reu/dma/saved_state.rb +50 -0
- data/lib/badline/reu/dma.rb +56 -11
- data/lib/badline/reu/ram.rb +15 -0
- data/lib/badline/reu/saved_state.rb +53 -0
- data/lib/badline/reu.rb +23 -10
- data/lib/badline/sdl.rb +123 -51
- data/lib/badline/sid/envelope/state.rb +68 -0
- data/lib/badline/sid/envelope.rb +7 -0
- data/lib/badline/sid/filter.rb +38 -0
- data/lib/badline/sid/voice.rb +10 -0
- data/lib/badline/sid/waveform/noise_writeback.rb +33 -11
- data/lib/badline/sid/waveform/state.rb +66 -0
- data/lib/badline/sid/waveform.rb +4 -3
- data/lib/badline/sid.rb +34 -0
- data/lib/badline/snapshot/container.rb +117 -0
- data/lib/badline/snapshot/fields.rb +54 -0
- data/lib/badline/snapshot/image.rb +70 -0
- data/lib/badline/snapshot/machine_state.rb +77 -0
- data/lib/badline/snapshot/setup.rb +58 -0
- data/lib/badline/snapshot/state.rb +178 -0
- data/lib/badline/snapshot/vice/c64_mem.rb +53 -0
- data/lib/badline/snapshot/vice/cias.rb +89 -0
- data/lib/badline/snapshot/vice/cias_import.rb +70 -0
- data/lib/badline/snapshot/vice/main_cpu.rb +76 -0
- data/lib/badline/snapshot/vice/peripherals.rb +47 -0
- data/lib/badline/snapshot/vice/restore.rb +125 -0
- data/lib/badline/snapshot/vice/sid_extended.rb +96 -0
- data/lib/badline/snapshot/vice/sid_registers.rb +46 -0
- data/lib/badline/snapshot/vice/vicii.rb +119 -0
- data/lib/badline/snapshot/vice/vicii_import.rb +131 -0
- data/lib/badline/snapshot/vice.rb +74 -0
- data/lib/badline/snapshot.rb +52 -0
- data/lib/badline/storage/crt_file.rb +9 -3
- data/lib/badline/storage/d64_image.rb +2 -0
- data/lib/badline/storage/d71_image.rb +2 -0
- data/lib/badline/storage/d81_image.rb +2 -0
- data/lib/badline/storage/disk_image.rb +11 -2
- data/lib/badline/storage/host_directory.rb +5 -0
- data/lib/badline/storage/t64.rb +6 -0
- data/lib/badline/storage/tap.rb +10 -1
- data/lib/badline/storage/unavailable.rb +20 -0
- data/lib/badline/storage.rb +34 -0
- data/lib/badline/time_of_day.rb +56 -0
- data/lib/badline/version.rb +1 -1
- data/lib/badline/via/control_lines.rb +15 -0
- data/lib/badline/via/interrupt_register.rb +9 -0
- data/lib/badline/via/shift_register.rb +13 -0
- data/lib/badline/via/state.rb +42 -0
- data/lib/badline/via/timer1.rb +13 -0
- data/lib/badline/via/timer2.rb +18 -0
- data/lib/badline/via.rb +2 -0
- data/lib/badline/vic/bank.rb +21 -0
- data/lib/badline/vic/border_mask.rb +10 -0
- data/lib/badline/vic/collisions.rb +11 -0
- data/lib/badline/vic/color_patches.rb +11 -0
- data/lib/badline/vic/display_state.rb +29 -1
- data/lib/badline/vic/graphics_shifter.rb +26 -0
- data/lib/badline/vic/register_log.rb +18 -0
- data/lib/badline/vic/registers.rb +13 -2
- data/lib/badline/vic/sequencer.rb +12 -0
- data/lib/badline/vic/sequencer_state.rb +89 -0
- data/lib/badline/vic/sprite/internal_bus.rb +11 -0
- data/lib/badline/vic/sprite/saved_state.rb +64 -0
- data/lib/badline/vic/sprite.rb +2 -0
- data/lib/badline/vic/sprites.rb +3 -0
- data/lib/badline/vic/sprites_state.rb +57 -0
- data/lib/badline/vic.rb +109 -16
- data/lib/badline.rb +1 -0
- metadata +59 -18
- data/.claude/hooks/session-start.sh +0 -57
- data/.claude/settings.json +0 -14
- data/lib/badline/audio/sdl_sink.rb +0 -70
- data/lib/badline/audio/stream.rb +0 -117
- data/lib/badline/gui/application.rb +0 -216
- data/lib/badline/gui/drive_led_pane.rb +0 -29
- data/lib/badline/gui/gamepads.rb +0 -97
- data/lib/badline/gui/joy_map.rb +0 -27
- data/lib/badline/gui/key_map.rb +0 -39
- data/lib/badline/gui/palette.rb +0 -35
- data/lib/badline/gui/pane.rb +0 -36
- data/lib/badline/gui/screen_pane.rb +0 -46
- data/lib/badline/gui/window.rb +0 -61
- data/lib/badline/gui.rb +0 -13
- data/lib/badline/sdl/events.rb +0 -47
- data/lib/badline/sdl/functions.rb +0 -74
- data/vendor/.gitkeep +0 -0
data/lib/badline/vic.rb
CHANGED
|
@@ -17,6 +17,10 @@ module Badline
|
|
|
17
17
|
attr_reader :address_bus, :display, :width, :height, :vic_bank, :column,
|
|
18
18
|
:rasterline, :dirty_lines, :model, :region
|
|
19
19
|
|
|
20
|
+
# The parts a VICE snapshot reads and sets.
|
|
21
|
+
attr_reader :registers, :display_state, :sequencer, :sprites, :character_buffer, :color_buffer,
|
|
22
|
+
:fetch_d011
|
|
23
|
+
|
|
20
24
|
# Returns the byte the CPU's halted read would see, for the c-accesses
|
|
21
25
|
# that run before AEC. Without it they read colour RAM.
|
|
22
26
|
attr_writer :open_bus
|
|
@@ -82,6 +86,7 @@ module Badline
|
|
|
82
86
|
@grey_dots = model == :mos8565
|
|
83
87
|
@delayed_fetch = model == :mos8565
|
|
84
88
|
@dma_delay_idle = model == :mos6569
|
|
89
|
+
@bank_swaps = model == :mos8565
|
|
85
90
|
@address_bus = address_bus || AddressBus.new
|
|
86
91
|
@vic_bank = VIC::Bank.new(@address_bus)
|
|
87
92
|
@debug = debug
|
|
@@ -139,6 +144,36 @@ module Badline
|
|
|
139
144
|
@raster_match = false
|
|
140
145
|
end
|
|
141
146
|
|
|
147
|
+
# Everything the VIC holds between cycles: the beam, the fetch and
|
|
148
|
+
# g-access pipeline, the light pen and raster latches, the finished
|
|
149
|
+
# lines, the registers and the display, sequencer and sprite logic.
|
|
150
|
+
# Whether it renders is the host's, and every line comes back dirty so
|
|
151
|
+
# a front end repaints.
|
|
152
|
+
def save_state(out)
|
|
153
|
+
out.marker("VIC")
|
|
154
|
+
out.int(@column).int(@rasterline).int(@cycles).boolean(@pending_write)
|
|
155
|
+
out.int(@g_tick).ints(@g_kind).int(@g_kept_char).int(@g_kept_color).boolean(@g_display)
|
|
156
|
+
out.int(@fetch_d011).boolean(@lp_triggered).boolean(@lp_low).boolean(@raster_match)
|
|
157
|
+
out.int(@vic_bank.lines)
|
|
158
|
+
out.blob(@character_buffer).blob(@color_buffer).booleans(@sprite_ba)
|
|
159
|
+
@lines.each { |line| out.blob(line) }
|
|
160
|
+
@registers.save_state(out)
|
|
161
|
+
@display_state.save_state(out)
|
|
162
|
+
@sequencer.save_state(out)
|
|
163
|
+
@sprites.save_state(out)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def load_state(input)
|
|
167
|
+
input.marker("VIC")
|
|
168
|
+
load_beam(input)
|
|
169
|
+
load_buffers(input)
|
|
170
|
+
load_lines(input)
|
|
171
|
+
@registers.load_state(input)
|
|
172
|
+
@display_state.load_state(input)
|
|
173
|
+
@sequencer.load_state(input)
|
|
174
|
+
@sprites.load_state(input)
|
|
175
|
+
end
|
|
176
|
+
|
|
142
177
|
def cycle!
|
|
143
178
|
start_line! if @column.zero?
|
|
144
179
|
|
|
@@ -227,14 +262,19 @@ module Badline
|
|
|
227
262
|
@column > DisplayState::DMA_FIRST && @column <= DisplayState::DMA_LAST + 1
|
|
228
263
|
end
|
|
229
264
|
|
|
230
|
-
#
|
|
231
|
-
#
|
|
232
|
-
#
|
|
265
|
+
# Whether this is the first cycle of sprite 0's BA window on the line
|
|
266
|
+
# whose raster matches its Y, where the sprite's DMA starts. An REU
|
|
267
|
+
# that moved a byte on the cycle before doesn't see BA fall here. Pinned by
|
|
233
268
|
# REU/bonzai/spritetiming.
|
|
234
|
-
def
|
|
235
|
-
|
|
269
|
+
def reu_ba_late?
|
|
270
|
+
@column == SPRITE_BA_FIRST + @sprite_shift && sprite_zero_starting?
|
|
271
|
+
end
|
|
236
272
|
|
|
237
|
-
|
|
273
|
+
# Whether BA passes straight from a bad line's window to sprite 0's on
|
|
274
|
+
# this cycle, the first of sprite 0's. An REU sees the bad line's DMA
|
|
275
|
+
# end here. Pinned by REU/reutiming2/e4-m2 and e6-m2.
|
|
276
|
+
def reu_ba_handed_on?
|
|
277
|
+
@column == DisplayState::DMA_LAST + 2 && @sprite_ba[@column] && @display_state.bad_line_condition?
|
|
238
278
|
end
|
|
239
279
|
|
|
240
280
|
# Light pen input level (CIA1 PB4). A falling edge triggers the latch.
|
|
@@ -288,6 +328,36 @@ module Badline
|
|
|
288
328
|
@sequencer.render = on
|
|
289
329
|
end
|
|
290
330
|
|
|
331
|
+
# Puts the beam at the start of `line`.
|
|
332
|
+
def restore_line(line)
|
|
333
|
+
@rasterline = line
|
|
334
|
+
@column = 0
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
# The latches a VICE snapshot holds: the raster match, the light pen's
|
|
338
|
+
# line held low and its trigger, as bits 0, 1 and 2.
|
|
339
|
+
def latch_bits = (@raster_match ? 1 : 0) | (@lp_low ? 2 : 0) | (@lp_triggered ? 4 : 0)
|
|
340
|
+
|
|
341
|
+
# Sets the latches from latch_bits, and the $D011 the next g-access
|
|
342
|
+
# holds.
|
|
343
|
+
def restore_latches(bits, fetch_d011)
|
|
344
|
+
@raster_match = bits.anybits?(1)
|
|
345
|
+
@lp_low = bits.anybits?(2)
|
|
346
|
+
@lp_triggered = bits.anybits?(4)
|
|
347
|
+
@fetch_d011 = fetch_d011
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
# Marks the columns BA is low for the sprites whose DMA runs.
|
|
351
|
+
def rebuild_sprite_ba
|
|
352
|
+
@sprite_ba.fill(false)
|
|
353
|
+
8.times do |n|
|
|
354
|
+
next unless @sprites[n].displaying?
|
|
355
|
+
|
|
356
|
+
@sprite_ba_tail[n].each { |c| @sprite_ba[c] = true }
|
|
357
|
+
@sprite_ba_head[n].each { |c| @sprite_ba[c] = true }
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
291
361
|
# Reset the dirty flags once the frontend has consumed them.
|
|
292
362
|
def clear_dirty_lines!
|
|
293
363
|
@dirty_lines.fill(false)
|
|
@@ -295,6 +365,38 @@ module Badline
|
|
|
295
365
|
|
|
296
366
|
private
|
|
297
367
|
|
|
368
|
+
def load_beam(input)
|
|
369
|
+
@column = input.int
|
|
370
|
+
@rasterline = input.int
|
|
371
|
+
@cycles = input.int
|
|
372
|
+
@pending_write = input.boolean?
|
|
373
|
+
@g_tick = input.int
|
|
374
|
+
input.ints_into(@g_kind)
|
|
375
|
+
@g_kept_char = input.int
|
|
376
|
+
@g_kept_color = input.int
|
|
377
|
+
@g_display = input.boolean?
|
|
378
|
+
@fetch_d011 = input.int
|
|
379
|
+
@lp_triggered = input.boolean?
|
|
380
|
+
@lp_low = input.boolean?
|
|
381
|
+
@raster_match = input.boolean?
|
|
382
|
+
@vic_bank.lines = input.int
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
def load_buffers(input)
|
|
386
|
+
input.blob_into(@character_buffer)
|
|
387
|
+
input.blob_into(@color_buffer)
|
|
388
|
+
input.booleans_into(@sprite_ba)
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
# The display is the finished lines one after another.
|
|
392
|
+
def load_lines(input)
|
|
393
|
+
@lines.each_with_index do |line, number|
|
|
394
|
+
input.blob_into(line)
|
|
395
|
+
@display[number * @width, @width] = line
|
|
396
|
+
end
|
|
397
|
+
@dirty_lines.fill(true)
|
|
398
|
+
end
|
|
399
|
+
|
|
298
400
|
# The raster counter as $D011/$D012 read it. Every line advances on the
|
|
299
401
|
# CPU cycle paired with column 62 except line 0, which the counter
|
|
300
402
|
# reaches a cycle later, together with the line 0 raster compare.
|
|
@@ -407,16 +509,6 @@ module Badline
|
|
|
407
509
|
@registers[0x15].anybits?(0x01) && @registers[0x01] == (@rasterline & 0xff)
|
|
408
510
|
end
|
|
409
511
|
|
|
410
|
-
def rebuild_sprite_ba
|
|
411
|
-
@sprite_ba.fill(false)
|
|
412
|
-
8.times do |n|
|
|
413
|
-
next unless @sprites[n].displaying?
|
|
414
|
-
|
|
415
|
-
@sprite_ba_tail[n].each { |c| @sprite_ba[c] = true }
|
|
416
|
-
@sprite_ba_head[n].each { |c| @sprite_ba[c] = true }
|
|
417
|
-
end
|
|
418
|
-
end
|
|
419
|
-
|
|
420
512
|
# Splits the sprite BA windows at the end of the line and marks the hook
|
|
421
513
|
# columns, for a line of the region's length: 14, 15, 53, 54 and 57, and
|
|
422
514
|
# the line's last column, which starts the vertical border for the line
|
|
@@ -452,6 +544,7 @@ module Badline
|
|
|
452
544
|
# on zero data with the screen byte and colour the last g-access
|
|
453
545
|
# latched, which an idle g-access clears.
|
|
454
546
|
def draw!
|
|
547
|
+
@vic_bank.sample_lines if @bank_swaps
|
|
455
548
|
slot = @g_tick = (@g_tick + 1) & 3
|
|
456
549
|
display_state = @display_state
|
|
457
550
|
access = display_state.graphics_column?(@column) && !@sequencer.vertical_closed?
|
data/lib/badline.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: badline
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Inge Jørgensen
|
|
@@ -34,8 +34,6 @@ executables:
|
|
|
34
34
|
extensions: []
|
|
35
35
|
extra_rdoc_files: []
|
|
36
36
|
files:
|
|
37
|
-
- ".claude/hooks/session-start.sh"
|
|
38
|
-
- ".claude/settings.json"
|
|
39
37
|
- CHANGELOG.md
|
|
40
38
|
- CLAUDE.md
|
|
41
39
|
- CODE_OF_CONDUCT.md
|
|
@@ -47,6 +45,7 @@ files:
|
|
|
47
45
|
- exe/badline-ruby
|
|
48
46
|
- lib/badline.rb
|
|
49
47
|
- lib/badline/address_bus.rb
|
|
48
|
+
- lib/badline/address_bus/saved_state.rb
|
|
50
49
|
- lib/badline/address_bus/ultimax_pages.rb
|
|
51
50
|
- lib/badline/addressable.rb
|
|
52
51
|
- lib/badline/audio.rb
|
|
@@ -59,8 +58,6 @@ files:
|
|
|
59
58
|
- lib/badline/audio/pcm_writer.rb
|
|
60
59
|
- lib/badline/audio/playback.rb
|
|
61
60
|
- lib/badline/audio/renderer.rb
|
|
62
|
-
- lib/badline/audio/sdl_sink.rb
|
|
63
|
-
- lib/badline/audio/stream.rb
|
|
64
61
|
- lib/badline/audio/terminal.rb
|
|
65
62
|
- lib/badline/audio/wav.rb
|
|
66
63
|
- lib/badline/cartridge.rb
|
|
@@ -96,41 +93,57 @@ files:
|
|
|
96
93
|
- lib/badline/cia.rb
|
|
97
94
|
- lib/badline/cia/interrupt_register.rb
|
|
98
95
|
- lib/badline/cia/serial.rb
|
|
96
|
+
- lib/badline/cia/state.rb
|
|
99
97
|
- lib/badline/cia/timer.rb
|
|
100
98
|
- lib/badline/color_memory.rb
|
|
101
99
|
- lib/badline/computer.rb
|
|
100
|
+
- lib/badline/computer/attachments.rb
|
|
101
|
+
- lib/badline/computer/saved_state.rb
|
|
102
102
|
- lib/badline/control_ports.rb
|
|
103
103
|
- lib/badline/cpu.rb
|
|
104
104
|
- lib/badline/cpu/addressing.rb
|
|
105
|
+
- lib/badline/cpu/boundary.rb
|
|
106
|
+
- lib/badline/cpu/core.rb
|
|
105
107
|
- lib/badline/cpu/microcode.rb
|
|
106
108
|
- lib/badline/cpu/operations.rb
|
|
109
|
+
- lib/badline/cpu/saved_state.rb
|
|
107
110
|
- lib/badline/cpu/stack_operations.rb
|
|
108
111
|
- lib/badline/cycleable.rb
|
|
109
112
|
- lib/badline/datasette.rb
|
|
110
113
|
- lib/badline/debug_register.rb
|
|
111
114
|
- lib/badline/drive1541.rb
|
|
112
115
|
- lib/badline/drive1541/bus.rb
|
|
116
|
+
- lib/badline/drive1541/cpu.rb
|
|
113
117
|
- lib/badline/drive1541/disk.rb
|
|
118
|
+
- lib/badline/drive1541/disk_state.rb
|
|
114
119
|
- lib/badline/drive1541/disk_via.rb
|
|
115
120
|
- lib/badline/drive1541/gcr.rb
|
|
116
121
|
- lib/badline/drive1541/idle.rb
|
|
117
122
|
- lib/badline/drive1541/mechanism.rb
|
|
123
|
+
- lib/badline/drive1541/mechanism_state.rb
|
|
118
124
|
- lib/badline/drive1541/orbit.rb
|
|
119
125
|
- lib/badline/drive1541/rotation.rb
|
|
120
126
|
- lib/badline/drive1541/sector_reader.rb
|
|
121
127
|
- lib/badline/drive1541/serial_port.rb
|
|
122
128
|
- lib/badline/drive1541/sleep.rb
|
|
123
129
|
- lib/badline/drive1541/track.rb
|
|
124
|
-
- lib/badline/
|
|
125
|
-
- lib/badline/
|
|
126
|
-
- lib/badline/
|
|
127
|
-
- lib/badline/
|
|
128
|
-
- lib/badline/
|
|
129
|
-
- lib/badline/
|
|
130
|
-
- lib/badline/
|
|
131
|
-
- lib/badline/
|
|
132
|
-
- lib/badline/
|
|
133
|
-
- lib/badline/
|
|
130
|
+
- lib/badline/ffi.rb
|
|
131
|
+
- lib/badline/frontend.rb
|
|
132
|
+
- lib/badline/frontend/app.rb
|
|
133
|
+
- lib/badline/frontend/audio_sink.rb
|
|
134
|
+
- lib/badline/frontend/boot.rb
|
|
135
|
+
- lib/badline/frontend/controls.rb
|
|
136
|
+
- lib/badline/frontend/drive_led.rb
|
|
137
|
+
- lib/badline/frontend/frame_rate.rb
|
|
138
|
+
- lib/badline/frontend/gamepads.rb
|
|
139
|
+
- lib/badline/frontend/keys.rb
|
|
140
|
+
- lib/badline/frontend/pacer.rb
|
|
141
|
+
- lib/badline/frontend/pad_port.rb
|
|
142
|
+
- lib/badline/frontend/screen.rb
|
|
143
|
+
- lib/badline/frontend/screenshot.rb
|
|
144
|
+
- lib/badline/frontend/snapshots.rb
|
|
145
|
+
- lib/badline/frontend/sound.rb
|
|
146
|
+
- lib/badline/frontend/timeline.rb
|
|
134
147
|
- lib/badline/iec_bus.rb
|
|
135
148
|
- lib/badline/input.rb
|
|
136
149
|
- lib/badline/input/mouse1351.rb
|
|
@@ -169,6 +182,10 @@ files:
|
|
|
169
182
|
- lib/badline/media/true_drive.rb
|
|
170
183
|
- lib/badline/memory.rb
|
|
171
184
|
- lib/badline/options.rb
|
|
185
|
+
- lib/badline/options/event.rb
|
|
186
|
+
- lib/badline/options/help.rb
|
|
187
|
+
- lib/badline/options/option.rb
|
|
188
|
+
- lib/badline/options/table.rb
|
|
172
189
|
- lib/badline/ram_expansion.rb
|
|
173
190
|
- lib/badline/ram_expansion/banking.rb
|
|
174
191
|
- lib/badline/ram_expansion/plus256k.rb
|
|
@@ -177,7 +194,9 @@ files:
|
|
|
177
194
|
- lib/badline/region.rb
|
|
178
195
|
- lib/badline/reu.rb
|
|
179
196
|
- lib/badline/reu/dma.rb
|
|
197
|
+
- lib/badline/reu/dma/saved_state.rb
|
|
180
198
|
- lib/badline/reu/ram.rb
|
|
199
|
+
- lib/badline/reu/saved_state.rb
|
|
181
200
|
- lib/badline/reu/trigger.rb
|
|
182
201
|
- lib/badline/rom.rb
|
|
183
202
|
- lib/badline/roms/README
|
|
@@ -189,18 +208,36 @@ files:
|
|
|
189
208
|
- lib/badline/roms/eapi/eapi-am29f040-14
|
|
190
209
|
- lib/badline/roms/kernal.rom
|
|
191
210
|
- lib/badline/sdl.rb
|
|
192
|
-
- lib/badline/sdl/events.rb
|
|
193
|
-
- lib/badline/sdl/functions.rb
|
|
194
211
|
- lib/badline/sid.rb
|
|
195
212
|
- lib/badline/sid/catch_up.rb
|
|
196
213
|
- lib/badline/sid/decimator.rb
|
|
197
214
|
- lib/badline/sid/envelope.rb
|
|
215
|
+
- lib/badline/sid/envelope/state.rb
|
|
198
216
|
- lib/badline/sid/filter.rb
|
|
199
217
|
- lib/badline/sid/voice.rb
|
|
200
218
|
- lib/badline/sid/waveform.rb
|
|
201
219
|
- lib/badline/sid/waveform/combined.rb
|
|
202
220
|
- lib/badline/sid/waveform/fast_forward.rb
|
|
203
221
|
- lib/badline/sid/waveform/noise_writeback.rb
|
|
222
|
+
- lib/badline/sid/waveform/state.rb
|
|
223
|
+
- lib/badline/snapshot.rb
|
|
224
|
+
- lib/badline/snapshot/container.rb
|
|
225
|
+
- lib/badline/snapshot/fields.rb
|
|
226
|
+
- lib/badline/snapshot/image.rb
|
|
227
|
+
- lib/badline/snapshot/machine_state.rb
|
|
228
|
+
- lib/badline/snapshot/setup.rb
|
|
229
|
+
- lib/badline/snapshot/state.rb
|
|
230
|
+
- lib/badline/snapshot/vice.rb
|
|
231
|
+
- lib/badline/snapshot/vice/c64_mem.rb
|
|
232
|
+
- lib/badline/snapshot/vice/cias.rb
|
|
233
|
+
- lib/badline/snapshot/vice/cias_import.rb
|
|
234
|
+
- lib/badline/snapshot/vice/main_cpu.rb
|
|
235
|
+
- lib/badline/snapshot/vice/peripherals.rb
|
|
236
|
+
- lib/badline/snapshot/vice/restore.rb
|
|
237
|
+
- lib/badline/snapshot/vice/sid_extended.rb
|
|
238
|
+
- lib/badline/snapshot/vice/sid_registers.rb
|
|
239
|
+
- lib/badline/snapshot/vice/vicii.rb
|
|
240
|
+
- lib/badline/snapshot/vice/vicii_import.rb
|
|
204
241
|
- lib/badline/status.rb
|
|
205
242
|
- lib/badline/storage.rb
|
|
206
243
|
- lib/badline/storage/crt_file.rb
|
|
@@ -220,6 +257,7 @@ files:
|
|
|
220
257
|
- lib/badline/storage/song_lengths.rb
|
|
221
258
|
- lib/badline/storage/t64.rb
|
|
222
259
|
- lib/badline/storage/tap.rb
|
|
260
|
+
- lib/badline/storage/unavailable.rb
|
|
223
261
|
- lib/badline/time_of_day.rb
|
|
224
262
|
- lib/badline/traps.rb
|
|
225
263
|
- lib/badline/version.rb
|
|
@@ -228,6 +266,7 @@ files:
|
|
|
228
266
|
- lib/badline/via/fast_forward.rb
|
|
229
267
|
- lib/badline/via/interrupt_register.rb
|
|
230
268
|
- lib/badline/via/shift_register.rb
|
|
269
|
+
- lib/badline/via/state.rb
|
|
231
270
|
- lib/badline/via/timer1.rb
|
|
232
271
|
- lib/badline/via/timer2.rb
|
|
233
272
|
- lib/badline/vic.rb
|
|
@@ -242,13 +281,15 @@ files:
|
|
|
242
281
|
- lib/badline/vic/registers.rb
|
|
243
282
|
- lib/badline/vic/sequencer.rb
|
|
244
283
|
- lib/badline/vic/sequencer_output.rb
|
|
284
|
+
- lib/badline/vic/sequencer_state.rb
|
|
245
285
|
- lib/badline/vic/sprite.rb
|
|
246
286
|
- lib/badline/vic/sprite/internal_bus.rb
|
|
287
|
+
- lib/badline/vic/sprite/saved_state.rb
|
|
247
288
|
- lib/badline/vic/sprite/shifter.rb
|
|
248
289
|
- lib/badline/vic/sprite/timing.rb
|
|
249
290
|
- lib/badline/vic/sprites.rb
|
|
291
|
+
- lib/badline/vic/sprites_state.rb
|
|
250
292
|
- packaging/homebrew/badline.rb
|
|
251
|
-
- vendor/.gitkeep
|
|
252
293
|
homepage: https://github.com/elektronaut/badline
|
|
253
294
|
licenses:
|
|
254
295
|
- MIT
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Prepares a Claude Code on the web container to run `bundle exec rubocop`
|
|
3
|
-
# and `bundle exec rspec`. The regression suites need vendor/ and aren't set
|
|
4
|
-
# up here.
|
|
5
|
-
set -euo pipefail
|
|
6
|
-
|
|
7
|
-
if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then
|
|
8
|
-
exit 0
|
|
9
|
-
fi
|
|
10
|
-
|
|
11
|
-
cd "${CLAUDE_PROJECT_DIR:-$(dirname "$0")/../..}"
|
|
12
|
-
|
|
13
|
-
# The SDL specs open libSDL2 through Fiddle, so only the runtime library is
|
|
14
|
-
# needed, as in CI.
|
|
15
|
-
if ! ldconfig -p | grep 'libSDL2-2\.0\.so\.0' >/dev/null; then
|
|
16
|
-
export DEBIAN_FRONTEND=noninteractive
|
|
17
|
-
apt-get update -qq
|
|
18
|
-
apt-get install -y -qq libsdl2-2.0-0 >/dev/null
|
|
19
|
-
fi
|
|
20
|
-
|
|
21
|
-
# The image ships Ruby 3.3 and an rbenv. Install the newest Ruby 4.0.x, as
|
|
22
|
-
# CI's ruby-version "4.0" picks, from the prebuilt binaries setup-ruby uses,
|
|
23
|
-
# unless a 4.0 is installed already.
|
|
24
|
-
export RBENV_ROOT=/opt/rbenv
|
|
25
|
-
export PATH="$RBENV_ROOT/bin:$RBENV_ROOT/shims:$PATH"
|
|
26
|
-
ruby_version=$(rbenv versions --bare | grep -E '^4\.0\.[0-9]+$' | sort -V | tail -1 || true)
|
|
27
|
-
if [ -z "$ruby_version" ]; then
|
|
28
|
-
ruby_version=$(curl -fsSL https://raw.githubusercontent.com/ruby/setup-ruby/master/ruby-builder-versions.json |
|
|
29
|
-
ruby -rjson -e 'puts JSON.parse($stdin.read)["ruby"].grep(/\A4\.0\.\d+\z/).max_by { Gem::Version.new(_1) }')
|
|
30
|
-
# The binaries only run from the prefix they were built with, so unpack
|
|
31
|
-
# there and link it into rbenv.
|
|
32
|
-
. /etc/os-release
|
|
33
|
-
prefix="/opt/hostedtoolcache/Ruby/$ruby_version/x64"
|
|
34
|
-
mkdir -p "$prefix"
|
|
35
|
-
if curl -fsSL "https://github.com/ruby/ruby-builder/releases/download/ruby-$ruby_version/ruby-$ruby_version-ubuntu-$VERSION_ID-x64.tar.gz" |
|
|
36
|
-
tar -xz -C "$prefix" --strip-components=1; then
|
|
37
|
-
ln -sfn "$prefix" "$RBENV_ROOT/versions/$ruby_version"
|
|
38
|
-
else
|
|
39
|
-
# No binary for this Ubuntu release: build from source, which takes minutes.
|
|
40
|
-
rm -rf "$prefix"
|
|
41
|
-
git -C "$RBENV_ROOT/plugins/ruby-build" pull --ff-only -q || true
|
|
42
|
-
MAKE_OPTS="-j$(nproc)" rbenv install --skip-existing "$ruby_version"
|
|
43
|
-
fi
|
|
44
|
-
fi
|
|
45
|
-
rbenv global "$ruby_version"
|
|
46
|
-
rbenv rehash
|
|
47
|
-
|
|
48
|
-
# Put rbenv's shims ahead of /usr/local/bin/ruby for the session.
|
|
49
|
-
if [ -n "${CLAUDE_ENV_FILE:-}" ]; then
|
|
50
|
-
{
|
|
51
|
-
echo "export RBENV_ROOT=$RBENV_ROOT"
|
|
52
|
-
echo "export PATH=\"$RBENV_ROOT/bin:$RBENV_ROOT/shims:\$PATH\""
|
|
53
|
-
} >> "$CLAUDE_ENV_FILE"
|
|
54
|
-
fi
|
|
55
|
-
|
|
56
|
-
# Bundler switches to the version Gemfile.lock was bundled with.
|
|
57
|
-
bundle install --jobs "$(nproc)"
|
data/.claude/settings.json
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
module Audio
|
|
5
|
-
# The host's audio device, fed through SDL's queue: mono signed 16-bit
|
|
6
|
-
# samples go in at the device's rate and SDL plays them out behind us.
|
|
7
|
-
class SDLSink
|
|
8
|
-
class Error < Playback::DeviceError; end
|
|
9
|
-
|
|
10
|
-
# int freq; Uint16 format; Uint8 channels, silence; Uint16 samples,
|
|
11
|
-
# padding; Uint32 size; then the callback and userdata pointers.
|
|
12
|
-
SPEC_LAYOUT = "lSCCSSLQQ"
|
|
13
|
-
|
|
14
|
-
attr_reader :rate
|
|
15
|
-
|
|
16
|
-
# With `exact_rate` false SDL may pick the device's own rate instead,
|
|
17
|
-
# which #rate then reports.
|
|
18
|
-
def initialize(rate:, exact_rate: false, buffer: 1024)
|
|
19
|
-
load_sdl
|
|
20
|
-
check(SDL::InitSubSystem.call(SDL::INIT_AUDIO))
|
|
21
|
-
@device = open_device(rate, exact_rate ? 0 : SDL::AUDIO_ALLOW_FREQUENCY_CHANGE, buffer)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def queue(samples)
|
|
25
|
-
data = samples.pack("s*")
|
|
26
|
-
check(SDL::QueueAudio.call(@device, data, data.bytesize))
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def queued_seconds = SDL::GetQueuedAudioSize.call(@device).fdiv(2 * rate)
|
|
30
|
-
|
|
31
|
-
def start = SDL::PauseAudioDevice.call(@device, 0)
|
|
32
|
-
|
|
33
|
-
def pause = SDL::PauseAudioDevice.call(@device, 1)
|
|
34
|
-
|
|
35
|
-
def clear = SDL::ClearQueuedAudio.call(@device)
|
|
36
|
-
|
|
37
|
-
def close
|
|
38
|
-
return unless @device
|
|
39
|
-
|
|
40
|
-
SDL::CloseAudioDevice.call(@device)
|
|
41
|
-
SDL::QuitSubSystem.call(SDL::INIT_AUDIO)
|
|
42
|
-
@device = nil
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
private
|
|
46
|
-
|
|
47
|
-
def open_device(rate, allowed_changes, buffer)
|
|
48
|
-
wanted = [rate, SDL::AUDIO_S16SYS, 1, 0, buffer, 0, 0, 0, 0].pack(SPEC_LAYOUT)
|
|
49
|
-
obtained = "\0".b * 32
|
|
50
|
-
device = SDL::OpenAudioDevice.call(nil, 0, wanted, obtained, allowed_changes)
|
|
51
|
-
raise Error, SDL.error if device.zero?
|
|
52
|
-
|
|
53
|
-
@rate = obtained.unpack1("l")
|
|
54
|
-
device
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def load_sdl
|
|
58
|
-
require "badline/sdl"
|
|
59
|
-
rescue SDL::Error => e
|
|
60
|
-
raise Error, e.message
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def check(result)
|
|
64
|
-
raise Error, SDL.error if result.negative?
|
|
65
|
-
|
|
66
|
-
result
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
data/lib/badline/audio/stream.rb
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Badline
|
|
4
|
-
module Audio
|
|
5
|
-
# Plays a running machine's SID through a sink, for the window: #feed
|
|
6
|
-
# queues whatever the SID recorded since the last call, once a frame,
|
|
7
|
-
# and #pace holds the machine to the device's clock.
|
|
8
|
-
#
|
|
9
|
-
# The device starts once the queue holds `ahead` seconds. Below real time
|
|
10
|
-
# the queue runs dry, and the device then stops until it holds `ahead`
|
|
11
|
-
# again, so the sound stutters with silent gaps rather than slowing
|
|
12
|
-
# down; `on_underrun` hears about the first time. A frame that would
|
|
13
|
-
# take the queue past `limit` seconds, as an unpaced machine above real
|
|
14
|
-
# time makes, is dropped whole.
|
|
15
|
-
class Stream
|
|
16
|
-
AHEAD = 0.08
|
|
17
|
-
LIMIT = 0.25
|
|
18
|
-
|
|
19
|
-
attr_reader :underruns, :dropped
|
|
20
|
-
|
|
21
|
-
# What #pace reads the time from and sleeps on: #now and #sleep.
|
|
22
|
-
attr_writer :clock
|
|
23
|
-
|
|
24
|
-
def initialize(sink, sid, ahead: AHEAD, limit: LIMIT, on_underrun: nil)
|
|
25
|
-
@sink = sink
|
|
26
|
-
@sid = sid
|
|
27
|
-
@ahead = ahead
|
|
28
|
-
@limit = limit
|
|
29
|
-
@on_underrun = on_underrun
|
|
30
|
-
@clock = Clock.new
|
|
31
|
-
@next_frame = nil
|
|
32
|
-
@started = false
|
|
33
|
-
@muted = false
|
|
34
|
-
@underruns = 0
|
|
35
|
-
@dropped = 0
|
|
36
|
-
sid.record(rate: sink.rate)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def rate = @sink.rate
|
|
40
|
-
|
|
41
|
-
def muted? = @muted
|
|
42
|
-
|
|
43
|
-
def playing? = @started
|
|
44
|
-
|
|
45
|
-
# Muting drops the queue; unmuting fills it to `ahead` again before
|
|
46
|
-
# the device restarts.
|
|
47
|
-
def toggle_mute
|
|
48
|
-
@muted = !@muted
|
|
49
|
-
return unless @muted
|
|
50
|
-
|
|
51
|
-
halt
|
|
52
|
-
@sink.clear
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def feed
|
|
56
|
-
samples = @sid.drain_samples
|
|
57
|
-
return if @muted || samples.empty?
|
|
58
|
-
|
|
59
|
-
queued = @sink.queued_seconds
|
|
60
|
-
return @dropped += samples.size if queued + samples.size.fdiv(rate) > @limit
|
|
61
|
-
|
|
62
|
-
underrun! if @started && queued.zero?
|
|
63
|
-
@sink.queue(samples)
|
|
64
|
-
start if @sink.queued_seconds >= @ahead
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Waits out the frame just run. While the device plays, that is until
|
|
68
|
-
# it has played the queue down to `ahead`, so the machine runs at the
|
|
69
|
-
# device's rate and the queue neither drifts dry nor grows. Muted or
|
|
70
|
-
# filling up, the clock paces frames `seconds` apart instead.
|
|
71
|
-
def pace(seconds)
|
|
72
|
-
return wait_for_device if playing?
|
|
73
|
-
|
|
74
|
-
now = @clock.now
|
|
75
|
-
@next_frame = now if @next_frame.nil? || @next_frame < now
|
|
76
|
-
@clock.sleep(@next_frame - now)
|
|
77
|
-
@next_frame += seconds
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def close = @sink.close
|
|
81
|
-
|
|
82
|
-
private
|
|
83
|
-
|
|
84
|
-
def start
|
|
85
|
-
return if @started
|
|
86
|
-
|
|
87
|
-
@started = true
|
|
88
|
-
@sink.start
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def wait_for_device
|
|
92
|
-
@next_frame = nil
|
|
93
|
-
while (excess = @sink.queued_seconds - @ahead).positive?
|
|
94
|
-
@clock.sleep([excess, 0.001].max)
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def halt
|
|
99
|
-
@started = false
|
|
100
|
-
@sink.pause
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def underrun!
|
|
104
|
-
@underruns += 1
|
|
105
|
-
@on_underrun&.call if @underruns == 1
|
|
106
|
-
halt
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# The host's monotonic clock.
|
|
110
|
-
class Clock
|
|
111
|
-
def now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
112
|
-
|
|
113
|
-
def sleep(seconds) = Kernel.sleep(seconds)
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|