1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//! DOS-era PC video for [game-toolkit](https://docs.rs/game-toolkit): VGA (mode 13h, Mode X,
//! planar 16-color, text), EGA, CGA (with composite artifact colors and snow), Hercules,
//! Tandy 1000 and VESA SVGA, emulated at the register level with a beam-accurate CRT.
//!
//! # The model
//!
//! A [`Dos`] is a machine with a clock. Everything a program does costs time: a port write
//! ([`Dos::outb`]), a video memory write ([`Dos::poke`], priced by the configured
//! [`BusTiming`]), computation you choose to charge ([`Dos::cpu`]), and waiting for the beam
//! ([`Dos::wait_vretrace`], [`Dos::wait_line`]) or polling the status port like DOS programs
//! did (`while dos.inb(0x3DA) & 8 == 0 {}` works).
//!
//! The CRT paints the picture as the beam sweeps, from the adapter's state *at that moment*.
//! So all the tricks of the era fall out by themselves: palette changes between scanlines
//! (copper bars), changing the start address or line compare for page flipping and split
//! screens, pel panning for smooth scrolling, palette rotation, and the failure modes too:
//! tearing when a copy is overtaken by the beam, a start address that only latches at
//! vertical retrace, the attribute controller flip-flop, CRTC write protection, CGA snow.
//!
//! # Running a program
//!
//! With the default `toolkit` feature, implement [`DosGame`] and hand it to [`run`]. `step` is
//! one pass of your main loop; the host calls it as often as emulated time allows and shows the
//! frames the CRT produces.
//!
//! ```no_run
//! use game_toolkit_dosvideo::prelude::*;
//!
//! struct Hello;
//!
//! impl DosGame for Hello {
//! fn init(dos: &mut Dos) -> anyhow::Result<Self> {
//! dos.set_mode(0x13);
//! Ok(Self)
//! }
//!
//! fn step(&mut self, dos: &mut Dos) {
//! dos.wait_vretrace();
//! let t = dos.frames() as u32;
//! for y in 0..200u32 {
//! let row: Vec<u8> = (0..320u32).map(|x| ((x ^ y) + t) as u8).collect();
//! dos.poke_slice(0xA0000 + y * 320, &row);
//! }
//! if dos.key(sc::ESC) {
//! dos.exit();
//! }
//! }
//! }
//!
//! fn main() -> anyhow::Result<()> {
//! run::<Hello>(DosConfig::new("hello", Adapter::Vga))
//! }
//! ```
pub use CgaMonitor;
pub use ;
pub use Font;
pub use ;
pub use ;
pub use Phosphor;
pub use VbeMode;
pub use ;
pub use ;
/// `use game_toolkit_dosvideo::prelude::*;`
pub use game_toolkit;
/// The sound hardware behind [`speaker`]: prepared speaker music, the crystal clock.
pub use game_toolkit_dosaudio;