1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-10-25 09:27:01 +00:00

Compare commits

...

159 Commits

Author SHA1 Message Date
Thomas Harte
e2414af901 Test with debug builds. 2024-01-21 22:08:48 -05:00
Thomas Harte
977c961824 Update Z80 access interface. 2024-01-21 21:24:58 -05:00
Thomas Harte
2e5636a879 Merge branch 'master' into Z80Tests 2024-01-21 21:17:39 -05:00
Thomas Harte
9361f29479 Merge pull request #1314 from ryandesign/nullptr_t 2024-01-21 19:02:42 -05:00
Thomas Harte
981f8a9aac Merge pull request #1316 from TomHarte/SMSScrolling 2024-01-21 19:01:32 -05:00
Thomas Harte
295d5ae0c3 Ensure Master System horizontal scroll is latched every line. 2024-01-21 17:09:51 -05:00
Ryan Carsten Schmidt
070efd99e0 Include <cstddef> and use std::nullptr_t not nullptr_t
Fixes "error: use of undeclared identifier 'nullptr_t'; did you mean
'nullptr'?" when compiling with Xcode 12.4.
2024-01-20 19:17:18 -06:00
Thomas Harte
789c4a080f Merge pull request #1312 from TomHarte/BetterLogging
Switch to a better logging interface.
2024-01-20 15:40:49 -05:00
Thomas Harte
8eb38ac437 Make use of bound_shader. 2024-01-19 22:34:42 -05:00
Thomas Harte
b08c7f8b68 Remove dangling LOG_PREFIXs. 2024-01-19 22:19:35 -05:00
Thomas Harte
0c2a4f442e Resolve all commented-out old logging references. 2024-01-19 22:17:35 -05:00
Thomas Harte
18814f7b2c Update use of logging. 2024-01-19 22:14:24 -05:00
Thomas Harte
b61317ba7e Continue conversion of logging. 2024-01-19 22:02:26 -05:00
Thomas Harte
b5e3858c46 Update logging. 2024-01-19 15:38:40 -05:00
Thomas Harte
a1df2ef401 Use updated logger. 2024-01-19 14:24:40 -05:00
Thomas Harte
2200940efe Update logging. 2024-01-19 14:22:23 -05:00
Thomas Harte
7e47329e2a Update use of logger. 2024-01-19 14:16:13 -05:00
Thomas Harte
54aae60c92 Update logging. 2024-01-19 14:01:10 -05:00
Thomas Harte
6497cae39d Attempt a full listing. 2024-01-19 14:00:53 -05:00
Thomas Harte
55d7a7e5f6 Flood the zone with sources; work incomplete. 2024-01-19 11:45:29 -05:00
Thomas Harte
040f276bf1 Update logging interface. 2024-01-19 10:57:30 -05:00
Thomas Harte
119b45001c Add SCC source. 2024-01-19 10:47:21 -05:00
Thomas Harte
70a753d8a8 Update to latest logging. 2024-01-19 10:41:59 -05:00
Thomas Harte
bdfbf779fa Promote source to a template paramter, to unify cases. 2024-01-19 10:41:47 -05:00
Thomas Harte
1d6537c3a9 Switch to newer logging interface. 2024-01-19 10:36:09 -05:00
Thomas Harte
e6ee8acfd6 Use an enum for source, for compile-time disabling. 2024-01-19 10:35:34 -05:00
Thomas Harte
07fe219148 Sketch out saner logging interface. 2024-01-18 16:37:07 -05:00
Thomas Harte
e8917cd294 Merge pull request #1310 from TomHarte/MoreUniquePtr
Remove macros and raw pointers from static analyser.
2024-01-18 13:32:30 -05:00
Thomas Harte
16add86372 Eliminate final macro. 2024-01-18 12:02:38 -05:00
Thomas Harte
9cc572ee7f Unstage temporary Qt build files. 2024-01-18 11:56:42 -05:00
Thomas Harte
c619e353bd Remove one further macro. 2024-01-18 11:36:30 -05:00
Thomas Harte
ab4ecccf57 Avoid raw pointers. 2024-01-17 14:59:36 -05:00
Thomas Harte
3ee81efe40 Merge pull request #1309 from TomHarte/TypeWarnings
Resolve minor dangling type conversion warnings.
2024-01-17 10:22:13 -05:00
Thomas Harte
a402e30edf Combine all per-bank information into a single struct.
(while fixing the indexing type)
2024-01-17 09:44:07 -05:00
Thomas Harte
16baa05aec Correct type. 2024-01-17 09:43:44 -05:00
Thomas Harte
1ccb2e72fc Eliminate a few further macros. 2024-01-17 09:43:33 -05:00
Thomas Harte
20c1f4f0e5 Merge pull request #1308 from ryandesign/no-preferredDevice
Fix color video performance on macOS 10.15+
2024-01-17 09:23:49 -05:00
Thomas Harte
e8d43a28f1 Merge pull request #1306 from TomHarte/FewerMacros
Reduce use of macros.
2024-01-17 09:22:34 -05:00
Ryan Carsten Schmidt
c74305be56 Fix color video performance on macOS 10.15+
Closes #1178
2024-01-17 01:33:00 -06:00
Thomas Harte
fafe43f013 Give value a type. 2024-01-16 23:42:04 -05:00
Thomas Harte
108c584ddb Comment out unused macros. 2024-01-16 23:40:52 -05:00
Thomas Harte
53d6d311a7 Use constexpr functions in preference to macros. 2024-01-16 23:40:40 -05:00
Thomas Harte
a3d37640aa Switch include guards to #pragma once. 2024-01-16 23:34:46 -05:00
Thomas Harte
a1f6f2c7f7 Eliminate remaining macros. 2024-01-16 22:42:20 -05:00
Thomas Harte
d85afc0caf Convert bus access macros. 2024-01-16 22:36:52 -05:00
Thomas Harte
112f3d1e73 Convert 6502 Personality-related macros. 2024-01-16 22:30:35 -05:00
Thomas Harte
dc53d6e6fa Convert check_schedule and bus_access macros. 2024-01-16 22:28:15 -05:00
Thomas Harte
30bf187119 Transcribe GetMediaAndPlatforms away from macros. 2024-01-16 22:17:19 -05:00
Thomas Harte
baac0768b8 Creep towards eliminating all macros. 2024-01-16 16:46:31 -05:00
Thomas Harte
a315deb60c Eliminate palette macro. 2024-01-16 14:32:04 -05:00
Thomas Harte
9ea71c97db Consolidate on std::array. 2024-01-16 14:28:15 -05:00
Thomas Harte
a047c6493a Eliminate joystick macros. 2024-01-16 14:26:55 -05:00
Thomas Harte
8c436c2df8 Eliminate BLOCK macro. 2024-01-16 14:22:15 -05:00
Thomas Harte
ca30cf6376 Eliminate surviving uses of old naming convention. 2024-01-16 14:18:29 -05:00
Thomas Harte
980ccbd45b Eliminate repetition macros. 2024-01-16 14:17:31 -05:00
Thomas Harte
cc635fd3ea Eliminate set_decimal_rotate_flags entirely. 2024-01-16 13:59:03 -05:00
Thomas Harte
fe34083ab8 Demacroise set_shift_flags, reduce casting. 2024-01-16 13:51:16 -05:00
Thomas Harte
ea4cc4c9b3 Convert set_rotate_flags and decline_conditional macros. 2024-01-16 13:40:44 -05:00
Thomas Harte
5b5ae69a18 Convert set_logical_flags and set_arithmetic_flags to lambdas. 2024-01-16 10:13:30 -05:00
Thomas Harte
de038fe28f Eliminate easy macros from Z80 implementation. 2024-01-16 09:43:41 -05:00
Thomas Harte
9990725cfb Merge pull request #1305 from TomHarte/LessRaw
Avoid use of raw pointers in machine creation.
2024-01-12 22:35:35 -05:00
Thomas Harte
3ab6953246 Avoid use of raw pointers in machine creation. 2024-01-12 22:03:19 -05:00
Thomas Harte
ad3632cbe4 Merge pull request #1304 from TomHarte/CRTCEGA
Use named fields during CRTC execution.
2024-01-11 22:14:17 -05:00
Thomas Harte
42731be11f Remove non-functional EGA switches. 2024-01-11 22:00:48 -05:00
Thomas Harte
e919386c79 Grab cursor type. 2024-01-11 15:10:43 -05:00
Thomas Harte
22b4b4d4e3 Switch to named values for everything except blink mode. 2024-01-09 22:03:24 -05:00
Thomas Harte
177e741bca Fix test. 2024-01-09 21:19:44 -05:00
Thomas Harte
5f00d29297 Subsume vertical sync position. 2024-01-08 22:28:46 -05:00
Thomas Harte
f1453d9363 Introduce some vertical metrics. 2024-01-08 21:49:24 -05:00
Thomas Harte
8290220657 Begin process of meaningful naming.
This is in part for readability, but primarily because the differences in VGA/EGA register definitions are better handled at set rather than during execution.
2024-01-08 15:35:44 -05:00
Thomas Harte
0cfd29fafc Merge pull request #1303 from TomHarte/IIgsCleanliness
Clean up what there currently is of a IIgs.
2024-01-04 12:36:40 -05:00
Thomas Harte
ed91956c30 Add missing #include. 2024-01-04 11:21:32 -05:00
Thomas Harte
24d64bf788 ROM is never shadowed; also add assert. 2024-01-04 11:17:20 -05:00
Thomas Harte
386f572e9a Add assert. 2024-01-04 11:11:26 -05:00
Thomas Harte
dae80217bc Adjust names of the newly-private. 2024-01-04 10:36:33 -05:00
Thomas Harte
bfbaebb661 Improve const correctness. 2024-01-04 10:29:38 -05:00
Thomas Harte
4affbe7556 Relocate using. 2024-01-04 10:28:41 -05:00
Thomas Harte
c151a73059 Remove dead srand. 2024-01-04 10:25:39 -05:00
Thomas Harte
ae48f05c80 Shuffle most of the MemoryMap ugliness into a source file. 2024-01-04 10:25:27 -05:00
Thomas Harte
cd7a152bed Remove a lot of dead logging detritus. 2024-01-04 09:59:46 -05:00
Thomas Harte
9cc37945b7 Avoid over-logging. 2024-01-04 09:57:01 -05:00
Thomas Harte
9bceb59f6c Merge pull request #1302 from TomHarte/IIgsShadowingAgain
Be consistent in shadowing IIgs *physical* addresses.
2024-01-03 15:23:40 -05:00
Thomas Harte
cf00a709ec Be consistent in shadowing physical addresses. 2024-01-03 15:02:54 -05:00
Thomas Harte
ad31c50dfd Merge pull request #1301 from TomHarte/MoreIIgsPaging
Normalise IIgs memory map interface.
2024-01-03 14:04:14 -05:00
Thomas Harte
bbaaa520c8 Eliminate MemoryMap access macros, fix tests target. 2024-01-03 13:21:39 -05:00
Thomas Harte
d01c306187 Pull PagingType::Main to top, eliminate macros. 2024-01-03 11:40:04 -05:00
Thomas Harte
439535e44b Merge pull request #1300 from TomHarte/ElectronPaging
Don't page if acknowleding interrupts.
2024-01-02 22:34:11 -05:00
Thomas Harte
2447029631 Don't page if acknowleding interrupts. 2024-01-02 22:23:40 -05:00
Thomas Harte
ce2337f91e Merge pull request #1299 from TomHarte/SpectreNIB
Mildly clean up around NIBs.
2024-01-02 09:52:55 -05:00
Thomas Harte
db4c802003 Make references to constant non-specific. 2024-01-02 09:26:47 -05:00
Thomas Harte
e69c777373 Merge branch 'master' into SpectreNIB 2024-01-02 09:17:37 -05:00
Thomas Harte
2db83acb98 Merge pull request #1298 from TomHarte/CRTC16bit
Make CRTC model part of type.
2024-01-01 22:57:29 -05:00
Thomas Harte
8c0ac6158c Adjust indentation. 2024-01-01 22:45:11 -05:00
Thomas Harte
34b98be6d4 Merge branch 'master' into CRTC16bit 2024-01-01 22:34:48 -05:00
Thomas Harte
8a85ef8426 Merge pull request #1297 from TomHarte/InverseText
Fix Apple II inverse text errors.
2024-01-01 22:18:11 -05:00
Thomas Harte
344fec0683 Fix Apple II inverse text errors. 2024-01-01 22:08:06 -05:00
Thomas Harte
afa2dad2e2 Merge pull request #1292 from TomHarte/KeyRepeat
Indicate whether a keypress is a repeat. Treat appropriately in the Apple II.
2024-01-01 15:27:25 -05:00
Thomas Harte
26123bf399 Mostly hide state. 2024-01-01 15:15:40 -05:00
Thomas Harte
2698ac2d0f Comment and clarify. 2024-01-01 09:33:20 -05:00
Thomas Harte
b7e1ac840f Add necessary Qt change. 2023-12-31 16:43:32 -05:00
Thomas Harte
a58f643b4d Improve repeat behaviour. 2023-12-31 15:21:20 -05:00
Thomas Harte
4f846ef8d0 Remove absolute path. 2023-12-31 15:11:45 -05:00
Thomas Harte
7f26cb0ecf Merge branch 'KeyRepeat' of github.com:TomHarte/CLK into KeyRepeat 2023-12-31 15:03:52 -05:00
Thomas Harte
a1da6db0ee Merge pull request #1296 from TomHarte/Qt5Too
Reintroduce Qt5 support.
2023-12-30 23:08:07 -05:00
Thomas Harte
a7fda83ea5 Reintroduce shortcuts; eliminate bad auto-UI additions. 2023-12-30 23:05:49 -05:00
Thomas Harte
c1778a8fee Reintroduce Qt5 support. 2023-12-30 23:03:15 -05:00
Thomas Harte
7cb40f5d45 Merge pull request #1293 from TomHarte/Qt6
Update to Qt 6.
2023-12-29 23:05:43 -05:00
Thomas Harte
0c770c474b Add PC startup options. 2023-12-29 22:55:34 -05:00
Thomas Harte
134a11b948 Mildly circuitously, accept ROM images. 2023-12-29 22:38:08 -05:00
Thomas Harte
09059ab869 Apply de minimis adaptations to get to build under Qt6. 2023-12-29 22:04:24 -05:00
Thomas Harte
051cdc63b8 Fix SDL build. 2023-12-29 14:54:47 -05:00
Thomas Harte
1b5b3e575c Add repeat-only functionality. 2023-12-29 14:45:48 -05:00
Thomas Harte
21e6f4d823 Update SDL intermediate struct. 2023-12-28 15:12:06 -05:00
Thomas Harte
2baae216ea This TODO is also already dispatched. 2023-12-28 15:09:45 -05:00
Thomas Harte
ffb992d04a Erase done TODO. 2023-12-28 15:07:39 -05:00
Thomas Harte
9344f6a824 Indicate whether a keypress is a repeat. Treat appropriately in the Apple II. 2023-12-28 15:05:55 -05:00
Thomas Harte
74bee31a78 Update version number. 2023-12-28 10:41:52 -05:00
Thomas Harte
96bcbc741f Merge pull request #1291 from TomHarte/LoneDensityParser
Avoid erroneous early Parser exit.
2023-12-28 10:27:43 -05:00
Thomas Harte
54ddbb6b2b Avoid erroneous early exit. 2023-12-28 10:06:18 -05:00
Thomas Harte
99351ee2de Extend refresh address to 16-bit in 'EGA' mode. 2023-12-27 16:17:25 -05:00
Thomas Harte
a617f7305a Move personality into type. 2023-12-27 16:15:52 -05:00
Thomas Harte
be8994a7b4 Merge pull request #1289 from TomHarte/BuildWarnings
Resolve macOS/SDL build warnings.
2023-12-27 11:44:32 -05:00
Thomas Harte
574de0dbf3 Further reduce state. 2023-12-27 11:25:47 -05:00
Thomas Harte
518cd69d5c Merge pull request #1288 from TomHarte/EGAVGAROMs
Add EGA and VGA ROM references; mildly clean up PC.
2023-12-27 11:14:38 -05:00
Thomas Harte
3793fbd978 Remove much unused storage; add virtual destructor. 2023-12-27 11:14:08 -05:00
Thomas Harte
eca0984739 Resolve switch-statement warnings. 2023-12-27 10:58:13 -05:00
Thomas Harte
d6073e0407 Fix typo, add bonus comment. 2023-12-27 10:52:43 -05:00
Thomas Harte
001b161568 Treat speed as more of a runtime selection. 2023-12-27 10:44:51 -05:00
Thomas Harte
088445575e 'Corresponding' better refers back, I think. 2023-12-27 10:12:46 -05:00
Thomas Harte
180ff2f0a7 Fix capitalisation. 2023-12-27 10:10:59 -05:00
Thomas Harte
11c7f2ee6e Make GlaTICK optional. 2023-12-27 10:10:42 -05:00
Thomas Harte
29ed449373 Add EGA and VGA ROMs. 2023-12-27 10:05:41 -05:00
Thomas Harte
f83c3e7af0 Name repeated constant.
(... and, I think, four is enough)
2023-12-27 10:00:01 -05:00
Thomas Harte
7b343b25cc Mildly reduce bit count weight; eliminate !!s. 2023-12-26 14:13:01 -05:00
Thomas Harte
3927ebf763 Merge branch 'master' into Z80Tests 2022-10-20 10:33:33 -04:00
Thomas Harte
7a8674f0d7 Start being more granular on data/address timing. 2022-10-10 10:43:18 -04:00
Thomas Harte
ef0fb5d16f Prepare provisionally to offer instantaneous Z80 bus sampling. 2022-09-29 22:04:16 -04:00
Thomas Harte
c50c98ebad Fix parsing of recorded address and data. 2022-09-27 16:10:11 -04:00
Thomas Harte
34e9870c3c Switch away from enum. 2022-09-27 16:09:48 -04:00
Thomas Harte
47c1e98e91 Make a first pass at bus state comparison. 2022-09-26 22:10:42 -04:00
Thomas Harte
b0d0ea9f92 Take a const ref. 2022-09-26 21:57:42 -04:00
Thomas Harte
02638b7963 Improve alignment for all RegisterPairs. 2022-09-26 13:28:41 -04:00
Thomas Harte
3455f6393a Add but disable multithreaded runner. 2022-09-26 13:18:17 -04:00
Thomas Harte
f806eb7ae2 Capture bus activity; install I and R correctly. 2022-09-22 15:34:46 -04:00
Thomas Harte
152ffbcbb6 Update permit[/current failure] list. 2022-09-20 20:04:47 -04:00
Thomas Harte
de33ee3e46 Log all digressions. 2022-09-20 15:08:55 -04:00
Thomas Harte
42aae39f35 Fix effect on flags of DD- and FD-page SCF and CCF. 2022-09-20 14:43:21 -04:00
Thomas Harte
e84c6a4e60 Apply and verify 'Q' status. 2022-09-20 14:42:52 -04:00
Thomas Harte
bda2ab47e9 Expose flag adjustment history. 2022-09-20 14:37:47 -04:00
Thomas Harte
277cdb858b Extend notes. 2022-09-20 12:20:28 -04:00
Thomas Harte
382af4fa3f Use std::swap rather than reimplementing a subset of it. 2022-09-20 12:20:10 -04:00
Thomas Harte
bf2e879798 Attempt proper IO replay, correcting 26 tests. 2022-09-20 11:55:29 -04:00
Thomas Harte
9b1d4bcf87 Sort permit list, ensure future outputs are sorted. 2022-09-20 11:20:07 -04:00
Thomas Harte
7922920094 Add initial 200 failures to the permit list. 2022-09-20 11:16:10 -04:00
Thomas Harte
a8092c73ac Fully revoke use of exceptions. 2022-09-19 22:05:53 -04:00
Thomas Harte
7f6c2e84d3 Stop a file upon any failure. 2022-09-19 22:03:55 -04:00
Thomas Harte
ec2184894d Test final register state; carve out option for permit list. 2022-09-19 22:01:49 -04:00
Thomas Harte
b67f9d4205 Mask addresses, prepare for a compact summary. 2022-09-19 16:08:16 -04:00
Thomas Harte
89b5daa160 Start attempting to apply JSMoo tests. 2022-09-19 15:44:35 -04:00
517 changed files with 3516 additions and 4017 deletions

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef ActivityObserver_h
#define ActivityObserver_h
#pragma once
#include <cstdint>
#include <string>
@@ -24,6 +23,8 @@ namespace Activity {
*/
class Observer {
public:
virtual ~Observer() {}
/// Provides hints as to the sort of information presented on an LED.
enum LEDPresentation: uint8_t {
/// This LED informs the user of some sort of persistent state, e.g. scroll lock.
@@ -56,5 +57,3 @@ class Observer {
};
}
#endif /* ActivityObserver_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef ActivitySource_h
#define ActivitySource_h
#pragma once
#include "Observer.hpp"
@@ -19,6 +18,3 @@ class Source {
};
}
#endif /* ActivitySource_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef ConfidenceCounter_hpp
#define ConfidenceCounter_hpp
#pragma once
#include "ConfidenceSource.hpp"
@@ -41,5 +40,3 @@ class ConfidenceCounter: public ConfidenceSource {
};
}
#endif /* ConfidenceCounter_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef ConfidenceSource_hpp
#define ConfidenceSource_hpp
#pragma once
namespace Analyser::Dynamic {
@@ -22,5 +21,3 @@ struct ConfidenceSource {
};
}
#endif /* ConfidenceSource_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef ConfidenceSummary_hpp
#define ConfidenceSummary_hpp
#pragma once
#include "ConfidenceSource.hpp"
@@ -40,5 +39,3 @@ class ConfidenceSummary: public ConfidenceSource {
};
}
#endif /* ConfidenceSummary_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiConfigurable_hpp
#define MultiConfigurable_hpp
#pragma once
#include "../../../../Machines/DynamicMachine.hpp"
#include "../../../../Configurable/Configurable.hpp"
@@ -36,5 +35,3 @@ class MultiConfigurable: public Configurable::Device {
};
}
#endif /* MultiConfigurable_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiJoystickMachine_hpp
#define MultiJoystickMachine_hpp
#pragma once
#include "../../../../Machines/DynamicMachine.hpp"
@@ -34,5 +33,3 @@ class MultiJoystickMachine: public MachineTypes::JoystickMachine {
};
}
#endif /* MultiJoystickMachine_hpp */

