badline 0.2.0 → 0.3.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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +67 -0
  3. data/CLAUDE.md +6 -0
  4. data/README.md +24 -6
  5. data/doc/pinned-behaviour.md +18 -6
  6. data/exe/badline +5 -2
  7. data/lib/badline/address_bus.rb +14 -6
  8. data/lib/badline/addressable.rb +1 -1
  9. data/lib/badline/audio/bare_player.rb +20 -3
  10. data/lib/badline/audio/machine_player.rb +9 -6
  11. data/lib/badline/audio/renderer.rb +3 -3
  12. data/lib/badline/audio/stream.rb +117 -0
  13. data/lib/badline/audio.rb +1 -0
  14. data/lib/badline/cartridge/easy_flash.rb +6 -2
  15. data/lib/badline/cartridge/epyx_fastload.rb +1 -1
  16. data/lib/badline/cartridge/mach5.rb +1 -1
  17. data/lib/badline/cartridge/magic_desk.rb +5 -1
  18. data/lib/badline/cartridge/ocean.rb +5 -2
  19. data/lib/badline/cartridge/rex_utility.rb +1 -1
  20. data/lib/badline/cartridge/rgcd.rb +1 -1
  21. data/lib/badline/cartridge/simons_basic.rb +2 -2
  22. data/lib/badline/cartridge/westermann.rb +2 -2
  23. data/lib/badline/cartridge.rb +16 -8
  24. data/lib/badline/checkpoint.rb +98 -0
  25. data/lib/badline/cia/interrupt_register.rb +20 -6
  26. data/lib/badline/cia.rb +36 -19
  27. data/lib/badline/color_memory.rb +2 -2
  28. data/lib/badline/computer.rb +41 -11
  29. data/lib/badline/cpu/microcode.rb +41 -43
  30. data/lib/badline/cpu.rb +3 -3
  31. data/lib/badline/gui/application.rb +41 -9
  32. data/lib/badline/kernal_trap/channel.rb +118 -8
  33. data/lib/badline/kernal_trap/drive/block_commands.rb +79 -0
  34. data/lib/badline/kernal_trap/drive/channels.rb +53 -0
  35. data/lib/badline/kernal_trap/drive/memory.rb +109 -0
  36. data/lib/badline/kernal_trap/drive/parameters.rb +28 -0
  37. data/lib/badline/kernal_trap/drive/status.rb +49 -0
  38. data/lib/badline/kernal_trap/drive.rb +148 -132
  39. data/lib/badline/kernal_trap/file.rb +0 -5
  40. data/lib/badline/kernal_trap/load.rb +93 -25
  41. data/lib/badline/kernal_trap/routine.rb +17 -0
  42. data/lib/badline/kernal_trap/save.rb +48 -15
  43. data/lib/badline/kernal_trap/serial.rb +34 -2
  44. data/lib/badline/media.rb +2 -2
  45. data/lib/badline/memory.rb +7 -2
  46. data/lib/badline/rom.rb +14 -5
  47. data/lib/badline/sid/catch_up.rb +110 -0
  48. data/lib/badline/sid/decimator.rb +6 -1
  49. data/lib/badline/sid/filter.rb +5 -5
  50. data/lib/badline/sid/waveform/fast_forward.rb +10 -10
  51. data/lib/badline/sid/waveform.rb +7 -7
  52. data/lib/badline/sid.rb +16 -92
  53. data/lib/badline/status.rb +255 -32
  54. data/lib/badline/storage/d64_image.rb +6 -0
  55. data/lib/badline/storage/d71_image.rb +4 -0
  56. data/lib/badline/storage/d81_image.rb +4 -0
  57. data/lib/badline/storage/disk_image.rb +78 -17
  58. data/lib/badline/storage/host_directory.rb +26 -2
  59. data/lib/badline/storage/sid_file.rb +37 -3
  60. data/lib/badline/storage.rb +3 -1
  61. data/lib/badline/time_of_day.rb +7 -0
  62. data/lib/badline/version.rb +1 -1
  63. data/lib/badline/vic/graphics_shifter.rb +8 -2
  64. data/lib/badline/vic/registers.rb +16 -27
  65. data/lib/badline/vic.rb +23 -10
  66. data/lib/badline.rb +1 -0
  67. metadata +9 -1
@@ -9,7 +9,8 @@ module Badline
9
9
  #
10
10
  # The byte a group draws loads at pixel XSCROLL. ECM and BMM take hold at
11
11
  # pixel 4 as they rise and at pixel 6 as they fall (the 6569's colour
12
- # latency). MCM takes hold at pixel 4 for the colour lookup but only at
12
+ # latency), except that BMM falls at pixel 5 out of any mode but hi-res
13
+ # bitmap. MCM takes hold at pixel 4 for the colour lookup but only at
13
14
  # pixel 7 for how the register is read, where a rising MCM also resets
14
15
  # the multicolour flip-flop. An MCM that falls out of the invalid
