badline 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.claude/hooks/session-start.sh +57 -0
- data/.claude/settings.json +14 -0
- data/CHANGELOG.md +107 -0
- data/CLAUDE.md +51 -16
- data/CONTRIBUTING.md +95 -3
- data/README.md +119 -51
- data/SECURITY.md +9 -0
- data/doc/pinned-behaviour.md +293 -39
- data/exe/badline-ruby +59 -0
- data/lib/badline/address_bus.rb +28 -14
- data/lib/badline/addressable.rb +1 -1
- data/lib/badline/audio/aiff.rb +8 -3
- data/lib/badline/audio/bare_player.rb +20 -3
- data/lib/badline/audio/cli.rb +17 -12
- data/lib/badline/audio/console.rb +12 -58
- data/lib/badline/audio/machine_player.rb +9 -6
- data/lib/badline/audio/playback.rb +3 -0
- data/lib/badline/audio/renderer.rb +3 -3
- data/lib/badline/audio/sdl_sink.rb +20 -52
- data/lib/badline/audio/stream.rb +117 -0
- data/lib/badline/audio/terminal.rb +90 -0
- data/lib/badline/audio.rb +3 -2
- data/lib/badline/cartridge/easy_flash.rb +6 -2
- data/lib/badline/cartridge/epyx_fastload.rb +1 -1
- data/lib/badline/cartridge/geo_ram.rb +63 -0
- data/lib/badline/cartridge/mach5.rb +1 -1
- data/lib/badline/cartridge/magic_desk.rb +5 -1
- data/lib/badline/cartridge/ocean.rb +5 -2
- data/lib/badline/cartridge/rex_utility.rb +1 -1
- data/lib/badline/cartridge/rgcd.rb +1 -1
- data/lib/badline/cartridge/simons_basic.rb +2 -2
- data/lib/badline/cartridge/westermann.rb +2 -2
- data/lib/badline/cartridge.rb +9 -0
- data/lib/badline/checkpoint.rb +98 -0
- data/lib/badline/cia/interrupt_register.rb +34 -10
- data/lib/badline/cia.rb +19 -10
- data/lib/badline/color_memory.rb +2 -2
- data/lib/badline/computer.rb +34 -14
- data/lib/badline/cpu.rb +2 -2
- data/lib/badline/gui/application.rb +70 -26
- data/lib/badline/gui/gamepads.rb +22 -22
- data/lib/badline/gui/joy_map.rb +1 -1
- data/lib/badline/gui/key_map.rb +6 -1
- data/lib/badline/gui/pane.rb +7 -6
- data/lib/badline/gui/screen_pane.rb +9 -13
- data/lib/badline/gui/window.rb +35 -20
- data/lib/badline/gui.rb +1 -1
- data/lib/badline/input/mouse1351.rb +21 -6
- data/lib/badline/input/paddles.rb +11 -6
- data/lib/badline/kernal_trap/channel.rb +102 -7
- data/lib/badline/kernal_trap/drive/block_commands.rb +108 -0
- data/lib/badline/kernal_trap/drive/channels.rb +53 -0
- data/lib/badline/kernal_trap/drive/memory.rb +109 -0
- data/lib/badline/kernal_trap/drive/parameters.rb +28 -0
- data/lib/badline/kernal_trap/drive/status.rb +3 -0
- data/lib/badline/kernal_trap/drive/write_file.rb +41 -0
- data/lib/badline/kernal_trap/drive/writes.rb +92 -0
- data/lib/badline/kernal_trap/drive.rb +109 -131
- data/lib/badline/kernal_trap/file.rb +6 -14
- data/lib/badline/kernal_trap/load.rb +6 -0
- data/lib/badline/kernal_trap/save.rb +13 -7
- data/lib/badline/keyboard.rb +19 -3
- data/lib/badline/media.rb +44 -13
- data/lib/badline/memory.rb +2 -2
- data/lib/badline/options.rb +209 -0
- data/lib/badline/ram_expansion/banking.rb +30 -0
- data/lib/badline/ram_expansion/plus256k.rb +38 -0
- data/lib/badline/ram_expansion/plus60k.rb +31 -0
- data/lib/badline/ram_expansion/unexpanded.rb +22 -0
- data/lib/badline/ram_expansion.rb +21 -0
- data/lib/badline/region.rb +51 -0
- data/lib/badline/rom.rb +14 -5
- data/lib/badline/sdl/events.rb +47 -0
- data/lib/badline/sdl/functions.rb +73 -0
- data/lib/badline/sdl.rb +67 -0
- data/lib/badline/sid/catch_up.rb +110 -0
- data/lib/badline/sid/decimator.rb +6 -1
- data/lib/badline/sid/filter.rb +5 -5
- data/lib/badline/sid/waveform/fast_forward.rb +10 -10
- data/lib/badline/sid/waveform/noise_writeback.rb +32 -14
- data/lib/badline/sid/waveform.rb +8 -8
- data/lib/badline/sid.rb +19 -93
- data/lib/badline/storage/d64_image.rb +10 -0
- data/lib/badline/storage/d71_image.rb +12 -0
- data/lib/badline/storage/d81_image.rb +9 -0
- data/lib/badline/storage/disk_image/bam.rb +111 -0
- data/lib/badline/storage/disk_image/directory.rb +79 -0
- data/lib/badline/storage/disk_image/writing.rb +110 -0
- data/lib/badline/storage/disk_image.rb +49 -4
- data/lib/badline/storage/host_directory.rb +17 -4
- data/lib/badline/storage/sid_file.rb +36 -2
- data/lib/badline/storage.rb +18 -1
- data/lib/badline/time_of_day.rb +11 -2
- data/lib/badline/version.rb +1 -1
- data/lib/badline/via/control_lines.rb +104 -0
- data/lib/badline/via/interrupt_register.rb +58 -0
- data/lib/badline/via/shift_register.rb +135 -0
- data/lib/badline/via/timer1.rb +82 -0
- data/lib/badline/via/timer2.rb +84 -0
- data/lib/badline/via.rb +262 -0
- data/lib/badline/vic/bank.rb +4 -3
- data/lib/badline/vic/color_patches.rb +6 -3
- data/lib/badline/vic/display_state.rb +4 -0
- data/lib/badline/vic/graphics_shifter.rb +49 -8
- data/lib/badline/vic/registers.rb +19 -27
- data/lib/badline/vic/sequencer.rb +18 -18
- data/lib/badline/vic/sequencer_output.rb +4 -4
- data/lib/badline/vic/sprite/internal_bus.rb +4 -0
- data/lib/badline/vic/sprite/shifter.rb +25 -3
- data/lib/badline/vic/sprite.rb +5 -4
- data/lib/badline/vic/sprites.rb +8 -3
- data/lib/badline/vic.rb +98 -46
- data/lib/badline.rb +5 -0
- data/packaging/homebrew/badline.rb +34 -0
- metadata +37 -20
- data/exe/badline +0 -75
- data/exe/badline-sid +0 -34
- data/lib/badline/audio/options.rb +0 -137
data/doc/pinned-behaviour.md
CHANGED
|
@@ -24,7 +24,9 @@ only catches the rows that happen to move.
|
|
|
24
24
|
- [VIC graphics pipeline](#vic-graphics-pipeline)
|
|
25
25
|
- [VIC phi1 bus](#vic-phi1-bus)
|
|
26
26
|
- [VIC light pen](#vic-light-pen)
|
|
27
|
+
- [VIC-II 8565](#vic-ii-8565)
|
|
27
28
|
- [CIA 6526 timer pipeline](#cia-6526-timer-pipeline)
|
|
29
|
+
- [CIA 6526A interrupt register](#cia-6526a-interrupt-register)
|
|
28
30
|
- [CIA serial shift register](#cia-serial-shift-register)
|
|
29
31
|
- [6510 I/O port](#6510-io-port)
|
|
30
32
|
- [SID oscillator](#sid-oscillator)
|
|
@@ -400,6 +402,14 @@ only catches the rows that happen to move.
|
|
|
400
402
|
- Spec guard: *#collide_upto* in
|
|
401
403
|
[`vic/sprites_spec.rb`](../spec/badline/vic/sprites_spec.rb). Its first
|
|
402
404
|
four examples each fail on a one-pixel change.
|
|
405
|
+
- $D01E and $D01F are read-only. A write, including the write-back of a
|
|
406
|
+
read-modify-write such as `LSR $D01E`, changes neither register.
|
|
407
|
+
- Pinned by `general/fuxxortest/ef2-inst4a`, which shifts each frame's
|
|
408
|
+
collision out of $D01E with `LSR`. Storing the shifted value back
|
|
409
|
+
leaves bit 0 set for the next frame, which reads as a collision one
|
|
410
|
+
pixel to the right of every real one.
|
|
411
|
+
- Spec guard: *with a collision register* in
|
|
412
|
+
[`vic/registers_spec.rb`](../spec/badline/vic/registers_spec.rb).
|
|
403
413
|
|
|
404
414
|
## VIC border and idle state
|
|
405
415
|
|
|
@@ -576,6 +586,31 @@ only catches the rows that happen to move.
|
|
|
576
586
|
cells take their colour from the halted opcode.
|
|
577
587
|
- Spec guard: *an FLI match in column 13* in
|
|
578
588
|
[`vic_spec.rb`](../spec/badline/vic_spec.rb).
|
|
589
|
+
- On the 6569, a match that opens display state in a g-access column, which
|
|
590
|
+
is a DMA delay out of idle state, moves that column's idle g-access from
|
|
591
|
+
`$3fff` (or `$39ff`) to `$38ff`, but only when YSCROLL is nonzero, so
|
|
592
|
+
only when the trigger line's low three bits are nonzero. The address wins over
|
|
593
|
+
ECM's `$39ff`. Nothing else enters the condition: not the column, BMM,
|
|
594
|
+
RC, VC or the previous fetch. The column is the one just before the
|
|
595
|
+
first display-state g-access. This rule is empirical and fitted to the
|
|
596
|
+
two tests below. It is the same condition the Denise emulator converged
|
|
597
|
+
on, and no hardware explanation for the YSCROLL gate is known. The
|
|
598
|
+
readme lists `$38ff` for every 6569 it measured. Among 8565s it lists
|
|
599
|
+
`$3807`, `$38c7`, `$38d7` and `$38ff`, varying from chip to chip, and no
|
|
600
|
+
testbench row pins one, so the 8565 keeps `$3fff` there.
|
|
601
|
+
`VIC::DMA_DELAY_IDLE_ADDRESS` holds the 6569's address.
|
|
602
|
+
- Pinned by `vsp-tester`, which triggers on raster `$32` with YSCROLL 2
|
|
603
|
+
and reads the address back through sprite collisions. It passes on
|
|
604
|
+
`$38ff`, `$3807`, `$38c7` or `$38d7`, and reports `$3fff` (exit `$ff`)
|
|
605
|
+
without this rule.
|
|
606
|
+
- Pinned by `colorfetchbug/main`, whose only idle trigger is on raster
|
|
607
|
+
`$30` with YSCROLL 0 and whose reference shows `$3fff` there. Without
|
|
608
|
+
the YSCROLL gate it fails by 7 px. `sequencer-bug` (YSCROLL 3) reads
|
|
609
|
+
`$38ff` and passes either way.
|
|
610
|
+
- Spec guard: *reads the idle byte at $38ff when YSCROLL is nonzero* and
|
|
611
|
+
*reads the idle byte at $3fff when YSCROLL is 0*, plus the 8565's
|
|
612
|
+
*reads the idle byte at $3fff when YSCROLL is nonzero*, in
|
|
613
|
+
[`vic_spec.rb`](../spec/badline/vic_spec.rb).
|
|
579
614
|
- These rows can't be read as pixel counts. The sweep became readable by
|
|
580
615
|
OCRing each reference PNG against `lib/badline/roms/character.rom` and
|
|
581
616
|
matching every display row back to its offset in screen memory, so a diff
|
|
@@ -650,12 +685,24 @@ VICE x64sc's `vicii_fetch_graphics` and `draw_graphics8` for the 6569.
|
|
|
650
685
|
- Pinned by `modesplit` (48 → 1222 px painting whole groups, 428 with
|
|
651
686
|
MCM read at pixel 4), the `videomode` rows and `vicii_reg_timing`
|
|
652
687
|
(pass → 274).
|
|
653
|
-
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
688
|
+
- A falling BMM shows at pixel 5 instead of 6 unless it leaves hi-res
|
|
689
|
+
bitmap: out of multicolour bitmap, and out of the invalid ECM+BMM
|
|
690
|
+
modes, whether ECM falls with it or stays.
|
|
691
|
+
- Pinned by `modesplit` (48 px → pass), whose first section drops BMM
|
|
692
|
+
out of ECM+BMM, by the E+B row of `vicii_reg_timing-a5` and `-ff`
|
|
693
|
+
(7 px each → pass), which drops ECM and BMM together, and by
|
|
694
|
+
`videomode-y` (1 px → pass), which drops it out of multicolour
|
|
695
|
+
bitmap. The hi-res exception is pinned by `videomode2` and the BMM
|
|
696
|
+
row of `vicii_reg_timing` (pass → 1 and 7 px without it).
|
|
697
|
+
- Two references disagree, and both are marked unsafe in the
|
|
698
|
+
testlist: `videomode-v` drops BMM out of multicolour bitmap and
|
|
699
|
+
`videomode-w` out of ECM+BMM, and both want pixel 6 (+1 px each).
|
|
700
|
+
The readme says these delays vary with the chip and its
|
|
701
|
+
temperature.
|
|
702
|
+
- Spec guard: *takes a BMM falling out of hi-res bitmap at pixel 6*,
|
|
703
|
+
*out of ECM+BMM at pixel 5* and *out of multicolour bitmap at
|
|
704
|
+
pixel 5* in
|
|
705
|
+
[`vic/graphics_shifter_spec.rb`](../spec/badline/vic/graphics_shifter_spec.rb).
|
|
659
706
|
- An MCM that falls out of the invalid ECM+MCM text mode is a pixel
|
|
660
707
|
later on both counts. The lookup stays black through pixel 4 and
|
|
661
708
|
changes at pixel 5, and the pairs are read through pixel 7, with
|
|
@@ -722,12 +769,125 @@ VICE x64sc's `vicii_fetch_graphics` and `draw_graphics8` for the 6569.
|
|
|
722
769
|
reference, as `makeref` corrects it: the test fixes up the tail bytes of
|
|
723
770
|
pre-R03 dumps before comparing. All five pages match, the raster-read
|
|
724
771
|
pages included (see [VIC raster IRQ phase](#vic-raster-irq-phase)).
|
|
725
|
-
- The 6569's offset is 2 half-pixels and the 8565's is 1
|
|
726
|
-
|
|
727
|
-
badline models only the 6569, and `bin/testbench` skips `vicii-new` rows.
|
|
772
|
+
- The 6569's offset is 2 half-pixels and the 8565's is 1 (see
|
|
773
|
+
[VIC-II 8565](#vic-ii-8565)).
|
|
728
774
|
- Pinned by `lplatency`, `lp-trigger`, and the `fldscroll` tests, which sync
|
|
729
775
|
through the light pen instead of the double IRQ.
|
|
730
776
|
|
|
777
|
+
## VIC-II 8565
|
|
778
|
+
|
|
779
|
+
The 8565 (`VIC.new(model: :mos8565)`, `Computer.new(vic_model:
|
|
780
|
+
:mos8565)`), fitted to the C64C, runs every rule above except the ones
|
|
781
|
+
below. They follow VICE x64sc's model checks (`color_latency` clear), and
|
|
782
|
+
each is gated on the model and was knocked out: removing it fails the rows
|
|
783
|
+
named, all in `testbench-vicii-new`, and moves no 6569 row. Pixel counts
|
|
784
|
+
are the row's diff with the rule removed.
|
|
785
|
+
|
|
786
|
+
- **Grey dots.** Where the 6569 still shows a colour register's old value
|
|
787
|
+
on the first pixel after a write, the 8565 shows light grey
|
|
788
|
+
(`VIC::GREY_DOT`, `$f`), for the border, the background registers
|
|
789
|
+
(`VIC::ColorPatches`) and the sprite colours (`VIC#log_sprite_change`).
|
|
790
|
+
A write that leaves the value as it was shows its dot too.
|
|
791
|
+
- The background and border dot is pinned by `rmwtest` (1655 px), every
|
|
792
|
+
spritesplit row whose `$d021` staircase it crosses (60 px each) and
|
|
793
|
+
`vicii_reg_timing` (275 px, 282/289 for `-a5`/`-ff`). The sprite dot
|
|
794
|
+
by `ss-hires-color` and `ss-mc-color0`/`1`/`2` (44 px each) and
|
|
795
|
+
`vicii_reg_timing` (136 px). The same-value dot by `rmwtest` (775 px)
|
|
796
|
+
and `vicii_reg_timing` (22 px), whose read-modify-write instructions
|
|
797
|
+
store each value twice.
|
|
798
|
+
- Spec guard: the *on the 8565* group in
|
|
799
|
+
[`color_patches_spec.rb`](../spec/badline/vic/color_patches_spec.rb),
|
|
800
|
+
*shows a grey dot on the pixel before a new sprite color* in
|
|
801
|
+
[`sprites_spec.rb`](../spec/badline/vic/sprites_spec.rb) and *shows a
|
|
802
|
+
grey dot for a background write of the same color* in
|
|
803
|
+
[`vic_spec.rb`](../spec/badline/vic_spec.rb).
|
|
804
|
+
- **Sprite multicolour.** `$d01c` reaches the sprite sequencers a pixel
|
|
805
|
+
sooner, 6 pixels on instead of 7, and works on the multicolour
|
|
806
|
+
flip-flop (VICE `update_sprite_mc_bits_8565`). The X match leaves the
|
|
807
|
+
flip-flop set in hi-res as well as clear after the first multicolour
|
|
808
|
+
pixel. A change flips it only when it lands between the two halves of
|
|
809
|
+
an expanded pixel, where a switch to hi-res sets it instead. A hi-res
|
|
810
|
+
pixel with the flip-flop clear sets it and loads nothing, so the latch
|
|
811
|
+
holds its last pixel.
|
|
812
|
+
- The delay is pinned by `ss-hires-mc`, `ss-mc-hires` and their `-exp`
|
|
813
|
+
twins (528/88/1452/88 px at 7). The flip-flop after the X match by
|
|
814
|
+
`ss-hires-mc`, `ss-pri`, `ss-unexp-exp-hires` (168 px each) and
|
|
815
|
+
`ss-hires-mc-exp`, `ss-pri-exp`, `ss-exp-unexp-hires` (336 px each).
|
|
816
|
+
The flip on a change by `ss-hires-mc-exp` (1364 px) and
|
|
817
|
+
`ss-mc-hires-exp` (44 px), and the hi-res hold by `ss-mc-hires` and
|
|
818
|
+
`ss-mc-hires-exp` (44 px each).
|
|
819
|
+
- Spec guard: *reaches the multicolor flip-flop six pixels on* in
|
|
820
|
+
[`sprites_spec.rb`](../spec/badline/vic/sprites_spec.rb) and the *with
|
|
821
|
+
an 8565* group of *mid-line writes* in
|
|
822
|
+
[`sprite_spec.rb`](../spec/badline/vic/sprite_spec.rb).
|
|
823
|
+
- **The g-access addresses with the `$d011` of the column before**,
|
|
824
|
+
whole, instead of the 6569's hold of BMM and, on the character ROM, ECM.
|
|
825
|
+
- Pinned by `modesplit` (598 px), `vicii_reg_timing` (92, 99/106 px),
|
|
826
|
+
`fetchsplit` (180 px) and every videomode row but `videomode1` (3 to
|
|
827
|
+
16 px).
|
|
828
|
+
- Spec guard: *addresses with the $d011 of the column before* in
|
|
829
|
+
[`vic_spec.rb`](../spec/badline/vic_spec.rb).
|
|
830
|
+
- **ECM and BMM take hold at the next group's pixel 0**, rising or
|
|
831
|
+
falling, where the 6569 takes them at pixel 4 as they rise and 5 or 6 as
|
|
832
|
+
they fall. MCM keeps the 6569's timing, but an MCM that falls out of
|
|
833
|
+
ECM+MCM does so on time instead of a pixel late.
|
|
834
|
+
- The pixel 0 is pinned by `modesplit` (916 px), `vicii_reg_timing` (86,
|
|
835
|
+
100/114 px) and every videomode row (6 to 13 px). The on-time MCM by
|
|
836
|
+
`videomode1` and `videomode-z` (2 px each).
|
|
837
|
+
- Spec guard: the *on the 8565* group in
|
|
838
|
+
[`graphics_shifter_spec.rb`](../spec/badline/vic/graphics_shifter_spec.rb).
|
|
839
|
+
- **Out of an invalid mode into multicolour bitmap, a background pixel 0
|
|
840
|
+
is still black, and into hi-res text any pixel 0 is.** Into multicolour
|
|
841
|
+
text and ECM text it shows on time.
|
|
842
|
+
- The multicolour bitmap case is pinned by `videomode-v` and `videomode2`
|
|
843
|
+
(1 px each) and `modesplit` (92 → 124 px), whose `%00` and `%01` pairs
|
|
844
|
+
after an ECM+MCM or ECM+BMM+MCM split keep their first pixel black.
|
|
845
|
+
`videomode-y` shows a `%01` pair on time into multicolour text.
|
|
846
|
+
- The hi-res text case is empirical, pinned by the E+B row of
|
|
847
|
+
`vicii_reg_timing-a5` and `-ff` (pass and 7 px, 7 and 14 px without
|
|
848
|
+
it), which drops ECM+BMM back to text. All three `vicii_reg_timing`
|
|
849
|
+
references keep that pixel 0 black, a foreground pixel in `-a5` and
|
|
850
|
+
`-ff`. `$d021` is black there, so no reference tells a background
|
|
851
|
+
pixel 0 apart, and the rule blackens both.
|
|
852
|
+
- `videomode-w` shows ECM+BMM into ECM text on time (1 px if it goes
|
|
853
|
+
black), while `modesplit`'s section 1 keeps the same move black (48 of
|
|
854
|
+
its 92 px). The two references disagree about the same move, and the
|
|
855
|
+
videomode one is kept.
|
|
856
|
+
- Spec guard: *keeps a background pixel 0 black out of an invalid mode
|
|
857
|
+
into multicolour bitmap*, *keeps pixel 0 black out of an invalid mode
|
|
858
|
+
into hi-res text*, *shows pixel 0 on time out of an invalid mode into
|
|
859
|
+
multicolour text* and *shows pixel 0 on time out of an invalid mode into
|
|
860
|
+
ECM text* in
|
|
861
|
+
[`graphics_shifter_spec.rb`](../spec/badline/vic/graphics_shifter_spec.rb).
|
|
862
|
+
- **The light pen latches one extra half-pixel**, where the 6569 adds two.
|
|
863
|
+
- Pinned by `lp-trigger/test2new`, which measures the trigger delay and
|
|
864
|
+
fails with two.
|
|
865
|
+
- Spec guard: *adds one extra half-pixel on the 8565* in
|
|
866
|
+
[`vic_spec.rb`](../spec/badline/vic_spec.rb).
|
|
867
|
+
|
|
868
|
+
What the 8565 references don't settle, and so what stays as it is:
|
|
869
|
+
|
|
870
|
+
- The pixel 0 of a group that leaves ECM or BMM is not consistent across
|
|
871
|
+
the references. Moving every falling edge to pixel 1 passes `modesplit`
|
|
872
|
+
but fails every videomode row but `videomode1` and all three
|
|
873
|
+
`vicii_reg_timing` rows, and the same move out of hi-res bitmap into
|
|
874
|
+
text is the new mode in `vicii_reg_timing-a5` and the old one in `-ff`.
|
|
875
|
+
The videomode readme says these delays "may depend on the type of VICII,
|
|
876
|
+
and the temperature of the chip". So `modesplit` (92 px) and
|
|
877
|
+
`vicii_reg_timing-ff` (7 px, the hi-res bitmap into text row) stay FAIL.
|
|
878
|
+
No emulator in the testbench results passes `vicii_reg_timing-a5` or
|
|
879
|
+
`-ff` on the 8565, and only Hoxs64 passes `modesplit`, against the
|
|
880
|
+
`8565early` reference.
|
|
881
|
+
- `fetchsplit` (154 px) stays FAIL: its readme says its 8565 artefacts
|
|
882
|
+
differ from chip to chip and change as the machine warms up, and its
|
|
883
|
+
`M1` and `M7` captures differ. The differences sit in the first character
|
|
884
|
+
after a `$dd00` bank switch on some lines. Delaying every rising, or
|
|
885
|
+
every falling, bank bit by a cycle on the 8565 makes it 656 or 752 px.
|
|
886
|
+
- VICE's idle g-access also reads ECM from the `$d011` of the column
|
|
887
|
+
before on the 8565. No testprog tells it apart, so the 8565 keeps the
|
|
888
|
+
6569's idle access, without the 6569's `$38ff` read where a DMA delay
|
|
889
|
+
starts.
|
|
890
|
+
|
|
731
891
|
## CIA 6526 timer pipeline
|
|
732
892
|
|
|
733
893
|
- Start and stop go through two stages. A force load lands one tick after
|
|
@@ -759,13 +919,17 @@ VICE x64sc's `vicii_fetch_graphics` and `draw_graphics8` for the 6569.
|
|
|
759
919
|
`CIA/ciavarious/cia3` K/L, `cia3a` D/H, `cia4` X, `cia8` A/C/F/J/L
|
|
760
920
|
(the readme's old-versus-new CIA cells) and `CIA/cia-timer/cia-timer-oldcias`,
|
|
761
921
|
and ported from VICE's `CIA_IM_TBB`.
|
|
762
|
-
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
922
|
+
- Every rule in this section is the **6526**'s, the chip `CIA.new`
|
|
923
|
+
builds unless given `model: :mos6526a`, and the one `Lorenz.d81`
|
|
924
|
+
expects. That is all the `(*1)` cells of `cia1ta`/`cia1tb` measure, and
|
|
925
|
+
it is an ICR difference, not a counter one. Those cells read the ICR on
|
|
926
|
+
the very cycle the underflow flag rises, so the source bit is up while
|
|
927
|
+
IR is not: they read `$01`/`$02`, where a 6526A reads `$81`/`$82`.
|
|
928
|
+
Counter readback is identical on both revisions. `Lorenznew.d81` expects
|
|
929
|
+
the 6526A and must not be mixed into the `lorenz` chain. Its tests run
|
|
930
|
+
one at a time on a 6526A machine in `testbench-cia-new` instead. See
|
|
931
|
+
[CIA 6526A interrupt register](#cia-6526a-interrupt-register) for what
|
|
932
|
+
changes.
|
|
769
933
|
- Timer B's cascade decodes CRB, not CRA. Every count source (ø2, a CNT
|
|
770
934
|
edge, a cascaded timer A underflow) drives the same two-stage
|
|
771
935
|
count-enable pipeline, so a timer A underflow decrements timer B two
|
|
@@ -793,6 +957,65 @@ VICE x64sc's `vicii_fetch_graphics` and `draw_graphics8` for the 6569.
|
|
|
793
957
|
acknowledge* and *6526 timer B bug* groups guard the three ICR rules
|
|
794
958
|
above, on a bare CIA.
|
|
795
959
|
|
|
960
|
+
## CIA 6526A interrupt register
|
|
961
|
+
|
|
962
|
+
The 6526A (`CIA.new(model: :mos6526a)`, `Computer.new(cia_model:
|
|
963
|
+
:mos6526a)`), fitted to the C64C, differs from the 6526 only in its
|
|
964
|
+
interrupt control register. Its timers and shift register run the rules
|
|
965
|
+
above unchanged: every `testbench-cia-new` row passes on the 6526's
|
|
966
|
+
timer and serial code, the long counter sweeps `cia1tanew`, `cia1tbnew`,
|
|
967
|
+
`cia2tanew` and `cia2tbnew` included. VICE's `ciatimer.c` has no model
|
|
968
|
+
check either. Each rule below is gated on the model in
|
|
969
|
+
[`cia/interrupt_register.rb`](../lib/badline/cia/interrupt_register.rb),
|
|
970
|
+
and each was knocked out: removing it fails the rows named.
|
|
971
|
+
|
|
972
|
+
- **IR on the flag's cycle.** A source flag whose mask bit is set raises
|
|
973
|
+
IR on the cycle the flag rises, not a cycle later. The exception is a
|
|
974
|
+
flag that rises on the cycle after an ICR read: that one raises IR a
|
|
975
|
+
cycle later, as on the 6526 (VICE's `rdi + 1 == rclk`).
|
|
976
|
+
- The early IR is pinned by `CIA/irqdelay/irqdelay-new`,
|
|
977
|
+
`irqdelay-oneshot-new`, `irqdelay2-new`, `irqdelay-cia1-4-new` and
|
|
978
|
+
`irqdelay-cia1-oneshot-4-new`, `interrupts/branchquirk/branchquirk-new`
|
|
979
|
+
and `branchquirk-nminew`, `interrupts/cia-int/cia-int-irq-new` and
|
|
980
|
+
`cia-int-nmi-new`, `interrupts/irq-ackn-bug/cia1new` and `cia2new`,
|
|
981
|
+
`interrupts/irqnmi/irqnmi-new`, `CIA/CIA-AcountsB/cmp-b-counts-a-new`,
|
|
982
|
+
`CIA/cia-timer/cia-timer-newcias`, `CIA/timerbasics/timer_test1_new`
|
|
983
|
+
and `CIA/dd0dtest/dd0dtest`.
|
|
984
|
+
- The exception after a read is pinned by `cia-int-irq-new`,
|
|
985
|
+
`cia-int-nmi-new` and `dd0dtest` test 17, which fail when every flag
|
|
986
|
+
raises IR at once.
|
|
987
|
+
- **A read sees an IR about to rise.** A read on the cycle before IR is
|
|
988
|
+
due returns IR set, and cancels the assert as on the 6526. On the 6526,
|
|
989
|
+
only a read on the next cycle sees it.
|
|
990
|
+
- Pinned by `dd0dtest` test 17. The two reads of `inc $dd0d,x` land on
|
|
991
|
+
the cycles before and of timer A's flag, so the second sees `$81` and
|
|
992
|
+
the RMW writes `$81`/`$82` back, arming timer B, whose NMI handler
|
|
993
|
+
then reads `$82`. Without the rule the second read sees `$01`, timer B
|
|
994
|
+
stays masked and no NMI comes.
|
|
995
|
+
- **The acknowledge holds every bit.** A read releases the interrupt line
|
|
996
|
+
at once, but the bits it read, sources and IR alike, stay readable on
|
|
997
|
+
the next cycle, along with anything flagged since. They clear the cycle
|
|
998
|
+
after that. The 6526 holds only IR (see *Old-CIA acknowledge* above).
|
|
999
|
+
- Pinned by `dd0dtest` tests 18 and 19. Their `inc $dd0d,x` reads `$81`
|
|
1000
|
+
on the flag cycle and again on the next cycle, where a 6526 reads
|
|
1001
|
+
`$80`, so the RMW writes `$82` and arms timer B.
|
|
1002
|
+
- **A mask write raises IR a cycle later**, where the 6526 takes two.
|
|
1003
|
+
- Pinned by Lorenz `imrnew`.
|
|
1004
|
+
- **No timer B bug.** An underflow on the cycle after an ICR read keeps
|
|
1005
|
+
its flag.
|
|
1006
|
+
- Pinned by `CIA/ciavarious/cia3new`, `cia3anew`, `cia4new` and
|
|
1007
|
+
`cia8new` (the readme's old-versus-new cells) and
|
|
1008
|
+
`CIA/cia-timer/cia-timer-newcias`.
|
|
1009
|
+
- Two of VICE's model checks are left out, because no testprog tells
|
|
1010
|
+
them apart. VICE stops a mask write from raising IR on the cycle after
|
|
1011
|
+
an ICR read, and applies the 6526's mask cancel (*Old-CIA mask cancel*
|
|
1012
|
+
above) only to the 6526. Adding the first, or dropping the second for
|
|
1013
|
+
the 6526A, passes every `testbench-cia-new` row, so the 6526A keeps the
|
|
1014
|
+
6526's behaviour on both.
|
|
1015
|
+
- Spec guard: *the 6526A interrupt register* in
|
|
1016
|
+
[`cia_spec.rb`](../spec/badline/cia_spec.rb), one example per rule,
|
|
1017
|
+
each failing when its rule is knocked out.
|
|
1018
|
+
|
|
796
1019
|
## CIA serial shift register
|
|
797
1020
|
|
|
798
1021
|
- The register counts itself empty on the 15th timer A underflow, when the
|
|
@@ -858,6 +1081,15 @@ VICE x64sc's `vicii_fetch_graphics` and `draw_graphics8` for the 6569.
|
|
|
858
1081
|
before the KERNAL does.
|
|
859
1082
|
- Spec guard: *when powered on* in
|
|
860
1083
|
[`address_bus_spec.rb`](../spec/badline/address_bus_spec.rb).
|
|
1084
|
+
- A write to `$00` or `$01` goes to the port, and the RAM below takes the
|
|
1085
|
+
byte the VIC fetched in the phi1 half of the same cycle, as in VICE's
|
|
1086
|
+
`zero_store`. Only the VIC reads that RAM.
|
|
1087
|
+
- Pinned by `general/ram0001/test1`, which puts the byte in `$3fff` for
|
|
1088
|
+
the idle fetch, and `general/fuxxortest/ef2-inst4a`, which uses two
|
|
1089
|
+
sprite pointer fetches. Both read the RAM back through sprite
|
|
1090
|
+
collisions.
|
|
1091
|
+
- Spec guard: *when a program writes to the port* in
|
|
1092
|
+
[`address_bus_spec.rb`](../spec/badline/address_bus_spec.rb).
|
|
861
1093
|
|
|
862
1094
|
## SID oscillator
|
|
863
1095
|
|
|
@@ -902,6 +1134,15 @@ VICE x64sc's `vicii_fetch_graphics` and `draw_graphics8` for the 6569.
|
|
|
902
1134
|
[`sid_spec.rb`](../spec/badline/sid_spec.rb): a catch-up that
|
|
903
1135
|
fast-forwards across a rise carries the shift still in flight into the
|
|
904
1136
|
next span.
|
|
1137
|
+
- Setting the test bit onto noise combined with another waveform writes
|
|
1138
|
+
that combination's output back into the LFSR first, from the accumulator
|
|
1139
|
+
it had, before the bit clears it.
|
|
1140
|
+
- Pinned by `SID/noiselfsrinit`'s `simple` and `scan` (both chips). Their
|
|
1141
|
+
`$f8`/`$80` pairs set the test bit onto all four waveforms from noise
|
|
1142
|
+
alone, and zero the register only if this writes back. The release that
|
|
1143
|
+
follows goes to noise alone, which writes nothing back (below).
|
|
1144
|
+
- Spec guard: *as the test bit rises* in
|
|
1145
|
+
[`sid/waveform_spec.rb`](../spec/badline/sid/waveform_spec.rb).
|
|
905
1146
|
- The test bit does not clear the LFSR. It stalls it halfway through a
|
|
906
1147
|
shift with bit 22 forced high. While the bit is held, every bit bleeds up
|
|
907
1148
|
to `$7fffff`: after `$950000` cycles on the 8580 (`SID/bitfade`'s
|
|
@@ -921,28 +1162,33 @@ VICE x64sc's `vicii_fetch_graphics` and `draw_graphics8` for the 6569.
|
|
|
921
1162
|
that varies with the chip's temperature (`SID/wf12nsr`'s
|
|
922
1163
|
`quicktest.prg` on a 6581), which nothing scored depends on.
|
|
923
1164
|
- Spec guard: *bleeding through a held test bit* in
|
|
924
|
-
[`sid/waveform_spec.rb`](../spec/badline/sid/waveform_spec.rb).
|
|
1165
|
+
[`sid/waveform_spec.rb`](../spec/badline/sid/waveform_spec.rb).
|
|
1166
|
+
- Before the bit clocks in on release, the old waveform's output is
|
|
925
1167
|
written back only for some waveform changes. Noise has to have been
|
|
926
|
-
combined before the release and still be
|
|
927
|
-
noise alone writes nothing back
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
1168
|
+
combined before the release and still be combined after it, so a change
|
|
1169
|
+
to noise alone writes nothing back. A change to pulse+noise writes
|
|
1170
|
+
nothing back, nor does a change from pulse+noise to sawtooth+noise. On
|
|
1171
|
+
the 6581, trading triangle for sawtooth or back writes nothing back. The
|
|
1172
|
+
rule follows libresidfp's `do_writeback`. What is written is the
|
|
1173
|
+
writeback shape below, not the OSC3 read. Two more cases are not in that
|
|
1174
|
+
rule. On the 6581, a change that keeps only pulse+noise of the old
|
|
1175
|
+
waveform (`D`/`E`/`F`→`C`, `D`→`E`) writes the three lowest noise lines
|
|
1176
|
+
low (`$f8`). On the 8580, a change from pulse+noise to all four
|
|
1177
|
+
(`C`→`F`) writes every line low.
|
|
1178
|
+
- Pinned by `SID/wb_testsuite` (the `9`/`A`/`D`/`E`/`F`→`8` rows on both
|
|
936
1179
|
chips, and the 6581's `9`↔`A`, `9`/`A`→`C` and `D`→`A` rows) and by
|
|
937
1180
|
`SID/noisewriteback`'s `noise_writeback_test1`. The 6581's `$f8` case
|
|
938
1181
|
is pinned by its `D`→`C`, `D`→`E`, `E`→`C` and `F`→`C` rows, and
|
|
939
1182
|
dropping it fails all four. The 8580's `C`→`A` row pins the
|
|
940
1183
|
pulse+noise to sawtooth+noise exception: without it the release writes
|
|
941
|
-
the 8580's `$fc` and the row fails.
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
1184
|
+
the 8580's `$fc` and the row fails. The 8580's `C`→`F` row pins the
|
|
1185
|
+
all-low case: writing the old waveform's `$fc` back makes the first read
|
|
1186
|
+
`$fc`, where the row expects the `$6c` that `F`→`F` reads. Both 8580
|
|
1187
|
+
samplings in `SID/wb_testsuite/samplings` read `$6c` for `C`→`F`.
|
|
1188
|
+
- `F`→`8` wrote back until the test bit's rise (above) took over
|
|
1189
|
+
zeroing the register for `SID/noiselfsrinit`. Every sampling in
|
|
1190
|
+
`SID/wb_testsuite/samplings`, both chips, reads `F`→`8` as a plain
|
|
1191
|
+
shift.
|
|
946
1192
|
- Spec guard: *as the test bit falls* in
|
|
947
1193
|
[`sid/waveform_spec.rb`](../spec/badline/sid/waveform_spec.rb).
|
|
948
1194
|
- A combined waveform shorts the shapers onto the lines the oscillator reads
|
|
@@ -986,11 +1232,15 @@ VICE x64sc's `vicii_fetch_graphics` and `draw_graphics8` for the 6569.
|
|
|
986
1232
|
fails wfc and the `C`→`9`/`C`→`E` rows; applying the lone-line rule to
|
|
987
1233
|
the read as well makes `noise_writeback_test2` read `$00` on both
|
|
988
1234
|
chips.
|
|
989
|
-
-
|
|
990
|
-
never
|
|
991
|
-
the
|
|
992
|
-
|
|
993
|
-
|
|
1235
|
+
- Can't pass: the 6581's pulse+noise row of `SID/wf12nsr`. The program
|
|
1236
|
+
never writes voice 3's pulse width, so the row depends on whatever width
|
|
1237
|
+
the machine it was recorded on held. The 6581 reference reads `$00`
|
|
1238
|
+
right after the release into pulse+noise at frequency `$ffff`, as if
|
|
1239
|
+
the pulse was still low and grounding every line. After power-on or
|
|
1240
|
+
reset the width is zero and the pulse is high. With the width set
|
|
1241
|
+
before the program runs, the row passes from `$1a0` up and fails from
|
|
1242
|
+
`$198` down. The 8580 program passes from a zero width. `SID/wf12nsr`'s `quicktest.prg` doesn't set the width
|
|
1243
|
+
either. The row stays failing.
|
|
994
1244
|
- Spec guard: *writes a lone line of a noise combination back low*, *with
|
|
995
1245
|
pulse+noise on the 8580* and *as the test bit falls* in
|
|
996
1246
|
[`sid/waveform_spec.rb`](../spec/badline/sid/waveform_spec.rb).
|
|
@@ -1098,9 +1348,13 @@ VICE x64sc's `vicii_fetch_graphics` and `draw_graphics8` for the 6569.
|
|
|
1098
1348
|
- A tune's init and play routines must run with the ROMs banked to match
|
|
1099
1349
|
the address they live at, following libsidplayfp's iomap: `$37` below
|
|
1100
1350
|
`$a000`, `$36` under BASIC, `$34` in the `$d000` I/O window, `$35` under
|
|
1101
|
-
the KERNAL.
|
|
1102
|
-
|
|
1351
|
+
the KERNAL. A routine below `$a000` gets `$36` too when the tune's image
|
|
1352
|
+
reaches under BASIC, as VSID does, since it may call into that part.
|
|
1353
|
+
Restore `$01` afterwards so the caller's banking survives. This entry is
|
|
1354
|
+
the rule, and it should outlive whichever code carries it.
|
|
1103
1355
|
- Derived against six OneLoad64 tunes (Galway, Tel, Gray, Dunn, Cooksey).
|
|
1356
|
+
Green Beret's init sits at `$9fe3` and calls its own code at `$aaca`,
|
|
1357
|
+
which forces the `$36` below `$a000`.
|
|
1104
1358
|
`SIDFile#bank_for` is the one copy of the map: `Driver` wraps both calls
|
|
1105
1359
|
in a `$01` save/bank/restore, and `BarePlayer#dispatch` pokes it before
|
|
1106
1360
|
handing the CPU the stub.
|
data/exe/badline-ruby
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
lib = File.expand_path("../lib", __dir__)
|
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
6
|
+
|
|
7
|
+
require "badline/options"
|
|
8
|
+
|
|
9
|
+
begin
|
|
10
|
+
options = Badline::Options.parse(ARGV)
|
|
11
|
+
rescue Badline::Options::Error => e
|
|
12
|
+
warn "badline-ruby: #{e.message}"
|
|
13
|
+
warn "Try 'badline-ruby --help' for more information."
|
|
14
|
+
exit 1
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
if options.help?
|
|
18
|
+
puts options.help
|
|
19
|
+
exit
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
jit_available = defined?(RubyVM::YJIT) && !RubyVM::YJIT.enabled?
|
|
23
|
+
RubyVM::YJIT.enable if options.jit? && jit_available
|
|
24
|
+
|
|
25
|
+
require "badline"
|
|
26
|
+
|
|
27
|
+
if options.headless?
|
|
28
|
+
begin
|
|
29
|
+
Badline::Audio::CLI.new(options, sink: Badline::Audio::SDLSink.method(:new),
|
|
30
|
+
console: Badline::Audio::Console.method(:new)).run
|
|
31
|
+
rescue Badline::Audio::CLI::Error => e
|
|
32
|
+
warn "badline-ruby: #{e.message}"
|
|
33
|
+
exit 1
|
|
34
|
+
rescue Interrupt
|
|
35
|
+
exit 130
|
|
36
|
+
end
|
|
37
|
+
exit
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
begin
|
|
41
|
+
require "badline/gui"
|
|
42
|
+
rescue Badline::SDL::Error => e
|
|
43
|
+
warn "badline-ruby: can't open the window: #{e.message}. " \
|
|
44
|
+
"Install SDL2 with 'brew install sdl2' or 'apt install libsdl2-2.0-0'."
|
|
45
|
+
exit 1
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
begin
|
|
49
|
+
application = Badline::GUI::Application.new(media_path: options.media_path, autostart: options.autostart?,
|
|
50
|
+
song: options.song, sid_model: options.sid_model,
|
|
51
|
+
sound: options.sound?, disk: { read_only: options.read_only? })
|
|
52
|
+
rescue Badline::Storage::SIDFile::FormatError, Badline::Storage::T64::FormatError,
|
|
53
|
+
Badline::Storage::TAP::FormatError, Badline::Storage::CRTFile::FormatError,
|
|
54
|
+
Badline::Cartridge::UnsupportedTypeError => e
|
|
55
|
+
warn "badline-ruby: #{options.media_path}: #{e.message}"
|
|
56
|
+
exit 1
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
application.run
|
data/lib/badline/address_bus.rb
CHANGED
|
@@ -49,10 +49,14 @@ module Badline
|
|
|
49
49
|
|
|
50
50
|
attr_reader :io_port, :ram, :basic_rom, :character_rom, :kernal_rom,
|
|
51
51
|
:vic, :sid, :color_ram, :cia1, :cia2, :keyboard, :joystick1, :joystick2,
|
|
52
|
-
:control_ports, :cartridge, :ultimax, :phi1_ultimax, :datasette
|
|
52
|
+
:control_ports, :cartridge, :ultimax, :phi1_ultimax, :datasette, :region, :video_ram
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
# ram_expansion fits a +60K (:plus60k) or +256K (:plus256k).
|
|
55
|
+
def initialize(sid_model: :mos6581, cia_model: :mos6526, vic_model: :mos6569, region: Region::PAL,
|
|
56
|
+
ram_expansion: nil)
|
|
57
|
+
@region = region
|
|
55
58
|
@ram = Memory.new(RAM_POWER_ON, length: 2**16, start: 0)
|
|
59
|
+
@ram_expansion = RAMExpansion.build(ram_expansion, @ram) { update_overlays! }
|
|
56
60
|
@cartridge = nil
|
|
57
61
|
@debug_register = nil
|
|
58
62
|
|
|
@@ -64,9 +68,9 @@ module Badline
|
|
|
64
68
|
@joystick1 = Joystick.new
|
|
65
69
|
@joystick2 = Joystick.new
|
|
66
70
|
@control_ports = ControlPorts.new(keyboard: @keyboard, joystick1: @joystick1, joystick2: @joystick2)
|
|
67
|
-
@vic = VIC.new(self)
|
|
68
|
-
@cia1 = CIA.new(start: 0xdc00, peripheral: @control_ports)
|
|
69
|
-
@cia2 = CIA.new(start: 0xdd00)
|
|
71
|
+
@vic = VIC.new(self, model: vic_model, region:)
|
|
72
|
+
@cia1 = CIA.new(start: 0xdc00, peripheral: @control_ports, model: cia_model, region:)
|
|
73
|
+
@cia2 = CIA.new(start: 0xdd00, model: cia_model, region:)
|
|
70
74
|
@control_ports.port_a_source = @cia1
|
|
71
75
|
@cia1.on_port_b4_change { |high| @vic.lightpen_level(high) }
|
|
72
76
|
@sid = SID.new(model: sid_model, pots: @control_ports)
|
|
@@ -97,11 +101,14 @@ module Badline
|
|
|
97
101
|
|
|
98
102
|
def power_on!
|
|
99
103
|
@ram.clear!(RAM_POWER_ON)
|
|
104
|
+
@ram_expansion.power_on!
|
|
100
105
|
end
|
|
101
106
|
|
|
102
|
-
# The
|
|
103
|
-
# The floating bits keep
|
|
104
|
-
|
|
107
|
+
# The RES line clears the 6510 port's direction and output registers,
|
|
108
|
+
# and a RAM expansion's bank register. The port's floating bits keep
|
|
109
|
+
# their charge.
|
|
110
|
+
def reset!
|
|
111
|
+
@ram_expansion.reset!
|
|
105
112
|
@port_ddr = 0x00
|
|
106
113
|
@port_out = 0x00
|
|
107
114
|
update_port!
|
|
@@ -124,8 +131,12 @@ module Badline
|
|
|
124
131
|
@read_pages[addr >> 8].peek(addr)
|
|
125
132
|
end
|
|
126
133
|
|
|
134
|
+
# A write to $00 or $01 goes to the port, but the RAM below is still
|
|
135
|
+
# write-enabled, and takes whatever is left on the bus: the byte the VIC
|
|
136
|
+
# fetched in the phi1 half of the cycle.
|
|
127
137
|
def poke(addr, value)
|
|
128
138
|
if addr < 0x02
|
|
139
|
+
@ram.poke(addr, @vic.phi1_data)
|
|
129
140
|
addr.zero? ? @port_ddr = value : @port_out = value
|
|
130
141
|
update_port!
|
|
131
142
|
else
|
|
@@ -162,8 +173,8 @@ module Badline
|
|
|
162
173
|
def update_overlays!
|
|
163
174
|
@ultimax = @cartridge ? @cartridge.ultimax? : false
|
|
164
175
|
@phi1_ultimax = @cartridge ? @cartridge.phi1_ultimax? : false
|
|
165
|
-
@
|
|
166
|
-
@
|
|
176
|
+
@ram_expansion.map(@read_pages, @write_pages)
|
|
177
|
+
@video_ram = @ram_expansion.video_ram
|
|
167
178
|
|
|
168
179
|
@ultimax ? map_ultimax_pages : map_banked_pages
|
|
169
180
|
end
|
|
@@ -180,10 +191,12 @@ module Badline
|
|
|
180
191
|
end
|
|
181
192
|
end
|
|
182
193
|
|
|
194
|
+
# EXROM and GAME select the cartridge whether or not it has a chip
|
|
195
|
+
# there, and an empty socket leaves the bus floating.
|
|
183
196
|
def map_rom_overlays
|
|
184
|
-
@read_pages.fill(@cartridge.roml, 0x80, 0x20) if roml?
|
|
197
|
+
@read_pages.fill(@cartridge.roml || @open_bus, 0x80, 0x20) if roml?
|
|
185
198
|
if romh?
|
|
186
|
-
@read_pages.fill(@cartridge.romh, 0xa0, 0x20)
|
|
199
|
+
@read_pages.fill(@cartridge.romh || @open_bus, 0xa0, 0x20)
|
|
187
200
|
elsif basic?
|
|
188
201
|
@read_pages.fill(basic_rom, 0xa0, 0x20)
|
|
189
202
|
end
|
|
@@ -236,6 +249,7 @@ module Badline
|
|
|
236
249
|
}.each do |chip, pages|
|
|
237
250
|
pages.each { |p| @read_pages[p] = @write_pages[p] = chip }
|
|
238
251
|
end
|
|
252
|
+
@ram_expansion.map_io(@read_pages, @write_pages)
|
|
239
253
|
@read_pages[0xd7] = @write_pages[0xd7] = @debug_register if @debug_register
|
|
240
254
|
map_cartridge_io if @cartridge
|
|
241
255
|
end
|
|
@@ -254,11 +268,11 @@ module Badline
|
|
|
254
268
|
end
|
|
255
269
|
|
|
256
270
|
def roml?
|
|
257
|
-
@cartridge&.
|
|
271
|
+
@cartridge&.exrom&.zero? && io_port.kernal? && io_port.basic?
|
|
258
272
|
end
|
|
259
273
|
|
|
260
274
|
def romh?
|
|
261
|
-
@cartridge&.
|
|
275
|
+
@cartridge&.exrom&.zero? && @cartridge.game.zero? && io_port.kernal?
|
|
262
276
|
end
|
|
263
277
|
|
|
264
278
|
# In 16K mode LORAM alone leaves $d000 as RAM, where it still maps I/O.
|
data/lib/badline/addressable.rb
CHANGED
data/lib/badline/audio/aiff.rb
CHANGED
|
@@ -25,11 +25,16 @@ module Badline
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
# Sign bit, 15-bit biased exponent, then a 64-bit mantissa that keeps
|
|
28
|
-
# its leading one rather than hiding it.
|
|
28
|
+
# its leading one rather than hiding it, packed as two 32-bit halves.
|
|
29
29
|
def extended(value)
|
|
30
30
|
exponent = EXPONENT_BIAS + value.bit_length - 1
|
|
31
|
-
mantissa
|
|
32
|
-
|
|
31
|
+
[exponent, *mantissa(value, 64 - value.bit_length)].pack("nNN")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def mantissa(value, shift)
|
|
35
|
+
return [value << (shift - 32), 0] if shift >= 32
|
|
36
|
+
|
|
37
|
+
[value >> (32 - shift), (value & ((1 << (32 - shift)) - 1)) << shift]
|
|
33
38
|
end
|
|
34
39
|
end
|
|
35
40
|
end
|