View File

@@ -56,10 +56,10 @@ MultiKeyboardMachine::MultiKeyboard::MultiKeyboard(const std::vector<::MachineTy
}
}
bool MultiKeyboardMachine::MultiKeyboard::set_key_pressed(Key key, char value, bool is_pressed) {
bool MultiKeyboardMachine::MultiKeyboard::set_key_pressed(Key key, char value, bool is_pressed, bool is_repeat) {
bool was_consumed = false;
for(const auto &machine: machines_) {
was_consumed |= machine->get_keyboard().set_key_pressed(key, value, is_pressed);
was_consumed |= machine->get_keyboard().set_key_pressed(key, value, is_pressed, is_repeat);
}
return was_consumed;
}

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiKeyboardMachine_hpp
#define MultiKeyboardMachine_hpp
#pragma once
#include "../../../../Machines/DynamicMachine.hpp"
#include "../../../../Machines/KeyboardMachine.hpp"
@@ -31,7 +30,7 @@ class MultiKeyboardMachine: public MachineTypes::KeyboardMachine {
public:
MultiKeyboard(const std::vector<MachineTypes::KeyboardMachine *> &machines);
bool set_key_pressed(Key key, char value, bool is_pressed) final;
bool set_key_pressed(Key key, char value, bool is_pressed, bool is_repeat) final;
void reset_all_keys() final;
const std::set<Key> &observed_keys() const final;
bool is_exclusive() const final;
@@ -55,5 +54,3 @@ class MultiKeyboardMachine: public MachineTypes::KeyboardMachine {
};
}
#endif /* MultiKeyboardMachine_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiMediaTarget_hpp
#define MultiMediaTarget_hpp
#pragma once
#include "../../../../Machines/MediaTarget.hpp"
#include "../../../../Machines/DynamicMachine.hpp"
@@ -35,5 +34,3 @@ struct MultiMediaTarget: public MachineTypes::MediaTarget {
};
}
#endif /* MultiMediaTarget_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiProducer_hpp
#define MultiProducer_hpp
#pragma once
#include "../../../../Concurrency/AsyncTaskQueue.hpp"
#include "../../../../Machines/MachineTypes.hpp"
@@ -115,5 +114,3 @@ class MultiAudioProducer: public MultiInterface<MachineTypes::AudioProducer>, pu
*/
}
#endif /* MultiProducer_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiSpeaker_hpp
#define MultiSpeaker_hpp
#pragma once
#include "../../../../Machines/DynamicMachine.hpp"
#include "../../../../Outputs/Speaker/Speaker.hpp"
@@ -55,5 +54,3 @@ class MultiSpeaker: public Outputs::Speaker::Speaker, Outputs::Speaker::Speaker:
};
}
#endif /* MultiSpeaker_hpp */

View File

