badline 0.16.1 → 0.18.0

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