1 /*
2 * SPDX-License-Identifier: GPL-2.0-or-later
3 *
4 * Copyright (C) 2020-2021 The DOSBox Staging Team
5 * Copyright (C) 2002-2021 The DOSBox Team
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 #include "dosbox.h"
23
24 #include <array>
25 #include <iomanip>
26 #include <memory>
27 #include <string>
28 #include <unistd.h>
29 #include <vector>
30
31 #include "control.h"
32 #include "dma.h"
33 #include "hardware.h"
34 #include "mixer.h"
35 #include "pic.h"
36 #include "setup.h"
37 #include "shell.h"
38 #include "soft_limiter.h"
39 #include "string_utils.h"
40
41 #define LOG_GUS 0 // set to 1 for detailed logging
42
43 // Global Constants
44 // ----------------
45
46 // AdLib emulation state constant
47 constexpr uint8_t ADLIB_CMD_DEFAULT = 85u;
48
49 // Buffer and memory constants
50 constexpr int BUFFER_FRAMES = 48;
51 constexpr uint32_t RAM_SIZE = 1024 * 1024; // 1 MiB
52
53 // DMA transfer size and rate constants
54 constexpr uint32_t BYTES_PER_DMA_XFER = 8 * 1024; // 8 KiB per transfer
55 constexpr uint32_t ISA_BUS_THROUGHPUT = 32 * 1024 * 1024; // 32 MiB/s
56 constexpr uint16_t DMA_TRANSFERS_PER_S = ISA_BUS_THROUGHPUT / BYTES_PER_DMA_XFER;
57 constexpr double MS_PER_DMA_XFER = 1000.0 / DMA_TRANSFERS_PER_S;
58
59 // Voice-channel and state related constants
60 constexpr uint8_t MAX_VOICES = 32u;
61 constexpr uint8_t MIN_VOICES = 14u;
62 constexpr uint8_t VOICE_DEFAULT_STATE = 3u;
63
64 // DMA and IRQ extents and quantities
65 constexpr uint8_t MIN_DMA_ADDRESS = 0u;
66 constexpr uint8_t MAX_DMA_ADDRESS = 7u;
67 constexpr uint8_t MIN_IRQ_ADDRESS = 0u;
68 constexpr uint8_t MAX_IRQ_ADDRESS = 15u;
69 constexpr uint8_t DMA_IRQ_ADDRESSES = 8u; // number of IRQ and DMA channels
70 constexpr uint16_t DMA_TC_STATUS_BITMASK = 0b100000000; // Status in 9th bit
71
72 // Pan position constants
73 constexpr uint8_t PAN_DEFAULT_POSITION = 7u;
74 constexpr uint8_t PAN_POSITIONS = 16u; // 0: -45-deg, 7: centre, 15: +45-deg
75
76 // Timer delay constants
77 constexpr double TIMER_1_DEFAULT_DELAY = 0.080;
78 constexpr double TIMER_2_DEFAULT_DELAY = 0.320;
79
80 // Volume scaling and dampening constants
81 constexpr auto DELTA_DB = 0.002709201; // 0.0235 dB increments
82 constexpr int16_t VOLUME_INC_SCALAR = 512; // Volume index increment scalar
83 constexpr uint16_t VOLUME_LEVELS = 4096u;
84
85 // Interwave addressing constant
86 constexpr int16_t WAVE_WIDTH = 1 << 9; // Wave interpolation width (9 bits)
87
88 // IO address quantities
89 constexpr uint8_t READ_HANDLERS = 8u;
90 constexpr uint8_t WRITE_HANDLERS = 9u;
91
92 // A group of parameters defining the Gus's voice IRQ control that's also shared
93 // (as a reference) into each instantiated voice.
94 struct VoiceIrq {
95 uint32_t vol_state = 0u;
96 uint32_t wave_state = 0u;
97 uint8_t status = 0u;
98 };
99
100 // A group of parameters used in the Voice class to track the Wave and Volume
101 // controls.
102 struct VoiceCtrl {
103 uint32_t &irq_state;
104 int32_t start = 0;
105 int32_t end = 0;
106 int32_t pos = 0;
107 int32_t inc = 0;
108 uint16_t rate = 0;
109 uint8_t state = VOICE_DEFAULT_STATE;
110 };
111
112 // Collection types involving constant quantities
113 using address_array_t = std::array<uint8_t, DMA_IRQ_ADDRESSES>;
114 using autoexec_array_t = std::array<AutoexecObject, 2>;
115 using pan_scalars_array_t = std::array<AudioFrame, PAN_POSITIONS>;
116 using ram_array_t = std::array<uint8_t, RAM_SIZE>;
117 using read_io_array_t = std::array<IO_ReadHandleObject, READ_HANDLERS>;
118 using vol_scalars_array_t = std::array<float, VOLUME_LEVELS>;
119 using write_io_array_t = std::array<IO_WriteHandleObject, WRITE_HANDLERS>;
120
121 // A Voice is used by the Gus class and instantiates 32 of these.
122 // Each voice represents a single "mono" render_buffer of audio having its own
123 // characteristics defined by the running program, such as:
124 // - being 8bit or 16bit
125 // - having a "position" along a left-right axis (panned)
126 // - having its volume reduced by some amount (native-level down to 0)
127 // - having start, stop, loop, and loop-backward controls
128 // - informing the GUS DSP as to when an IRQ is needed to keep it playing
129 //
130 class Voice {
131 public:
132 Voice(uint8_t num, VoiceIrq &irq) noexcept;
133 void GenerateSamples(std::vector<float> &render_buffer,
134 const ram_array_t &ram,
135 const vol_scalars_array_t &vol_scalars,
136 const pan_scalars_array_t &pan_scalars,
137 uint16_t requested_frames);
138
139 uint8_t ReadVolState() const noexcept;
140 uint8_t ReadWaveState() const noexcept;
141 void ResetCtrls() noexcept;
142 void WritePanPot(uint8_t pos) noexcept;
143 void WriteVolRate(uint16_t rate) noexcept;
144 void WriteWaveRate(uint16_t rate) noexcept;
145 bool UpdateVolState(uint8_t state) noexcept;
146 bool UpdateWaveState(uint8_t state) noexcept;
147
148 VoiceCtrl vol_ctrl;
149 VoiceCtrl wave_ctrl;
150
151 uint32_t generated_8bit_ms = 0u;
152 uint32_t generated_16bit_ms = 0u;
153
154 private:
155 Voice() = delete;
156 Voice(const Voice &) = delete; // prevent copying
157 Voice &operator=(const Voice &) = delete; // prevent assignment
158 bool CheckWaveRolloverCondition() noexcept;
159 bool Is8Bit() const noexcept;
160 float GetVolScalar(const vol_scalars_array_t &vol_scalars);
161 float GetSample(const ram_array_t &ram) noexcept;
162 int32_t PopWavePos() noexcept;
163 float PopVolScalar(const vol_scalars_array_t &vol_scalars);
164 float Read8BitSample(const ram_array_t &ram, int32_t addr) const noexcept;
165 float Read16BitSample(const ram_array_t &ram, int32_t addr) const noexcept;
166 uint8_t ReadCtrlState(const VoiceCtrl &ctrl) const noexcept;
167 void IncrementCtrlPos(VoiceCtrl &ctrl, bool skip_loop) noexcept;
168 bool UpdateCtrlState(VoiceCtrl &ctrl, uint8_t state) noexcept;
169
170 // Control states
171 enum CTRL : uint8_t {
172 RESET = 0x01,
173 STOPPED = 0x02,
174 DISABLED = RESET | STOPPED,
175 BIT16 = 0x04,
176 LOOP = 0x08,
177 BIDIRECTIONAL = 0x10,
178 RAISEIRQ = 0x20,
179 DECREASING = 0x40,
180 };
181
182 uint32_t irq_mask = 0u;
183 uint8_t &shared_irq_status;
184 uint8_t pan_position = PAN_DEFAULT_POSITION;
185 };
186
187 static void GUS_TimerEvent(uint32_t t);
188 static void GUS_DMA_Event(uint32_t val);
189
190 using voice_array_t = std::array<std::unique_ptr<Voice>, MAX_VOICES>;
191
192 // The Gravis UltraSound GF1 DSP (classic)
193 // This class:
194 // - Registers, receives, and responds to port address inputs, which are used
195 // by the emulated software to configure and control the GUS card.
196 // - Reads or provides audio samples via direct memory access (DMA)
197 // - Provides shared resources to all of the Voices, such as the volume
198 // reducing table, constant-power panning table, and IRQ states.
199 // - Accumulates the audio from each active voice into a floating point
200 // vector (the render_buffer), without resampling.
201 // - Populates an autoexec line (ULTRASND=...) with its port, irq, and dma
202 // addresses.
203 //
204 class Gus {
205 public:
206 Gus(uint16_t port, uint8_t dma, uint8_t irq, const std::string &dir);
207 virtual ~Gus();
208 bool CheckTimer(size_t t);
209 void PrintStats();
210
211 struct Timer {
212 double delay = 0.0;
213 uint8_t value = 0xff;
214 bool has_expired = true;
215 bool is_counting_down = false;
216 bool is_masked = false;
217 bool should_raise_irq = false;
218 };
219 Timer timer_one = {TIMER_1_DEFAULT_DELAY};
220 Timer timer_two = {TIMER_2_DEFAULT_DELAY};
221 bool PerformDmaTransfer();
222
223 private:
224 Gus() = delete;
225 Gus(const Gus &) = delete; // prevent copying
226 Gus &operator=(const Gus &) = delete; // prevent assignment
227
228 void ActivateVoices(uint8_t requested_voices);
229 void AudioCallback(uint16_t requested_frames);
230 void BeginPlayback();
231 void CheckIrq();
232 void CheckVoiceIrq();
233 uint32_t Dma8Addr() noexcept;
234 uint32_t Dma16Addr() noexcept;
235 void DmaCallback(DmaChannel *chan, DMAEvent event);
236 void StartDmaTransfers();
237 bool IsDmaPcm16Bit() noexcept;
238 bool IsDmaXfer16Bit() noexcept;
239 uint16_t ReadFromRegister();
240 void PopulateAutoExec(uint16_t port, const std::string &dir);
241 void PopulatePanScalars() noexcept;
242 void PopulateVolScalars() noexcept;
243 void PrepareForPlayback() noexcept;
244 uint16_t ReadFromPort(io_port_t port, io_width_t width);
245
246 void RegisterIoHandlers();
247 void Reset(uint8_t state);
248 void SetLevelCallback(const AudioFrame &levels);
249 void StopPlayback();
250 void UpdateDmaAddress(uint8_t new_address);
251 void UpdateWaveMsw(int32_t &addr) const noexcept;
252 void UpdateWaveLsw(int32_t &addr) const noexcept;
253 void WriteToPort(io_port_t port, io_val_t value, io_width_t width);
254
255 void WriteToRegister();
256
257 // Collections
258 vol_scalars_array_t vol_scalars = {{}};
259 std::vector<float> render_buffer = {};
260 std::vector<int16_t> play_buffer = {};
261 pan_scalars_array_t pan_scalars = {{}};
262 ram_array_t ram = {{0u}};
263 read_io_array_t read_handlers = {}; // std::functions
264 write_io_array_t write_handlers = {}; // std::functions
265 const address_array_t dma_addresses = {
266 {MIN_DMA_ADDRESS, 1, 3, 5, 6, MAX_IRQ_ADDRESS, 0, 0}};
267 const address_array_t irq_addresses = {
268 {MIN_IRQ_ADDRESS, 2, 5, 3, 7, 11, 12, MAX_IRQ_ADDRESS}};
269 voice_array_t voices = {{nullptr}};
270 autoexec_array_t autoexec_lines = {};
271
272 // Struct and pointer members
273 VoiceIrq voice_irq = {};
274 SoftLimiter soft_limiter;
275 Voice *target_voice = nullptr;
276 DmaChannel *dma_channel = nullptr;
277 mixer_channel_t audio_channel = nullptr;
278 uint8_t &adlib_command_reg = adlib_commandreg;
279
280 // Port address
281 io_port_t port_base = 0u;
282
283 // Voice states
284 uint32_t active_voice_mask = 0u;
285 uint16_t voice_index = 0u;
286 uint8_t active_voices = 0u;
287 uint8_t prev_logged_voices = 0u;
288
289 // Register and playback rate
290 uint32_t dram_addr = 0u;
291 uint32_t playback_rate = 0u;
292 uint16_t register_data = 0u;
293 uint8_t selected_register = 0u;
294
295 // Control states
296 uint8_t mix_ctrl = 0x0b; // latches enabled, LINEs disabled
297 uint8_t sample_ctrl = 0u;
298 uint8_t timer_ctrl = 0u;
299
300 // DMA states
301 uint16_t dma_addr = 0u;
302 // dma_ctrl would normally be a uint8_t as real hardware uses 8 bits,
303 // but we store the DMA terminal count status in the 9th bit
304 uint16_t dma_ctrl = 0u;
305 uint8_t dma1 = 0u; // playback DMA
306 uint8_t dma2 = 0u; // recording DMA
307
308 // IRQ states
309 uint8_t irq1 = 0u; // playback IRQ
310 uint8_t irq2 = 0u; // MIDI IRQ
311 uint8_t irq_status = 0u;
312
313 bool dac_enabled = false;
314 bool irq_enabled = false;
315 bool is_running = false;
316 bool should_change_irq_dma = false;
317 };
318
319 using namespace std::placeholders;
320
321 // External Tie-in for OPL FM-audio
322 uint8_t adlib_commandreg = ADLIB_CMD_DEFAULT;
323
324 static std::unique_ptr<Gus> gus = nullptr;
325
Voice(uint8_t num,VoiceIrq & irq)326 Voice::Voice(uint8_t num, VoiceIrq &irq) noexcept
327 : vol_ctrl{irq.vol_state},
328 wave_ctrl{irq.wave_state},
329 irq_mask(1 << num),
330 shared_irq_status(irq.status)
331 {}
332
333 /*
334 Gravis SDK, Section 3.11. Rollover feature:
335 Each voice has a 'rollover' feature that allows an application to be notified
336 when a voice's playback position passes over a particular place in DRAM. This
337 is very useful for getting seamless digital audio playback. Basically, the GF1
338 will generate an IRQ when a voice's current position is equal to the end
339 position. However, instead of stopping or looping back to the start position,
340 the voice will continue playing in the same direction. This means that there
341 will be no pause (or gap) in the playback.
342
343 Note that this feature is enabled/disabled through the voice's VOLUME control
344 register (since there are no more bits available in the voice control
345 registers). A voice's loop enable bit takes precedence over the rollover. This
346 means that if a voice's loop enable is on, it will loop when it hits the end
347 position, regardless of the state of the rollover enable.
348 ---
349 Joh Campbell, maintainer of DOSox-X:
350 Despite the confusing description above, that means that looping takes
351 precedence over rollover. If not looping, then rollover means to fire the IRQ
352 but keep moving. If looping, then fire IRQ and carry out loop behavior. Gravis
353 Ultrasound Windows 3.1 drivers expect this behavior, else Windows WAVE output
354 will not work correctly.
355 */
CheckWaveRolloverCondition()356 bool Voice::CheckWaveRolloverCondition() noexcept
357 {
358 return (vol_ctrl.state & CTRL::BIT16) && !(wave_ctrl.state & CTRL::LOOP);
359 }
360
IncrementCtrlPos(VoiceCtrl & ctrl,bool dont_loop_or_restart)361 void Voice::IncrementCtrlPos(VoiceCtrl &ctrl, bool dont_loop_or_restart) noexcept
362 {
363 if (ctrl.state & CTRL::DISABLED)
364 return;
365 int32_t remaining = 0;
366 if (ctrl.state & CTRL::DECREASING) {
367 ctrl.pos -= ctrl.inc;
368 remaining = ctrl.start - ctrl.pos;
369 } else {
370 ctrl.pos += ctrl.inc;
371 remaining = ctrl.pos - ctrl.end;
372 }
373 // Not yet reaching a boundary
374 if (remaining < 0)
375 return;
376
377 // Generate an IRQ if requested
378 if (ctrl.state & CTRL::RAISEIRQ) {
379 ctrl.irq_state |= irq_mask;
380 }
381
382 // Allow the current position to move beyond its limit
383 if (dont_loop_or_restart)
384 return;
385
386 // Should we loop?
387 if (ctrl.state & CTRL::LOOP) {
388 /* Bi-directional looping */
389 if (ctrl.state & CTRL::BIDIRECTIONAL)
390 ctrl.state ^= CTRL::DECREASING;
391 ctrl.pos = (ctrl.state & CTRL::DECREASING)
392 ? ctrl.end - remaining
393 : ctrl.start + remaining;
394 }
395 // Otherwise, restart the position back to its start or end
396 else {
397 ctrl.state |= 1; // Stop the voice
398 ctrl.pos = (ctrl.state & CTRL::DECREASING) ? ctrl.start : ctrl.end;
399 }
400 return;
401 }
402
Is8Bit() const403 bool Voice::Is8Bit() const noexcept
404 {
405 return !(wave_ctrl.state & CTRL::BIT16);
406 }
407
GetSample(const ram_array_t & ram)408 float Voice::GetSample(const ram_array_t &ram) noexcept
409 {
410 const int32_t pos = PopWavePos();
411 const auto addr = pos / WAVE_WIDTH;
412 const auto fraction = pos & (WAVE_WIDTH - 1);
413 const bool should_interpolate = wave_ctrl.inc < WAVE_WIDTH && fraction;
414 float sample = Is8Bit() ? Read8BitSample(ram, addr)
415 : Read16BitSample(ram, addr);
416 if (should_interpolate) {
417 const auto next_addr = addr + 1;
418 const float next_sample = Is8Bit() ? Read8BitSample(ram, next_addr)
419 : Read16BitSample(ram, next_addr);
420 constexpr float WAVE_WIDTH_INV = 1.0 / WAVE_WIDTH;
421 sample += (next_sample - sample) *
422 static_cast<float>(fraction) * WAVE_WIDTH_INV;
423 }
424 assert(sample >= static_cast<float>(MIN_AUDIO) &&
425 sample <= static_cast<float>(MAX_AUDIO));
426 return sample;
427 }
428
GenerateSamples(std::vector<float> & render_buffer,const ram_array_t & ram,const vol_scalars_array_t & vol_scalars,const pan_scalars_array_t & pan_scalars,const uint16_t requested_frames)429 void Voice::GenerateSamples(std::vector<float> &render_buffer,
430 const ram_array_t &ram,
431 const vol_scalars_array_t &vol_scalars,
432 const pan_scalars_array_t &pan_scalars,
433 const uint16_t requested_frames)
434 {
435 if (vol_ctrl.state & wave_ctrl.state & CTRL::DISABLED)
436 return;
437
438 // Setup our iterators and pan percents
439 auto val = render_buffer.begin();
440 const auto last_val = val + requested_frames * 2; // L * R channels
441 assert(last_val <= render_buffer.end());
442 const auto pan_scalar = pan_scalars.at(pan_position);
443
444 // Add the samples to the render_buffer, angled in L-R space
445 while (val < last_val) {
446 float sample = GetSample(ram);
447 sample *= PopVolScalar(vol_scalars);
448 *val++ += sample * pan_scalar.left;
449 *val++ += sample * pan_scalar.right;
450 }
451 // Keep track of how many ms this voice has generated
452 Is8Bit() ? generated_8bit_ms++ : generated_16bit_ms++;
453 }
454
455 // Returns the current wave position and increments the position
456 // to the next wave position.
PopWavePos()457 int32_t Voice::PopWavePos() noexcept
458 {
459 const int32_t current_pos = wave_ctrl.pos;
460 IncrementCtrlPos(wave_ctrl, CheckWaveRolloverCondition());
461 return current_pos;
462 }
463
464 // Returns the current vol scalar and increments the volume control's position.
PopVolScalar(const vol_scalars_array_t & vol_scalars)465 float Voice::PopVolScalar(const vol_scalars_array_t &vol_scalars)
466 {
467 // transform the current position into an index into the volume array
468 const auto i = ceil_sdivide(vol_ctrl.pos, VOLUME_INC_SCALAR);
469 IncrementCtrlPos(vol_ctrl, false); // don't check wave rollover
470 return vol_scalars.at(static_cast<size_t>(i));
471 }
472
473 // Read an 8-bit sample scaled into the 16-bit range, returned as a float
Read8BitSample(const ram_array_t & ram,const int32_t addr) const474 float Voice::Read8BitSample(const ram_array_t &ram, const int32_t addr) const noexcept
475 {
476 const auto i = static_cast<size_t>(addr) & 0xfffffu;
477 constexpr auto bits_in_16 = std::numeric_limits<int16_t>::digits;
478 constexpr auto bits_in_8 = std::numeric_limits<int8_t>::digits;
479 constexpr float to_16bit_range = 1 << (bits_in_16 - bits_in_8);
480 return static_cast<int8_t>(ram.at(i)) * to_16bit_range;
481 }
482
483 // Read a 16-bit sample returned as a float
Read16BitSample(const ram_array_t & ram,const int32_t addr) const484 float Voice::Read16BitSample(const ram_array_t &ram, const int32_t addr) const noexcept
485 {
486 // Calculate offset of the 16-bit sample
487 const auto lower = addr & 0b1100'0000'0000'0000'0000;
488 const auto upper = addr & 0b0001'1111'1111'1111'1111;
489 const auto i = static_cast<size_t>(lower | (upper << 1));
490 return static_cast<int16_t>(host_readw(&ram.at(i)));
491 }
492
ReadCtrlState(const VoiceCtrl & ctrl) const493 uint8_t Voice::ReadCtrlState(const VoiceCtrl &ctrl) const noexcept
494 {
495 uint8_t state = ctrl.state;
496 if (ctrl.irq_state & irq_mask)
497 state |= 0x80;
498 return state;
499 }
500
ReadVolState() const501 uint8_t Voice::ReadVolState() const noexcept
502 {
503 return ReadCtrlState(vol_ctrl);
504 }
505
ReadWaveState() const506 uint8_t Voice::ReadWaveState() const noexcept
507 {
508 return ReadCtrlState(wave_ctrl);
509 }
510
ResetCtrls()511 void Voice::ResetCtrls() noexcept
512 {
513 vol_ctrl.pos = 0u;
514 UpdateVolState(0x1);
515 UpdateWaveState(0x1);
516 WritePanPot(PAN_DEFAULT_POSITION);
517 }
518
UpdateCtrlState(VoiceCtrl & ctrl,uint8_t state)519 bool Voice::UpdateCtrlState(VoiceCtrl &ctrl, uint8_t state) noexcept
520 {
521 const uint32_t orig_irq_state = ctrl.irq_state;
522 // Manually set the irq
523 if ((state & 0xa0) == 0xa0)
524 ctrl.irq_state |= irq_mask;
525 else
526 ctrl.irq_state &= ~irq_mask;
527
528 // Always update the state
529 ctrl.state = state & 0x7f;
530
531 // Indicate if the IRQ state changed
532 return orig_irq_state != ctrl.irq_state;
533 }
534
UpdateVolState(uint8_t state)535 bool Voice::UpdateVolState(uint8_t state) noexcept
536 {
537 return UpdateCtrlState(vol_ctrl, state);
538 }
539
UpdateWaveState(uint8_t state)540 bool Voice::UpdateWaveState(uint8_t state) noexcept
541 {
542 return UpdateCtrlState(wave_ctrl, state);
543 }
544
WritePanPot(uint8_t pos)545 void Voice::WritePanPot(uint8_t pos) noexcept
546 {
547 constexpr uint8_t max_pos = PAN_POSITIONS - 1;
548 pan_position = std::min(pos, max_pos);
549 }
550
551 // Four volume-index-rate "banks" are available that define the number of
552 // volume indexes that will be incremented (or decremented, depending on the
553 // volume_ctrl value) each step, for a given voice. The banks are:
554 //
555 // - 0 to 63, which defines single index increments,
556 // - 64 to 127 defines fractional index increments by 1/8th,
557 // - 128 to 191 defines fractional index increments by 1/64ths, and
558 // - 192 to 255 defines fractional index increments by 1/512ths.
559 //
560 // To ensure the smallest increment (1/512) effects an index change, we
561 // normalize all the volume index variables (including this) by multiplying by
562 // VOLUME_INC_SCALAR (or 512). Note that "index" qualifies all these variables
563 // because they are merely indexes into the vol_scalars[] array. The actual
564 // volume scalar value (a floating point fraction between 0.0 and 1.0) is never
565 // actually operated on, and is simply looked up from the final index position
566 // at the time of sample population.
WriteVolRate(uint16_t val)567 void Voice::WriteVolRate(uint16_t val) noexcept
568 {
569 vol_ctrl.rate = val;
570 constexpr uint8_t bank_lengths = 63u;
571 const int pos_in_bank = val & bank_lengths;
572 const int decimator = 1 << (3 * (val >> 6));
573 vol_ctrl.inc = ceil_sdivide(pos_in_bank * VOLUME_INC_SCALAR, decimator);
574
575 // Sanity check the bounds of the incrementer
576 assert(vol_ctrl.inc >= 0 && vol_ctrl.inc <= bank_lengths * VOLUME_INC_SCALAR);
577 }
578
WriteWaveRate(uint16_t val)579 void Voice::WriteWaveRate(uint16_t val) noexcept
580 {
581 wave_ctrl.rate = val;
582 wave_ctrl.inc = ceil_udivide(val, 2u);
583 }
584
Gus(uint16_t port,uint8_t dma,uint8_t irq,const std::string & ultradir)585 Gus::Gus(uint16_t port, uint8_t dma, uint8_t irq, const std::string &ultradir)
586 : render_buffer(BUFFER_FRAMES * 2), // 2 samples/frame, L & R channels
587 play_buffer(BUFFER_FRAMES * 2), // 2 samples/frame, L & R channels
588 soft_limiter("GUS"),
589 port_base(port - 0x200u),
590 dma2(dma),
591 irq1(irq),
592 irq2(irq)
593 {
594 // Create the internal voice channels
595 for (uint8_t i = 0; i < MAX_VOICES; ++i) {
596 voices.at(i) = std::make_unique<Voice>(i, voice_irq);
597 }
598
599 RegisterIoHandlers();
600
601 // Register the Audio and DMA channels
602 const auto mixer_callback = std::bind(&Gus::AudioCallback, this,
603 std::placeholders::_1);
604 audio_channel = MIXER_AddChannel(mixer_callback, 1, "GUS");
605
606 // Let the mixer command adjust the GUS's internal amplitude level's
607 const auto set_level_callback = std::bind(&Gus::SetLevelCallback, this, _1);
608 audio_channel->RegisterLevelCallBack(set_level_callback);
609
610 UpdateDmaAddress(dma);
611
612 // Populate the volume, pan, and auto-exec arrays
613 PopulateVolScalars();
614 PopulatePanScalars();
615 PopulateAutoExec(port, ultradir);
616 }
617
ActivateVoices(uint8_t requested_voices)618 void Gus::ActivateVoices(uint8_t requested_voices)
619 {
620 requested_voices = clamp(requested_voices, MIN_VOICES, MAX_VOICES);
621 if (requested_voices != active_voices) {
622 active_voices = requested_voices;
623 assert(active_voices <= voices.size());
624 active_voice_mask = 0xffffffffu >> (MAX_VOICES - active_voices);
625 playback_rate = static_cast<uint32_t>(
626 round(1000000.0 / (1.619695497 * active_voices)));
627 audio_channel->SetFreq(playback_rate);
628 }
629 }
630
SetLevelCallback(const AudioFrame & levels)631 void Gus::SetLevelCallback(const AudioFrame &levels)
632 {
633 soft_limiter.UpdateLevels(levels, 1);
634 }
635
AudioCallback(const uint16_t requested_frames)636 void Gus::AudioCallback(const uint16_t requested_frames)
637 {
638 uint16_t generated_frames = 0;
639 while (generated_frames < requested_frames) {
640 const uint16_t frames = static_cast<uint16_t>(
641 std::min(BUFFER_FRAMES, requested_frames - generated_frames));
642
643 // Zero our buffer. The audio sequence for each active voice
644 // will be accumulated one at a time by the buffer's elements.
645 assert(frames <= render_buffer.size());
646 const auto num_samples = frames * 2;
647 std::fill_n(render_buffer.begin(), num_samples, 0.0f);
648
649 if (dac_enabled) {
650 auto voice = voices.begin();
651 const auto last_voice = voice + active_voices;
652 while (voice < last_voice && *voice) {
653 voice->get()->GenerateSamples(render_buffer,
654 ram, vol_scalars,
655 pan_scalars, frames);
656 ++voice;
657 }
658 }
659 soft_limiter.Process(render_buffer, frames, play_buffer);
660 audio_channel->AddSamples_s16(frames, play_buffer.data());
661 CheckVoiceIrq();
662 generated_frames += frames;
663 }
664 }
665
BeginPlayback()666 void Gus::BeginPlayback()
667 {
668 dac_enabled = ((register_data & 0x200) != 0);
669 irq_enabled = ((register_data & 0x400) != 0);
670 audio_channel->Enable(true);
671 if (prev_logged_voices != active_voices) {
672 LOG_MSG("GUS: Activated %u voices at %u Hz", active_voices,
673 playback_rate);
674 prev_logged_voices = active_voices;
675 }
676 is_running = true;
677 }
678
CheckIrq()679 void Gus::CheckIrq()
680 {
681 const bool should_interrupt = irq_status & (irq_enabled ? 0xff : 0x9f);
682 const bool lines_enabled = mix_ctrl & 0x08;
683 if (should_interrupt && lines_enabled)
684 PIC_ActivateIRQ(irq1);
685 }
686
CheckTimer(const size_t t)687 bool Gus::CheckTimer(const size_t t)
688 {
689 auto &timer = t == 0 ? timer_one : timer_two;
690 if (!timer.is_masked)
691 timer.has_expired = true;
692 if (timer.should_raise_irq) {
693 irq_status |= 0x4 << t;
694 CheckIrq();
695 }
696 return timer.is_counting_down;
697 }
698
CheckVoiceIrq()699 void Gus::CheckVoiceIrq()
700 {
701 irq_status &= 0x9f;
702 const Bitu totalmask = (voice_irq.vol_state | voice_irq.wave_state) &
703 active_voice_mask;
704 if (!totalmask)
705 return;
706 if (voice_irq.vol_state)
707 irq_status |= 0x40;
708 if (voice_irq.wave_state)
709 irq_status |= 0x20;
710 CheckIrq();
711 while (!(totalmask & 1ULL << voice_irq.status)) {
712 voice_irq.status++;
713 if (voice_irq.status >= active_voices)
714 voice_irq.status = 0;
715 }
716 }
717
Dma8Addr()718 uint32_t Gus::Dma8Addr() noexcept
719 {
720 return static_cast<uint32_t>(dma_addr << 4);
721 }
722
Dma16Addr()723 uint32_t Gus::Dma16Addr() noexcept
724 {
725 const auto lower = dma_addr & 0b0001'1111'1111'1111;
726 const auto upper = dma_addr & 0b1100'0000'0000'0000;
727 const auto combined = (lower << 1) | upper;
728 return static_cast<uint32_t>(combined << 4);
729 }
730
PerformDmaTransfer()731 bool Gus::PerformDmaTransfer()
732 {
733 if (dma_channel->masked || !(dma_ctrl & 0x01))
734 return false;
735
736 #if LOG_GUS
737 LOG_MSG("GUS DMA event: max %u bytes. DMA: tc=%u mask=0 cnt=%u",
738 BYTES_PER_DMA_XFER, dma_channel->tcount ? 1 : 0,
739 dma_channel->currcnt + 1);
740 #endif
741
742 const auto offset = IsDmaXfer16Bit() ? Dma16Addr() : Dma8Addr();
743 const uint16_t desired = dma_channel->currcnt + 1;
744
745 // All of the operations below involve reading, writing, or skipping
746 // starting at the offset for N-desired samples
747 assert(static_cast<size_t>(offset) + desired <= ram.size());
748
749 // Copy samples via DMA from GUS memory
750 if (dma_ctrl & 0x2) {
751 dma_channel->Write(desired, &ram.at(offset));
752 }
753 // Skip DMA content
754 else if (!(dma_ctrl & 0x80)) {
755 dma_channel->Read(desired, &ram.at(offset));
756 }
757 // Copy samples via DMA into GUS memory
758 else {
759 //
760 const auto samples = dma_channel->Read(desired, &ram.at(offset));
761 auto ram_pos = ram.begin() + offset;
762 const auto positions = samples *
763 (static_cast<size_t>(dma_channel->DMA16) + 1u);
764 const auto ram_pos_end = ram_pos + positions;
765 // adjust our start and skip size if handling 16-bit
766 ram_pos += IsDmaPcm16Bit() ? 1u : 0u;
767 const auto skip = IsDmaPcm16Bit() ? 2u : 1u;
768 assert(ram_pos >= ram.begin() && ram_pos <= ram_pos_end && ram_pos_end <= ram.end());
769 while (ram_pos < ram_pos_end) {
770 *ram_pos ^= 0x80;
771 ram_pos += skip;
772 }
773 }
774 // Raise the TC irq if needed
775 if ((dma_ctrl & 0x20) != 0) {
776 // We've hit the terminal count, so enable that bit
777 dma_ctrl |= DMA_TC_STATUS_BITMASK;
778 irq_status |= 0x80;
779 CheckIrq();
780 return false;
781 }
782 return true;
783 }
784
IsDmaPcm16Bit()785 bool Gus::IsDmaPcm16Bit() noexcept
786 {
787 return dma_ctrl & 0x40;
788 }
789
IsDmaXfer16Bit()790 bool Gus::IsDmaXfer16Bit() noexcept
791 {
792 // What bit-size should DMA memory be transferred as?
793 // Mode PCM/DMA Address Use-16 Note
794 // 0x00 8/ 8 Any No Most DOS programs
795 // 0x04 8/16 >= 4 Yes 16-bit if using High DMA
796 // 0x04 8/16 < 4 No 8-bit if using Low DMA
797 // 0x40 16/ 8 Any No Windows 3.1, Quake
798 // 0x44 16/16 >= 4 Yes Windows 3.1, Quake
799 return (dma_ctrl & 0x4) && (dma1 >= 4);
800 }
801
GUS_DMA_Event(uint32_t)802 static void GUS_DMA_Event(uint32_t)
803 {
804 if (gus->PerformDmaTransfer())
805 PIC_AddEvent(GUS_DMA_Event, MS_PER_DMA_XFER);
806 }
807
StartDmaTransfers()808 void Gus::StartDmaTransfers()
809 {
810 PIC_AddEvent(GUS_DMA_Event, MS_PER_DMA_XFER);
811 }
812
DmaCallback(DmaChannel *,DMAEvent event)813 void Gus::DmaCallback(DmaChannel *, DMAEvent event)
814 {
815 if (event == DMA_UNMASKED)
816 StartDmaTransfers();
817 }
818
PopulateAutoExec(uint16_t port,const std::string & ultradir)819 void Gus::PopulateAutoExec(uint16_t port, const std::string &ultradir)
820 {
821 // Ensure our port and addresses will fit in our format widths
822 // The config selection controls their actual values, so this is a
823 // maximum-limit.
824 assert(port < 0xfff);
825 assert(dma1 < 10 && dma2 < 10);
826 assert(irq1 < 10 && irq2 < 10);
827
828 // ULTRASND variable
829 char set_ultrasnd[] = "@SET ULTRASND=HHH,D,D,I,I";
830 safe_sprintf(set_ultrasnd,
831 "@SET ULTRASND=%x,%u,%u,%u,%u", port, dma1, dma2, irq1, irq2);
832 LOG_MSG("GUS: %s", set_ultrasnd);
833 autoexec_lines.at(0).Install(set_ultrasnd);
834
835 // ULTRADIR variable
836 std::string dirline = "@SET ULTRADIR=" + ultradir;
837 autoexec_lines.at(1).Install(dirline);
838 }
839
840 // Generate logarithmic to linear volume conversion tables
PopulateVolScalars()841 void Gus::PopulateVolScalars() noexcept
842 {
843 constexpr auto VOLUME_LEVEL_DIVISOR = 1.0 + DELTA_DB;
844 double scalar = 1.0;
845 auto volume = vol_scalars.end();
846 // The last element starts at 1.0 and we divide downward to
847 // the first element that holds zero, which is directly assigned
848 // after the loop.
849 while (volume != vol_scalars.begin()) {
850 *(--volume) = static_cast<float>(scalar);
851 scalar /= VOLUME_LEVEL_DIVISOR;
852 }
853 vol_scalars.front() = 0.0;
854 }
855
856 /*
857 Constant-Power Panning
858 -------------------------
859 The GUS SDK describes having 16 panning positions (0 through 15)
860 with 0 representing the full-left rotation, 7 being the mid-point,
861 and 15 being the full-right rotation. The SDK also describes
862 that output power is held constant through this range.
863
864 #!/usr/bin/env python3
865 import math
866 print(f'Left-scalar Pot Norm. Right-scalar | Power')
867 print(f'----------- --- ----- ------------ | -----')
868 for pot in range(16):
869 norm = (pot - 7.) / (7.0 if pot < 7 else 8.0)
870 direction = math.pi * (norm + 1.0 ) / 4.0
871 lscale = math.cos(direction)
872 rscale = math.sin(direction)
873 power = lscale * lscale + rscale * rscale
874 print(f'{lscale:.5f} <~~~ {pot:2} ({norm:6.3f})'\
875 f' ~~~> {rscale:.5f} | {power:.3f}')
876
877 Left-scalar Pot Norm. Right-scalar | Power
878 ----------- --- ----- ------------ | -----
879 1.00000 <~~~ 0 (-1.000) ~~~> 0.00000 | 1.000
880 0.99371 <~~~ 1 (-0.857) ~~~> 0.11196 | 1.000
881 0.97493 <~~~ 2 (-0.714) ~~~> 0.22252 | 1.000
882 0.94388 <~~~ 3 (-0.571) ~~~> 0.33028 | 1.000
883 0.90097 <~~~ 4 (-0.429) ~~~> 0.43388 | 1.000
884 0.84672 <~~~ 5 (-0.286) ~~~> 0.53203 | 1.000
885 0.78183 <~~~ 6 (-0.143) ~~~> 0.62349 | 1.000
886 0.70711 <~~~ 7 ( 0.000) ~~~> 0.70711 | 1.000
887 0.63439 <~~~ 8 ( 0.125) ~~~> 0.77301 | 1.000
888 0.55557 <~~~ 9 ( 0.250) ~~~> 0.83147 | 1.000
889 0.47140 <~~~ 10 ( 0.375) ~~~> 0.88192 | 1.000
890 0.38268 <~~~ 11 ( 0.500) ~~~> 0.92388 | 1.000
891 0.29028 <~~~ 12 ( 0.625) ~~~> 0.95694 | 1.000
892 0.19509 <~~~ 13 ( 0.750) ~~~> 0.98079 | 1.000
893 0.09802 <~~~ 14 ( 0.875) ~~~> 0.99518 | 1.000
894 0.00000 <~~~ 15 ( 1.000) ~~~> 1.00000 | 1.000
895 */
PopulatePanScalars()896 void Gus::PopulatePanScalars() noexcept
897 {
898 int i = 0;
899 auto pan_scalar = pan_scalars.begin();
900 while (pan_scalar != pan_scalars.end()) {
901 // Normalize absolute range [0, 15] to [-1.0, 1.0]
902 const auto norm = (i - 7.0) / (i < 7 ? 7 : 8);
903 // Convert to an angle between 0 and 90-degree, in radians
904 const auto angle = (norm + 1) * M_PI / 4;
905 pan_scalar->left = static_cast<float>(cos(angle));
906 pan_scalar->right = static_cast<float>(sin(angle));
907 ++pan_scalar;
908 ++i;
909 // DEBUG_LOG_MSG("GUS: pan_scalar[%u] = %f | %f", i,
910 // pan_scalar->left,
911 // pan_scalar->right);
912 }
913 }
914
PrepareForPlayback()915 void Gus::PrepareForPlayback() noexcept
916 {
917 // Initialize the voice states
918 for (auto &voice : voices)
919 voice->ResetCtrls();
920
921 // Initialize the OPL emulator state
922 adlib_command_reg = ADLIB_CMD_DEFAULT;
923
924 voice_irq = VoiceIrq{};
925 timer_one = Timer{TIMER_1_DEFAULT_DELAY};
926 timer_two = Timer{TIMER_2_DEFAULT_DELAY};
927
928 if (!is_running) {
929 register_data = 0x100; // DAC/IRQ disabled
930 is_running = true;
931 }
932 }
933
PrintStats()934 void Gus::PrintStats()
935 {
936 // Aggregate stats from all voices
937 uint32_t combined_8bit_ms = 0u;
938 uint32_t combined_16bit_ms = 0u;
939 uint32_t used_8bit_voices = 0u;
940 uint32_t used_16bit_voices = 0u;
941 for (const auto &voice : voices) {
942 if (voice->generated_8bit_ms) {
943 combined_8bit_ms += voice->generated_8bit_ms;
944 used_8bit_voices++;
945 }
946 if (voice->generated_16bit_ms) {
947 combined_16bit_ms += voice->generated_16bit_ms;
948 used_16bit_voices++;
949 }
950 }
951 const uint32_t combined_ms = combined_8bit_ms + combined_16bit_ms;
952
953 // Is there enough information to be meaningful?
954 const auto peak = soft_limiter.GetPeaks();
955 if (combined_ms < 10000u || (peak.left + peak.right) < 10 ||
956 !(used_8bit_voices + used_16bit_voices))
957 return;
958
959 // Print info about the type of audio and voices used
960 if (used_16bit_voices == 0u)
961 LOG_MSG("GUS: Audio comprised of 8-bit samples from %u voices",
962 used_8bit_voices);
963 else if (used_8bit_voices == 0u)
964 LOG_MSG("GUS: Audio comprised of 16-bit samples from %u voices",
965 used_16bit_voices);
966 else {
967 const auto ratio_8bit = ceil_udivide(100u * combined_8bit_ms,
968 combined_ms);
969 const auto ratio_16bit = ceil_udivide(100u * combined_16bit_ms,
970 combined_ms);
971 LOG_MSG("GUS: Audio was made up of %u%% 8-bit %u-voice and "
972 "%u%% 16-bit %u-voice samples",
973 ratio_8bit, used_8bit_voices, ratio_16bit,
974 used_16bit_voices);
975 }
976 soft_limiter.PrintStats();
977 }
978
ReadFromPort(const io_port_t port,io_width_t width)979 uint16_t Gus::ReadFromPort(const io_port_t port, io_width_t width)
980 {
981 // LOG_MSG("GUS: Read from port %x", port);
982 switch (port - port_base) {
983 case 0x206: return irq_status;
984 case 0x208:
985 uint8_t time;
986 time = 0u;
987 if (timer_one.has_expired)
988 time |= (1 << 6);
989 if (timer_two.has_expired)
990 time |= 1 << 5;
991 if (time & 0x60)
992 time |= 1 << 7;
993 if (irq_status & 0x04)
994 time |= 1 << 2;
995 if (irq_status & 0x08)
996 time |= 1 << 1;
997 return time;
998 case 0x20a: return adlib_command_reg;
999 case 0x302: return static_cast<uint8_t>(voice_index);
1000 case 0x303: return selected_register;
1001 case 0x304:
1002 if (width == io_width_t::word)
1003 return ReadFromRegister() & 0xffff;
1004 else
1005 return ReadFromRegister() & 0xff;
1006 case 0x305: return ReadFromRegister() >> 8;
1007 case 0x307:
1008 return dram_addr < ram.size() ? ram.at(dram_addr) : 0;
1009 default:
1010 #if LOG_GUS
1011 LOG_MSG("GUS: Read at port %#x", port);
1012 #endif
1013 break;
1014 }
1015 return 0xff;
1016 }
1017
ReadFromRegister()1018 uint16_t Gus::ReadFromRegister()
1019 {
1020 // LOG_MSG("GUS: Read register %x", selected_register);
1021 uint8_t reg = 0;
1022
1023 // Registers that read from the general DSP
1024 switch (selected_register) {
1025 case 0x41: // DMA control register - read acknowledges DMA IRQ
1026 reg = dma_ctrl & 0xbf;
1027 // get the status and store it in bit 6 of the register
1028 reg |= (dma_ctrl & DMA_TC_STATUS_BITMASK) >> 2;
1029 dma_ctrl &= ~DMA_TC_STATUS_BITMASK; // clear the status bit
1030 irq_status &= 0x7f;
1031 CheckIrq();
1032 return static_cast<uint16_t>(reg << 8);
1033 case 0x42: // DMA address register
1034 return dma_addr;
1035 case 0x45: // Timer control register matches Adlib's behavior
1036 return static_cast<uint16_t>(timer_ctrl << 8);
1037 case 0x49: // DMA sample register
1038 reg = dma_ctrl & 0xbf;
1039 // get the status and store it in bit 6 of the register
1040 reg |= (dma_ctrl & DMA_TC_STATUS_BITMASK) >> 2;
1041 return static_cast<uint16_t>(reg << 8);
1042 case 0x4c: // Reset register
1043 reg = is_running ? 1 : 0;
1044 if (dac_enabled)
1045 reg |= 2;
1046 if (irq_enabled)
1047 reg |= 4;
1048 return static_cast<uint16_t>(reg << 8);
1049 case 0x8f: // General voice IRQ status register
1050 reg = voice_irq.status | 0x20;
1051 uint32_t mask;
1052 mask = 1 << voice_irq.status;
1053 if (!(voice_irq.vol_state & mask))
1054 reg |= 0x40;
1055 if (!(voice_irq.wave_state & mask))
1056 reg |= 0x80;
1057 voice_irq.vol_state &= ~mask;
1058 voice_irq.wave_state &= ~mask;
1059 CheckVoiceIrq();
1060 return static_cast<uint16_t>(reg << 8);
1061 default:
1062 break;
1063 // If the above weren't triggered, then fall-through
1064 // to the voice-specific register switch below.
1065 }
1066
1067 if (!target_voice)
1068 return (selected_register == 0x80 || selected_register == 0x8d)
1069 ? 0x0300
1070 : 0u;
1071
1072 // Registers that read from from the current voice
1073 switch (selected_register) {
1074 case 0x80: // Voice wave control read register
1075 return static_cast<uint16_t>(target_voice->ReadWaveState() << 8);
1076 case 0x82: // Voice MSB start address register
1077 return static_cast<uint16_t>(target_voice->wave_ctrl.start >> 16);
1078 case 0x83: // Voice LSW start address register
1079 return static_cast<uint16_t>(target_voice->wave_ctrl.start);
1080 case 0x89: // Voice volume register
1081 {
1082 const int i = ceil_sdivide(target_voice->vol_ctrl.pos,
1083 VOLUME_INC_SCALAR);
1084 assert(i >= 0 && i < static_cast<int>(vol_scalars.size()));
1085 return static_cast<uint16_t>(i << 4);
1086 }
1087 case 0x8a: // Voice MSB current address register
1088 return static_cast<uint16_t>(target_voice->wave_ctrl.pos >> 16);
1089 case 0x8b: // Voice LSW current address register
1090 return static_cast<uint16_t>(target_voice->wave_ctrl.pos);
1091 case 0x8d: // Voice volume control register
1092 return static_cast<uint16_t>(target_voice->ReadVolState() << 8);
1093 default:
1094 #if LOG_GUS
1095 LOG_MSG("GUS: Register %#x not implemented for reading",
1096 selected_register);
1097 #endif
1098 break;
1099 }
1100 return register_data;
1101 }
1102
RegisterIoHandlers()1103 void Gus::RegisterIoHandlers()
1104 {
1105 // Register the IO read addresses
1106 assert(read_handlers.size() > 7);
1107 const auto read_from = std::bind(&Gus::ReadFromPort, this, _1, _2);
1108 read_handlers.at(0).Install(0x302 + port_base, read_from, io_width_t::byte);
1109 read_handlers.at(1).Install(0x303 + port_base, read_from, io_width_t::byte);
1110 read_handlers.at(2).Install(0x304 + port_base, read_from, io_width_t::word);
1111 read_handlers.at(3).Install(0x305 + port_base, read_from, io_width_t::byte);
1112 read_handlers.at(4).Install(0x206 + port_base, read_from, io_width_t::byte);
1113 read_handlers.at(5).Install(0x208 + port_base, read_from, io_width_t::byte);
1114 read_handlers.at(6).Install(0x307 + port_base, read_from, io_width_t::byte);
1115 // Board Only
1116 read_handlers.at(7).Install(0x20a + port_base, read_from, io_width_t::byte);
1117
1118 // Register the IO write addresses
1119 // We'll leave the MIDI interface to the MPU-401
1120 // Ditto for the Joystick
1121 // GF1 Synthesizer
1122 assert(write_handlers.size() > 8);
1123 const auto write_to = std::bind(&Gus::WriteToPort, this, _1, _2, _3);
1124 write_handlers.at(0).Install(0x302 + port_base, write_to, io_width_t::byte);
1125 write_handlers.at(1).Install(0x303 + port_base, write_to, io_width_t::byte);
1126 write_handlers.at(2).Install(0x304 + port_base, write_to, io_width_t::word);
1127 write_handlers.at(3).Install(0x305 + port_base, write_to, io_width_t::byte);
1128 write_handlers.at(4).Install(0x208 + port_base, write_to, io_width_t::byte);
1129 write_handlers.at(5).Install(0x209 + port_base, write_to, io_width_t::byte);
1130 write_handlers.at(6).Install(0x307 + port_base, write_to, io_width_t::byte);
1131 // Board Only
1132 write_handlers.at(7).Install(0x200 + port_base, write_to, io_width_t::byte);
1133 write_handlers.at(8).Install(0x20b + port_base, write_to, io_width_t::byte);
1134 }
1135
StopPlayback()1136 void Gus::StopPlayback()
1137 {
1138 // Halt playback before altering the DSP state
1139 audio_channel->Enable(false);
1140
1141 soft_limiter.Reset();
1142
1143 dac_enabled = false;
1144 irq_enabled = false;
1145 irq_status = 0;
1146
1147 dma_ctrl = 0u;
1148 mix_ctrl = 0xb; // latches enabled, LINEs disabled
1149 timer_ctrl = 0u;
1150 sample_ctrl = 0u;
1151
1152 target_voice = nullptr;
1153 voice_index = 0u;
1154 active_voices = 0u;
1155
1156 dma_addr = 0u;
1157 dram_addr = 0u;
1158 register_data = 0u;
1159 selected_register = 0u;
1160 should_change_irq_dma = false;
1161 PIC_RemoveEvents(GUS_TimerEvent);
1162 is_running = false;
1163 }
1164
GUS_TimerEvent(uint32_t t)1165 static void GUS_TimerEvent(uint32_t t)
1166 {
1167 if (gus->CheckTimer(t)) {
1168 const auto &timer = t == 0 ? gus->timer_one : gus->timer_two;
1169 PIC_AddEvent(GUS_TimerEvent, timer.delay, t);
1170 }
1171 }
1172
UpdateDmaAddress(const uint8_t new_address)1173 void Gus::UpdateDmaAddress(const uint8_t new_address)
1174 {
1175 // Has it changed?
1176 if (new_address == dma1)
1177 return;
1178
1179 // Unregister the current callback
1180 if (dma_channel)
1181 dma_channel->Register_Callback(nullptr);
1182
1183 // Update the address, channel, and callback
1184 dma1 = new_address;
1185 dma_channel = GetDMAChannel(dma1);
1186 assert(dma_channel);
1187 dma_channel->Register_Callback(std::bind(&Gus::DmaCallback, this, _1, _2));
1188 #if LOG_GUS
1189 LOG_MSG("GUS: Assigned DMA1 address to %u", dma1);
1190 #endif
1191 }
1192
WriteToPort(io_port_t port,io_val_t value,io_width_t width)1193 void Gus::WriteToPort(io_port_t port, io_val_t value, io_width_t width)
1194 {
1195 const auto val = check_cast<uint16_t>(value);
1196
1197 // LOG_MSG("GUS: Write to port %x val %x", port, val);
1198 switch (port - port_base) {
1199 case 0x200:
1200 mix_ctrl = static_cast<uint8_t>(val);
1201 should_change_irq_dma = true;
1202 return;
1203 case 0x208: adlib_command_reg = static_cast<uint8_t>(val); break;
1204 case 0x209:
1205 // TODO adlib_command_reg should be 4 for this to work
1206 // else it should just latch the value
1207 if (val & 0x80) {
1208 timer_one.has_expired = false;
1209 timer_two.has_expired = false;
1210 return;
1211 }
1212 timer_one.is_masked = (val & 0x40) > 0;
1213 timer_two.is_masked = (val & 0x20) > 0;
1214 if (val & 0x1) {
1215 if (!timer_one.is_counting_down) {
1216 PIC_AddEvent(GUS_TimerEvent, timer_one.delay, 0);
1217 timer_one.is_counting_down = true;
1218 }
1219 } else
1220 timer_one.is_counting_down = false;
1221 if (val & 0x2) {
1222 if (!timer_two.is_counting_down) {
1223 PIC_AddEvent(GUS_TimerEvent, timer_two.delay, 1);
1224 timer_two.is_counting_down = true;
1225 }
1226 } else
1227 timer_two.is_counting_down = false;
1228 break;
1229 // TODO Check if 0x20a register is also available on the gus
1230 // like on the interwave
1231 case 0x20b:
1232 if (!should_change_irq_dma)
1233 break;
1234 should_change_irq_dma = false;
1235 if (mix_ctrl & 0x40) {
1236 // IRQ configuration, only use low bits for irq 1
1237 const auto i = val & 7u;
1238 const auto &address = irq_addresses.at(i);
1239 if (address)
1240 irq1 = address;
1241 #if LOG_GUS
1242 LOG_MSG("GUS: Assigned IRQ1 to %d", irq1);
1243 #endif
1244 } else {
1245 // DMA configuration, only use low bits for dma 1
1246 const uint8_t i = val & 0x7;
1247 const auto address = dma_addresses.at(i);
1248 if (address)
1249 UpdateDmaAddress(address);
1250 }
1251 break;
1252 case 0x302:
1253 voice_index = val & 31;
1254 target_voice = voices.at(voice_index).get();
1255 break;
1256 case 0x303:
1257 selected_register = static_cast<uint8_t>(val);
1258 register_data = 0;
1259 break;
1260 case 0x304:
1261 if (width == io_width_t::word) {
1262 register_data = val;
1263 WriteToRegister();
1264 } else
1265 register_data = val;
1266 break;
1267 case 0x305:
1268 register_data = static_cast<uint16_t>((0x00ff & register_data) |
1269 val << 8);
1270 WriteToRegister();
1271 break;
1272 case 0x307:
1273 if (dram_addr < ram.size())
1274 ram.at(dram_addr) = static_cast<uint8_t>(val);
1275 break;
1276 default:
1277 #if LOG_GUS
1278 LOG_MSG("GUS: Write to port %#x with value %x", port, val);
1279 #endif
1280 break;
1281 }
1282 }
1283
UpdateWaveLsw(int32_t & addr) const1284 void Gus::UpdateWaveLsw(int32_t &addr) const noexcept
1285 {
1286 constexpr auto WAVE_LSW_MASK = ~((1 << 16) - 1); // Lower wave mask
1287 const auto lower = addr & WAVE_LSW_MASK;
1288 addr = lower | register_data;
1289 }
1290
UpdateWaveMsw(int32_t & addr) const1291 void Gus::UpdateWaveMsw(int32_t &addr) const noexcept
1292 {
1293 constexpr auto WAVE_MSW_MASK = (1 << 16) - 1; // Upper wave mask
1294 const auto upper = register_data & 0x1fff;
1295 const auto lower = addr & WAVE_MSW_MASK;
1296 addr = lower | (upper << 16);
1297 }
1298
WriteToRegister()1299 void Gus::WriteToRegister()
1300 {
1301 // Registers that write to the general DSP
1302 switch (selected_register) {
1303 case 0xe: // Set number of active voices
1304 selected_register = register_data >> 8; // Jazz Jackrabbit needs this
1305 {
1306 const uint8_t num_voices = 1 + ((register_data >> 8) & 31);
1307 ActivateVoices(num_voices);
1308 }
1309 return;
1310 case 0x10: // Undocumented register used in Fast Tracker 2
1311 return;
1312 case 0x41: // DMA control register
1313 // Clear all bits except the status and then replace dma_ctrl's
1314 // lower bits with reg's top 8 bits
1315 dma_ctrl &= DMA_TC_STATUS_BITMASK;
1316 dma_ctrl |= register_data >> 8;
1317 if (dma_ctrl & 1)
1318 StartDmaTransfers();
1319 return;
1320 case 0x42: // Gravis DRAM DMA address register
1321 dma_addr = register_data;
1322 return;
1323 case 0x43: // LSW Peek/poke DRAM position
1324 dram_addr = (0xf0000 & dram_addr) |
1325 (static_cast<uint32_t>(register_data));
1326 return;
1327 case 0x44: // MSB Peek/poke DRAM position
1328 dram_addr = (0x0ffff & dram_addr) |
1329 (static_cast<uint32_t>(register_data) & 0x0f00) << 8;
1330 return;
1331 case 0x45: // Timer control register. Identical in operation to Adlib's
1332 timer_ctrl = static_cast<uint8_t>(register_data >> 8);
1333 timer_one.should_raise_irq = (timer_ctrl & 0x04) > 0;
1334 if (!timer_one.should_raise_irq)
1335 irq_status &= ~0x04;
1336 timer_two.should_raise_irq = (timer_ctrl & 0x08) > 0;
1337 if (!timer_two.should_raise_irq)
1338 irq_status &= ~0x08;
1339 return;
1340 case 0x46: // Timer 1 control
1341 timer_one.value = static_cast<uint8_t>(register_data >> 8);
1342 timer_one.delay = (0x100 - timer_one.value) * TIMER_1_DEFAULT_DELAY;
1343 return;
1344 case 0x47: // Timer 2 control
1345 timer_two.value = static_cast<uint8_t>(register_data >> 8);
1346 timer_two.delay = (0x100 - timer_two.value) * TIMER_2_DEFAULT_DELAY;
1347 return;
1348 case 0x49: // DMA sampling control register
1349 sample_ctrl = static_cast<uint8_t>(register_data >> 8);
1350 if (sample_ctrl & 1)
1351 StartDmaTransfers();
1352 return;
1353 case 0x4c: // Runtime control
1354 {
1355 const auto state = (register_data >> 8) & 7;
1356 if (state == 0)
1357 StopPlayback();
1358 else if (state == 1)
1359 PrepareForPlayback();
1360 else if (active_voices)
1361 BeginPlayback();
1362 }
1363 return;
1364 default:
1365 break;
1366 // If the above weren't triggered, then fall-through
1367 // to the target_voice-specific switch below.
1368 }
1369
1370 // All the registers below operated on the target voice
1371 if (!target_voice)
1372 return;
1373
1374 uint8_t data = 0;
1375 // Registers that write to the current voice
1376 switch (selected_register) {
1377 case 0x0: // Voice wave control register
1378 if (target_voice->UpdateWaveState(register_data >> 8))
1379 CheckVoiceIrq();
1380 break;
1381 case 0x1: // Voice rate control register
1382 target_voice->WriteWaveRate(register_data);
1383 break;
1384 case 0x2: // Voice MSW start address register
1385 UpdateWaveMsw(target_voice->wave_ctrl.start);
1386 break;
1387 case 0x3: // Voice LSW start address register
1388 UpdateWaveLsw(target_voice->wave_ctrl.start);
1389 break;
1390 case 0x4: // Voice MSW end address register
1391 UpdateWaveMsw(target_voice->wave_ctrl.end);
1392 break;
1393 case 0x5: // Voice LSW end address register
1394 UpdateWaveLsw(target_voice->wave_ctrl.end);
1395 break;
1396 case 0x6: // Voice volume rate register
1397 target_voice->WriteVolRate(register_data >> 8);
1398 break;
1399 case 0x7: // Voice volume start register EEEEMMMM
1400 data = register_data >> 8;
1401 // Don't need to bounds-check the value because it's implied:
1402 // 'data' is a uint8, so is 255 at most. 255 << 4 = 4080, which
1403 // falls within-bounds of the 4096-long vol_scalars array.
1404 target_voice->vol_ctrl.start = (data << 4) * VOLUME_INC_SCALAR;
1405 break;
1406 case 0x8: // Voice volume end register EEEEMMMM
1407 data = register_data >> 8;
1408 // Same as above regarding bound-checking.
1409 target_voice->vol_ctrl.end = (data << 4) * VOLUME_INC_SCALAR;
1410 break;
1411 case 0x9: // Voice current volume register
1412 // Don't need to bounds-check the value because it's implied:
1413 // reg data is a uint16, and 65535 >> 4 takes it down to 4095,
1414 // which is the last element in the 4096-long vol_scalars array.
1415 target_voice->vol_ctrl.pos = (register_data >> 4) * VOLUME_INC_SCALAR;
1416 break;
1417 case 0xa: // Voice MSW current address register
1418 UpdateWaveMsw(target_voice->wave_ctrl.pos);
1419 break;
1420 case 0xb: // Voice LSW current address register
1421 UpdateWaveLsw(target_voice->wave_ctrl.pos);
1422 break;
1423 case 0xc: // Voice pan pot register
1424 target_voice->WritePanPot(register_data >> 8);
1425 break;
1426 case 0xd: // Voice volume control register
1427 if (target_voice->UpdateVolState(register_data >> 8))
1428 CheckVoiceIrq();
1429 break;
1430 default:
1431 #if LOG_GUS
1432 LOG_MSG("GUS: Register %#x not implemented for writing",
1433 selected_register);
1434 #endif
1435 break;
1436 }
1437 return;
1438 }
1439
~Gus()1440 Gus::~Gus()
1441 {
1442 DEBUG_LOG_MSG("GUS: Shutting down");
1443 StopPlayback();
1444
1445 // remove the mixer channel
1446 audio_channel.reset();
1447
1448 // remove the IO handlers
1449 for (auto &rh : read_handlers)
1450 rh.Uninstall();
1451 for (auto &wh : write_handlers)
1452 wh.Uninstall();
1453 }
1454
gus_destroy(Section * sec)1455 static void gus_destroy([[maybe_unused]] Section *sec)
1456 {
1457 // GUS destroy is run when the user wants to deactivate the GUS:
1458 // C:\> config -set gus=false
1459 // TODO: therefore, this function should also remove the
1460 // ULTRASND and ULTRADIR environment variables.
1461
1462 if (gus) {
1463 gus->PrintStats();
1464 gus.reset();
1465 }
1466 }
1467
gus_init(Section * sec)1468 static void gus_init(Section *sec)
1469 {
1470 assert(sec);
1471 const Section_prop *conf = dynamic_cast<Section_prop *>(sec);
1472 if (!conf || !conf->Get_bool("gus"))
1473 return;
1474
1475 // Read the GUS config settings
1476 const auto port = static_cast<uint16_t>(conf->Get_hex("gusbase"));
1477 const auto dma = clamp(static_cast<uint8_t>(conf->Get_int("gusdma")), MIN_DMA_ADDRESS, MAX_DMA_ADDRESS);
1478 const auto irq = clamp(static_cast<uint8_t>(conf->Get_int("gusirq")), MIN_IRQ_ADDRESS, MAX_IRQ_ADDRESS);
1479 const std::string ultradir = conf->Get_string("ultradir");
1480
1481 // Instantiate the GUS with the settings
1482 gus = std::make_unique<Gus>(port, dma, irq, ultradir);
1483 sec->AddDestroyFunction(&gus_destroy, true);
1484 }
1485
init_gus_dosbox_settings(Section_prop & secprop)1486 void init_gus_dosbox_settings(Section_prop &secprop)
1487 {
1488 constexpr auto when_idle = Property::Changeable::WhenIdle;
1489
1490 auto *bool_prop = secprop.Add_bool("gus", when_idle, false);
1491 assert(bool_prop);
1492 bool_prop->Set_help("Enable Gravis UltraSound emulation.");
1493
1494 auto *hex_prop = secprop.Add_hex("gusbase", when_idle, 0x240);
1495 assert(hex_prop);
1496 const char *const bases[] = {"240", "220", "260", "280", "2a0",
1497 "2c0", "2e0", "300", nullptr};
1498 hex_prop->Set_values(bases);
1499 hex_prop->Set_help("The IO base address of the Gravis UltraSound.");
1500
1501 auto *int_prop = secprop.Add_int("gusirq", when_idle, 5);
1502 assert(int_prop);
1503 const char *const irqs[] = {"5", "3", "7", "9",
1504 "10", "11", "12", nullptr};
1505 int_prop->Set_values(irqs);
1506 int_prop->Set_help("The IRQ number of the Gravis UltraSound.");
1507
1508 int_prop = secprop.Add_int("gusdma", when_idle, 3);
1509 assert(int_prop);
1510 const char *const dmas[] = {"3", "0", "1", "5", "6", "7", nullptr};
1511 int_prop->Set_values(dmas);
1512 int_prop->Set_help("The DMA channel of the Gravis UltraSound.");
1513
1514 auto *str_prop = secprop.Add_string("ultradir", when_idle, "C:\\ULTRASND");
1515 assert(str_prop);
1516 str_prop->Set_help("Path to UltraSound directory. In this directory\n"
1517 "there should be a MIDI directory that contains\n"
1518 "the patch files for GUS playback. Patch sets used\n"
1519 "with Timidity should work fine.");
1520 }
1521
GUS_AddConfigSection(Config * conf)1522 void GUS_AddConfigSection(Config *conf)
1523 {
1524 assert(conf);
1525 Section_prop *sec = conf->AddSection_prop("gus", &gus_init, true);
1526 assert(sec);
1527 init_gus_dosbox_settings(*sec);
1528 }
1529