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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//! The Sega Master System's chips (`dev-sms`).
//!
//! The second half of phase 4's *genericity proof* (`ROADMAP.md` §13). The Game
//! Boy was the first, and it was arguably an easy one: a memory-mapped console
//! with one bus, built from a CPU descended from the same family as the NES's.
//! This machine is deliberately not that.
//!
//! | The Master System needs | The core already had |
//! | --- | --- |
//! | A **separate I/O address space** the VDP and pads live in | a space per name, and `BindCtx::space_named` ([`crate::cpu::z80`]) |
//! | One address that is the sound chip on a write and the VDP's counters on a read | [`Region::split`], and `split()` in the DSL |
//! | Bank switching three 16 KiB windows | [`AddressSpace::rebase`]: an atomic store, no retopology |
//! | Pause as a **non-maskable** interrupt | a wire to the core's `nmi` pin, and its edge detector |
//! | `/INT` held until the guest reads a status register | wire *levels*, not pulses |
//! | Two television standards with different line counts | two oscillators in two machine files ([`core::clock`]) |
//! | A VDP that must not be disturbed by a debugger | [`MemAttrs::debug`], honoured on every port |
//!
//! [`Region::split`]: crate::core::space::Region::split
//! [`AddressSpace::rebase`]: crate::core::space::AddressSpace::rebase
//! [`MemAttrs::debug`]: crate::core::space::MemAttrs::debug
//! [`core::clock`]: crate::core::clock
//!
//! # The modules
//!
//! | Module | Covers |
//! | --- | --- |
//! | [`vdp`] | the 315-5124: mode 4, the TMS9918A modes, VRAM, CRAM, the line interrupt |
//! | [`psg`] | the SN76489: three square channels and one noise channel |
//! | [`mapper`] | Sega's standard cartridge mapper and its cartridge RAM |
//! | [`io`] | the two control pads, `$3E`/`$3F`, and the Pause and Reset buttons |
//! | [`sdsc`] | the SDSC debug console, which is how a test ROM reports headlessly |
//!
//! The CPU is [`crate::cpu::z80`], under its own feature: a machine is a
//! *feature set*, and a build that wants only the chips can have only the chips.
//!
//! # The oscillators
//!
//! One crystal, and which one depends on the television standard the console was
//! built for. Both are exact rationals rather than the rounded decimals every
//! reference prints, because a rounded frequency nails a rounding error into the
//! timeline (`ROADMAP.md` §4.2):
//!
//! ```text
//! NTSC 945000000/88 Hz = 3 x the NTSC colour subcarrier (315/88 MHz)
//! PAL 10640685 Hz = 12/5 x the PAL subcarrier (4433618.75 Hz)
//! ```
//!
//! Everything descends from it by an integer divisor — the Z80 by 3, the VDP's
//! pixel clock by 2 — so every ratio inside the console is exact by
//! construction. What differs between the two machines is the frequency *and*
//! the frame: 262 lines against 313. That is why `sms-ntsc` and `sms-pal` are
//! two files rather than one file with a flag, exactly as `nes-ntsc` and
//! `nes-pal` are.
//!
//! # Sources
//!
//! [SMS Power!'s development documents](https://www.smspower.org/Development/Documents)
//! throughout, plus the TMS9918A and SN76489 datasheets and Zilog's Z80 manual.
//! `docs/platforms/master-system.md` has the register. **No emulator source of
//! any licence was consulted** — not MAME, not higan, not Emulicious, not
//! anything derived from them (`ROADMAP.md` §1).
// The conformance runner reads a downloaded ROM off the filesystem, so it exists
// only where there is one (`ROADMAP.md` §12).
// The conformance runner reads a downloaded ROM off the filesystem, so it exists
// only where there is one (`ROADMAP.md` §12).
pub use ;
pub use SegaMapper;
pub use SmsPsg;
pub use SdscConsole;
pub use ;
use crateResult;
/// The NTSC console's crystal, as an exact rational number of hertz.
///
/// 945000000/88 = 10 738 636.36…, which is three times the NTSC colour
/// subcarrier. Every reference prints "10.738635 MHz"; that is the rounded
/// figure, and writing it down would fix a 1.4 Hz error in the timeline
/// forever.
pub const NTSC_MASTER_HZ: = ;
/// The PAL console's crystal, in hertz.
///
/// 12/5 of the PAL subcarrier, 4 433 618.75 Hz, which comes out an exact
/// integer.
pub const PAL_MASTER_HZ: = ;
/// What the master clock is divided by to clock the Z80.
pub const CPU_DIVIDER: u64 = 3;
/// What it is divided by to clock the VDP's pixel counter.
pub const DOT_DIVIDER: u64 = 2;
/// Register every Master System device class this build has.
///
/// # Errors
///
/// [`crate::Error::Config`] if a name is already taken, which means two features
/// collided.
/// Bind every Master System device class into the machine graph.
///
/// # Errors
///
/// As [`register`].
/// What the validator should know about every Master System class.