15
16
  # ECM+MCM mode is a pixel later on both counts: the lookup changes at
@@ -67,7 +68,7 @@ module Badline
67
68
  case pixel
68
69
  when 0 then end_late_read
69
70
  when 4 then step_lookup(mode)
70
- when 5 then @mode_lookup &= ~1 if @late_mcm
71
+ when 5 then step_early_fall(mode)
71
72
  when 6 then @mode_lookup &= mode | 1
72
73
  when 7 then step_read
73
74
  end
@@ -78,6 +79,11 @@ module Badline
78
79
  @mode_lookup = (@mode_lookup & ~1) | (mode & 1) | (@late_mcm ? 1 : 0) | (mode & ECM_BMM)
79
80
  end
80
81
 
82
+ def step_early_fall(mode)
83
+ @mode_lookup &= ~1 if @late_mcm
84
+ @mode_lookup &= mode | ~BMM unless @mode_lookup == BMM
85
+ end
86
+
81
87
  def step_read
82
88
  return @late_read = true if @late_mcm
83
89
 
@@ -53,21 +53,21 @@ module Badline
53
53
  #
54
54
  # All color registers are 4bit, bits 4-7 always read 1.
55
55
  #
56
- # $D020: Border color - Default: 14, light blue
57
- # $D021: Background color 0 - Default: 6, blue
58
- # $D022: Background color 1 - Default: 1, white
59
- # $D023: Background color 2 - Default: 2, red
60
- # $D024: Background color 3 - Default: 3, cyan
61
- # $D025: Sprite multicolor 0 - Default: 4, purple
62
- # $D026: Sprite multicolor 1 - Default: 0, black
63
- # $D027: Sprite 0 color - Default: 1, white
64
- # $D028: Sprite 1 color - Default: 2, red
65
- # $D029: Sprite 2 color - Default: 3, cyan
66
- # $D02A: Sprite 3 color - Default: 4, purple
67
- # $D02B: Sprite 4 color - Default: 5, green
68
- # $D02C: Sprite 5 color - Default: 6, blue
69
- # $D02D: Sprite 6 color - Default: 7, yellow
70
- # $D02E: Sprite 7 color - Default: 12, medium gray
56
+ # $D020: Border color
57
+ # $D021: Background color 0
58
+ # $D022: Background color 1
59
+ # $D023: Background color 2
60
+ # $D024: Background color 3
61
+ # $D025: Sprite multicolor 0
62
+ # $D026: Sprite multicolor 1
63
+ # $D027: Sprite 0 color
64
+ # $D028: Sprite 1 color
65
+ # $D029: Sprite 2 color
66
+ # $D02A: Sprite 3 color
67
+ # $D02B: Sprite 4 color
68
+ # $D02C: Sprite 5 color
69
+ # $D02D: Sprite 6 color
70
+ # $D02E: Sprite 7 color
71
71
  #
72
72
  # $D02F-$D03F: Not in use, always reads 0xff
73
73
  # $D040-$D3FF: Repeat $D0000 to $D03F every 64 bytes
@@ -77,10 +77,10 @@ module Badline
77
77
  # The raw register bytes, for the per-column reads on the hot path.
78
78
  attr_reader :bytes
79
79
 
80
+ # Every register powers on as zero, as in VICE.
80
81
  def initialize
81
82
  @bytes = Array.new(2**6, 0)
82
83
  @irq_line = false
83
- write_defaults
84
84
  end
85
85
 
86
86
  # True while any enabled latch bit is set in $D019/$D01A. Cached and
@@ -157,17 +157,6 @@ module Badline
157
157
  def read_clear(reg)
158
158
  @bytes[reg].tap { @bytes[reg] = 0 }
159
159
  end
160
-
161
- def write_defaults
162
- write_each(0x20, [14, 6, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 12])
163
- write_each(0x11, [0x1b, 0]) # $D011: DEN=1, RSEL=1, YSCROLL=3
164
- write_each(0x16, [0xc8]) # $D016: Text mode, XSCROLL=0
165
- write_each(0x19, [0, 0]) # IRQ flags
166
- end
167
-
168
- def write_each(addr, values)
169
- values.each_with_index { |v, i| @bytes[addr + i] = v }
170
- end
171
160
  end
172
161
  end
173
162
  end
data/lib/badline/vic.rb CHANGED
@@ -57,20 +57,33 @@ module Badline
57
57
 
58
58
  @width = 504
59
59
  @height = 312
60
+ @columns_per_line = @width / 8
61
+ @last_line = @height - 1
62
+ @display = Array.new(@width * @height, 0)
63
+ @lines = Array.new(@height) { Array.new(@width, 0) }
64
+ @dirty_lines = Array.new(@height, true)
65
+ @render = true
66
+
67
+ power_on!
68
+ super()
69
+ end
60
70
 
