mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +00:00
All proper inputs are now provided to the audio generator.
Hopefully. The next job is to generate audio. If that sounds correct, then the disk motor speed question can be tackled.
This commit is contained in:
parent
723137c0d4
commit
6d985866ee
34
Machines/Apple/Macintosh/DeferredAudio.hpp
Normal file
34
Machines/Apple/Macintosh/DeferredAudio.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
//
|
||||
// DeferredAudio.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 01/06/2019.
|
||||
// Copyright © 2019 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef DeferredAudio_h
|
||||
#define DeferredAudio_h
|
||||
|
||||
#include "Audio.hpp"
|
||||
#include "../../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
|
||||
|
||||
namespace Apple {
|
||||
namespace Macintosh {
|
||||
|
||||
struct DeferredAudio {
|
||||
Concurrency::DeferringAsyncTaskQueue queue;
|
||||
Audio audio;
|
||||
Outputs::Speaker::LowpassSpeaker<Audio> speaker;
|
||||
HalfCycles time_since_update;
|
||||
|
||||
DeferredAudio() : audio(queue), speaker(audio) {}
|
||||
|
||||
void flush() {
|
||||
speaker.run_for(queue, time_since_update.flush_cycles());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DeferredAudio_h */
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "Audio.hpp"
|
||||
#include "DeferredAudio.hpp"
|
||||
#include "Keyboard.hpp"
|
||||
#include "RealTimeClock.hpp"
|
||||
#include "Video.hpp"
|
||||
@ -21,7 +21,6 @@
|
||||
|
||||
#include "../../../Components/6522/6522.hpp"
|
||||
#include "../../../Components/DiskII/IWM.hpp"
|
||||
#include "../../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
|
||||
#include "../../../Processors/68000/68000.hpp"
|
||||
|
||||
#include "../../Utility/MemoryPacker.hpp"
|
||||
@ -42,7 +41,7 @@ class ConcreteMachine:
|
||||
public:
|
||||
ConcreteMachine(const ROMMachine::ROMFetcher &rom_fetcher) :
|
||||
mc68000_(*this),
|
||||
video_(ram_.data()),
|
||||
video_(ram_.data(), audio_),
|
||||
via_(via_port_handler_),
|
||||
via_port_handler_(*this, clock_, keyboard_, video_, audio_, iwm_),
|
||||
iwm_(CLOCK_RATE) {
|
||||
@ -57,6 +56,7 @@ class ConcreteMachine:
|
||||
|
||||
// The Mac runs at 7.8336mHz.
|
||||
set_clock_rate(double(CLOCK_RATE));
|
||||
audio_.speaker.set_input_rate(float(CLOCK_RATE));
|
||||
}
|
||||
|
||||
void set_scan_target(Outputs::Display::ScanTarget *scan_target) override {
|
||||
@ -243,8 +243,8 @@ class ConcreteMachine:
|
||||
ROM_is_overlay_ = rom_is_overlay;
|
||||
}
|
||||
|
||||
void set_use_alternate_screen_buffer(bool use_alternate_screen_buffer) {
|
||||
video_.set_use_alternate_screen_buffer(use_alternate_screen_buffer);
|
||||
void set_use_alternate_buffers(bool use_alternate_screen_buffer, bool use_alternate_audio_buffer) {
|
||||
video_.set_use_alternate_buffers(use_alternate_screen_buffer, use_alternate_audio_buffer);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -259,22 +259,9 @@ class ConcreteMachine:
|
||||
}
|
||||
};
|
||||
|
||||
struct Audio {
|
||||
Concurrency::DeferringAsyncTaskQueue queue;
|
||||
Apple::Macintosh::Audio audio;
|
||||
Outputs::Speaker::LowpassSpeaker<Apple::Macintosh::Audio> speaker;
|
||||
HalfCycles time_since_update;
|
||||
|
||||
Audio() : audio(queue), speaker(audio) {}
|
||||
|
||||
void flush() {
|
||||
speaker.run_for(queue, time_since_update.flush_cycles());
|
||||
}
|
||||
};
|
||||
|
||||
class VIAPortHandler: public MOS::MOS6522::PortHandler {
|
||||
public:
|
||||
VIAPortHandler(ConcreteMachine &machine, RealTimeClock &clock, Keyboard &keyboard, Video &video, Audio &audio, IWM &iwm) :
|
||||
VIAPortHandler(ConcreteMachine &machine, RealTimeClock &clock, Keyboard &keyboard, Video &video, DeferredAudio &audio, IWM &iwm) :
|
||||
machine_(machine), clock_(clock), keyboard_(keyboard), video_(video), audio_(audio), iwm_(iwm) {}
|
||||
|
||||
using Port = MOS::MOS6522::Port;
|
||||
@ -299,13 +286,11 @@ class ConcreteMachine:
|
||||
iwm_.flush();
|
||||
iwm_.iwm.set_select(!(value & 0x20));
|
||||
|
||||
machine_.set_use_alternate_screen_buffer(!(value & 0x40));
|
||||
machine_.set_use_alternate_buffers(!(value & 0x40), !(value&0x08));
|
||||
machine_.set_rom_is_overlay(!!(value & 0x10));
|
||||
|
||||
audio_.flush();
|
||||
audio_.audio.set_volume(value & 7);
|
||||
|
||||
// TODO: alternate sound buffer.
|
||||
break;
|
||||
|
||||
case Port::B:
|
||||
@ -360,7 +345,7 @@ class ConcreteMachine:
|
||||
RealTimeClock &clock_;
|
||||
Keyboard &keyboard_;
|
||||
Video &video_;
|
||||
Audio &audio_;
|
||||
DeferredAudio &audio_;
|
||||
IWM &iwm_;
|
||||
};
|
||||
|
||||
@ -369,8 +354,8 @@ class ConcreteMachine:
|
||||
|
||||
CPU::MC68000::Processor<ConcreteMachine, true> mc68000_;
|
||||
|
||||
DeferredAudio audio_;
|
||||
Video video_;
|
||||
Audio audio_;
|
||||
|
||||
RealTimeClock clock_;
|
||||
Keyboard keyboard_;
|
||||
|
@ -33,7 +33,8 @@ const int sync_end = 38;
|
||||
// "The visible portion of a full-screen display consists of 342 horizontal scan lines...
|
||||
// During the vertical blanking interval, the turned-off beam ... traces out an additional 28 scan lines,"
|
||||
//
|
||||
Video::Video(uint16_t *ram) :
|
||||
Video::Video(uint16_t *ram, DeferredAudio &audio) :
|
||||
audio_(audio),
|
||||
crt_(704, 1, 370, Outputs::Display::ColourSpace::YIQ, 1, 1, 6, false, Outputs::Display::InputDataType::Luminance1),
|
||||
ram_(ram) {
|
||||
|
||||
@ -131,6 +132,14 @@ void Video::run_for(HalfCycles duration) {
|
||||
crt_.output_blank((44 - sync_end) * 16);
|
||||
}
|
||||
}
|
||||
|
||||
// Audio and disk fetches occur "just before video data".
|
||||
if(final_word == 44) {
|
||||
const uint16_t audio_word = ram_[audio_address_];
|
||||
++audio_address_;
|
||||
audio_.audio.post_sample(audio_word >> 8);
|
||||
// TODO: post disk byte.
|
||||
}
|
||||
}
|
||||
|
||||
duration -= cycles_left_in_line;
|
||||
@ -141,6 +150,12 @@ void Video::run_for(HalfCycles duration) {
|
||||
Video: $1A700 and the alternate buffer starts at $12700; for a 512K Macintosh, add $60000 to these numbers.
|
||||
*/
|
||||
video_address_ = use_alternate_screen_buffer_ ? (0x12700 >> 1) : (0x1a700 >> 1);
|
||||
|
||||
/*
|
||||
"The main sound buffer is at $1FD00 in a 128K Macintosh, and the alternate buffer is at $1A100;
|
||||
for a 512K Macintosh, add $60000 to these values."
|
||||
*/
|
||||
audio_address_ = use_alternate_audio_buffer_ ? (0x1fd00 >> 1) : (0x1a100 >> 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -156,7 +171,7 @@ bool Video::is_outputting() {
|
||||
return line < 342 && column < 32;
|
||||
}
|
||||
|
||||
void Video::set_use_alternate_screen_buffer(bool use_alternate_screen_buffer) {
|
||||
void Video::set_use_alternate_buffers(bool use_alternate_screen_buffer, bool use_alternate_audio_buffer) {
|
||||
use_alternate_screen_buffer_ = use_alternate_screen_buffer;
|
||||
use_alternate_audio_buffer_ = use_alternate_audio_buffer;
|
||||
}
|
||||
|
||||
|
@ -11,29 +11,38 @@
|
||||
|
||||
#include "../../../Outputs/CRT/CRT.hpp"
|
||||
#include "../../../ClockReceiver/ClockReceiver.hpp"
|
||||
#include "DeferredAudio.hpp"
|
||||
|
||||
namespace Apple {
|
||||
namespace Macintosh {
|
||||
|
||||
class Video {
|
||||
public:
|
||||
Video(uint16_t *ram);
|
||||
Video(uint16_t *ram, DeferredAudio &audio);
|
||||
void set_scan_target(Outputs::Display::ScanTarget *scan_target);
|
||||
void run_for(HalfCycles duration);
|
||||
void set_use_alternate_screen_buffer(bool use_alternate_screen_buffer);
|
||||
|
||||
void set_use_alternate_buffers(bool use_alternate_screen_buffer, bool use_alternate_audio_buffer);
|
||||
|
||||
// TODO: feedback on blanks and syncs.
|
||||
bool vsync();
|
||||
bool is_outputting();
|
||||
|
||||
private:
|
||||
DeferredAudio &audio_;
|
||||
uint16_t *ram_ = nullptr;
|
||||
|
||||
Outputs::CRT::CRT crt_;
|
||||
|
||||
HalfCycles frame_position_;
|
||||
|
||||
size_t video_address_ = 0;
|
||||
uint16_t *ram_ = nullptr;
|
||||
size_t audio_address_ = 0;
|
||||
|
||||
uint8_t *pixel_buffer_ = nullptr;
|
||||
|
||||
bool use_alternate_screen_buffer_ = false;
|
||||
bool use_alternate_audio_buffer_ = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1328,6 +1328,7 @@
|
||||
4BB298EC1B587D8400A49093 /* txsn */ = {isa = PBXFileReference; lastKnownFileType = file; path = txsn; sourceTree = "<group>"; };
|
||||
4BB298ED1B587D8400A49093 /* tyan */ = {isa = PBXFileReference; lastKnownFileType = file; path = tyan; sourceTree = "<group>"; };
|
||||
4BB2A9AE1E13367E001A5C23 /* CRCTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CRCTests.mm; sourceTree = "<group>"; };
|
||||
4BB4BFAA22A300710069048D /* DeferredAudio.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DeferredAudio.hpp; sourceTree = "<group>"; };
|
||||
4BB697C61D4B558F00248BDF /* Factors.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Factors.hpp; path = ../../NumberTheory/Factors.hpp; sourceTree = "<group>"; };
|
||||
4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimedEventLoop.cpp; sourceTree = "<group>"; };
|
||||
4BB697CA1D4B6D3E00248BDF /* TimedEventLoop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TimedEventLoop.hpp; sourceTree = "<group>"; };
|
||||
@ -3072,6 +3073,7 @@
|
||||
4BCE0058227CFFCA000CA200 /* Macintosh.cpp */,
|
||||
4BCE005E227D39AB000CA200 /* Video.cpp */,
|
||||
4B9378E322A199C600973513 /* Audio.hpp */,
|
||||
4BB4BFAA22A300710069048D /* DeferredAudio.hpp */,
|
||||
4BDB3D8522833321002D3CEE /* Keyboard.hpp */,
|
||||
4BCE0059227CFFCA000CA200 /* Macintosh.hpp */,
|
||||
4BD0692B22828A2D00D2A54F /* RealTimeClock.hpp */,
|
||||
|
Loading…
Reference in New Issue
Block a user