@@ -11,6 +11,12 @@
#include <algorithm>
namespace {
Log::Logger<Log::Source::MultiMachine> logger;
}
using namespace Analyser::Dynamic;
MultiMachine::MultiMachine(std::vector<std::unique_ptr<DynamicMachine>> &&machines) :
@@ -61,13 +67,14 @@ bool MultiMachine::would_collapse(const std::vector<std::unique_ptr<DynamicMachi
void MultiMachine::did_run_machines(MultiTimedMachine *) {
std::lock_guard machines_lock(machines_mutex_);
#ifndef NDEBUG
for(const auto &machine: machines_) {
auto timed_machine = machine->timed_machine();
LOGNBR(PADHEX(2) << timed_machine->get_confidence() << " " << timed_machine->debug_type() << "; ");
if constexpr (logger.enabled) {
auto line = logger.info();
for(const auto &machine: machines_) {
auto timed_machine = machine->timed_machine();
line.append("%0.4f %s; ", timed_machine->get_confidence(), timed_machine->debug_type().c_str());
}
}
LOGNBR(std::endl);
#endif
DynamicMachine *front = machines_.front().get();
std::stable_sort(machines_.begin(), machines_.end(),

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiMachine_hpp
#define MultiMachine_hpp
#pragma once
#include "../../../Machines/DynamicMachine.hpp"
@@ -80,5 +79,3 @@ class MultiMachine: public ::Machine::DynamicMachine, public MultiTimedMachine::
};
}
#endif /* MultiMachine_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Machines_h
#define Machines_h
#pragma once
namespace Analyser {
@@ -32,5 +31,3 @@ enum class Machine {
};
}
#endif /* Machines_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Acorn_Disk_hpp
#define StaticAnalyser_Acorn_Disk_hpp
#pragma once
#include "File.hpp"
#include "../../../Storage/Disk/Disk.hpp"
@@ -30,5 +29,3 @@ std::unique_ptr<Catalogue> GetDFSCatalogue(const std::shared_ptr<Storage::Disk::
std::unique_ptr<Catalogue> GetADFSCatalogue(const std::shared_ptr<Storage::Disk::Disk> &disk);
}
#endif /* Disk_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Acorn_File_hpp
#define StaticAnalyser_Acorn_File_hpp
#pragma once
#include <memory>
#include <string>
@@ -59,5 +58,3 @@ struct File {
};
}
#endif /* File_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Acorn_StaticAnalyser_hpp
#define StaticAnalyser_Acorn_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::Acorn {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* AcornAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Acorn_Tape_hpp
#define StaticAnalyser_Acorn_Tape_hpp
#pragma once
#include <memory>
@@ -19,5 +18,3 @@ namespace Analyser::Static::Acorn {
std::vector<File> GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape);
}
#endif /* Tape_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_Acorn_Target_h
#define Analyser_Static_Acorn_Target_h
#pragma once
#include "../../../Reflection/Struct.hpp"
#include "../StaticAnalyser.hpp"
@@ -36,5 +35,3 @@ struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<
};
}
#endif /* Analyser_Static_Acorn_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_Amiga_StaticAnalyser_hpp
#define Analyser_Static_Amiga_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::Amiga {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* Analyser_Static_Amiga_StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_Amiga_Target_h
#define Analyser_Static_Amiga_Target_h
#pragma once
#include "../../../Reflection/Struct.hpp"
#include "../StaticAnalyser.hpp"
@@ -40,5 +39,3 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
};
}
#endif /* Analyser_Static_Amiga_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_AmstradCPC_StaticAnalyser_hpp
#define Analyser_Static_AmstradCPC_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::AmstradCPC {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* Analyser_Static_AmstradCPC_StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_AmstradCPC_Target_h
#define Analyser_Static_AmstradCPC_Target_h
#pragma once
#include "../../../Reflection/Enum.hpp"
#include "../../../Reflection/Struct.hpp"
@@ -30,5 +29,3 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
};
}
#endif /* Analyser_Static_AmstradCPC_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_AppleII_StaticAnalyser_hpp
#define Analyser_Static_AppleII_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::AppleII {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* Analyser_Static_AppleII_StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_AppleII_Target_h
#define Analyser_Static_AppleII_Target_h
#pragma once
#include "../../../Reflection/Enum.hpp"
#include "../../../Reflection/Struct.hpp"
@@ -50,5 +49,3 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
};
}
#endif /* Analyser_Static_AppleII_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_AppleIIgs_StaticAnalyser_hpp
#define Analyser_Static_AppleIIgs_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::AppleIIgs {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* Analyser_Static_AppleIIgs_StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_AppleIIgs_Target_h
#define Analyser_Static_AppleIIgs_Target_h
#pragma once
#include "../../../Reflection/Enum.hpp"
#include "../../../Reflection/Struct.hpp"
@@ -41,5 +40,3 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
};
}
#endif /* Analyser_Static_AppleIIgs_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Atari_StaticAnalyser_hpp
#define StaticAnalyser_Atari_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::Atari2600 {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_Atari2600_Target_h
#define Analyser_Static_Atari2600_Target_h
#pragma once
#include "../StaticAnalyser.hpp"
@@ -37,5 +36,3 @@ struct Target: public ::Analyser::Static::Target {
};
}
#endif /* Analyser_Static_Atari_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_AtariST_StaticAnalyser_hpp
#define Analyser_Static_AtariST_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::AtariST {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* Analyser_Static_AtariST_StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_AtariST_Target_h
#define Analyser_Static_AtariST_Target_h
#pragma once
#include "../../../Reflection/Struct.hpp"
#include "../StaticAnalyser.hpp"
@@ -30,5 +29,3 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
};
}
#endif /* Analyser_Static_AtariST_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Coleco_StaticAnalyser_hpp
#define StaticAnalyser_Coleco_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::Coleco {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Commodore_Disk_hpp
#define StaticAnalyser_Commodore_Disk_hpp
#pragma once
#include "../../../Storage/Disk/Disk.hpp"
#include "File.hpp"
@@ -19,5 +18,3 @@ namespace Analyser::Static::Commodore {
std::vector<File> GetFiles(const std::shared_ptr<Storage::Disk::Disk> &disk);
}
#endif /* Disk_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef File_hpp
#define File_hpp
#pragma once
#include <cstdint>
#include <string>
@@ -35,5 +34,3 @@ struct File {
};
}
#endif /* File_hpp */

View File

@@ -93,7 +93,7 @@ Analyser::Static::TargetList Analyser::Static::Commodore::GetTargets(const Media
// make a first guess based on loading address
switch(files.front().starting_address) {
default:
LOG("Unrecognised loading address for Commodore program: " << PADHEX(4) << files.front().starting_address);
Log::Logger<Log::Source::CommodoreStaticAnalyser>().error().append("Unrecognised loading address for Commodore program: %04x", files.front().starting_address);
[[fallthrough]];
case 0x1001:
memory_model = Target::MemoryModel::Unexpanded;

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Commodore_StaticAnalyser_hpp
#define StaticAnalyser_Commodore_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::Commodore {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* CommodoreAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Commodore_Tape_hpp
#define StaticAnalyser_Commodore_Tape_hpp
#pragma once
#include "../../../Storage/Tape/Tape.hpp"
#include "File.hpp"
@@ -17,5 +16,3 @@ namespace Analyser::Static::Commodore {
std::vector<File> GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape);
}
#endif /* Tape_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_Commodore_Target_h
#define Analyser_Static_Commodore_Target_h
#pragma once
#include "../../../Reflection/Enum.hpp"
#include "../../../Reflection/Struct.hpp"
@@ -70,5 +69,3 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
};
}
#endif /* Analyser_Static_Commodore_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Disassembler_6502_hpp
#define StaticAnalyser_Disassembler_6502_hpp
#pragma once
#include <cstdint>
#include <functional>
@@ -93,5 +92,3 @@ Disassembly Disassemble(
std::vector<uint16_t> entry_points);
}
#endif /* Disassembler6502_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef AddressMapper_hpp
#define AddressMapper_hpp
#pragma once
#include <functional>
@@ -24,5 +23,3 @@ template <typename T> std::function<std::size_t(T)> OffsetMapper(T start_address
}
}
#endif /* AddressMapper_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef Kernel_hpp
#define Kernel_hpp
#pragma once
namespace Analyser::Static::Disassembly {
@@ -65,5 +64,3 @@ template <typename D, typename S, typename Disassembler> D Disassemble(
}
}
#endif /* Kernel_hpp */

View File

@@ -56,11 +56,11 @@ class Accessor {
bool overrun_ = false;
};
#define x(v) (v >> 6)
#define y(v) ((v >> 3) & 7)
#define q(v) ((v >> 3) & 1)
#define p(v) ((v >> 4) & 3)
#define z(v) (v & 7)
constexpr uint8_t x(uint8_t v) { return v >> 6; }
constexpr uint8_t y(uint8_t v) { return (v >> 3) & 7; }
constexpr uint8_t q(uint8_t v) { return (v >> 3) & 1; }
constexpr uint8_t p(uint8_t v) { return (v >> 4) & 3; }
constexpr uint8_t z(uint8_t v) { return v & 7; }
Instruction::Condition condition_table[] = {
Instruction::Condition::NZ, Instruction::Condition::Z,

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Disassembler_Z80_hpp
#define StaticAnalyser_Disassembler_Z80_hpp
#pragma once
#include <cstdint>
#include <functional>
@@ -91,5 +90,3 @@ Disassembly Disassemble(
Approach approach);
}
#endif /* StaticAnalyser_Disassembler_Z80_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_DiskII_StaticAnalyser_hpp
#define Analyser_Static_DiskII_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::DiskII {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* Analyser_Static_DiskII_StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_Enterprise_StaticAnalyser_hpp
#define Analyser_Static_Enterprise_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::Enterprise {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* Analyser_Static_Enterprise_StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_Enterprise_Target_h
#define Analyser_Static_Enterprise_Target_h
#pragma once
#include "../../../Reflection/Enum.hpp"
#include "../../../Reflection/Struct.hpp"
@@ -49,5 +48,3 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
};
}
#endif /* Analyser_Static_Enterprise_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2023 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_FAT12_StaticAnalyser_hpp
#define Analyser_Static_FAT12_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::FAT12 {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* Analyser_Static_FAT12_StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Cartridge_hpp
#define Cartridge_hpp
#pragma once
#include "../../../Storage/Cartridge/Cartridge.hpp"
@@ -32,5 +31,3 @@ struct Cartridge: public ::Storage::Cartridge::Cartridge {
};
}
#endif /* Cartridge_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_MSX_StaticAnalyser_hpp
#define StaticAnalyser_MSX_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::MSX {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* StaticAnalyser_MSX_StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_MSX_Tape_hpp
#define StaticAnalyser_MSX_Tape_hpp
#pragma once
#include "../../../Storage/Tape/Tape.hpp"
@@ -36,5 +35,3 @@ struct File {
std::vector<File> GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape);
}
#endif /* StaticAnalyser_MSX_Tape_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_MSX_Target_h
#define Analyser_Static_MSX_Target_h
#pragma once
#include "../../../Reflection/Enum.hpp"
#include "../../../Reflection/Struct.hpp"
@@ -47,5 +46,3 @@ struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<
};
}
#endif /* Analyser_Static_MSX_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_Macintosh_StaticAnalyser_hpp
#define Analyser_Static_Macintosh_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::Macintosh {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* Analyser_Static_Macintosh_StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_Macintosh_Target_h
#define Analyser_Static_Macintosh_Target_h
#pragma once
#include "../../../Reflection/Enum.hpp"
#include "../../../Reflection/Struct.hpp"
@@ -29,5 +28,3 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
};
}
#endif /* Analyser_Static_Macintosh_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Oric_StaticAnalyser_hpp
#define StaticAnalyser_Oric_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::Oric {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Oric_Tape_hpp
#define StaticAnalyser_Oric_Tape_hpp
#pragma once
#include "../../../Storage/Tape/Tape.hpp"
@@ -32,5 +31,3 @@ struct File {
std::vector<File> GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape);
}
#endif /* Tape_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_Oric_Target_h
#define Analyser_Static_Oric_Target_h
#pragma once
#include "../../../Reflection/Enum.hpp"
#include "../../../Reflection/Struct.hpp"
@@ -55,5 +54,3 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
};
}
#endif /* Analyser_Static_Oric_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright © 2023 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_PCCompatible_StaticAnalyser_hpp
#define Analyser_Static_PCCompatible_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::PCCompatible {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* Analyser_Static_PCCompatible_StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright © 2023 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_PCCompatible_Target_h
#define Analyser_Static_PCCompatible_Target_h
#pragma once
#include "../../../Reflection/Struct.hpp"
#include "../StaticAnalyser.hpp"
@@ -36,5 +35,3 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
};
}
#endif /* Analyser_Static_PCCompatible_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright © 2018 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Sega_StaticAnalyser_hpp
#define StaticAnalyser_Sega_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::Sega {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright © 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_Sega_Target_h
#define Analyser_Static_Sega_Target_h
#pragma once
#include "../../../Reflection/Enum.hpp"
#include "../../../Reflection/Struct.hpp"
@@ -51,5 +50,3 @@ constexpr bool is_master_system(Analyser::Static::Sega::Target::Model model) {
}
}
#endif /* Analyser_Static_Sega_Target_h */

View File