71
+ # The VIC has no reset pin, so only a power cycle brings back the
72
+ # registers, the raster position and the fetch and sprite state it
73
+ # starts with. The display keeps its buffers, cleared to black.
74
+ def power_on!
61
75
  @registers = VIC::Registers.new
62
76
  @register_bytes = @registers.bytes
63
77
  @display_state = VIC::DisplayState.new(@registers)
64
78
  @sequencer = VIC::Sequencer.new(@width, @registers, @vic_bank)
79
+ @sequencer.render = @render
65
80
  @sprites = VIC::Sprites.new(@registers, @vic_bank, @width)
66
- @display = Array.new(@width * @height, 0)
67
- @lines = Array.new(@height) { Array.new(@width, 0) }
68
- @dirty_lines = Array.new(@height, true)
81
+ @display.fill(0)
82
+ @lines.each { |line| line.fill(0) }
83
+ @dirty_lines.fill(true)
69
84
 
70
85
  @column = 0
71
86
  @rasterline = 0
72
- @columns_per_line = @width / 8
73
- @last_line = @height - 1
74
87
 
75
88
  @character_buffer = Array.new(40, 0)
76
89
  @color_buffer = Array.new(40, 0)
@@ -87,9 +100,6 @@ module Badline
87
100
  @lp_triggered = false
88
101
  @lp_low = false
89
102
  @raster_match = false
90
- @render = true
91
-
92
- super()
93
103
  end
94
104
 
95
105
  def cycle!
@@ -141,7 +151,7 @@ module Badline
141
151
  end
142
152
 
143
153
  def peek(addr)
144
- i = index(addr) % (2**6)
154
+ i = offset_of(addr) % (2**6)
145
155
  case i
146
156
  when 0x11 then (@registers[0x11] & 0x7f) | ((raster_counter & 0x100) >> 1)
147
157
  when 0x12 then raster_counter & 0xff
@@ -151,8 +161,11 @@ module Badline
151
161
  end.tap { |value| @sprites.bus_data(@column, value) }
152
162
  end
153
163
 
164
+ # The register file as stored, read without a bus access's side effects.
165
+ def register_file = Array.new(0x40) { |reg| @registers[reg] }
166
+
154
167
  def poke(addr, value)
155
- reg = index(addr) % (2**6)
168
+ reg = offset_of(addr) % (2**6)
156
169
  @sprites.bus_data(@column, value)
157
170
  log_register_change(reg, value)
158
171
  @registers.write(reg, value)
data/lib/badline.rb CHANGED
@@ -26,6 +26,7 @@ require "badline/cpu"
26
26
  require "badline/vic"
27
27
  require "badline/keyboard_buffer"
28
28
  require "badline/computer"
29
+ require "badline/checkpoint"
29
30
  require "badline/storage"
30
31
  require "badline/cartridge"
31
32
  require "badline/kernal_trap"
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.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Inge Jørgensen
@@ -73,6 +73,7 @@ files:
73
73
  - lib/badline/audio/playback.rb
74
74
  - lib/badline/audio/renderer.rb
75
75
  - lib/badline/audio/sdl_sink.rb
76
+ - lib/badline/audio/stream.rb
76
77
  - lib/badline/audio/wav.rb
77
78
  - lib/badline/cartridge.rb
78
79
  - lib/badline/cartridge/action_replay.rb
@@ -101,6 +102,7 @@ files:
101
102
  - lib/badline/cartridge/super_games.rb
102
103
  - lib/badline/cartridge/westermann.rb
103
104
  - lib/badline/cartridge/zaxxon.rb
105
+ - lib/badline/checkpoint.rb
104
106
  - lib/badline/chrout_trap.rb
105
107
  - lib/badline/cia.rb
106
108
  - lib/badline/cia/interrupt_register.rb
@@ -145,6 +147,11 @@ files:
145
147
  - lib/badline/kernal_trap.rb
146
148
  - lib/badline/kernal_trap/channel.rb
147
149
  - lib/badline/kernal_trap/drive.rb
150
+ - lib/badline/kernal_trap/drive/block_commands.rb
151
+ - lib/badline/kernal_trap/drive/channels.rb
152
+ - lib/badline/kernal_trap/drive/memory.rb
153
+ - lib/badline/kernal_trap/drive/parameters.rb
154
+ - lib/badline/kernal_trap/drive/status.rb
148
155
  - lib/badline/kernal_trap/file.rb
149
156
  - lib/badline/kernal_trap/load.rb
150
157
  - lib/badline/kernal_trap/routine.rb
@@ -163,6 +170,7 @@ files:
163
170
  - lib/badline/roms/eapi/eapi-am29f040-14
164
171
  - lib/badline/roms/kernal.rom
165
172
  - lib/badline/sid.rb
173
+ - lib/badline/sid/catch_up.rb
166
174
  - lib/badline/sid/decimator.rb
167
175
  - lib/badline/sid/envelope.rb
168
176
  - lib/badline/sid/filter.rb