@@ -9,6 +9,7 @@
#include "StaticAnalyser.hpp"
#include <algorithm>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <iterator>
@@ -88,6 +89,7 @@
template<class> inline constexpr bool always_false_v = false;
using namespace Analyser::Static;
using namespace Storage;
namespace {
@@ -101,46 +103,90 @@ std::string get_extension(const std::string &name) {
return extension;
}
class MediaAccumulator {
public:
MediaAccumulator(const std::string &file_name, TargetPlatform::IntType &potential_platforms) :
file_name_(file_name), potential_platforms_(potential_platforms), extension_(get_extension(file_name)) {}
/// Adds @c instance to the media collection and adds @c platforms to the set of potentials.
/// If @c instance is an @c TargetPlatform::TypeDistinguisher then it is given an opportunity to restrict the set of potentials.
template <typename InstanceT>
void insert(TargetPlatform::IntType platforms, std::shared_ptr<InstanceT> instance) {
if constexpr (std::is_base_of_v<Storage::Disk::Disk, InstanceT>) {
media.disks.push_back(instance);
} else if constexpr (std::is_base_of_v<Storage::Tape::Tape, InstanceT>) {
media.tapes.push_back(instance);
} else if constexpr (std::is_base_of_v<Storage::Cartridge::Cartridge, InstanceT>) {
media.cartridges.push_back(instance);
} else if constexpr (std::is_base_of_v<Storage::MassStorage::MassStorageDevice, InstanceT>) {
media.mass_storage_devices.push_back(instance);
} else {
static_assert(always_false_v<InstanceT>, "Unexpected type encountered.");
}
potential_platforms_ |= platforms;
// Check whether the instance itself has any input on target platforms.
TargetPlatform::TypeDistinguisher *const distinguisher =
dynamic_cast<TargetPlatform::TypeDistinguisher *>(instance.get());
if(distinguisher) potential_platforms_ &= distinguisher->target_platform_type();
}
/// Concstructs a new instance of @c InstanceT supplying @c args and adds it to the back of @c list using @c insert_instance.
template <typename InstanceT, typename... Args>
void insert(TargetPlatform::IntType platforms, Args &&... args) {
insert(platforms, std::make_shared<InstanceT>(std::forward<Args>(args)...));
}
/// Calls @c insert with the specified parameters, ignoring any exceptions thrown.
template <typename InstanceT, typename... Args>
void try_insert(TargetPlatform::IntType platforms, Args &&... args) {
try {
insert<InstanceT>(platforms, std::forward<Args>(args)...);
} catch(...) {}
}
/// Performs a @c try_insert for an object of @c InstanceT if @c extension matches that of the file name,
/// providing the file name as the only construction argument.
template <typename InstanceT>
void try_standard(TargetPlatform::IntType platforms, const char *extension) {
if(name_matches(extension)) {
try_insert<InstanceT>(platforms, file_name_);
}
}
bool name_matches(const char *extension) {
return extension_ == extension;
}
Media media;
private:
const std::string &file_name_;
TargetPlatform::IntType &potential_platforms_;
const std::string extension_;
};
}
static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::IntType &potential_platforms) {
Media result;
const std::string extension = get_extension(file_name);
#define InsertInstance(list, instance, platforms) \
list.emplace_back(instance);\
potential_platforms |= platforms;\
TargetPlatform::TypeDistinguisher *const distinguisher = dynamic_cast<TargetPlatform::TypeDistinguisher *>(list.back().get());\
if(distinguisher) potential_platforms &= distinguisher->target_platform_type();
#define Insert(list, class, platforms, ...) \
InsertInstance(list, new Storage::class(__VA_ARGS__), platforms);
#define TryInsert(list, class, platforms, ...) \
try {\
Insert(list, class, platforms, __VA_ARGS__) \
} catch(...) {}
#define Format(ext, list, class, platforms) \
if(extension == ext) { \
TryInsert(list, class, platforms, file_name) \
}
MediaAccumulator accumulator(file_name, potential_platforms);
// 2MG
if(extension == "2mg") {
if(accumulator.name_matches("2mg")) {
// 2MG uses a factory method; defer to it.
try {
const auto media = Storage::Disk::Disk2MG::open(file_name);
std::visit([&result, &potential_platforms](auto &&arg) {
const auto media = Disk::Disk2MG::open(file_name);
std::visit([&](auto &&arg) {
using Type = typename std::decay<decltype(arg)>::type;
if constexpr (std::is_same<Type, nullptr_t>::value) {
if constexpr (std::is_same<Type, std::nullptr_t>::value) {
// It's valid for no media to be returned.
} else if constexpr (std::is_same<Type, Storage::Disk::DiskImageHolderBase *>::value) {
InsertInstance(result.disks, arg, TargetPlatform::DiskII);
} else if constexpr (std::is_same<Type, Storage::MassStorage::MassStorageDevice *>::value) {
} else if constexpr (std::is_same<Type, Disk::DiskImageHolderBase *>::value) {
accumulator.insert(TargetPlatform::DiskII, std::shared_ptr<Disk::DiskImageHolderBase>(arg));
} else if constexpr (std::is_same<Type, MassStorage::MassStorageDevice *>::value) {
// TODO: or is it Apple IIgs?
InsertInstance(result.mass_storage_devices, arg, TargetPlatform::AppleII);
accumulator.insert(TargetPlatform::AppleII, std::shared_ptr<MassStorage::MassStorageDevice>(arg));
} else {
static_assert(always_false_v<Type>, "Unexpected type encountered.");
}
@@ -148,106 +194,108 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::
} catch(...) {}
}
Format("80", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 80
Format("81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 81
Format("a26", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // A26
Format("adf", result.disks, Disk::DiskImageHolder<Storage::Disk::AcornADF>, TargetPlatform::Acorn) // ADF (Acorn)
Format("adf", result.disks, Disk::DiskImageHolder<Storage::Disk::AmigaADF>, TargetPlatform::Amiga) // ADF (Amiga)
Format("adl", result.disks, Disk::DiskImageHolder<Storage::Disk::AcornADF>, TargetPlatform::Acorn) // ADL
Format("bin", result.cartridges, Cartridge::BinaryDump, TargetPlatform::AllCartridge) // BIN (cartridge dump)
Format("cas", result.tapes, Tape::CAS, TargetPlatform::MSX) // CAS
Format("cdt", result.tapes, Tape::TZX, TargetPlatform::AmstradCPC) // CDT
Format("col", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Coleco) // COL
Format("csw", result.tapes, Tape::CSW, TargetPlatform::AllTape) // CSW
Format("d64", result.disks, Disk::DiskImageHolder<Storage::Disk::D64>, TargetPlatform::Commodore) // D64
Format("dat", result.mass_storage_devices, MassStorage::DAT, TargetPlatform::Acorn) // DAT
Format("dmk", result.disks, Disk::DiskImageHolder<Storage::Disk::DMK>, TargetPlatform::MSX) // DMK
Format("do", result.disks, Disk::DiskImageHolder<Storage::Disk::AppleDSK>, TargetPlatform::DiskII) // DO
Format("dsd", result.disks, Disk::DiskImageHolder<Storage::Disk::SSD>, TargetPlatform::Acorn) // DSD
Format( "dsk",
result.disks,
Disk::DiskImageHolder<Storage::Disk::CPCDSK>,
TargetPlatform::AmstradCPC | TargetPlatform::Oric | TargetPlatform::ZXSpectrum) // DSK (Amstrad CPC, etc)
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::AppleDSK>, TargetPlatform::DiskII) // DSK (Apple II)
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::Macintosh) // DSK (Macintosh, floppy disk)
Format("dsk", result.mass_storage_devices, MassStorage::HFV, TargetPlatform::Macintosh) // DSK (Macintosh, hard disk, single volume image)
Format("dsk", result.mass_storage_devices, MassStorage::DSK, TargetPlatform::Macintosh) // DSK (Macintosh, hard disk, full device image)
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::FAT12>, TargetPlatform::MSX) // DSK (MSX)
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::OricMFMDSK>, TargetPlatform::Oric) // DSK (Oric)
Format("g64", result.disks, Disk::DiskImageHolder<Storage::Disk::G64>, TargetPlatform::Commodore) // G64
Format("hdv", result.mass_storage_devices, MassStorage::HDV, TargetPlatform::AppleII) // HDV (Apple II, hard disk, single volume image)
Format( "hfe",
result.disks,
Disk::DiskImageHolder<Storage::Disk::HFE>,
TargetPlatform::Acorn | TargetPlatform::AmstradCPC | TargetPlatform::Commodore | TargetPlatform::Oric | TargetPlatform::ZXSpectrum)
// HFE (TODO: switch to AllDisk once the MSX stops being so greedy)
Format("ima", result.disks, Disk::DiskImageHolder<Storage::Disk::FAT12>, TargetPlatform::PCCompatible) // IMG (MS-DOS style)
Format("image", result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2)
Format("imd", result.disks, Disk::DiskImageHolder<Storage::Disk::IMD>, TargetPlatform::PCCompatible) // IMD
Format("img", result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2)
accumulator.try_standard<Tape::ZX80O81P>(TargetPlatform::ZX8081, "80");
accumulator.try_standard<Tape::ZX80O81P>(TargetPlatform::ZX8081, "81");
accumulator.try_standard<Cartridge::BinaryDump>(TargetPlatform::Atari2600, "a26");
accumulator.try_standard<Disk::DiskImageHolder<Disk::AcornADF>>(TargetPlatform::Acorn, "adf");
accumulator.try_standard<Disk::DiskImageHolder<Disk::AmigaADF>>(TargetPlatform::Amiga, "adf");
accumulator.try_standard<Disk::DiskImageHolder<Disk::AcornADF>>(TargetPlatform::Acorn, "adl");
accumulator.try_standard<Cartridge::BinaryDump>(TargetPlatform::AllCartridge, "bin");
accumulator.try_standard<Tape::CAS>(TargetPlatform::MSX, "cas");
accumulator.try_standard<Tape::TZX>(TargetPlatform::AmstradCPC, "cdt");
accumulator.try_standard<Cartridge::BinaryDump>(TargetPlatform::Coleco, "col");
accumulator.try_standard<Tape::CSW>(TargetPlatform::AllTape, "csw");
accumulator.try_standard<Disk::DiskImageHolder<Disk::D64>>(TargetPlatform::Commodore, "d64");
accumulator.try_standard<MassStorage::DAT>(TargetPlatform::Acorn, "dat");
accumulator.try_standard<Disk::DiskImageHolder<Disk::DMK>>(TargetPlatform::MSX, "dmk");
accumulator.try_standard<Disk::DiskImageHolder<Disk::AppleDSK>>(TargetPlatform::DiskII, "do");
accumulator.try_standard<Disk::DiskImageHolder<Disk::SSD>>(TargetPlatform::Acorn, "dsd");
accumulator.try_standard<Disk::DiskImageHolder<Disk::CPCDSK>>(
TargetPlatform::AmstradCPC | TargetPlatform::Oric | TargetPlatform::ZXSpectrum, "dsk");
accumulator.try_standard<Disk::DiskImageHolder<Disk::AppleDSK>>(TargetPlatform::DiskII, "dsk");
accumulator.try_standard<Disk::DiskImageHolder<Disk::MacintoshIMG>>(TargetPlatform::Macintosh, "dsk");
accumulator.try_standard<MassStorage::HFV>(TargetPlatform::Macintosh, "dsk");
accumulator.try_standard<MassStorage::DSK>(TargetPlatform::Macintosh, "dsk");
accumulator.try_standard<Disk::DiskImageHolder<Disk::FAT12>>(TargetPlatform::MSX, "dsk");
accumulator.try_standard<Disk::DiskImageHolder<Disk::OricMFMDSK>>(TargetPlatform::Oric, "dsk");
accumulator.try_standard<Disk::DiskImageHolder<Disk::G64>>(TargetPlatform::Commodore, "g64");
accumulator.try_standard<MassStorage::HDV>(TargetPlatform::AppleII, "hdv");
accumulator.try_standard<Disk::DiskImageHolder<Disk::HFE>>(
TargetPlatform::Acorn | TargetPlatform::AmstradCPC | TargetPlatform::Commodore | TargetPlatform::Oric | TargetPlatform::ZXSpectrum,
"hfe"); // TODO: switch to AllDisk once the MSX stops being so greedy.
accumulator.try_standard<Disk::DiskImageHolder<Disk::FAT12>>(TargetPlatform::PCCompatible, "ima");
accumulator.try_standard<Disk::DiskImageHolder<Disk::MacintoshIMG>>(TargetPlatform::Macintosh, "image");
accumulator.try_standard<Disk::DiskImageHolder<Disk::IMD>>(TargetPlatform::PCCompatible, "imd");
accumulator.try_standard<Disk::DiskImageHolder<Disk::MacintoshIMG>>(TargetPlatform::Macintosh, "img");
// Treat PC booter as a potential backup only if this doesn't parse as a FAT12.
if(extension == "img") {
if(accumulator.name_matches("img")) {
try {
Insert(result.disks, Disk::DiskImageHolder<Storage::Disk::FAT12>, TargetPlatform::FAT12, file_name) // IMG (Enterprise or MS-DOS style)
accumulator.insert<Disk::DiskImageHolder<Disk::FAT12>>(TargetPlatform::FAT12, file_name);
} catch(...) {
Format("img", result.disks, Disk::DiskImageHolder<Storage::Disk::PCBooter>, TargetPlatform::PCCompatible) // IMG (PC raw booter)
accumulator.try_standard<Disk::DiskImageHolder<Disk::PCBooter>>(TargetPlatform::PCCompatible, "img");
}
}
Format( "ipf",
result.disks,
Disk::DiskImageHolder<Storage::Disk::IPF>,
TargetPlatform::Amiga | TargetPlatform::AtariST | TargetPlatform::AmstradCPC | TargetPlatform::ZXSpectrum) // IPF
Format("msa", result.disks, Disk::DiskImageHolder<Storage::Disk::MSA>, TargetPlatform::AtariST) // MSA
Format("mx2", result.cartridges, Cartridge::BinaryDump, TargetPlatform::MSX) // MX2
Format("nib", result.disks, Disk::DiskImageHolder<Storage::Disk::NIB>, TargetPlatform::DiskII) // NIB
Format("o", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // O
Format("p", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P
Format("po", result.disks, Disk::DiskImageHolder<Storage::Disk::AppleDSK>, TargetPlatform::DiskII) // PO (original Apple II kind)
accumulator.try_standard<Disk::DiskImageHolder<Disk::IPF>>(
TargetPlatform::Amiga | TargetPlatform::AtariST | TargetPlatform::AmstradCPC | TargetPlatform::ZXSpectrum,
"ipf");
// PO (Apple IIgs kind)
if(extension == "po") {
TryInsert(result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::AppleIIgs, file_name, Storage::Disk::MacintoshIMG::FixedType::GCR)
accumulator.try_standard<Disk::DiskImageHolder<Disk::MSA>>(TargetPlatform::AtariST, "msa");
accumulator.try_standard<Cartridge::BinaryDump>(TargetPlatform::MSX, "mx2");
accumulator.try_standard<Disk::DiskImageHolder<Disk::NIB>>(TargetPlatform::DiskII, "nib");
accumulator.try_standard<Tape::ZX80O81P>(TargetPlatform::ZX8081, "o");
accumulator.try_standard<Tape::ZX80O81P>(TargetPlatform::ZX8081, "p");
accumulator.try_standard<Disk::DiskImageHolder<Disk::AppleDSK>>(TargetPlatform::DiskII, "po");
if(accumulator.name_matches("po")) {
accumulator.try_insert<Disk::DiskImageHolder<Disk::MacintoshIMG>>(
TargetPlatform::AppleIIgs,
file_name, Disk::MacintoshIMG::FixedType::GCR);
}
Format("p81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P81
accumulator.try_standard<Tape::ZX80O81P>(TargetPlatform::ZX8081, "p81");
// PRG
if(extension == "prg") {
// try instantiating as a ROM; failing that accept as a tape
if(accumulator.name_matches("prg")) {
// Try instantiating as a ROM; failing that accept as a tape.
try {
Insert(result.cartridges, Cartridge::PRG, TargetPlatform::Commodore, file_name)
accumulator.insert<Cartridge::PRG>(TargetPlatform::Commodore, file_name);
} catch(...) {
try {
Insert(result.tapes, Tape::PRG, TargetPlatform::Commodore, file_name)
accumulator.insert<Tape::PRG>(TargetPlatform::Commodore, file_name);
} catch(...) {}
}
}
Format( "rom",
result.cartridges,
Cartridge::BinaryDump,
TargetPlatform::AcornElectron | TargetPlatform::Coleco | TargetPlatform::MSX) // ROM
Format("sg", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Sega) // SG
Format("sms", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Sega) // SMS
Format("ssd", result.disks, Disk::DiskImageHolder<Storage::Disk::SSD>, TargetPlatform::Acorn) // SSD
Format("st", result.disks, Disk::DiskImageHolder<Storage::Disk::FAT12>, TargetPlatform::AtariST) // ST
Format("stx", result.disks, Disk::DiskImageHolder<Storage::Disk::STX>, TargetPlatform::AtariST) // STX
Format("tap", result.tapes, Tape::CommodoreTAP, TargetPlatform::Commodore) // TAP (Commodore)
Format("tap", result.tapes, Tape::OricTAP, TargetPlatform::Oric) // TAP (Oric)
Format("tap", result.tapes, Tape::ZXSpectrumTAP, TargetPlatform::ZXSpectrum) // TAP (ZX Spectrum)
Format("tsx", result.tapes, Tape::TZX, TargetPlatform::MSX) // TSX
Format("tzx", result.tapes, Tape::TZX, TargetPlatform::ZX8081 | TargetPlatform::ZXSpectrum) // TZX
Format("uef", result.tapes, Tape::UEF, TargetPlatform::Acorn) // UEF (tape)
Format("woz", result.disks, Disk::DiskImageHolder<Storage::Disk::WOZ>, TargetPlatform::DiskII) // WOZ
accumulator.try_standard<Cartridge::BinaryDump>(
TargetPlatform::AcornElectron | TargetPlatform::Coleco | TargetPlatform::MSX,
"rom");
#undef Format
#undef Insert
#undef TryInsert
#undef InsertInstance
accumulator.try_standard<Cartridge::BinaryDump>(TargetPlatform::Sega, "sg");
accumulator.try_standard<Cartridge::BinaryDump>(TargetPlatform::Sega, "sms");
accumulator.try_standard<Disk::DiskImageHolder<Disk::SSD>>(TargetPlatform::Acorn, "ssd");
accumulator.try_standard<Disk::DiskImageHolder<Disk::FAT12>>(TargetPlatform::AtariST, "st");
accumulator.try_standard<Disk::DiskImageHolder<Disk::STX>>(TargetPlatform::AtariST, "stx");
return result;
accumulator.try_standard<Tape::CommodoreTAP>(TargetPlatform::Commodore, "tap");
accumulator.try_standard<Tape::OricTAP>(TargetPlatform::Oric, "tap");
accumulator.try_standard<Tape::ZXSpectrumTAP>(TargetPlatform::ZXSpectrum, "tap");
accumulator.try_standard<Tape::TZX>(TargetPlatform::MSX, "tsx");
accumulator.try_standard<Tape::TZX>(TargetPlatform::ZX8081 | TargetPlatform::ZXSpectrum, "tzx");
accumulator.try_standard<Tape::UEF>(TargetPlatform::Acorn, "uef");
accumulator.try_standard<Disk::DiskImageHolder<Disk::WOZ>>(TargetPlatform::DiskII, "woz");
return accumulator.media;
}
Media Analyser::Static::GetMedia(const std::string &file_name) {
@@ -256,26 +304,28 @@ Media Analyser::Static::GetMedia(const std::string &file_name) {
}
TargetList Analyser::Static::GetTargets(const std::string &file_name) {
TargetList targets;
const std::string extension = get_extension(file_name);
TargetList targets;
// Check whether the file directly identifies a target; if so then just return that.
#define Format(ext, class) \
if(extension == ext) { \
try { \
auto target = Storage::State::class::load(file_name); \
if(target) { \
targets.push_back(std::move(target)); \
return targets; \
} \
} catch(...) {} \
}
const auto try_snapshot = [&](const char *ext, auto loader) -> bool {
if(extension != ext) {
return false;
}
try {
auto target = loader(file_name);
if(target) {
targets.push_back(std::move(target));
return true;
}
} catch(...) {}
Format("sna", SNA);
Format("szx", SZX);
Format("z80", Z80);
return false;
};
#undef TryInsert
if(try_snapshot("sna", Storage::State::SNA::load)) return targets;
if(try_snapshot("szx", Storage::State::SZX::load)) return targets;
if(try_snapshot("z80", Storage::State::Z80::load)) return targets;
// Otherwise:
//
@@ -286,30 +336,33 @@ TargetList Analyser::Static::GetTargets(const std::string &file_name) {
// Hand off to platform-specific determination of whether these
// things are actually compatible and, if so, how to load them.
#define Append(x) if(potential_platforms & TargetPlatform::x) {\
auto new_targets = x::GetTargets(media, file_name, potential_platforms);\
std::move(new_targets.begin(), new_targets.end(), std::back_inserter(targets));\
}
Append(Acorn);
Append(AmstradCPC);
Append(AppleII);
Append(AppleIIgs);
Append(Amiga);
Append(Atari2600);
Append(AtariST);
Append(Coleco);
Append(Commodore);
Append(DiskII);
Append(Enterprise);
Append(FAT12);
Append(Macintosh);
Append(MSX);
Append(Oric);
Append(PCCompatible);
Append(Sega);
Append(ZX8081);
Append(ZXSpectrum);
#undef Append
const auto append = [&](TargetPlatform::IntType platform, auto evaluator) {
if(!(potential_platforms & platform)) {
return;
}
auto new_targets = evaluator(media, file_name, potential_platforms);
std::move(new_targets.begin(), new_targets.end(), std::back_inserter(targets));
};
append(TargetPlatform::Acorn, Acorn::GetTargets);
append(TargetPlatform::AmstradCPC, AmstradCPC::GetTargets);
append(TargetPlatform::AppleII, AppleII::GetTargets);
append(TargetPlatform::AppleIIgs, AppleIIgs::GetTargets);
append(TargetPlatform::Amiga, Amiga::GetTargets);
append(TargetPlatform::Atari2600, Atari2600::GetTargets);
append(TargetPlatform::AtariST, AtariST::GetTargets);
append(TargetPlatform::Coleco, Coleco::GetTargets);
append(TargetPlatform::Commodore, Commodore::GetTargets);
append(TargetPlatform::DiskII, DiskII::GetTargets);
append(TargetPlatform::Enterprise, Enterprise::GetTargets);
append(TargetPlatform::FAT12, FAT12::GetTargets);
append(TargetPlatform::Macintosh, Macintosh::GetTargets);
append(TargetPlatform::MSX, MSX::GetTargets);
append(TargetPlatform::Oric, Oric::GetTargets);
append(TargetPlatform::PCCompatible, PCCompatible::GetTargets);
append(TargetPlatform::Sega, Sega::GetTargets);
append(TargetPlatform::ZX8081, ZX8081::GetTargets);
append(TargetPlatform::ZXSpectrum, ZXSpectrum::GetTargets);
// Reset any tapes to their initial position.
for(const auto &target : targets) {

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_hpp
#define StaticAnalyser_hpp
#pragma once
#include "../Machines.hpp"
@@ -79,5 +78,3 @@ TargetList GetTargets(const std::string &file_name);
Media GetMedia(const std::string &file_name);
}
#endif /* StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_ZX8081_StaticAnalyser_hpp
#define Analyser_Static_ZX8081_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::ZX8081 {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_ZX8081_Target_h
#define Analyser_Static_ZX8081_Target_h
#pragma once
#include "../../../Reflection/Enum.hpp"
#include "../../../Reflection/Struct.hpp"
@@ -39,5 +38,3 @@ struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<
};
}
#endif /* Analyser_Static_ZX8081_Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_ZXSpectrum_StaticAnalyser_hpp
#define Analyser_Static_ZXSpectrum_StaticAnalyser_hpp
#pragma once
#include "../StaticAnalyser.hpp"
#include "../../../Storage/TargetPlatforms.hpp"
@@ -18,5 +17,3 @@ namespace Analyser::Static::ZXSpectrum {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
}
#endif /* StaticAnalyser_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_ZXSpectrum_Target_h
#define Analyser_Static_ZXSpectrum_Target_h
#pragma once
#include "../../../Reflection/Enum.hpp"
#include "../../../Reflection/Struct.hpp"
@@ -37,5 +36,3 @@ struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<
};
}
#endif /* Target_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef ClockReceiver_hpp
#define ClockReceiver_hpp
#pragma once
#include "ForceInline.hpp"
@@ -277,5 +276,3 @@ template <class T> class HalfClockReceiver: public T {
private:
HalfCycles half_cycles_;
};
#endif /* ClockReceiver_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef ClockingHintSource_hpp
#define ClockingHintSource_hpp
#pragma once
namespace ClockingHint {
@@ -84,5 +83,3 @@ class Source {
};
}
#endif /* ClockingHintSource_h */

View File

@@ -6,8 +6,7 @@
// Copyright © 2018 Thomas Harte. All rights reserved.
//
#ifndef DeferredQueue_h
#define DeferredQueue_h
#pragma once
#include <functional>
#include <vector>
@@ -120,5 +119,3 @@ template <typename TimeUnit> class DeferredQueuePerformer: public DeferredQueue<
private:
std::function<void(TimeUnit)> target_;
};
#endif /* DeferredQueue_h */

View File

@@ -6,8 +6,7 @@
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#ifndef DeferredValue_h
#define DeferredValue_h
#pragma once
/*!
Provides storage for a single deferred value: one with a current value and a certain number
@@ -44,5 +43,3 @@ template <int DeferredDepth, typename ValueT> class DeferredValue {
(backlog[DeferredDepth / elements_per_uint32] & insert_mask) | (value << insert_shift);
}
};
#endif /* DeferredValue_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef ForceInline_hpp
#define ForceInline_hpp
#pragma once
#ifndef NDEBUG
@@ -22,5 +21,3 @@
#endif
#endif
#endif /* ForceInline_h */

View File

@@ -6,8 +6,7 @@
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef JustInTime_h
#define JustInTime_h
#pragma once
#include "ClockReceiver.hpp"
#include "../Concurrency/AsyncTaskQueue.hpp"
@@ -335,5 +334,3 @@ template <class T, class LocalTimeScale = HalfCycles, class TargetTimeScale = Lo
bool is_flushed_ = true;
Concurrency::AsyncTaskQueue<true> task_queue_;
};
#endif /* JustInTime_h */

View File

@@ -6,8 +6,7 @@
// Copyright © 2020 Thomas Harte. All rights reserved.
//
#ifndef ScanSynchroniser_h
#define ScanSynchroniser_h
#pragma once
#include "../Outputs/ScanTarget.hpp"
@@ -84,5 +83,3 @@ class ScanSynchroniser {
};
}
#endif /* ScanSynchroniser_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef TimeTypes_h
#define TimeTypes_h
#pragma once
#include <chrono>
@@ -25,6 +24,3 @@ inline Seconds seconds(Nanos nanos) {
}
}
#endif /* TimeTypes_h */

View File

@@ -6,8 +6,7 @@
// Copyright © 2020 Thomas Harte. All rights reserved.
//
#ifndef VSyncPredictor_hpp
#define VSyncPredictor_hpp
#pragma once
#include "TimeTypes.hpp"
#include <cassert>
@@ -151,5 +150,3 @@ class VSyncPredictor {
};
}
#endif /* VSyncPredictor_hpp */

View File

@@ -9,10 +9,12 @@
#include "1770.hpp"
#include "../../Storage/Disk/Encodings/MFM/Constants.hpp"
#define LOG_PREFIX "[WD FDC] "
#include "../../Outputs/Log.hpp"
namespace {
Log::Logger<Log::Source::WDFDC> logger;
}
using namespace WD;
WD1770::WD1770(Personality p) :
@@ -29,10 +31,10 @@ void WD1770::write(int address, uint8_t value) {
if((value&0xf0) == 0xd0) {
if(value == 0xd0) {
// Force interrupt **immediately**.
LOG("Force interrupt immediately");
logger.info().append("Force interrupt immediately");
posit_event(int(Event1770::ForceInterrupt));
} else {
ERROR("!!!TODO: force interrupt!!!");
logger.error().append("TODO: force interrupt");
update_status([] (Status &status) {
status.type = Status::One;
});
@@ -99,14 +101,14 @@ uint8_t WD1770::read(int address) {
if(status_.type == Status::One)
status |= (status_.spin_up ? Flag::SpinUp : 0);
}
// LOG("Returned status " << PADHEX(2) << int(status) << " of type " << 1+int(status_.type));
// logger.info().append("Returned status %02x of type %d", status, 1+int(status_.type));
return status;
}
case 1:
LOG("Returned track " << int(track_));
logger.info().append("Returned track %d", track_);
return track_;
case 2:
LOG("Returned sector " << int(sector_));
logger.info().append("Returned sector %d", sector_);
return sector_;
case 3:
update_status([] (Status &status) {
@@ -212,7 +214,7 @@ void WD1770::posit_event(int new_event_type) {
// Wait for a new command, branch to the appropriate handler.
case 0:
wait_for_command:
LOG("Idle...");
logger.info().append("Idle...");
set_data_mode(DataMode::Scanning);
index_hole_count_ = 0;
@@ -229,7 +231,7 @@ void WD1770::posit_event(int new_event_type) {
status.track_zero = false; // Always reset by a non-type 1; so reset regardless and set properly later.
});
LOG("Starting " << PADHEX(2) << int(command_));
logger.info().append("Starting %02x", command_);
if(!(command_ & 0x80)) goto begin_type_1;
if(!(command_ & 0x40)) goto begin_type_2;
@@ -259,7 +261,7 @@ void WD1770::posit_event(int new_event_type) {
status.data_request = false;
});
LOG("Step/Seek/Restore with track " << int(track_) << " data " << int(data_));
logger.info().append("Step/Seek/Restore with track %d data %d", track_, data_);
if(!has_motor_on_line() && !has_head_load_line()) goto test_type1_type;
if(has_motor_on_line()) goto begin_type1_spin_up;
@@ -339,7 +341,7 @@ void WD1770::posit_event(int new_event_type) {
READ_ID();
if(index_hole_count_ == 6) {
LOG("Nothing found to verify");
logger.info().append("Nothing found to verify");
update_status([] (Status &status) {
status.seek_error = true;
});
@@ -357,7 +359,7 @@ void WD1770::posit_event(int new_event_type) {
}
if(header_[0] == track_) {
LOG("Reached track " << std::dec << int(track_));
logger.info().append("Reached track %d", track_);
update_status([] (Status &status) {
status.crc_error = false;
});
@@ -430,7 +432,7 @@ void WD1770::posit_event(int new_event_type) {
READ_ID();
if(index_hole_count_ == 5) {
LOG("Failed to find sector " << std::dec << int(sector_));
logger.info().append("Failed to find sector %d", sector_);
update_status([] (Status &status) {
status.record_not_found = true;
});
@@ -440,12 +442,12 @@ void WD1770::posit_event(int new_event_type) {
distance_into_section_ = 0;
set_data_mode(DataMode::Scanning);
LOG("Considering " << std::dec << int(header_[0]) << "/" << int(header_[2]));
logger.info().append("Considering %d/%d", header_[0], header_[2]);
if( header_[0] == track_ && header_[2] == sector_ &&
(has_motor_on_line() || !(command_&0x02) || ((command_&0x08) >> 3) == header_[1])) {
LOG("Found " << std::dec << int(header_[0]) << "/" << int(header_[2]));
logger.info().append("Found %d/%d", header_[0], header_[2]);
if(get_crc_generator().get_value()) {
LOG("CRC error; back to searching");
logger.info().append("CRC error; back to searching");
update_status([] (Status &status) {
status.crc_error = true;
});
@@ -503,18 +505,18 @@ void WD1770::posit_event(int new_event_type) {
set_data_mode(DataMode::Scanning);
if(get_crc_generator().get_value()) {
LOG("CRC error; terminating");
logger.info().append("CRC error; terminating");
update_status([] (Status &status) {
status.crc_error = true;
});
goto wait_for_command;
}
LOG("Finished reading sector " << std::dec << int(sector_));
logger.info().append("Finished reading sector %d", sector_);
if(command_ & 0x10) {
sector_++;
LOG("Advancing to search for sector " << std::dec << int(sector_));
logger.info().append("Advancing to search for sector %d", sector_);
goto test_type2_write_protection;
}
goto wait_for_command;
@@ -598,7 +600,7 @@ void WD1770::posit_event(int new_event_type) {
sector_++;
goto test_type2_write_protection;
}
LOG("Wrote sector " << std::dec << int(sector_));
logger.info().append("Wrote sector %d", sector_);
goto wait_for_command;

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef _770_hpp
#define _770_hpp
#pragma once
#include "../../Storage/Disk/Controller/MFMDiskController.hpp"
@@ -141,5 +140,3 @@ class WD1770: public Storage::Disk::MFMController {
};
}
#endif /* _770_hpp */

View File

@@ -8,13 +8,11 @@
#include "ncr5380.hpp"
#ifndef NDEBUG
#define NDEBUG
#endif
#define LOG_PREFIX "[5380] "
#include "../../Outputs/Log.hpp"
namespace {
Log::Logger<Log::Source::NCR5380> logger;
}
// TODO:
//
// end_of_dma_ should be set if: /EOP && /DACK && (/RD || /WR); for at least 100ns.
@@ -38,7 +36,7 @@ NCR5380::NCR5380(SCSI::Bus &bus, int clock_rate) :
void NCR5380::write(int address, uint8_t value, bool) {
switch(address & 7) {
case 0:
LOG("[0] Set current SCSI bus state to " << PADHEX(2) << int(value));
logger.info().append("[0] Set current SCSI bus state to %02x", value);
data_bus_ = value;
if(dma_request_ && dma_operation_ == DMAOperation::Send) {
@@ -47,7 +45,7 @@ void NCR5380::write(int address, uint8_t value, bool) {
break;
case 1: {
LOG("[1] Initiator command register set: " << PADHEX(2) << int(value));
logger.info().append("[1] Initiator command register set: %02x", value);
initiator_command_ = value;
bus_output_ &= ~(Line::Reset | Line::Acknowledge | Line::Busy | Line::SelectTarget | Line::Attention);
@@ -63,7 +61,7 @@ void NCR5380::write(int address, uint8_t value, bool) {
} break;
case 2:
LOG("[2] Set mode: " << PADHEX(2) << int(value));
logger.info().append("[2] Set mode: %02x", value);
mode_ = value;
// bit 7: 1 = use block mode DMA mode (if DMA mode is also enabled)
@@ -104,27 +102,27 @@ void NCR5380::write(int address, uint8_t value, bool) {
break;
case 3: {
LOG("[3] Set target command: " << PADHEX(2) << int(value));
logger.info().append("[3] Set target command: %02x", value);
target_command_ = value;
update_control_output();
} break;
case 4:
LOG("[4] Set select enabled: " << PADHEX(2) << int(value));
logger.info().append("[4] Set select enabled: %02x", value);
break;
case 5:
LOG("[5] Start DMA send: " << PADHEX(2) << int(value));
logger.info().append("[5] Start DMA send: %02x", value);
dma_operation_ = DMAOperation::Send;
break;
case 6:
LOG("[6] Start DMA target receive: " << PADHEX(2) << int(value));
logger.info().append("[6] Start DMA target receive: %02x", value);
dma_operation_ = DMAOperation::TargetReceive;
break;
case 7:
LOG("[7] Start DMA initiator receive: " << PADHEX(2) << int(value));
logger.info().append("[7] Start DMA initiator receive: %02x", value);
dma_operation_ = DMAOperation::InitiatorReceive;
break;
}
@@ -148,7 +146,7 @@ void NCR5380::write(int address, uint8_t value, bool) {
uint8_t NCR5380::read(int address, bool) {
switch(address & 7) {
case 0:
LOG("[0] Get current SCSI bus state: " << PADHEX(2) << (bus_.get_state() & 0xff));
logger.info().append("[0] Get current SCSI bus state: %02x", (bus_.get_state() & 0xff));
if(dma_request_ && dma_operation_ == DMAOperation::InitiatorReceive) {
return dma_acknowledge();
@@ -156,7 +154,7 @@ uint8_t NCR5380::read(int address, bool) {
return uint8_t(bus_.get_state());
case 1:
LOG("[1] Initiator command register get: " << (arbitration_in_progress_ ? 'p' : '-') << (lost_arbitration_ ? 'l' : '-'));
logger.info().append("[1] Initiator command register get: %c%c", arbitration_in_progress_ ? 'p' : '-', lost_arbitration_ ? 'l' : '-');
return
// Bits repeated as they were set.
(initiator_command_ & ~0x60) |
@@ -168,11 +166,11 @@ uint8_t NCR5380::read(int address, bool) {
(lost_arbitration_ ? 0x20 : 0x00);
case 2:
LOG("[2] Get mode");
logger.info().append("[2] Get mode");
return mode_;
case 3:
LOG("[3] Get target command");
logger.info().append("[3] Get target command");
return target_command_;
case 4: {
@@ -186,7 +184,7 @@ uint8_t NCR5380::read(int address, bool) {
((bus_state & Line::Input) ? 0x04 : 0x00) |
((bus_state & Line::SelectTarget) ? 0x02 : 0x00) |
((bus_state & Line::Parity) ? 0x01 : 0x00);
LOG("[4] Get current bus state: " << PADHEX(2) << int(result));
logger.info().append("[4] Get current bus state: %02x", result);
return result;
}
@@ -201,16 +199,16 @@ uint8_t NCR5380::read(int address, bool) {
/* b2 = busy error */
((bus_state & Line::Attention) ? 0x02 : 0x00) |
((bus_state & Line::Acknowledge) ? 0x01 : 0x00);
LOG("[5] Get bus and status: " << PADHEX(2) << int(result));
logger.info().append("[5] Get bus and status: %02x", result);
return result;
}
case 6:
LOG("[6] Get input data");
logger.info().append("[6] Get input data");
return 0xff;
case 7:
LOG("[7] Reset parity/interrupt");
logger.info().append("[7] Reset parity/interrupt");
irq_ = false;
return 0xff;
}

View File

@@ -6,8 +6,7 @@
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef ncr5380_hpp
#define ncr5380_hpp
#pragma once
#include <cstdint>
@@ -86,5 +85,3 @@ class NCR5380 final: public SCSI::Bus::Observer {
};
}
#endif /* ncr5380_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef _522_hpp
#define _522_hpp
#pragma once
#include <cstdint>
@@ -140,5 +139,3 @@ template <class BusHandlerT> class MOS6522: public MOS6522Storage {
}
#include "Implementation/6522Implementation.hpp"
#endif /* _522_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef _522Storage_hpp
#define _522Storage_hpp
#pragma once
#include <cstdint>
@@ -107,5 +106,3 @@ class MOS6522Storage {
};
}
#endif /* _522Storage_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#ifndef _526_h
#define _526_h
#pragma once
#include <cstdint>
@@ -88,5 +87,3 @@ template <typename PortHandlerT, Personality personality> class MOS6526:
}
#include "Implementation/6526Implementation.hpp"
#endif /* _526_h */

View File

@@ -6,8 +6,7 @@
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#ifndef _526Implementation_h
#define _526Implementation_h
#pragma once
#include <cassert>
#include <cstdio>
@@ -238,5 +237,3 @@ bool MOS6526<BusHandlerT, personality>::serial_line_did_produce_bit(Serial::Line
}
}
#endif /* _526Implementation_h */

View File

@@ -6,8 +6,7 @@
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#ifndef _526Storage_h
#define _526Storage_h
#pragma once
#include <array>
@@ -322,8 +321,6 @@ struct MOS6526Storage {
static constexpr int TestInputNow = 1 << 8;
static constexpr int PendingClearMask = ~(ReloadNow | OneShotNow | ApplyClockNow);
bool active_ = false;
} counter_[2];
static constexpr int InterruptInOne = 1 << 0;
@@ -333,5 +330,3 @@ struct MOS6526Storage {
};
}
#endif /* _526Storage_h */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef _532_hpp
#define _532_hpp
#pragma once
#include <cstdint>
#include <cstdio>
@@ -188,5 +187,3 @@ template <class T> class MOS6532 {
};
}
#endif /* _532_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef _560_hpp
#define _560_hpp
#pragma once
#include "../../ClockReceiver/ClockReceiver.hpp"
#include "../../Concurrency/AsyncTaskQueue.hpp"
@@ -515,5 +514,3 @@ template <class BusHandler> class MOS6560 {
};
}
#endif /* _560_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef CRTC6845_hpp
#define CRTC6845_hpp
#pragma once
#include "../../ClockReceiver/ClockReceiver.hpp"
@@ -46,19 +45,25 @@ class BusHandler {
void perform_bus_cycle_phase2(const BusState &) {}
};
enum Personality {
enum class Personality {
HD6845S, // Type 0 in CPC parlance. Zero-width HSYNC available, no status, programmable VSYNC length.
// Considered exactly identical to the UM6845, so this enum covers both.
UM6845R, // Type 1 in CPC parlance. Status register, fixed-length VSYNC.
MC6845, // Type 2. No status register, fixed-length VSYNC, no zero-length HSYNC.
AMS40226 // Type 3. Status is get register, fixed-length VSYNC, no zero-length HSYNC.
AMS40226, // Type 3. Status is get register, fixed-length VSYNC, no zero-length HSYNC.
EGA, // Extended EGA-style CRTC; uses 16-bit addressing throughout.
};
constexpr bool is_egavga(Personality p) {
return p >= Personality::EGA;
}
// https://www.pcjs.org/blog/2018/03/20/ advises that "the behavior of bits 5 and 6 [of register 10, the cursor start
// register is really card specific".
//
// This enum captures those specifics.
enum CursorType {
enum class CursorType {
/// No cursor signal is generated.
None,
/// MDA style: 00 => symmetric blinking; 01 or 10 => no blinking; 11 => short on, long off.
@@ -69,21 +74,20 @@ enum CursorType {
// TODO UM6845R and R12/R13; see http://www.cpcwiki.eu/index.php/CRTC#CRTC_Differences
template <class T, CursorType cursor_type> class CRTC6845 {
template <class BusHandlerT, Personality personality, CursorType cursor_type> class CRTC6845 {
public:
CRTC6845(Personality p, T &bus_handler) noexcept :
personality_(p), bus_handler_(bus_handler), status_(0) {}
CRTC6845(BusHandlerT &bus_handler) noexcept :
bus_handler_(bus_handler), status_(0) {}
void select_register(uint8_t r) {
selected_register_ = r;
}
uint8_t get_status() {
switch(personality_) {
case UM6845R: return status_ | (bus_state_.vsync ? 0x20 : 0x00);
case AMS40226: return get_register();
default: return 0xff;
switch(personality) {
case Personality::UM6845R: return status_ | (bus_state_.vsync ? 0x20 : 0x00);
case Personality::AMS40226: return get_register();
default: return 0xff;
}
return 0xff;
}
@@ -92,30 +96,85 @@ template <class T, CursorType cursor_type> class CRTC6845 {
if(selected_register_ == 31) status_ &= ~0x80;
if(selected_register_ == 16 || selected_register_ == 17) status_ &= ~0x40;
if(personality_ == UM6845R && selected_register_ == 31) return dummy_register_;
if(personality == Personality::UM6845R && selected_register_ == 31) return dummy_register_;
if(selected_register_ < 12 || selected_register_ > 17) return 0xff;
return registers_[selected_register_];
}
void set_register(uint8_t value) {
static constexpr uint8_t masks[] = {
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f,
0xff, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff
static constexpr bool is_ega = is_egavga(personality);
auto load_low = [value](uint16_t &target) {
target = (target & 0xff00) | value;
};
auto load_high = [value](uint16_t &target) {
constexpr uint8_t mask = RefreshMask >> 8;
target = uint16_t((target & 0x00ff) | ((value & mask) << 8));
};
// Per CPC documentation, skew doesn't work on a "type 1 or 2", i.e. an MC6845 or a UM6845R.
if(selected_register_ == 8 && personality_ != UM6845R && personality_ != MC6845) {
switch((value >> 4)&3) {
default: display_skew_mask_ = 1; break;
case 1: display_skew_mask_ = 2; break;
case 2: display_skew_mask_ = 4; break;
}
switch(selected_register_) {
case 0: layout_.horizontal.total = value; break;
case 1: layout_.horizontal.displayed = value; break;
case 2: layout_.horizontal.start_sync = value; break;
case 3:
layout_.horizontal.sync_width = value & 0xf;
layout_.vertical.sync_lines = value >> 4;
// TODO: vertical sync lines:
// "(0 means 16 on some CRTC. Not present on all CRTCs, fixed to 16 lines on these)"
break;
case 4: layout_.vertical.total = value & 0x7f; break;
case 5: layout_.vertical.adjust = value & 0x1f; break;
case 6: layout_.vertical.displayed = value & 0x7f; break;
case 7: layout_.vertical.start_sync = value & 0x7f; break;
case 8:
switch(value & 3) {
default: layout_.interlace_mode_ = InterlaceMode::Off; break;
case 0b01: layout_.interlace_mode_ = InterlaceMode::InterlaceSync; break;
case 0b11: layout_.interlace_mode_ = InterlaceMode::InterlaceSyncAndVideo; break;
}
// Per CPC documentation, skew doesn't work on a "type 1 or 2", i.e. an MC6845 or a UM6845R.
if(personality != Personality::UM6845R && personality != Personality::MC6845) {
switch((value >> 4)&3) {
default: display_skew_mask_ = 1; break;
case 1: display_skew_mask_ = 2; break;
case 2: display_skew_mask_ = 4; break;
}
}
break;
case 9: layout_.vertical.end_row = value & 0x1f; break;
case 10:
layout_.vertical.start_cursor = value & 0x1f;
layout_.cursor_flags = (value >> 5) & 3;
break;
case 11:
layout_.vertical.end_cursor = value & 0x1f;
break;
case 12: load_high(layout_.start_address); break;
case 13: load_low(layout_.start_address); break;
case 14: load_high(layout_.cursor_address); break;
case 15: load_low(layout_.cursor_address); break;
}
static constexpr uint8_t masks[] = {
0xff, // Horizontal total.
0xff, // Horizontal display end.
0xff, // Start horizontal blank.
0xff, //
// EGA: b0b4: end of horizontal blank;
// b5b6: "Number of character clocks to delay start of display after Horizontal Total has been reached."
is_ega ? 0xff : 0x7f, // Start horizontal retrace.
0x1f, 0x7f, 0x7f,
0xff, 0x1f, 0x7f, 0x1f,
uint8_t(RefreshMask >> 8), uint8_t(RefreshMask),
uint8_t(RefreshMask >> 8), uint8_t(RefreshMask),
};
if(selected_register_ < 16) {
registers_[selected_register_] = value & masks[selected_register_];
}
if(selected_register_ == 31 && personality_ == UM6845R) {
if(selected_register_ == 31 && personality == Personality::UM6845R) {
dummy_register_ = value;
}
}
@@ -130,20 +189,20 @@ template <class T, CursorType cursor_type> class CRTC6845 {
auto cyles_remaining = cycles.as_integral();
while(cyles_remaining--) {
// Check for end of visible characters.
if(character_counter_ == registers_[1]) {
if(character_counter_ == layout_.horizontal.displayed) {
// TODO: consider skew in character_is_visible_. Or maybe defer until perform_bus_cycle?
character_is_visible_ = false;
end_of_line_address_ = bus_state_.refresh_address;
}
perform_bus_cycle_phase1();
bus_state_.refresh_address = (bus_state_.refresh_address + 1) & 0x3fff;
bus_state_.refresh_address = (bus_state_.refresh_address + 1) & RefreshMask;
bus_state_.cursor = is_cursor_line_ &&
bus_state_.refresh_address == (registers_[15] | (registers_[14] << 8));
bus_state_.refresh_address == layout_.cursor_address;
// Check for end-of-line.
if(character_counter_ == registers_[0]) {
if(character_counter_ == layout_.horizontal.total) {
character_counter_ = 0;
do_end_of_line();
character_is_visible_ = true;
@@ -153,7 +212,7 @@ template <class T, CursorType cursor_type> class CRTC6845 {
}
// Check for start of horizontal sync.
if(character_counter_ == registers_[2]) {
if(character_counter_ == layout_.horizontal.start_sync) {
hsync_counter_ = 0;
bus_state_.hsync = true;
}
@@ -162,15 +221,15 @@ template <class T, CursorType cursor_type> class CRTC6845 {
// cancellation of the plan to perform sync if this is an HD6845S or UM6845R; otherwise zero
// will end up counting as 16 as it won't be checked until after overflow.
if(bus_state_.hsync) {
switch(personality_) {
case HD6845S:
case UM6845R:
bus_state_.hsync = hsync_counter_ != (registers_[3] & 15);
switch(personality) {
case Personality::HD6845S:
case Personality::UM6845R:
bus_state_.hsync = hsync_counter_ != layout_.horizontal.sync_width;
hsync_counter_ = (hsync_counter_ + 1) & 15;
break;
default:
hsync_counter_ = (hsync_counter_ + 1) & 15;
bus_state_.hsync = hsync_counter_ != (registers_[3] & 15);
bus_state_.hsync = hsync_counter_ != layout_.horizontal.sync_width;
break;
}
}
@@ -184,6 +243,8 @@ template <class T, CursorType cursor_type> class CRTC6845 {
}
private:
static constexpr uint16_t RefreshMask = (personality >= Personality::EGA) ? 0xffff : 0x3fff;
inline void perform_bus_cycle_phase1() {
// Skew theory of operation: keep a history of the last three states, and apply whichever is selected.
character_is_visible_shifter_ = (character_is_visible_shifter_ << 1) | unsigned(character_is_visible_);
@@ -199,7 +260,7 @@ template <class T, CursorType cursor_type> class CRTC6845 {
if constexpr (cursor_type != CursorType::None) {
// Check for cursor disable.
// TODO: this is handled differently on the EGA, should I ever implement that.
is_cursor_line_ &= bus_state_.row_address != (registers_[11] & 0x1f);
is_cursor_line_ &= bus_state_.row_address != layout_.vertical.end_cursor;
}
// Check for end of vertical sync.
@@ -207,10 +268,10 @@ template <class T, CursorType cursor_type> class CRTC6845 {
vsync_counter_ = (vsync_counter_ + 1) & 15;
// On the UM6845R and AMS40226, honour the programmed vertical sync time; on the other CRTCs
// always use a vertical sync count of 16.
switch(personality_) {
case HD6845S:
case AMS40226:
bus_state_.vsync = vsync_counter_ != (registers_[3] >> 4);
switch(personality) {
case Personality::HD6845S:
case Personality::AMS40226:
bus_state_.vsync = vsync_counter_ != layout_.vertical.sync_lines;
break;
default:
bus_state_.vsync = vsync_counter_ != 0;
@@ -220,19 +281,19 @@ template <class T, CursorType cursor_type> class CRTC6845 {
if(is_in_adjustment_period_) {
line_counter_++;
if(line_counter_ == registers_[5]) {
if(line_counter_ == layout_.vertical.adjust) {
is_in_adjustment_period_ = false;
do_end_of_frame();
}
} else {
// Advance vertical counter.
if(bus_state_.row_address == registers_[9]) {
if(bus_state_.row_address == layout_.vertical.end_row) {
bus_state_.row_address = 0;
line_address_ = end_of_line_address_;
// Check for entry into the overflow area.
if(line_counter_ == registers_[4]) {
if(registers_[5]) {
if(line_counter_ == layout_.vertical.total) {
if(layout_.vertical.adjust) {
line_counter_ = 0;
is_in_adjustment_period_ = true;
} else {
@@ -242,13 +303,13 @@ template <class T, CursorType cursor_type> class CRTC6845 {
line_counter_ = (line_counter_ + 1) & 0x7f;
// Check for start of vertical sync.
if(line_counter_ == registers_[7]) {
if(line_counter_ == layout_.vertical.start_sync) {
bus_state_.vsync = true;
vsync_counter_ = 0;
}
// Check for end of visible lines.
if(line_counter_ == registers_[6]) {
if(line_counter_ == layout_.vertical.displayed) {
line_is_visible_ = false;
}
}
@@ -259,18 +320,18 @@ template <class T, CursorType cursor_type> class CRTC6845 {
bus_state_.refresh_address = line_address_;
character_counter_ = 0;
character_is_visible_ = (registers_[1] != 0);
character_is_visible_ = (layout_.horizontal.displayed != 0);
if constexpr (cursor_type != CursorType::None) {
// Check for cursor enable.
is_cursor_line_ |= bus_state_.row_address == (registers_[10] & 0x1f);
is_cursor_line_ |= bus_state_.row_address == layout_.vertical.start_cursor;
switch(cursor_type) {
// MDA-style blinking.
// https://retrocomputing.stackexchange.com/questions/27803/what-are-the-blinking-rates-of-the-caret-and-of-blinking-text-on-pc-graphics-car
// gives an 8/8 pattern for regular blinking though mode 11 is then just a guess.
case CursorType::MDA:
switch(registers_[10] >> 5) {
switch(layout_.cursor_flags) {
case 0b11: is_cursor_line_ &= (bus_state_.field_count & 8) < 3; break;
case 0b00: is_cursor_line_ &= bool(bus_state_.field_count & 8); break;
case 0b01: is_cursor_line_ = false; break;
@@ -285,16 +346,50 @@ template <class T, CursorType cursor_type> class CRTC6845 {
inline void do_end_of_frame() {
line_counter_ = 0;
line_is_visible_ = true;
line_address_ = uint16_t((registers_[12] << 8) | registers_[13]);
line_address_ = layout_.start_address;
bus_state_.refresh_address = line_address_;
++bus_state_.field_count;
}
Personality personality_;
T &bus_handler_;
BusHandlerT &bus_handler_;
BusState bus_state_;
uint8_t registers_[18] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
enum class InterlaceMode {
Off,
InterlaceSync,
InterlaceSyncAndVideo,
};
enum class BlinkMode {
// TODO.
};
struct {
struct {
uint8_t total;
uint8_t displayed;
uint8_t start_sync;
uint8_t sync_width;
} horizontal;
struct {
uint8_t total;
uint8_t displayed;
uint8_t start_sync;
uint8_t sync_lines;
uint8_t adjust;
uint8_t end_row;
uint8_t start_cursor;
uint8_t end_cursor;
} vertical;
InterlaceMode interlace_mode_ = InterlaceMode::Off;
uint16_t start_address;
uint16_t cursor_address;
uint16_t light_pen_address;
uint8_t cursor_flags;
} layout_;
uint8_t registers_[18]{};
uint8_t dummy_register_ = 0;
int selected_register_ = 0;
@@ -318,5 +413,3 @@ template <class T, CursorType cursor_type> class CRTC6845 {
};
}
#endif /* CRTC6845_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef Motorola_ACIA_6850_hpp
#define Motorola_ACIA_6850_hpp
#pragma once
#include <cstdint>
#include "../../ClockReceiver/ClockReceiver.hpp"
@@ -126,5 +125,3 @@ class ACIA: public ClockingHint::Source, private Serial::Line<false>::ReadDelega
};
}
#endif /* Motorola_ACIA_6850_hpp */

View File

@@ -11,13 +11,14 @@
#include <algorithm>
#include <cstring>
#ifndef NDEBUG
#define NDEBUG
#endif
#define LOG_PREFIX "[MFP] "
#include "../../Outputs/Log.hpp"
namespace {
Log::Logger<Log::Source::MFP68901> logger;
}
using namespace Motorola::MFP68901;
ClockingHint::Preference MFP68901::preferred_clocking() const {
@@ -64,11 +65,11 @@ uint8_t MFP68901::read(int address) {
case 0x11: case 0x12: return get_timer_data(address - 0xf);
// USART block: TODO.
case 0x13: LOG("Read: sync character generator"); break;
case 0x14: LOG("Read: USART control"); break;
case 0x15: LOG("Read: receiver status"); break;
case 0x16: LOG("Read: transmitter status"); break;
case 0x17: LOG("Read: USART data"); break;
case 0x13: logger.error().append("Read: sync character generator"); break;
case 0x14: logger.error().append("Read: USART control"); break;
case 0x15: logger.error().append("Read: receiver status"); break;
case 0x16: logger.error().append("Read: transmitter status"); break;
case 0x17: logger.error().append("Read: USART data"); break;
}
return 0x00;
}
@@ -169,11 +170,11 @@ void MFP68901::write(int address, uint8_t value) {
break;
// USART block: TODO.
case 0x13: LOG("Write: sync character generator"); break;
case 0x14: LOG("Write: USART control"); break;
case 0x15: LOG("Write: receiver status"); break;
case 0x16: LOG("Write: transmitter status"); break;
case 0x17: LOG("Write: USART data"); break;
case 0x13: logger.error().append("Write: sync character generator"); break;
case 0x14: logger.error().append("Write: USART control"); break;
case 0x15: logger.error().append("Write: receiver status"); break;
case 0x16: logger.error().append("Write: transmitter status"); break;
case 0x17: logger.error().append("Write: USART data"); break;
}
update_clocking_observer();
@@ -220,7 +221,7 @@ HalfCycles MFP68901::next_sequence_point() {
// MARK: - Timers
void MFP68901::set_timer_mode(int timer, TimerMode mode, int prescale, bool reset_timer) {
LOG("Timer " << timer << " mode set: " << int(mode) << "; prescale: " << prescale);
logger.error().append("Timer %d mode set: %d; prescale: %d", timer, mode, prescale);
timers_[timer].mode = mode;
if(reset_timer) {
timers_[timer].prescale_count = 0;
@@ -398,7 +399,7 @@ int MFP68901::acknowledge_interrupt() {
int selected = 0;
while((1 << selected) != mask) ++selected;
// LOG("Interrupt acknowledged: " << selected);
// logger.error().append("Interrupt acknowledged: %d", selected);
return (interrupt_vector_ & 0xf0) | uint8_t(selected);
}

View File

@@ -6,8 +6,7 @@
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef MFP68901_hpp
#define MFP68901_hpp
#pragma once
#include "../../ClockReceiver/ClockReceiver.hpp"
#include "../../ClockReceiver/ClockingHintSource.hpp"
@@ -184,5 +183,3 @@ class MFP68901: public ClockingHint::Source {
};
}
#endif /* MFP68901_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef i8255_hpp
#define i8255_hpp
#pragma once
#include <cstdint>
@@ -88,5 +87,3 @@ template <class T> class i8255 {
};
}
#endif /* i8255_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright © 2023 Thomas Harte. All rights reserved.
//
#ifndef CommandDecoder_hpp
#define CommandDecoder_hpp
#pragma once
#include <cstdint>
#include <cstddef>
@@ -217,5 +216,3 @@ class CommandDecoder {
};
}
#endif /* CommandDecoder_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright © 2023 Thomas Harte. All rights reserved.
//
#ifndef Results_hpp
#define Results_hpp
#pragma once
#include "CommandDecoder.hpp"
#include "Status.hpp"
@@ -61,5 +60,3 @@ class Results {
};
}
#endif /* Results_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright © 2023 Thomas Harte. All rights reserved.
//
#ifndef Status_hpp
#define Status_hpp
#pragma once
namespace Intel::i8272 {
@@ -130,5 +129,3 @@ class Status {
};
}
#endif /* Status_hpp */

View File

@@ -10,6 +10,12 @@
#include "../../Outputs/Log.hpp"
namespace {
Log::Logger<Log::Source::i8272> logger;
}
using namespace Intel::i8272;
i8272::i8272(BusHandler &bus_handler, Cycles clock_rate) :
@@ -54,7 +60,7 @@ void i8272::run_for(Cycles cycles) {
while(steps--) {
// Perform a step.
int direction = (drives_[c].target_head_position < drives_[c].head_position) ? -1 : 1;
LOG("Target " << PADDEC(0) << drives_[c].target_head_position << " versus believed " << int(drives_[c].head_position));
logger.info().append("Target %d versus believed %d", drives_[c].target_head_position, drives_[c].head_position);
select_drive(c);
get_drive().step(Storage::Disk::HeadPosition(direction));
if(drives_[c].target_head_position >= 0) drives_[c].head_position += direction;
@@ -303,17 +309,17 @@ void i8272::posit_event(int event_type) {
// the index hole limit is breached or a sector is found with a cylinder, head, sector and size equal to the
// values in the internal registers.
index_hole_limit_ = 2;
// LOG("Seeking " << PADDEC(0) << cylinder_ << " " << head_ " " << sector_ << " " << size_);
// logger.info().append("Seeking " << PADDEC(0) << cylinder_ << " " << head_ " " << sector_ << " " << size_);
find_next_sector:
FIND_HEADER();
if(!index_hole_limit_) {
// Two index holes have passed wihout finding the header sought.
// LOG("Not found");
// logger.info().append("Not found");
status_.set(Status1::NoData);
goto abort;
}
index_hole_count_ = 0;
// LOG("Header");
// logger.info().append("Header");
READ_HEADER();
if(index_hole_count_) {
// This implies an index hole was sighted within the header. Error out.
@@ -324,11 +330,11 @@ void i8272::posit_event(int event_type) {
// This implies a CRC error in the header; mark as such but continue.
status_.set(Status1::DataError);
}
// LOG("Considering << PADHEX(2) << header_[0] << " " << header_[1] << " " << header_[2] << " " << header_[3] << " [" << get_crc_generator().get_value() << "]");
// logger.info().append("Considering %02x %02x %02x %02x [%04x]", header_[0], header_[1], header_[2], header_[3], get_crc_generator().get_value());
if(header_[0] != cylinder_ || header_[1] != head_ || header_[2] != sector_ || header_[3] != size_) goto find_next_sector;
// Branch to whatever is supposed to happen next
// LOG("Proceeding");
// logger.info().append("Proceeding");
switch(command_.command()) {
default:
case Command::ReadData:
@@ -343,13 +349,13 @@ void i8272::posit_event(int event_type) {
// Performs the read data or read deleted data command.
read_data:
// LOG(PADHEX(2) << "Read [deleted] data ["
// << int(command_[2]) << " "
// << int(command_[3]) << " "
// << int(command_[4]) << " "
// << int(command_[5]) << " ... "
// << int(command_[6]) << " "
// << int(command_[8]) << "]");
// logger.info().append("Read [deleted] data [%02x %02x %02x %02x ... %02x %02x]",
// command_[2],
// command_[3],
// command_[4],
// command_[5],
// command_[6],
// command_[8]);
read_next_data:
goto read_write_find_header;
@@ -433,13 +439,13 @@ void i8272::posit_event(int event_type) {
goto post_st012chrn;
write_data:
// LOG(PADHEX(2) << "Write [deleted] data ["
// << int(command_[2]) << " "
// << int(command_[3]) << " "
// << int(command_[4]) << " "
// << int(command_[5]) << " ... "
// << int(command_[6]) << " "
// << int(command_[8]) << "]");
// logger.info().append("Write [deleted] data [%02x %02x %02x %02x ... %02x %02x]",
// command_[2],
// command_[3],
// command_[4],
// command_[5],
// command_[6],
// command_[8]);
if(get_drive().get_is_read_only()) {
status_.set(Status1::NotWriteable);
@@ -474,7 +480,7 @@ void i8272::posit_event(int event_type) {
goto write_loop;
}
LOG("Wrote " << PADDEC(0) << distance_into_section_ << " bytes");
logger.info().append("Wrote %d bytes", distance_into_section_);
write_crc();
expects_input_ = false;
WAIT_FOR_EVENT(Event::DataWritten);
@@ -490,7 +496,7 @@ void i8272::posit_event(int event_type) {
// Performs the read ID command.
read_id:
// Establishes the drive and head being addressed, and whether in double density mode.
// LOG(PADHEX(2) << "Read ID [" << int(command_[0]) << " " << int(command_[1]) << "]");
// logger.info().append("Read ID [%02x %02x]", command_[0], command_[1]);
// Sets a maximum index hole limit of 2 then waits either until it finds a header mark or sees too many index holes.
// If a header mark is found, reads in the following bytes that produce a header. Otherwise branches to data not found.
@@ -512,11 +518,11 @@ void i8272::posit_event(int event_type) {
// Performs read track.
read_track:
// LOG(PADHEX(2) << "Read track ["
// << int(command_[2]) << " "
// << int(command_[3]) << " "
// << int(command_[4]) << " "
// << int(command_[5]) << "]");
// logger.info().append("Read track [%02x %02x %02x %02x]"
// command_[2],
// command_[3],
// command_[4],
// command_[5]);
// Wait for the index hole.
WAIT_FOR_EVENT(Event::IndexHole);
@@ -557,7 +563,7 @@ void i8272::posit_event(int event_type) {
// Performs format [/write] track.
format_track:
LOG("Format track");
logger.info().append("Format track");
if(get_drive().get_is_read_only()) {
status_.set(Status1::NotWriteable);
goto abort;
@@ -601,12 +607,8 @@ void i8272::posit_event(int event_type) {
break;
}
LOG(PADHEX(2) << "W:"
<< int(header_[0]) << " "
<< int(header_[1]) << " "
<< int(header_[2]) << " "
<< int(header_[3]) << ", "
<< get_crc_generator().get_value());
logger.info().append("W: %02x %02x %02x %02x, %04x",
header_[0], header_[1], header_[2], header_[3], get_crc_generator().get_value());
write_crc();
// Write the sector body.
@@ -638,15 +640,15 @@ void i8272::posit_event(int event_type) {
goto post_st012chrn;
scan_low:
ERROR("Scan low unimplemented!!");
logger.error().append("Scan low unimplemented!!");
goto wait_for_command;
scan_low_or_equal:
ERROR("Scan low or equal unimplemented!!");
logger.error().append("Scan low or equal unimplemented!!");
goto wait_for_command;
scan_high_or_equal:
ERROR("Scan high or equal unimplemented!!");
logger.error().append("Scan high or equal unimplemented!!");
goto wait_for_command;
// Performs both recalibrate and seek commands. These commands occur asynchronously, so the actual work
@@ -677,11 +679,11 @@ void i8272::posit_event(int event_type) {
// up in run_for understands to mean 'keep going until track 0 is active').
if(command_.command() != Command::Recalibrate) {
drives_[drive].target_head_position = command_.seek_target();
LOG(PADHEX(2) << "Seek to " << int(command_.seek_target()));
logger.info().append("Seek to %d", command_.seek_target());
} else {
drives_[drive].target_head_position = -1;
drives_[drive].head_position = 0;
LOG("Recalibrate");
logger.info().append("Recalibrate");
}
// Check whether any steps are even needed; if not then mark as completed already.
@@ -694,7 +696,7 @@ void i8272::posit_event(int event_type) {
// Performs sense interrupt status.
sense_interrupt_status:
LOG("Sense interrupt status");
logger.info().append("Sense interrupt status");
{
// Find the first drive that is in the CompletedSeeking state.
int found_drive = -1;
@@ -722,7 +724,7 @@ void i8272::posit_event(int event_type) {
// Performs specify.
specify:
// Just store the values, and terminate the command.
LOG("Specify");
logger.info().append("Specify");
step_rate_time_ = command_.specify_specs().step_rate_time;
head_unload_time_ = command_.specify_specs().head_unload_time;
head_load_time_ = command_.specify_specs().head_load_time;
@@ -733,7 +735,7 @@ void i8272::posit_event(int event_type) {
goto wait_for_command;
sense_drive_status:
LOG("Sense drive status");
logger.info().append("Sense drive status");
{
int drive = command_.target().drive;
select_drive(drive);
@@ -772,11 +774,13 @@ void i8272::posit_event(int event_type) {
// Posts whatever is in result_stack_ as a result phase. Be aware that it is a stack, so the
// last thing in it will be returned first.
post_result:
// LOGNBR(PADHEX(2) << "Result to " << int(command_[0] & 0x1f) << ", main " << int(main_status_) << "; ");
// for(std::size_t c = 0; c < result_stack_.size(); c++) {
// LOGNBR(" " << int(result_stack_[result_stack_.size() - 1 - c]));
// {
// auto line = logger.info();
// line.append("Result to %02x, main %02x", command_[0] & 0x1f, main_status_);
// for(std::size_t c = 0; c < result_stack_.size(); c++) {
// line.append(" %02x", result_stack_[result_stack_.size() - 1 - c]);
// }
// }
// LOGNBR(std::endl);
// Set ready to send data to the processor, no longer in non-DMA execution phase.
is_executing_ = false;

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef i8272_hpp
#define i8272_hpp
#pragma once
#include "CommandDecoder.hpp"
#include "Status.hpp"
@@ -134,5 +133,3 @@ class i8272 : public Storage::Disk::MFMController {
};
}
#endif /* i8272_hpp */

View File

@@ -8,15 +8,16 @@
#include "z8530.hpp"
#ifndef NDEBUG
#define NDEBUG
#endif
#define LOG_PREFIX "[SCC] "
#include "../../Outputs/Log.hpp"
using namespace Zilog::SCC;
namespace {
Log::Logger<Log::Source::SCC> log;
}
void z8530::reset() {
// TODO.
}
@@ -53,7 +54,7 @@ std::uint8_t z8530::read(int address) {
case 2: // Handled non-symmetrically between channels.
if(address & 1) {
LOG("Unimplemented: register 2 status bits");
log.error().append("Unimplemented: register 2 status bits");
} else {
result = interrupt_vector_;
@@ -110,11 +111,11 @@ void z8530::write(int address, std::uint8_t value) {
case 2: // Interrupt vector register; used only by Channel B.
// So there's only one of these.
interrupt_vector_ = value;
LOG("Interrupt vector set to " << PADHEX(2) << int(value));
log.info().append("Interrupt vector set to %d", value);
break;
case 9: // Master interrupt and reset register; there is also only one of these.
LOG("Master interrupt and reset register: " << PADHEX(2) << int(value));
log.info().append("Master interrupt and reset register: %02x", value);
master_interrupt_control_ = value;
break;
}
@@ -151,7 +152,7 @@ uint8_t z8530::Channel::read(bool data, uint8_t pointer) {
if(data) {
return data_;
} else {
LOG("Control read from register " << int(pointer));
log.info().append("Control read from register %d", pointer);
// Otherwise, this is a control read...
switch(pointer) {
default:
@@ -236,10 +237,10 @@ void z8530::Channel::write(bool data, uint8_t pointer, uint8_t value) {
data_ = value;
return;
} else {
LOG("Control write: " << PADHEX(2) << int(value) << " to register " << int(pointer));
log.info().append("Control write: %02x to register %d", value, pointer);
switch(pointer) {
default:
LOG("Unrecognised control write: " << PADHEX(2) << int(value) << " to register " << int(pointer));
log.info().append("Unrecognised control write: %02x to register %d", value, pointer);
break;
case 0x0: // Write register 0 — CRC reset and other functions.
@@ -247,13 +248,13 @@ void z8530::Channel::write(bool data, uint8_t pointer, uint8_t value) {
switch(value >> 6) {
default: /* Do nothing. */ break;
case 1:
LOG("TODO: reset Rx CRC checker.");
log.error().append("TODO: reset Rx CRC checker.");
break;
case 2:
LOG("TODO: reset Tx CRC checker.");
log.error().append("TODO: reset Tx CRC checker.");
break;
case 3:
LOG("TODO: reset Tx underrun/EOM latch.");
log.error().append("TODO: reset Tx underrun/EOM latch.");
break;
}
@@ -261,24 +262,24 @@ void z8530::Channel::write(bool data, uint8_t pointer, uint8_t value) {
switch((value >> 3)&7) {
default: /* Do nothing. */ break;
case 2:
// LOG("reset ext/status interrupts.");
// log.info().append("reset ext/status interrupts.");
external_status_interrupt_ = false;
external_interrupt_status_ = 0;
break;
case 3:
LOG("TODO: send abort (SDLC).");
log.error().append("TODO: send abort (SDLC).");
break;
case 4:
LOG("TODO: enable interrupt on next Rx character.");
log.error().append("TODO: enable interrupt on next Rx character.");
break;
case 5:
LOG("TODO: reset Tx interrupt pending.");
log.error().append("TODO: reset Tx interrupt pending.");
break;
case 6:
LOG("TODO: reset error.");
log.error().append("TODO: reset error.");
break;
case 7:
LOG("TODO: reset highest IUS.");
log.error().append("TODO: reset highest IUS.");
break;
}
break;
@@ -303,7 +304,7 @@ void z8530::Channel::write(bool data, uint8_t pointer, uint8_t value) {
b1 = 1 => transmit buffer empty interrupt is enabled; 0 => it isn't.
b0 = 1 => external interrupt is enabled; 0 => it isn't.
*/
LOG("Interrupt mask: " << PADHEX(2) << int(value));
log.info().append("Interrupt mask: %02x", value);
break;
case 0x2: // Write register 2 - interrupt vector.
@@ -318,9 +319,7 @@ void z8530::Channel::write(bool data, uint8_t pointer, uint8_t value) {
case 2: receive_bit_count = 6; break;
case 3: receive_bit_count = 8; break;
}
LOG("Receive bit count: " << receive_bit_count);
(void)receive_bit_count;
log.info().append("Receive bit count: %d", receive_bit_count);
/*
b7,b6:

View File

@@ -6,8 +6,7 @@
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef z8530_hpp
#define z8530_hpp
#pragma once
#include <cstdint>
@@ -109,5 +108,3 @@ class z8530 {
};
}
#endif /* z8530_hpp */

View File

@@ -6,8 +6,7 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef TMS9918_hpp
#define TMS9918_hpp
#pragma once
#include "../../Outputs/CRT/CRT.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
@@ -127,5 +126,3 @@ template <Personality personality> class TMS9918: private Base<personality> {
};
}
#endif /* TMS9918_hpp */

Some files were not shown because too many files have changed in this diff Show More