1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-09-11 10:28:07 +00:00

Compare commits

...

2461 Commits

Author SHA1 Message Date
Thomas Harte
cad42beef4 Roll in some random style improvements. 2025-09-08 20:38:50 -04:00
Thomas Harte
96fd0b7892 Merge pull request #1553 from TomHarte/IndentationSomeMore
Further reduce indentation.
2025-09-05 23:20:19 -04:00
Thomas Harte
6f1db15d7c Further reduce indentation. 2025-09-05 23:07:45 -04:00
Thomas Harte
1854296ee8 Merge pull request #1552 from TomHarte/ElectronIDE
Reduce code duplication within the ROM catalogue.
2025-09-05 22:45:55 -04:00
Thomas Harte
515cc5f326 Correct spelling. 2025-09-05 22:09:38 -04:00
Thomas Harte
091be7eafe Remove unused header. 2025-09-05 22:03:45 -04:00
Thomas Harte
27a19ea417 Eliminate line-length violations. 2025-09-05 22:03:19 -04:00
Thomas Harte
9a5e9af67c Standardise layout. 2025-09-05 22:00:42 -04:00
Thomas Harte
3a493f2428 Merge pull request #1551 from TomHarte/LogLevels
Allow logging of errors but not info.
2025-09-05 21:04:56 -04:00
Thomas Harte
ca6e34f4b4 Fix dangling OpenGL accesses. 2025-09-05 19:30:33 -04:00
Thomas Harte
e1e68312c4 Transcribe remaining catalogue entries. 2025-09-05 17:23:38 -04:00
Thomas Harte
c7ff2cece4 Head in search of a more-compact form. 2025-09-05 16:55:00 -04:00
Thomas Harte
8e6f4fa36f Fix NDEBUG route. 2025-09-05 14:34:08 -04:00
Thomas Harte
4d302da9fa Allow logging of errors but not info. 2025-09-05 14:25:56 -04:00
Thomas Harte
26f82e8143 Merge pull request #1550 from TomHarte/SpaceshipOperator
Adopt spaceship.
2025-09-04 22:08:35 -04:00
Thomas Harte
6518f08bc7 Adopt spaceship. 2025-09-04 21:25:12 -04:00
Thomas Harte
8599123b30 Merge pull request #1549 from TomHarte/MoreFDC
Implement further FDC commands.
2025-09-04 19:25:32 -04:00
Thomas Harte
f934a1aa10 Ensure std::hash is known. 2025-09-04 17:53:18 -04:00
Thomas Harte
81be5f809f Fix logged statement. 2025-09-04 17:48:50 -04:00
Thomas Harte
8bb94804d4 Attempt to bluster to something for read ID. 2025-09-04 17:45:41 -04:00
Thomas Harte
c3f64e85ce Support unordered maps; use spaceship operator. 2025-09-04 17:39:09 -04:00
Thomas Harte
53057aff5d Reduce type redundancy. 2025-09-04 17:29:34 -04:00
Thomas Harte
8cad5ac7e9 Reduce repetitive array references. 2025-09-04 17:00:10 -04:00
Thomas Harte
b4f643f3dd Merge pull request #1541 from TomHarte/Spelling
Adopt my native spelling: 'licence' is a noun.
2025-09-04 16:01:11 -04:00
Thomas Harte
2d659289e8 Merge pull request #1546 from TomHarte/SomeIDE
Add some IDE/ATA structure.
2025-09-04 15:58:26 -04:00
Thomas Harte
9883640b63 Better record scope of incomplete work. 2025-09-04 15:22:04 -04:00
Thomas Harte
bc3a0c3c91 Fix stqtic declaration. 2025-09-04 15:17:24 -04:00
Thomas Harte
4e822347a5 Finally crack case of controller failure. 2025-09-04 15:16:48 -04:00
Thomas Harte
d5650da8c0 Avoid strict aliasing violation. 2025-09-04 14:23:29 -04:00
Thomas Harte
d3c77523c3 Report normal terminations, usually. 2025-09-04 11:41:29 -04:00
Thomas Harte
787a5ce568 Reduce speed multiplier. 2025-09-03 22:22:12 -04:00
Thomas Harte
91dfd405d1 Adjust logging. 2025-09-03 13:44:30 -04:00
Thomas Harte
08c615c493 Improve ready flag. 2025-09-03 13:31:06 -04:00
Thomas Harte
5483102276 Add missing #includes. 2025-09-02 21:29:49 -04:00
Thomas Harte
32686d898b Fix again for concurrent seeks. 2025-09-02 21:18:35 -04:00
Thomas Harte
4b50c8d96c Toy with sense interrupt status being directly seek-linked. 2025-09-02 17:50:59 -04:00
Thomas Harte
c1780ee26b Add some form of sense drive status. 2025-09-02 15:21:11 -04:00
Thomas Harte
46b2db00bc Establish that the AT actually wants SenseDriveStatus. 2025-09-02 12:52:04 -04:00
Thomas Harte
7042e457ab Fix OUT sizes. 2025-09-02 12:32:27 -04:00
Thomas Harte
faeec1701f Add logging, reduce template specialisation. 2025-09-02 12:31:16 -04:00
Thomas Harte
2a75a1f9f2 Add IDE logging. 2025-09-02 12:21:01 -04:00
Thomas Harte
8c65dccc53 Support 16-bit IO access. 2025-09-01 23:31:31 -04:00
Thomas Harte
de7c3ba92f Mostly kick IDE accesses down the road. 2025-09-01 00:02:16 -04:00
Thomas Harte
ac204aadd2 Clean up, better constify SCSI innards. 2025-08-31 10:56:01 -04:00
Thomas Harte
46fc0d677f Merge branch 'master' into SomeIDE 2025-08-30 23:52:58 -04:00
Thomas Harte
2d4f4b0036 Merge pull request #1545 from TomHarte/SomeConsts
Improve `const` arguments.
2025-08-30 23:36:49 -04:00
Thomas Harte
c1de00bf9d Improve const arguments. 2025-08-30 23:25:19 -04:00
Thomas Harte
4639e1c47c Merge pull request #1544 from TomHarte/Macros
Further reduce historical dependence on macros.
2025-08-30 14:19:17 -04:00
Thomas Harte
5d2c156bc9 Use popcount. 2025-08-30 10:44:00 -04:00
Thomas Harte
357f98f015 Remove macros, shorten line lengths. 2025-08-30 10:41:28 -04:00
Thomas Harte
62f23ac27c Commute macros. 2025-08-30 10:34:49 -04:00
Thomas Harte
0936646ef9 Eliminate macros. 2025-08-30 10:29:53 -04:00
Thomas Harte
856c12f46f Eliminate macro. 2025-08-30 10:24:27 -04:00
Thomas Harte
7489783837 Eliminate macros. 2025-08-30 10:22:21 -04:00
Thomas Harte
a4f0a4c310 Merge pull request #1543 from TomHarte/MinorTidies
Perform further tidying steps.
2025-08-30 10:00:41 -04:00
Thomas Harte
bb1ef114f1 Fix header declaration. 2025-08-30 09:40:06 -04:00
Thomas Harte
f1610b6407 Fix Qt speaker delegation. 2025-08-30 00:13:47 -04:00
Thomas Harte
5e48a4c724 Fix SDL speaker sample receipt. 2025-08-30 00:10:17 -04:00
Thomas Harte
d825c03372 Prefer references for delegate protocols. 2025-08-30 00:09:38 -04:00
Thomas Harte
d177549dd6 Reduce more indentation. 2025-08-29 23:56:35 -04:00
Thomas Harte
9d1543401f Merge pull request #1542 from TomHarte/VHD
Sketch out VHD support.
2025-08-29 23:47:01 -04:00
Thomas Harte
094eb7e252 Resolve Github build breakage. 2025-08-29 23:09:13 -04:00
Thomas Harte
95e6726468 Reduce indentation. 2025-08-29 23:02:34 -04:00
Thomas Harte
8fded8f210 Add consts, remove get_s. 2025-08-29 22:55:50 -04:00
Thomas Harte
19c4940abd Extend and constify MassStorageDevice. 2025-08-29 22:17:01 -04:00
Thomas Harte
7b1f6b3c53 Add negative asserts. 2025-08-29 22:02:54 -04:00
Thomas Harte
43042c3737 Parse a little further. 2025-08-29 21:55:21 -04:00
Thomas Harte
30b50b8a1b Add missing header, CMake file. 2025-08-28 21:56:03 -04:00
Thomas Harte
095be3072b Distinguish when to include the trailing NULL. 2025-08-28 21:53:52 -04:00
Thomas Harte
91831200d6 Eliminate runtime strlen. 2025-08-28 18:45:04 -04:00
Thomas Harte
8295d4511b Improve whence type safety. 2025-08-28 17:41:58 -04:00
Thomas Harte
df589d9588 Test image type. 2025-08-28 17:29:26 -04:00
Thomas Harte
b826e1c661 Do some small measure of header parsing. 2025-08-28 17:20:29 -04:00
Thomas Harte
6727e2fe73 Add shell of a class for VHD files. 2025-08-27 17:09:52 -04:00
Thomas Harte
ecdcee8d4e Adopt my native spelling: 'licence' is a noun. 2025-08-26 23:48:00 -04:00
Thomas Harte
8b4a4369c1 Add a target for IDE activity. 2025-08-26 23:47:39 -04:00
Thomas Harte
eeb06de916 Merge pull request #1540 from TomHarte/KeyboardAgain
Be more rigorous about `static constexpr`
2025-08-26 23:22:19 -04:00
Thomas Harte
5018d7d577 Be more rigorous about static constexpr. 2025-08-26 22:54:39 -04:00
Thomas Harte
1ca279d99d Add keyboard command lookaside; dummy IDE read. 2025-08-25 22:49:32 -04:00
Thomas Harte
8a149a188c Store keyboard command until enabled. 2025-08-25 22:44:22 -04:00
Thomas Harte
076334bc4e Take first stab at separating keyboard & controller. 2025-08-25 22:14:51 -04:00
Thomas Harte
e6b45c978c Merge pull request #1539 from TomHarte/KeyboardAgain
Name keyoard commands, implement a couple more.
2025-08-25 22:12:00 -04:00
Thomas Harte
a07615445f Uncover likely issue: commands directly to keyboard. 2025-08-23 22:51:09 -04:00
Thomas Harte
41d30c2835 More formally designate the resets. 2025-08-23 22:41:58 -04:00
Thomas Harte
71f1635e23 Name commands, implement a couple more. 2025-08-23 22:33:19 -04:00
Thomas Harte
57df6d9bf7 Merge pull request #1538 from TomHarte/LessMemory
Reduce AT to 640kb RAM.
2025-08-23 22:02:28 -04:00
Thomas Harte
fd670d5175 Reduce AT to 640kb RAM.
This substantially speeds up the boot process, clearing the way for other experimentation.
2025-08-23 21:51:48 -04:00
Thomas Harte
39d4c315c8 Merge pull request #1537 from TomHarte/FloppyExists
Increase floppy logging, adjust sense interrupt.
2025-08-23 21:33:22 -04:00
Thomas Harte
6487086354 Increase floppy logging, adjust sense interrupt. 2025-08-23 21:21:16 -04:00
Thomas Harte
7d6e24b8ed Merge pull request #1536 from TomHarte/8042Redo
Rejig 8042; extend logger for common conditional use case.
2025-08-21 23:23:59 -04:00
Thomas Harte
4922073300 Reestablish pre-AT keyboard link. 2025-08-21 16:48:05 -04:00
Thomas Harte
778a02324e Add enabled flag. 2025-08-20 22:56:04 -04:00
Thomas Harte
8e89aa97a0 Switch status bit 3; fix reading of is_tested_; guess at it self-setting. 2025-08-20 22:09:08 -04:00
Thomas Harte
dfd521e938 Attempt to reformulate keyboard controller. 2025-08-20 17:17:54 -04:00
Thomas Harte
d47332adf5 Reduce need for scopes. 2025-08-20 17:17:27 -04:00
Thomas Harte
14e7ba8fab Merge pull request #1535 from TomHarte/MDAStatus
Add MDA status register.
2025-08-19 16:39:03 -04:00
Thomas Harte
e68a356fd0 Adjust AT switches input. 2025-08-18 23:26:58 -04:00
Thomas Harte
6e77b8659c Add various missing enum -> string mappings. 2025-08-18 14:59:58 -04:00
Thomas Harte
00fad7e424 Merge pull request #1534 from TomHarte/PCBASIC
Add PC BASIC ROM to the PC AT.
2025-08-14 22:28:48 -04:00
Thomas Harte
0a65248bf7 Add MDA status register, various notes. 2025-08-14 22:28:22 -04:00
Thomas Harte
9cff26b163 Install BASIC ROM. 2025-08-13 23:36:07 -04:00
Thomas Harte
9309d8c3f2 Add ROM BIOS to the ROM catalogue. 2025-08-13 22:18:16 -04:00
Thomas Harte
07e96c10d2 Merge pull request #1533 from TomHarte/MultifacetedCall
Further implement the 80286
2025-08-13 19:05:52 -04:00
Thomas Harte
d95abc99d9 Slightly increase logging. 2025-08-13 16:44:53 -04:00
Thomas Harte
b83c2615de Limit LSL types. 2025-08-13 13:53:02 -04:00
Thomas Harte
78a2b27e65 Attempt LSL, LAR. 2025-08-13 13:43:19 -04:00
Thomas Harte
bae594e34c Fix ARPL flag. 2025-08-12 21:32:20 -04:00
Thomas Harte
4ded6fceea Fix VERR/VERW. 2025-08-12 21:20:01 -04:00
Thomas Harte
0e498829f7 Attempt VERR, VERW.
Without complete success; IBM's third invocation (which I think is a VERR) doesn't give the result that BIOS is looking for.
2025-08-12 17:22:14 -04:00
Thomas Harte
ddd090d581 Implement STR. 2025-08-12 16:21:23 -04:00
Thomas Harte
4cd979e5fb Take a shot at LTR. 2025-08-12 13:49:59 -04:00
Thomas Harte
2f7a6bb242 Establish a specialised validate_call. 2025-08-11 17:10:58 -04:00
Thomas Harte
3b3b2e61b0 Overtly separate call authorisation. 2025-08-11 13:24:51 -04:00
Thomas Harte
ab4fde9bd7 Slightly clean up. 2025-08-11 09:41:31 -04:00
Thomas Harte
a9996f0b81 Add consts. 2025-08-11 09:34:17 -04:00
Thomas Harte
246d34e072 Merge pull request #1532 from TomHarte/SimplerDescriptors
Boil down descriptor attributes.
2025-08-10 20:49:44 -04:00
Thomas Harte
d35efe3f32 Boil down descriptor attributes. 2025-08-09 23:10:26 -04:00
Thomas Harte
ebd1a6b47c Merge pull request #1531 from TomHarte/286DecodingTests
Resolve majority of 286 test case failures.
2025-08-08 15:04:58 -04:00
Thomas Harte
83980678a0 Add additional known bad.
38 failures left.
2025-08-08 12:06:48 -04:00
Thomas Harte
201393f87d Start discounting test cases that look broken.
39 failures remaining.
2025-08-08 12:00:58 -04:00
Thomas Harte
055eb3873e Switch far jump to piece-by-piece authorisation.
43 failures.
2025-08-08 11:30:51 -04:00
Thomas Harte
dc94d58148 Switch CALL to access-by-access validation.
47 failures remaining.
2025-08-08 11:28:32 -04:00
Thomas Harte
0adaec1665 Allow ENTER to write partially.
51 failures left.
2025-08-08 11:18:14 -04:00
Thomas Harte
4ee30dc36f Correct stack validation, fixing POPA.
71 failures.
2025-08-08 11:05:01 -04:00
Thomas Harte
54ff2fa01f Fix new LES/etc failures.
Remaining: 72.
2025-08-08 09:55:31 -04:00
Thomas Harte
03c70b49ba Throw GPF for overlong instructions; fix BOUND validation.
79 failures outstanding.
2025-08-08 09:43:16 -04:00
Thomas Harte
4b2d8e13d1 Add consts, TODO. 2025-08-08 07:39:34 -04:00
Thomas Harte
a0c50f0521 Support 286-style DAS.
321 failures to go.
2025-08-07 19:49:41 -04:00
Thomas Harte
b15a865c88 Add extra MOV sanity check.
Failures still standing: 406.
2025-08-07 17:40:13 -04:00
Thomas Harte
8e5bbbbc71 Implement 80286 INS/OUTS oddities.
795 failures outstanding.
2025-08-07 15:31:07 -04:00
Thomas Harte
615ebaf711 Correct RCL overflow when shift count is 0.
1,013 failures remaining.
2025-08-07 15:23:11 -04:00
Thomas Harte
0882d2b7ce Correct LEAVE authorisation.
Failures: 1,207.
2025-08-07 15:16:12 -04:00
Thomas Harte
900195efac Correct HLT IP comparison.
Failures: 1,425.
2025-08-07 15:01:22 -04:00
Thomas Harte
b58b962ccf Apply 80286 LODS craziness.
2,425 errors remaining.
2025-08-07 14:53:16 -04:00
Thomas Harte
5255499445 Implement 286 weirdness for SCAS.
2,690 failures.
2025-08-07 14:50:59 -04:00
Thomas Harte
d9a2be4250 Avoid upfront testing for POPA.
Failures: 2,966.
2025-08-07 14:41:01 -04:00
Thomas Harte
256e14a8a6 Decline upfront validation for PUSHA.
Total failures remaining: 3,239.
2025-08-07 14:36:11 -04:00
Thomas Harte
1ab26d4a2f Determine 80286 CMPS rules.
Remaining: 3,521 failures.
2025-08-07 12:28:50 -04:00
Thomas Harte
91b2c751af Determine 80286 logic for MOVS.
4,043 failures left.
2025-08-07 12:17:52 -04:00
Thomas Harte
edf7617d1e Fix is_address.
Failures: 4,568.
2025-08-07 09:25:23 -04:00
Thomas Harte
32666d304f Filter out some illegal JMP/CALL fars.
Failure count now: 5,966.
2025-08-07 09:18:23 -04:00
Thomas Harte
b65f7b4a6a Restrict BOUNDS checks to 80286. 2025-08-06 22:32:50 -04:00
Thomas Harte
7c4df23c1c Fix BOUND.
7085 remaining failures.
2025-08-06 22:19:35 -04:00
Thomas Harte
a8e60163e1 Commute Overflow from fault to trap.
9,331 failures remaining.
2025-08-06 21:30:08 -04:00
Thomas Harte
02ec1b5da6 Fix SHR overflow flag.
Failing: 11,802.
2025-08-06 21:14:15 -04:00
Thomas Harte
a9a6aba862 Correct RCR overflow.
Now: 14,097 failures.
2025-08-06 17:46:05 -04:00
Thomas Harte
03c6a60f68 Avoid extra judgment on LEAVE.
Failures remaining: 16,295.
2025-08-06 17:19:20 -04:00
Thomas Harte
8ab688687e Decode .6 as SAL.
Amazingly: now 20,814 failures outstanding.
2025-08-06 16:30:55 -04:00
Thomas Harte
bdec32722e Include failures/file. 2025-08-06 16:07:54 -04:00
Thomas Harte
ad50e5c754 Ensure an invalid instruction is generated upon length limit. 2025-08-06 15:59:24 -04:00
Thomas Harte
9c48e44e9e Fix fast-path selection.
50,814 failures.
2025-08-06 15:33:51 -04:00
Thomas Harte
76284eb462 Fix 8088 assumption about unused flags; 80286 PUSHF now passes amongst others.
51,091 failures still to fix though.
2025-08-06 15:31:03 -04:00
Thomas Harte
0745c5128a Avoid expensive path for 8088; pull out allow list. 2025-08-06 15:21:54 -04:00
Thomas Harte
01fbe2d3de Support 808286 STOS oddities. 2025-08-06 13:37:34 -04:00
Thomas Harte
9e14c22259 Take another run at ENTER. 2025-08-06 12:55:37 -04:00
Thomas Harte
dff0111cd5 Overtly capture decoding failures. 2025-08-05 13:03:54 -04:00
Thomas Harte
e7452b0ea1 Continue accepting F7.2 as TEST. 2025-08-04 21:45:14 -04:00
Thomas Harte
61a0f892c4 Fix PUSH immediate. 2025-08-04 21:23:27 -04:00
Thomas Harte
4ceab01ed4 Fix result of IMUL_3. 2025-08-04 21:05:14 -04:00
Thomas Harte
9908969eea Diagnose, correct AAA and AAS. 2025-08-04 17:49:07 -04:00
Thomas Harte
19a78ef1ac Correct for 286+ PUSH SP. 2025-08-04 17:23:02 -04:00
Thomas Harte
4785c1ae84 Grab new punchlist. 2025-08-04 17:19:11 -04:00
Thomas Harte
ef03841efa Deal with potential reason for wrong top-of-flags. 2025-08-04 17:14:16 -04:00
Thomas Harte
4747a70ce7 Correct for accesses right at segment end. 2025-08-04 17:08:01 -04:00
Thomas Harte
cd986cc2dc Ensure tests get the default IDT. 2025-08-04 12:47:52 -04:00
Thomas Harte
c29d5ca4a8 Catch address wraparound out-of-bounds access. 2025-08-04 09:32:35 -04:00
Thomas Harte
56b49011d6 Shorten reports. 2025-08-04 09:21:49 -04:00
Thomas Harte
48c55211e6 Fix descriptor bounds test. 2025-08-04 09:16:33 -04:00
Thomas Harte
72f68f3b0b Include hash in error record. 2025-08-03 20:11:35 -04:00
Thomas Harte
7b6dddc994 Include number. 2025-08-03 17:57:26 -04:00
Thomas Harte
51fbe4e8c5 Consume 286 HLT. 2025-08-03 17:41:02 -04:00
Thomas Harte
c148d9ee6c Ensure ENTER can execute. 2025-08-03 17:30:02 -04:00
Thomas Harte
9dfe59a104 Take a swing at three-operand IMUL. 2025-08-02 22:23:34 -04:00
Thomas Harte
b6aae65afd Clean up, separate. 2025-08-02 21:45:01 -04:00
Thomas Harte
9fed93a771 Use 286 test suite for decoding tests too. 2025-08-02 21:31:04 -04:00
Thomas Harte
cdfb68f261 Merge pull request #1530 from TomHarte/FullerTests
Utilise 80286 real-mode tests.
2025-08-02 19:00:47 -04:00
Thomas Harte
46450bd080 Use proper perform in tests. 2025-08-02 18:47:06 -04:00
Thomas Harte
9a25d601f1 Fully transfer faulting logic. 2025-08-02 18:37:56 -04:00
Thomas Harte
fe0834ecda Fix type difference. 2025-08-02 18:32:23 -04:00
Thomas Harte
846f745e2c Attempt to transfer ownership of fault. 2025-08-02 18:26:00 -04:00
Thomas Harte
30d40e6f9b Add TODO. 2025-08-01 20:58:12 -04:00
Thomas Harte
f7501b10f7 Move ExecutionSupport to heap. 2025-08-01 20:11:26 -04:00
Thomas Harte
379c513f8a Add const getter, mode getter; further template. 2025-08-01 19:56:57 -04:00
Thomas Harte
5a6d77e958 Generalise, towards using 80286 tests. 2025-08-01 15:59:40 -04:00
Thomas Harte
6646039ffe Templatise to allow beyond-8086 execution. 2025-07-31 21:26:29 -04:00
Thomas Harte
5e0994270f Merge pull request #1529 from TomHarte/StatusFlagsMask
Correct metadata observation.
2025-07-31 19:52:16 -04:00
Thomas Harte
44fc801720 Correct metadata observation. 2025-07-31 15:47:07 -04:00
Thomas Harte
405c61f53d Merge pull request #1528 from TomHarte/ZX81Typer
ZX80/81: Reduce typing speed.
2025-07-31 15:16:43 -04:00
Thomas Harte
c40acb9406 Reduce typing speed. 2025-07-29 21:55:56 -04:00
Thomas Harte
7778d2a47e Merge pull request #1527 from TomHarte/8088TestFailures
Restore proper register and memory contents.
2025-07-29 21:36:12 -04:00
Thomas Harte
96afb245a5 Fix test suite memory state. 2025-07-29 21:25:15 -04:00
Thomas Harte
cf0677c30b Avoid spurious register comparison failures. 2025-07-28 17:44:32 -04:00
Thomas Harte
667614d9de Merge pull request #1525 from TomHarte/x86Tests
Revive x86 JSON tests
2025-07-27 22:23:27 -04:00
Thomas Harte
652ede57b3 Further clone FlowController. 2025-07-27 22:00:54 -04:00
Thomas Harte
09a34f880e Start trying to return preauthorisation testability. 2025-07-27 21:17:54 -04:00
Thomas Harte
a9f9be330d Allow SegmentedMemory to take different LinearMemorys. 2025-07-26 08:18:16 -04:00
Thomas Harte
39568d2464 Run headfirst into a LinearMemory substitution brick wall. 2025-07-25 21:43:54 -04:00
Thomas Harte
10e07a9966 Add missing concept requirement. 2025-07-25 21:27:51 -04:00
Thomas Harte
fe00a69136 Start transitioning to PCCompatible::Segments. 2025-07-25 16:58:07 -04:00
Thomas Harte
9d0c2cd67f Switch to a parasitic use of PCCompatible::LinearMemory. 2025-07-25 16:47:08 -04:00
Thomas Harte
b5aab442f8 Template immediate-read Segments; continue fixing 8088Tests. 2025-07-24 22:24:53 -04:00
Thomas Harte
7c010bd1ef Relocate validation logic, such as it is. 2025-07-22 22:42:01 -04:00
Thomas Harte
1bf898405f Generalise 'Registers'. 2025-07-21 21:17:54 -04:00
Thomas Harte
c490166b35 Fully apply line length limit. 2025-07-21 17:09:07 -04:00
Thomas Harte
e6862364ed Correct syntax to the point of failing only concepts. 2025-07-21 17:06:17 -04:00
Thomas Harte
cf20c84edd Merge pull request #1523 from TomHarte/MacintoshIMGStyle
Use <algorithm>, and otherwise reduce.
2025-07-19 21:56:50 -04:00
Thomas Harte
88e776ad5b Use <algorithm>, and otherwise reduce. 2025-07-19 21:37:03 -04:00
Thomas Harte
e79a60f5cd Merge pull request #1522 from TomHarte/MacintoshIMGStyle
Make minor style improvements.
2025-07-16 22:47:46 -04:00
Thomas Harte
fd4a91ba72 Make minor style improvements. 2025-07-16 22:31:41 -04:00
Thomas Harte
5705ece2a3 Merge pull request #1521 from atsampson/includes
Add some missing <cstdint> includes
2025-07-10 21:20:28 -04:00
Thomas Harte
c723f20f39 Merge pull request #1520 from TomHarte/ElectronTiming
Electron: move CPU slots to first half of each 1Mhz window.
2025-07-10 19:06:06 -04:00
Adam Sampson
0f7447d539 Add some missing <cstdint> includes. 2025-07-10 23:58:12 +01:00
Thomas Harte
1a08944854 std::tuple is defined in utility, not tuple. 2025-07-09 09:26:16 -04:00
Thomas Harte
7b0b06f6df Adhere to line length limit. 2025-07-09 13:27:53 +08:00
Thomas Harte
d2ad227a24 Relocate CPU activity to start of each 1Mhz slot. 2025-07-09 13:18:54 +08:00
Thomas Harte
71d7982d14 Tweak ownership of lookahead logic. 2025-07-09 12:55:53 +08:00
Thomas Harte
a94dcc12ef Reformat, consider CPU slot repositioning. 2025-07-09 10:41:03 +08:00
Thomas Harte
b7bfcfa1e3 Add note to future self. 2025-07-07 17:41:11 +08:00
Thomas Harte
416ae0ca04 Separate location tests from loop. 2025-07-07 17:37:31 +08:00
Thomas Harte
8d66cd4874 Merge pull request #1519 from TomHarte/ElectronTiming
Deduplicate Electron palette work.
2025-06-25 16:47:15 +07:00
Thomas Harte
a701ba8030 Switch to requires. 2025-06-25 16:28:26 +07:00
Thomas Harte
0160908522 Further deduplicate palette actions. 2025-06-25 16:23:25 +07:00
Thomas Harte
cdd0d6d127 Add consts. 2025-06-23 14:40:48 +07:00
Thomas Harte
65ee745d6e Avoid repetition of palette data. 2025-06-23 14:35:31 +07:00
Thomas Harte
4141dfc353 Merge pull request #1518 from TomHarte/ElectronColoursEtc
Correct Electron 1bpp palette G/B confusion.
2025-06-22 05:18:29 -04:00
Thomas Harte
fb6cd105c3 Overtly name type. 2025-06-22 16:03:50 +07:00
Thomas Harte
6ff9168146 Correct G/B 1bpp mismapping. 2025-06-22 15:58:16 +07:00
Thomas Harte
7b5e08aab6 Slightly improve palette semantics. 2025-06-22 15:25:20 +07:00
Thomas Harte
c7dd4526c1 Merge pull request #1516 from TomHarte/JFDFiles
Add elementary JFD support.
2025-06-01 22:48:00 -04:00
Thomas Harte
066036ccdd Add to CMake. 2025-05-31 21:28:02 -04:00
Thomas Harte
7c164453a5 Correct overrun test. 2025-05-30 22:33:27 -04:00
Thomas Harte
8b31cfeafb Correct offset into track table. 2025-05-30 21:47:16 -04:00
Thomas Harte
2ddaf0afa3 Attempt preliminary track building. 2025-05-30 21:25:07 -04:00
Thomas Harte
a8a97b4606 Get as far as printing sector stats. 2025-05-29 22:37:10 -04:00
Thomas Harte
a55b63a210 Add skeleton for JFD support. 2025-05-29 09:27:13 -04:00
Thomas Harte
2e4f7cd667 Merge pull request #1511 from TomHarte/PrivilegeLevels
Implement some of the missing 80286 operations.
2025-05-28 22:39:05 -04:00
Thomas Harte
bf257a8d9e Adjust ownership for segment load detection. 2025-05-28 22:08:43 -04:00
Thomas Harte
c4e66f7a35 Merge branch 'master' into PrivilegeLevels 2025-05-28 21:05:36 -04:00
Thomas Harte
efff433aa0 Merge pull request #1515 from TomHarte/BitwiseAF
x86: clear auxiliary carry on AND, OR, XOR and TEST.
2025-05-27 11:37:03 -04:00
Thomas Harte
ee60e36a16 x86: clear auxiliary carry on AND, OR, XOR and TEST. 2025-05-27 11:23:17 -04:00
Thomas Harte
841fc3cfaf Accept version-number increase. 2025-05-26 22:49:35 -04:00
Thomas Harte
2a44caea6c Merge pull request #1514 from TomHarte/ElectronChangeObsevrer
Add Electron to `MediaChangeObserver` gang.
2025-05-26 22:45:45 -04:00
Thomas Harte
0f661928ae Add Electron to MediaChangeObserver gang. 2025-05-26 22:35:08 -04:00
Thomas Harte
0961e5cc2e Add TSS deserialiser. 2025-05-20 21:56:58 -04:00
Thomas Harte
df621a8205 Add real and protected callbacks. 2025-05-18 23:35:49 -04:00
Thomas Harte
bfa416ca99 Fix #include. 2025-05-18 22:30:20 -04:00
Thomas Harte
8041b87317 Introduce segment preauthorisation. 2025-05-18 22:11:23 -04:00
Thomas Harte
b3000f6350 Made mode knowable; factor out main part of far jump. 2025-05-17 23:08:07 -04:00
Thomas Harte
947baab269 Add TODO. 2025-05-14 22:12:59 -04:00
Thomas Harte
a41ea90ca7 Implement CLTS. 2025-05-14 21:08:26 -04:00
Thomas Harte
8b3f0d8fd6 Implement ARPL. 2025-05-14 21:01:48 -04:00
Thomas Harte
bd9740a9a4 Add additional informative static asserts. 2025-05-13 22:54:05 -04:00
Thomas Harte
3f735e44f1 Merge pull request #1510 from TomHarte/LLDT
Begin LDT support.
2025-05-13 22:41:53 -04:00
Thomas Harte
9e5235fd30 Descriptor tables are always at most 64kb. 2025-05-13 14:07:28 -04:00
Thomas Harte
159f3cb780 Add SLDT. 2025-05-12 23:17:34 -04:00
Thomas Harte
61469f8e09 Reindent to avoid many false warnings. 2025-05-12 21:36:49 -04:00
Thomas Harte
71343b5131 Add additional possible exception causes. 2025-05-12 21:34:59 -04:00
Thomas Harte
82caee6d7d Add potential LLDT exceptions. 2025-05-12 17:31:56 -04:00
Thomas Harte
275e75980c Take initial swing at LLDT. 2025-05-12 17:22:11 -04:00
Thomas Harte
2572da872a Improve consts, use concepts, reduce indentation. 2025-05-12 09:13:27 -04:00
Thomas Harte
6934618589 Add note to self. 2025-05-11 22:53:28 -04:00
Thomas Harte
01fd07c372 Merge pull request #1509 from TomHarte/GPFs
Implement per-access GPF checks.
2025-05-11 22:34:09 -04:00
Thomas Harte
02f9cf0318 Add basic partial GPF testing. 2025-05-11 22:24:21 -04:00
Thomas Harte
6bc586025a Attempt per-access part of GPF test. 2025-05-11 22:05:33 -04:00
Thomas Harte
0d34960d60 Properly place ownership of linear authorisation. 2025-05-11 21:36:36 -04:00
Thomas Harte
99b94a31ea Give descriptors knowledge of their indices. 2025-05-11 21:32:00 -04:00
Thomas Harte
b0d4bcd26c Route all authorisation messages to a common receiver. 2025-05-11 21:08:02 -04:00
Thomas Harte
248ea52e06 Merge pull request #1508 from TomHarte/ExceptionBackfill
Improve IDT support.
2025-05-11 20:40:32 -04:00
Thomas Harte
9b51fe3db4 Take a shot at IDT dispatch. 2025-05-10 21:34:43 -04:00
Thomas Harte
5f95696815 Remove done TODO. 2025-05-05 22:56:24 -04:00
Thomas Harte
8c9df5556d Generalise support for multiple speeds. 2025-05-05 22:55:23 -04:00
Thomas Harte
32495f47b3 Bifurcate descriptor types. 2025-05-05 17:26:39 -04:00
Thomas Harte
23bc561524 Add note to self. 2025-05-04 22:21:37 -04:00
Thomas Harte
fa2cc0f62e Proceed as far as believing I probably need a gate descriptor type. 2025-05-04 22:11:53 -04:00
Thomas Harte
a686a167cc Factor out 'read descriptor'. 2025-05-04 21:03:17 -04:00
Thomas Harte
8a2468a4fb Apply IDT reset condition, factor in to real-mode interrupts. 2025-05-04 16:57:14 -04:00
Thomas Harte
4cc21a2c20 Include descriptor table and MSW requirements. 2025-05-03 23:01:31 -04:00
Thomas Harte
5350e41da1 Switch to mildly-more-modern template form. 2025-05-02 13:50:06 -04:00
Thomas Harte
e07e6b6954 Merge pull request #1507 from TomHarte/Morex86Exceptions
Reformulate x86 exceptions.
2025-05-02 10:42:11 -04:00
Thomas Harte
0a60e38d82 Abandon Interrupt naming. 2025-05-02 10:23:20 -04:00
Thomas Harte
f53b40e127 Focus on an Exception as the interrupt token. 2025-05-01 22:36:58 -04:00
Thomas Harte
4df51a00ed Try to be a bit more rigorous in exception generation syntax. 2025-05-01 17:17:29 -04:00
Thomas Harte
3981c4d101 Merge pull request #1506 from TomHarte/x86Concepts
Apply concepts to x86 interface.
2025-04-30 22:07:50 -04:00
Thomas Harte
fc3e8f7cef Add memory subsystem requirements. 2025-04-30 21:30:36 -04:00
Thomas Harte
f4d67ec5e6 Eliminate bad #include. 2025-04-29 22:32:29 -04:00
Thomas Harte
59aafa6c1e Add linear memory concept. 2025-04-29 22:28:23 -04:00
Thomas Harte
75da46dac5 Add CPU control concept. 2025-04-29 22:24:06 -04:00
Thomas Harte
1f1d380e26 Fill in flow-controller requirements. 2025-04-29 22:09:59 -04:00
Thomas Harte
35b3e425be Spell out registers requirements. 2025-04-29 22:06:59 -04:00
Thomas Harte
b4535c489d Wrangle test for segments interface. 2025-04-29 21:55:17 -04:00
Thomas Harte
f6bb502e87 Start bashing out an attempt at is_context. 2025-04-27 23:40:40 -04:00
Thomas Harte
6cf825d3d8 Lock down Intruction type. 2025-04-27 21:43:46 -04:00
Thomas Harte
f766841fad Add usage-hint concepts. 2025-04-27 14:51:34 -04:00
Thomas Harte
10e4e7f6c6 Limit integer types. 2025-04-27 14:47:56 -04:00
Thomas Harte
1277e56435 Limit integers that can be the subject of accessors. 2025-04-27 14:44:07 -04:00
Thomas Harte
4089532f81 Merge pull request #1505 from TomHarte/OtherC++20Improvements
Make other scattered C++20 improvements.
2025-04-25 23:54:31 -04:00
Thomas Harte
9790b4d2e9 Throw in some consts. 2025-04-25 23:17:00 -04:00
Thomas Harte
ad37c0d2ac Use std::rotr. 2025-04-25 23:10:09 -04:00
Thomas Harte
b7a1fd4f8f Autodetect whether shift count could be a register. 2025-04-25 23:01:04 -04:00
Thomas Harte
be5362e393 Eliminate builtin. 2025-04-25 23:00:36 -04:00
Thomas Harte
4977c9bc4c Further use rotl/r. 2025-04-25 22:53:11 -04:00
Thomas Harte
e13dbc03da Make elementary use of rotl and rotr. 2025-04-25 22:37:43 -04:00
Thomas Harte
16fec0679b Use std::popcount further. 2025-04-25 22:24:00 -04:00
Thomas Harte
55361b8552 Remove unused popcount. 2025-04-25 22:18:39 -04:00
Thomas Harte
cc67993621 Temporarily disable, in lieu of splitting memory. 2025-04-25 22:18:25 -04:00
Thomas Harte
49ba4998d6 Use std::popcount for parity. 2025-04-25 22:18:05 -04:00
Thomas Harte
03eb381b3b Adopt std::ranges::copy where it is trivial to do so. 2025-04-25 22:17:07 -04:00
Thomas Harte
e5161faa43 Merge pull request #1504 from TomHarte/M_PI
Eliminate all references to M_PI.
2025-04-25 21:43:06 -04:00
Thomas Harte
de78fb7a1c Eliminate all references to M_PI. 2025-04-24 21:57:29 -04:00
Thomas Harte
a9ceb5e21a Merge pull request #1503 from TomHarte/C++20
Bump to C++20.
2025-04-24 21:52:01 -04:00
Thomas Harte
e62b41f615 Avoid implicit capture of 'this' via '='. 2025-04-24 21:27:23 -04:00
Thomas Harte
592e339b70 Resolve syntax error, fix line lengths. 2025-04-24 21:12:17 -04:00
Thomas Harte
84a9138df7 Bump to C++20. 2025-04-24 20:56:15 -04:00
Thomas Harte
6db7c4a8eb Merge pull request #1502 from TomHarte/LocalFilesystemAccess
Make style corrections to the Enterprise and CPC.
2025-04-23 12:38:36 -04:00
Thomas Harte
213bd09a9c Remove test trap. 2025-04-23 11:36:29 -04:00
Thomas Harte
8eb246cdec Improve consts, line lengths. 2025-04-23 11:01:23 -04:00
Thomas Harte
caacf8e373 Eliminate macros. 2025-04-23 10:51:49 -04:00
Thomas Harte
c53d42a578 Eliminate macro. 2025-04-23 10:38:42 -04:00
Thomas Harte
cfc5ef4a3c Eliminate risk of overrun. 2025-04-22 22:50:38 -04:00
Thomas Harte
e78c1bbec9 Improve consts, indentation. 2025-04-22 22:42:13 -04:00
Thomas Harte
b1582d33c0 Adjust indentation, remove one macro. 2025-04-22 21:45:36 -04:00
Thomas Harte
5abcf28a0e Merge pull request #1498 from TomHarte/Descriptors
Edge further along on x86 descriptors.
2025-04-22 21:23:17 -04:00
Thomas Harte
4cd57856ce Take ownership of 32-bit assumption. 2025-04-22 21:10:20 -04:00
Thomas Harte
a826fd5c0e Add return. 2025-04-21 23:14:28 -04:00
Thomas Harte
7de23ec2aa Be specific about types. 2025-04-21 23:03:57 -04:00
Thomas Harte
d7d2957319 Avoid fallthrough warning. 2025-04-21 22:57:07 -04:00
Thomas Harte
fbd81b9930 Merge branch 'master' into Descriptors 2025-04-21 22:43:30 -04:00
Thomas Harte
dacb52403a Merge pull request #1501 from TomHarte/NoVLAs
Eliminate VLAs, resolve some fallthrough warnings, reduce macros.
2025-04-21 15:24:40 -04:00
Thomas Harte
e008a02b99 Shuffle further to avoid optics of a fallthrough. 2025-04-21 15:13:10 -04:00
Thomas Harte
9363453720 Reduce macros. 2025-04-21 15:00:49 -04:00
Thomas Harte
9c70615fd1 Trim maximum line length. 2025-04-21 15:00:02 -04:00
Thomas Harte
1c78c65816 Add missing constraint. 2025-04-21 09:19:36 -04:00
Thomas Harte
2a9a68ca53 Annotate further fallthroughs. 2025-04-21 09:15:55 -04:00
Thomas Harte
fb16baab99 Add further fallthrough. 2025-04-20 23:39:26 -04:00
Thomas Harte
54f509c210 Enforce size restriction. 2025-04-20 23:27:44 -04:00
Thomas Harte
5be8e5eff3 Avoid improper fallthroughs. 2025-04-20 22:55:03 -04:00
Thomas Harte
29b9f129f6 Improve constness, line lengths, eliminate macros. 2025-04-20 22:33:44 -04:00
Thomas Harte
f41629daae Add compiler-calming fallthroughs. 2025-04-20 22:19:11 -04:00
Thomas Harte
feea6023f4 Eliminate macro. 2025-04-20 12:37:14 -07:00
Thomas Harte
262d8cd0d9 Enable further warnings. 2025-04-20 12:31:57 -07:00
Thomas Harte
fbbec04f8c Update version check. 2025-04-20 12:29:03 -07:00
Thomas Harte
3e4eaee96b Overtly cast. 2025-04-20 12:27:38 -07:00
Thomas Harte
5f99a2240d Shorten lines; apply minor style fixes. 2025-04-20 12:26:37 -07:00
Thomas Harte
5937387e94 Overtly note fallthrough. 2025-04-20 11:55:07 -07:00
Thomas Harte
b3099d8e71 Eliminate use of VLAs. 2025-04-12 14:34:57 -04:00
Thomas Harte
7721f74200 Further flesh out descriptors: decode all bits, add printf warnings. 2025-04-10 17:07:45 -04:00
Thomas Harte
fa58cc05f3 Attempt to avoid type punning. 2025-04-06 22:48:22 -04:00
Thomas Harte
c61a9e47b2 Slightly tweak constness. 2025-04-06 22:40:29 -04:00
Thomas Harte
148ee266ed Extend operator== path. 2025-04-06 22:37:59 -04:00
Thomas Harte
8ccec81cc6 Disable awaiting_eoi_. 2025-04-06 22:24:25 -04:00
Thomas Harte
668901f71d Fix comparison. 2025-04-06 22:24:09 -04:00
Thomas Harte
ad6ad144a5 Don't regress PC for external interrupts. 2025-04-05 21:39:37 -04:00
Thomas Harte
d5997a30b2 Reset output on latch write in applicable modes. 2025-04-04 12:30:08 -04:00
Thomas Harte
ecc7501377 Avoid explicit instantiation, precedence error. 2025-04-03 22:09:49 -04:00
Thomas Harte
45262a1a46 Copy reload value to latch. 2025-04-03 21:59:26 -04:00
Thomas Harte
3c04e08df2 Ensure 16-bit ins and outs always occur as two 8-bit operations.
Advances the AT to system error 108, something about timer 2.
2025-04-03 19:52:40 -04:00
Thomas Harte
7c7675179e Restrict shift operand size, causing text output at last. 2025-04-03 17:42:15 -04:00
Thomas Harte
88ed49a833 Enable A20 at reset; fully propagate return to real mode. 2025-04-03 16:14:49 -04:00
Thomas Harte
0c88e62815 Add various caveman debugging comments. 2025-04-02 23:28:20 -04:00
Thomas Harte
88d34012c4 Continue trying to flesh out exceptions. 2025-04-02 23:27:43 -04:00
Thomas Harte
3be8de6fb0 Enforce set-only nature of protected mode bit. 2025-04-02 23:26:21 -04:00
Thomas Harte
804fbf5d5f Add [S/L]MSW. 2025-04-02 23:24:28 -04:00
Thomas Harte
1a68dcbc14 PUSH always pushes a word. 2025-04-02 23:24:00 -04:00
Thomas Harte
a9a72a767d Improve fault pathways. 2025-04-01 09:13:41 -04:00
Thomas Harte
afc3a8d373 Correct header path. 2025-03-31 09:54:11 -04:00
Thomas Harte
da00e6588c Consolidate on class. 2025-03-31 09:34:17 -04:00
Thomas Harte
d6376d0ddf Remove improper header. 2025-03-31 09:33:30 -04:00
Thomas Harte
1cca711560 Name MSW bits. 2025-03-30 14:04:43 -04:00
Thomas Harte
552f9196af Convert INTO, AAM; map which instructions post their IP. 2025-03-30 13:39:52 -04:00
Thomas Harte
c6fa72cd83 Bring bound inside new orthodoxy. 2025-03-30 13:31:39 -04:00
Thomas Harte
42edc46887 Add invalid-opcode exception; transcribe has-code table. 2025-03-30 13:29:20 -04:00
Thomas Harte
ec7e343673 Start to establish throw/catch of 80286 exceptions. 2025-03-30 13:23:36 -04:00
Thomas Harte
69d4d8acb0 Switch to construct and copy. 2025-03-29 17:27:29 -04:00
Thomas Harte
a7eab8df22 Add getter for local descriptor table. 2025-03-29 17:24:30 -04:00
Thomas Harte
4247da9118 Add notes to self on exceptions. 2025-03-27 18:08:09 -04:00
Thomas Harte
cfba8aeb89 Make style improvements. 2025-03-27 18:07:52 -04:00
Thomas Harte
db26a26926 Fix decoding of PUSH immediate. 2025-03-27 13:07:13 -04:00
Thomas Harte
1551fbeb1f Make some stab at descriptor fetch. 2025-03-27 12:50:50 -04:00
Thomas Harte
d5c53ca624 Set A20 line properly. 2025-03-26 21:51:43 -04:00
Thomas Harte
b34702e370 Set an initial A20 state. 2025-03-26 07:35:17 -04:00
Thomas Harte
8b1543d9c9 Fuzz memory, setup FS and GS. 2025-03-25 17:16:36 -04:00
Thomas Harte
e264375a97 Attempt to reintroduce 80286 support (as was). 2025-03-25 09:24:55 -04:00
Thomas Harte
fd31d07f41 Begin division of memory into linear and segmented mappings. 2025-03-24 22:58:19 -04:00
Thomas Harte
fac15f5539 Introduce a linear-memory holder. 2025-03-24 21:23:08 -04:00
Thomas Harte
6ad88101f1 Saunter up to a circular issue: segments needs memory access. 2025-03-24 17:31:17 -04:00
Thomas Harte
2768b66d10 Propagate mode change. 2025-03-22 23:00:51 -04:00
Thomas Harte
d10164be26 Merge branch 'Descriptors' of github.com:TomHarte/CLK into Descriptors 2025-03-22 22:09:50 -04:00
Thomas Harte
ce7ff13bbe Proceed to a local assert on LMSW. 2025-03-22 21:57:56 -04:00
Thomas Harte
c1d2c159f3 Reenable backdoor AT. 2025-03-21 11:22:09 -04:00
Thomas Harte
d3dbdb153c Use indexed descriptors. 2025-03-21 11:20:33 -04:00
Thomas Harte
e7218c0321 Add means for indexed segment access. 2025-03-21 11:16:25 -04:00
Thomas Harte
48d8fdb875 Adopt descriptors in memory handling. 2025-03-21 10:18:26 -04:00
Thomas Harte
b387ca921a Merge branch 'master' into Descriptors 2025-03-20 21:09:09 -04:00
Thomas Harte
53c1a322ed Increase version number. 2025-03-20 15:39:42 -04:00
Thomas Harte
0c502fc9cf Adopt more consistent 'Pointer' naming; eliminate size warning. 2025-03-20 15:33:07 -04:00
Thomas Harte
5d1e3b6c93 Create a home for descriptors. 2025-03-19 14:20:50 -04:00
Thomas Harte
7fc16fa2c8 Merge pull request #1495 from TomHarte/286StatusWord
Add extra 80286 registers.
2025-03-19 14:12:56 -04:00
Thomas Harte
fe6a88c5df Install [L/S][I/G]DT wiring. 2025-03-18 22:11:28 -04:00
Thomas Harte
7b14df82e0 Merge branch 'master' into 286StatusWord 2025-03-18 21:47:32 -04:00
Thomas Harte
966b41313d Merge pull request #1497 from TomHarte/LargeWindowMousing
Correct potential SCSI crash; tweak macOS mouse behaviour.
2025-03-18 21:46:41 -04:00
Thomas Harte
91f1c3322c Ensure tracking areas are updated. 2025-03-18 21:12:48 -04:00
Thomas Harte
0b276c5a76 Remove focus rings. 2025-03-18 20:38:09 -04:00
Thomas Harte
b654c2e170 Avoid potential out-of-bounds access. 2025-03-18 20:23:31 -04:00
Thomas Harte
32c88da6c4 Iterate towards LGDT/LIDT.
Specifically: add a means to get just an indirect address; add an enum for descriptor tables; add an `ldt` function for the global and interrupt tables, which currently just authorises the access and then stops.
2025-03-18 18:22:04 -04:00
Thomas Harte
3d19d0816b Do something for SMSW. 2025-03-16 22:05:14 -04:00
Thomas Harte
15da707324 Merge pull request #1494 from TomHarte/MoreAT
AT: adjust reported RAM refresh timing.
2025-03-16 15:54:27 -04:00
Thomas Harte
387e8b04f9 Adjust reported refresh timing. 2025-03-16 15:44:05 -04:00
Thomas Harte
4ca47be8a8 Add const. 2025-03-15 22:21:35 -04:00
Thomas Harte
f9d9dc68b7 Factor out BIOS installation. 2025-03-15 22:19:26 -04:00
Thomas Harte
14a8f4511c Merge pull request #1492 from TomHarte/ATBIOS
Support real IBM BIOS, either in odd/even or complete form.
2025-03-15 22:12:54 -04:00
Thomas Harte
97d237eed0 Support real IBM BIOS, either in odd/even or complete form. 2025-03-15 21:13:31 -04:00
Thomas Harte
20d0406a24 Merge pull request #1491 from TomHarte/PUSHA
Fix PUSHA register list; add illegal asserts.
2025-03-14 22:27:19 -04:00
Thomas Harte
73e843abd3 Assert on some hopefully unreachables. 2025-03-12 22:03:12 -04:00
Thomas Harte
8d956da65b Correct final thing written to stack by PUSHA. 2025-03-12 21:40:03 -04:00
Thomas Harte
9b9cdfe937 Merge pull request #1489 from TomHarte/MinorExtraStrings
Slightly improve x86 instruction to string lexicon.
2025-03-12 21:34:18 -04:00
Thomas Harte
3dcba9362c Add a couple of missing Operation:: mappings. 2025-03-12 13:51:38 -04:00
Thomas Harte
2d3a3ada57 Add AccessType to string conversion. 2025-03-12 13:51:17 -04:00
Thomas Harte
143d1d5e35 Merge pull request #1488 from TomHarte/ATKeyboard
Implement some proportion of the AT keyboard controller.
2025-03-12 13:19:15 -04:00
Thomas Harte
13b32b269c Force the AT in debug mode only. 2025-03-12 12:47:04 -04:00
Thomas Harte
592cea6a27 Tweak timing to once again pass BIOS controller test. 2025-03-12 12:31:29 -04:00
Thomas Harte
e76ca304e6 Attempt to support 60 and c0. 2025-03-11 22:54:54 -04:00
Thomas Harte
d77d8df1ac Add closer-to-real keyboard command loop. 2025-03-11 22:35:13 -04:00
Thomas Harte
4f35d5dabd Log A20 line. 2025-03-09 23:09:58 -04:00
Thomas Harte
e927feb2d6 Reintroduce is-tested flag. 2025-03-08 21:59:40 -05:00
Thomas Harte
98f20c57c1 Attempt to support reset-by-8042, resulting in boot loop. 2025-03-08 00:47:56 -05:00
Thomas Harte
7a88d31fd9 Add include for strlen. 2025-03-07 23:47:34 -05:00
Thomas Harte
96326411bf Move explicit specialization to namespace scope. 2025-03-07 23:41:56 -05:00
Thomas Harte
4e882e7d4d Accept uint8_ts only. 2025-03-07 23:36:47 -05:00
Thomas Harte
bff10c1714 Resolve newfound log ambiguity. 2025-03-07 23:34:12 -05:00
Thomas Harte
cee2484108 Flip input/output, perform commands instantly. 2025-03-07 23:32:07 -05:00
Thomas Harte
93078abe87 Buffer lines prior to output. 2025-03-07 23:25:22 -05:00
Thomas Harte
8caa1a9664 Experiment with dialogue. 2025-03-07 14:24:08 -05:00
Thomas Harte
d7b46ee03c Adopt compact form. 2025-03-07 14:23:50 -05:00
Thomas Harte
e07b3da983 Add commentary; start fleshing out AT keyboard controller. 2025-03-07 14:01:59 -05:00
Thomas Harte
0f166cee48 Merge pull request #1487 from TomHarte/PCSeparate
Separate the speaker, and keyboard and floppy controllers.
2025-03-07 14:01:19 -05:00
Thomas Harte
08df42d05b Just 'POST' is fine. 2025-03-07 13:46:07 -05:00
Thomas Harte
2c165c3873 Avoid repetition of 'PC'. 2025-03-07 13:44:49 -05:00
Thomas Harte
9135402d9e Extract keyboard controller. 2025-03-07 13:43:21 -05:00
Thomas Harte
53135ec2c0 Extract floppy controller, speaker. 2025-03-07 13:39:45 -05:00
Thomas Harte
4eb8c8dea9 Merge pull request #1485 from TomHarte/FurtherATDMA
Add second PIC and DMA controllers.
2025-03-06 22:46:55 -05:00
Thomas Harte
f318bec53c Reduce indentation, improve constness. 2025-03-06 22:33:58 -05:00
Thomas Harte
7d84d6909e Add TODO. 2025-03-06 22:16:51 -05:00
Thomas Harte
9224645473 Add second PIC. 2025-03-06 22:15:58 -05:00
Thomas Harte
6717771f9a Rejig doubling of DMA controllers. 2025-03-05 23:02:08 -05:00
Thomas Harte
99e0902b74 Reconnect speaker. 2025-03-05 21:51:50 -05:00
Thomas Harte
c7f2805b05 Install the AT keyboard controller. 2025-03-05 21:28:22 -05:00
Thomas Harte
6e1909647b Reformat; hatch separate AT keyboard controller; print POST codes. 2025-03-05 21:08:53 -05:00
Thomas Harte
0c7db56e15 Merge branch 'master' into FurtherATDMA 2025-03-05 16:34:50 -05:00
Thomas Harte
3287ca449e Update macOS version number. 2025-03-05 16:23:23 -05:00
Thomas Harte
53a8f65ecc Merge branch 'master' into FurtherATDMA 2025-03-05 16:03:46 -05:00
Thomas Harte
113035b374 Merge pull request #1486 from TomHarte/macOSCrashes
macOS: Don't crash if mouse exits window while picking machine.
2025-03-05 16:03:04 -05:00
Thomas Harte
c6e64837c3 Don't crash if mouse moves while picking machine. 2025-03-05 15:51:31 -05:00
Thomas Harte
82419e6df1 Revoke 'ForceAT', **again**. 2025-03-05 14:34:44 -05:00
Thomas Harte
faa76ee017 Not quite accurate, but segment out keyboard writes for the AT. 2025-03-05 14:33:55 -05:00
Thomas Harte
ffdefb4106 Don't crash if mouse moves while picking machine. 2025-03-05 14:27:33 -05:00
Thomas Harte
ba7b1c47b9 Improve constness, reduce trips to system clock. 2025-03-05 14:17:31 -05:00
Thomas Harte
342b8105c4 Improve constness. 2025-03-04 22:53:26 -05:00
Thomas Harte
367c2b568a Attempt to offer expanded DMA top bytes. 2025-03-04 22:51:17 -05:00
Thomas Harte
0eef2c0d04 Merge pull request #1484 from TomHarte/286Decoding
Repair 286 decoding and `perform`.
2025-03-04 21:21:16 -05:00
Thomas Harte
c9a065107b Further tweak ENTER. 2025-03-04 21:08:59 -05:00
Thomas Harte
cacacc00f6 Undo ForceAT. 2025-03-04 20:56:38 -05:00
Thomas Harte
1b94cfc72c Add nullptr backstop. 2025-03-04 20:46:10 -05:00
Thomas Harte
89fd41124f Template various bits of hardware on machine type. 2025-03-04 17:08:49 -05:00
Thomas Harte
4e3b0ae3c1 Resolve type warnings in ENTER, spurious new lines in PC. 2025-03-04 14:10:28 -05:00
Thomas Harte
9df6d535e2 Patch up enough to get an 80286 performer compilable. 2025-03-04 13:52:02 -05:00
Thomas Harte
d545cce276 Merge pull request #1483 from TomHarte/PC-AT
Tee up for an AT-class PC.
2025-03-04 11:57:09 -05:00
Thomas Harte
71b481d3be Bake PC model into template. 2025-03-04 11:45:56 -05:00
Thomas Harte
2710acaae6 Avoid repeating CPU model, normalise member names. 2025-03-04 11:35:11 -05:00
Thomas Harte
d79135ea01 Eliminate non-functional workaround. 2025-03-04 11:30:43 -05:00
Thomas Harte
1464011f6f Try throwing some externs at it. 2025-03-04 11:23:55 -05:00
Thomas Harte
409c8a6859 Keep poking at this. 2025-03-04 11:10:35 -05:00
Thomas Harte
805ce36592 Fix spelling, namespace. 2025-03-04 11:01:07 -05:00
Thomas Harte
07fa56c53d Get heavier with GCC workarounds. 2025-03-04 10:56:45 -05:00
Thomas Harte
28fca80023 Attempt lighter GCC workaround. 2025-03-04 10:46:14 -05:00
Thomas Harte
08c0ee9ca8 Fix further speed reference; eliminate Decoder8086 entirely. 2025-03-04 10:35:16 -05:00
Thomas Harte
2878ab1578 Update Qt UI. 2025-03-04 10:25:27 -05:00
Thomas Harte
16f850cbcc Attempt to eliminate Decoder8086. 2025-03-04 10:13:57 -05:00
Thomas Harte
b9177e50d3 Commute 'speed' to 'model approximation'. 2025-03-04 09:57:34 -05:00
Thomas Harte
c3258551d7 Merge pull request #1481 from TomHarte/x86Macros
Reduce macros in x86 decoder.
2025-03-03 23:27:39 -05:00
Thomas Harte
ea0799c546 Transition off printf. 2025-03-03 23:17:52 -05:00
Thomas Harte
4843b7f7b8 Update name expectations. 2025-03-01 22:35:15 -05:00
Thomas Harte
61694c625e Merge branch 'master' into x86Macros 2025-02-28 22:53:19 -05:00
Thomas Harte
64b4b99d48 Shave icon. 2025-02-28 22:24:06 -05:00
Thomas Harte
dad966b551 Merge pull request #1482 from TomHarte/IconAndReadme
Update README icon, mention Plus 4.
2025-02-28 22:10:51 -05:00
Thomas Harte
e46f503641 Try icon below title. 2025-02-28 22:09:21 -05:00
Thomas Harte
fc4a1e6ace Revert "See whether this affects title underlining."
This reverts commit 02b9a20c11.
2025-02-28 22:07:21 -05:00
Thomas Harte
02b9a20c11 See whether this affects title underlining. 2025-02-28 22:07:00 -05:00
Thomas Harte
1db4e4caed Try for on-left with wrapping. 2025-02-28 22:06:14 -05:00
Thomas Harte
991e176c85 Try as raw HTML. 2025-02-28 22:05:30 -05:00
Thomas Harte
4a41a6bb85 Try right alignment. 2025-02-28 22:04:30 -05:00
Thomas Harte
6229e1049b Move icon to other side of text. 2025-02-28 22:03:25 -05:00
Thomas Harte
3cfd6ed109 Experiment with top-line layout. 2025-02-28 22:02:41 -05:00
Thomas Harte
ad70180edd Update README icon, mention Plus 4. 2025-02-28 22:01:29 -05:00
Thomas Harte
efd4a83bd2 Remove dead #undefs. 2025-02-28 21:55:52 -05:00
Thomas Harte
e13b4ab7c9 Reduce reliance upon macros. 2025-02-28 21:51:44 -05:00
Thomas Harte
fee89cbaad Switch to absolute include paths. 2025-02-28 14:53:48 -05:00
Thomas Harte
2bdcba437c Fix include path. 2025-02-28 13:27:36 -05:00
Thomas Harte
2c2216afae Further eliminate file-relative includes. 2025-02-28 13:18:48 -05:00
Thomas Harte
0823fc32fe Eliminate file-relative paths. 2025-02-28 12:30:25 -05:00
Thomas Harte
091d19caf5 Qt: overtly add project home as include path. 2025-02-28 11:34:27 -05:00
Thomas Harte
00a7381f08 Add top-level base for includes. 2025-02-28 11:32:44 -05:00
Thomas Harte
d494d1e3ee Add SConstruct top-level include path. 2025-02-28 11:30:08 -05:00
Thomas Harte
b1c331a1df Add a canary for include paths. 2025-02-28 11:26:43 -05:00
Thomas Harte
b1a4fd085b Permit project-relative includes. 2025-02-27 18:37:33 -05:00
Thomas Harte
511ab2afe9 Merge pull request #1478 from TomHarte/C++23SDL
Bump macOS SDL target to C++23; fix incompatibilities.
2025-02-27 18:36:23 -05:00
Thomas Harte
30387ad654 Merge branch 'master' into C++23SDL 2025-02-27 18:34:01 -05:00
Thomas Harte
5d528ee1f3 Merge pull request #1479 from TomHarte/x86Documentation
Improve x86 `const`ness.
2025-02-27 18:33:20 -05:00
Thomas Harte
96bb4d50ba Promote macOS SDL target to C++23 as a testing chamber; resolve issues. 2025-02-27 18:13:35 -05:00
Thomas Harte
45f850adae Improve constness. 2025-02-27 15:47:06 -05:00
Thomas Harte
09341ddbe9 Merge pull request #1477 from TomHarte/C++20Deprecations
Resolve two immediate warnings in a C++20 test build.
2025-02-27 15:29:41 -05:00
Thomas Harte
eab4274737 Capture 'this' by reference. 2025-02-27 11:56:51 -05:00
Thomas Harte
49fec1bc10 Remove meaningless 'volatile'. 2025-02-27 11:56:24 -05:00
Thomas Harte
de164469c4 Update version, copyright string. 2025-02-26 21:30:41 -05:00
Thomas Harte
f595871cd9 Merge pull request #1476 from TomHarte/MoreChangeEffects
Widen media change observation.
2025-02-26 21:23:19 -05:00
Thomas Harte
ff86cbd48e Remove more get_s. 2025-02-26 20:26:06 -05:00
Thomas Harte
47bd4dade5 Avoid direct cstdio where meaningful. 2025-02-26 18:04:13 -05:00
Thomas Harte
ff8180920f Simplify extension finder, 80/81 file grabbing. 2025-02-26 17:17:24 -05:00
Thomas Harte
d4f08f0006 Remove get_. 2025-02-26 17:09:47 -05:00
Thomas Harte
1db756063b Further remove type info from function naming. 2025-02-26 16:00:34 -05:00
Thomas Harte
b44ea31bbf Deal with default sizes delcaratively. 2025-02-26 11:33:38 -05:00
Thomas Harte
ddccb946ff Fix precedence error in put_le. 2025-02-25 23:24:11 -05:00
Thomas Harte
1f6f30ae9e Implement MediaChangeObserver for the consoles. 2025-02-25 23:03:45 -05:00
Thomas Harte
4b19a3f4ed Split interface, make const. 2025-02-25 22:58:36 -05:00
Thomas Harte
c39d0ce2f7 Add note to self. 2025-02-25 22:37:12 -05:00
Thomas Harte
cbdf1a941c Merge pull request #1475 from TomHarte/FileDidChange
macOS: Reinsert media and/or restart machines upon underlying file changes.
2025-02-24 23:12:17 -05:00
Thomas Harte
a340635de5 Fix lost audio, race condition. 2025-02-24 23:04:41 -05:00
Thomas Harte
d62362db1a Reduce copy and paste. 2025-02-24 22:50:56 -05:00
Thomas Harte
a0aba69306 Resolve lost options. 2025-02-24 22:46:44 -05:00
Thomas Harte
765683cd34 Copy and paste to a mostly working substitution. 2025-02-24 22:44:10 -05:00
Thomas Harte
93ddf4f0ba Ensure ZX Spectrum, at least, returns correct indication. 2025-02-24 22:34:15 -05:00
Thomas Harte
8dcccf11bf Improve constness, remove unnecessary virtuals. 2025-02-24 18:18:12 -05:00
Thomas Harte
43353ce892 Confirm and wire through semantics. 2025-02-24 15:36:18 -05:00
Thomas Harte
a698fea078 Spell out some options. 2025-02-23 18:15:14 -05:00
Thomas Harte
390d9b0fe1 Add further note to self. 2025-02-22 23:12:41 -05:00
Thomas Harte
fd3ff05b17 Avoid undefined behaviour on left shift. 2025-02-22 23:06:40 -05:00
Thomas Harte
a5e4c9dd7b Add pure file-content change observer. 2025-02-22 22:40:15 -05:00
Thomas Harte
37f07dcc5a Add note to self on intentions. 2025-02-21 17:51:14 -05:00
Thomas Harte
75bae9a59c Merge pull request #1474 from TomHarte/LighterMouseovers
Adjust macOS UI to show options/volume only when _directly_ mouseovered.
2025-02-21 12:42:15 -05:00
Thomas Harte
1684d88a3b Don't hide mouse cursor if over an interesting subview. 2025-02-21 11:43:47 -05:00
Thomas Harte
50acbb70da Rename protocol method. 2025-02-21 11:37:37 -05:00
Thomas Harte
4de1025468 Avoid potential MSX 2 crash at startup. 2025-02-21 11:37:24 -05:00
Thomas Harte
c2506dd115 Show controls immediately at startup. 2025-02-21 11:31:13 -05:00
Thomas Harte
f8c9aa8e6c Require mouseover near the volume/controls to activate. 2025-02-21 11:28:53 -05:00
Thomas Harte
e19dc1f067 Make scan target the window's native view. 2025-02-21 10:43:56 -05:00
Thomas Harte
84776bced1 Merge pull request #1473 from TomHarte/BetterBitReader
Slim FileHolder; improve and extract BitSerialiser.
2025-02-20 23:03:39 -05:00
Thomas Harte
9162c86e21 Test, improve BitStream. 2025-02-20 22:42:02 -05:00
Thomas Harte
88ffcbc62b Work in terms of the number of bits to be handled. 2025-02-19 22:04:51 -05:00
Thomas Harte
6aff0b74cd Reduce redundant types. 2025-02-19 00:09:57 -05:00
Thomas Harte
79671890c5 Generalise and improve BitStream. 2025-02-18 23:17:39 -05:00
Thomas Harte
edd4ed307f Template away repetition. 2025-02-18 22:48:47 -05:00
Thomas Harte
f786f8a970 Merge pull request #1472 from TomHarte/FastPRGs
Withdraw PRG support for the Plus 4.
2025-02-18 21:57:32 -05:00
Thomas Harte
a1d10adaa3 Support only the Vic-20 for PRGs for now. 2025-02-18 20:46:43 -05:00
Thomas Harte
7f480e8e56 Swing desperately at fast tape loading. 2025-02-11 21:49:58 -05:00
Thomas Harte
94b972aaf4 Improve style. 2025-02-11 21:48:56 -05:00
Thomas Harte
9470775292 Avoid race condition on input/output frequencies. 2025-02-11 21:48:23 -05:00
Thomas Harte
93eb63d930 Add interrupt register to TED check set. 2025-02-11 21:47:36 -05:00
Thomas Harte
ea81096a43 Reinstall debugging temporariness. 2025-02-07 18:09:33 -05:00
Thomas Harte
594045b4e7 Merge pull request #1471 from TomHarte/CRCInterface
Remove need for a CRC generator instance.
2025-02-05 22:18:59 -05:00
Thomas Harte
1449330ed3 Use updated interface. 2025-02-04 23:14:49 -05:00
Thomas Harte
07493a6b18 Remove need for a CRC generator instance. 2025-02-04 22:54:39 -05:00
Thomas Harte
0310db5f24 Merge pull request #1470 from TomHarte/SimplerReverse
Unify and simplify bit reversal functions.
2025-02-04 21:49:57 -05:00
Thomas Harte
ed6d5a7d38 Correct test target. 2025-02-04 00:05:09 -05:00
Thomas Harte
ca7c1bc631 Remove redundant inlines. 2025-02-04 00:00:12 -05:00
Thomas Harte
259070c658 Unify reverse functions. 2025-02-03 23:58:41 -05:00
Thomas Harte
e1a7dd9b24 Implement recursive reverse. 2025-02-03 23:50:15 -05:00
Thomas Harte
e5945fbb3d Merge pull request #1469 from TomHarte/AllWarnings
Resolve all current compiler warnings.
2025-02-03 22:08:12 -05:00
Thomas Harte
247f636988 Reinstate ZRLE support. 2025-02-03 21:56:12 -05:00
Thomas Harte
c58a2ee624 Remove redundant moves. 2025-02-03 21:44:30 -05:00
Thomas Harte
35a1b44c21 Remove unused elements. 2025-02-03 21:42:07 -05:00
Thomas Harte
fd09f06507 Merge pull request #1468 from TomHarte/Qt6CI
Reinstate Xcode CI.
2025-02-03 21:34:36 -05:00
Thomas Harte
d66b501a99 Request latest Xcode. 2025-02-03 21:27:53 -05:00
Thomas Harte
349f6766ac Switch to array. 2025-02-03 21:24:05 -05:00
Thomas Harte
cd55ed1514 Persevere. 2025-02-03 21:22:50 -05:00
Thomas Harte
14d4c8accc Disable Qt 6; try to reenable Xcode. 2025-02-03 21:21:25 -05:00
Thomas Harte
37bca96bde Strip back. 2025-02-03 21:17:19 -05:00
Thomas Harte
b0e6ae58c4 Try 6.7. 2025-02-03 21:00:40 -05:00
Thomas Harte
0375e47359 Accept any 6.8. 2025-02-03 20:48:56 -05:00
Thomas Harte
8450ad2856 Add Qt 6 CI. 2025-02-03 20:28:46 -05:00
Thomas Harte
015a1fbd53 Merge branch 'master' into Plus4PRGs 2025-02-03 00:06:14 -05:00
Thomas Harte
318b61b4d7 Merge pull request #1467 from TomHarte/QtCI
Add Qt to CI set.
2025-02-03 00:05:54 -05:00
Thomas Harte
60640517ca Remove crutch. 2025-02-02 23:58:25 -05:00
Thomas Harte
051e38f034 Reformat. 2025-02-02 23:48:20 -05:00
Thomas Harte
300054b9f7 Attempt a full make. 2025-02-02 23:46:26 -05:00
Thomas Harte
4f9e1e3a6b Add 'icu'. 2025-02-02 23:41:47 -05:00
Thomas Harte
856bc27bf1 Must specify qtbase, at least. 2025-02-02 23:36:15 -05:00
Thomas Harte
408b774b42 Switch to archives. 2025-02-02 23:29:59 -05:00
Thomas Harte
f82ef5aad4 Apply one of those architectures. 2025-02-02 23:23:34 -05:00
Thomas Harte
a92df41eb5 List architectures, hopefully. 2025-02-02 22:58:32 -05:00
Thomas Harte
605990929d Hit and hope. 2025-02-02 22:47:23 -05:00
Thomas Harte
925ca28659 Try without architecture. 2025-02-02 22:38:31 -05:00
Thomas Harte
41e3fa7aa7 Retreat. 2025-02-02 22:24:37 -05:00
Thomas Harte
5fa27448f8 Try to coax module names. 2025-02-02 22:19:44 -05:00
Thomas Harte
c3428bdaed Try without prefixes. 2025-02-02 22:11:32 -05:00
Thomas Harte
0539de9c4e Take a guess at modules. 2025-02-02 22:05:36 -05:00
Thomas Harte
eed87164b1 Attempt a Qt build action. 2025-02-02 22:00:21 -05:00
Thomas Harte
0fe726c503 Avoid overlong line. 2025-02-02 21:50:30 -05:00
Thomas Harte
f7f2113f1c Merge pull request #1465 from TomHarte/Plus4FastLoad
Edge towards fast loading in the Plus 4.
2025-02-02 21:49:22 -05:00
Thomas Harte
49d931f5cc Disable Mac job for now. 2025-02-02 21:41:37 -05:00
Thomas Harte
4dbd63de08 Attempt version rebump. 2025-01-31 12:33:21 -05:00
Thomas Harte
3a53c349a0 Abandon attempts to build on older macOS for now. 2025-01-31 11:45:43 -05:00
Thomas Harte
a9fe5d5c87 Manually revert Xcode project version. 2025-01-30 22:48:11 -05:00
Thomas Harte
9cecccf5da Correct TAP type check. 2025-01-30 21:04:36 -05:00
Thomas Harte
6cb3bbaa2d Ensure tape ending != infinite loop. 2025-01-29 23:30:16 -05:00
Thomas Harte
0ff6a0bb53 Slightly simplify template arguments. 2025-01-29 22:51:02 -05:00
Thomas Harte
8ba57dec03 Take another stab at read_dipole. 2025-01-29 22:07:17 -05:00
Thomas Harte
d749c305ed Merge branch 'master' into Plus4FastLoad 2025-01-28 20:20:21 -05:00
Thomas Harte
f46ac2d0ed Merge pull request #1464 from TomHarte/AheadOfTimeCRCTables
Grab bag: calculate CRC tables ahead of time; improve carry typing.
2025-01-28 20:16:03 -05:00
Thomas Harte
d7b7152315 Apply const liberally. 2025-01-28 18:26:34 -05:00
Thomas Harte
da1d52033b Use contractions. 2025-01-28 18:19:31 -05:00
Thomas Harte
01ddc24c02 Require overt acknowledgement of meaning. 2025-01-28 17:42:26 -05:00
Thomas Harte
53a3e88d16 Shunt CRC XOR table generation to compile time. 2025-01-28 17:36:32 -05:00
Thomas Harte
bc8d1cc384 Merge pull request #1463 from TomHarte/AcornAnalyserStyle
Tweak Acorn analyser style.
2025-01-26 21:58:50 -05:00
Thomas Harte
ed2ba63a5f Adjust style. 2025-01-26 21:42:38 -05:00
Thomas Harte
8a2c009653 Reduce copies, size()s, code duplication. 2025-01-26 21:34:01 -05:00
Thomas Harte
55690a4c7f Merge branch 'master' into Plus4FastLoad 2025-01-22 19:49:23 -05:00
Thomas Harte
161ad4b143 Merge pull request #1462 from TomHarte/VIAPortTemplate
Reduce repetitive dynamic work in 6522 usages.
2025-01-22 19:48:24 -05:00
Thomas Harte
d701990df4 Simplify ownership of the shift value. 2025-01-22 16:12:45 -05:00
Thomas Harte
95a2d1013c Remove unused dynamic dispatcher. 2025-01-22 16:06:09 -05:00
Thomas Harte
5d4f3c0b3e Remove already-done TODO. 2025-01-22 16:04:17 -05:00
Thomas Harte
f8e4023307 Reduce repetitive dynamic work in 6522 usages. 2025-01-22 15:57:03 -05:00
Thomas Harte
609aba7c73 Made various additional style improvements. 2025-01-22 13:47:25 -05:00
Thomas Harte
bc7ab0eba1 Extend parser, accelerate headers. 2025-01-21 22:37:10 -05:00
Thomas Harte
56f271c8ad Continue failing. This is the story of my life. 2025-01-21 17:24:12 -05:00
Thomas Harte
11190cff1d Eject zero-cost execution in favour of faulty HLE. 2025-01-21 16:45:05 -05:00
Thomas Harte
348a593dc1 Flail in attempt to implement fast loading. 2025-01-21 14:13:42 -05:00
Thomas Harte
b67bb50f4a Merge pull request #1461 from TomHarte/Vic20Confidence
Include VIC hits in Vic-20 confidence selection.
2025-01-20 23:21:19 -05:00
Thomas Harte
1174f651ab Switch to logger, ignore 0xfdfx. 2025-01-20 22:47:54 -05:00
Thomas Harte
dad9777c3e Merge pull request #1460 from TomHarte/Plus4DriveSelection
Add C1541 button to mac UI; respect Target setting.
2025-01-20 22:45:49 -05:00
Thomas Harte
4f6285a8e7 Include VIC hits in Vic-20 confidence selection. 2025-01-20 22:25:24 -05:00
Thomas Harte
20cecf4702 Add C1541 button to mac UI; respect Target setting. 2025-01-20 22:02:35 -05:00
Thomas Harte
5763eabff4 Merge pull request #1459 from TomHarte/UnitTestUpdates
Repair lagging unit tests.
2025-01-20 21:41:15 -05:00
Thomas Harte
0fc753949d Repair lagging unit tests. 2025-01-20 21:36:25 -05:00
Thomas Harte
083c1b7ca7 Merge pull request #1458 from TomHarte/Plus4PRGs
Introdice alternative tape timings for the +4.
2025-01-20 20:59:33 -05:00
Thomas Harte
8f6b1b11e5 Fix member name. 2025-01-20 20:35:14 -05:00
Thomas Harte
53b7d19c10 Ensure tape images proper destruct. 2025-01-20 20:33:17 -05:00
Thomas Harte
b0b4f5e51a Add Plus 4 to Qt UI. 2025-01-20 20:31:12 -05:00
Thomas Harte
b7414aa59c Improve logging. 2025-01-20 16:19:02 -05:00
Thomas Harte
f449045118 Add some basic attempts at dynamic analysis. 2025-01-20 16:15:53 -05:00
Thomas Harte
1e9ddada37 Retain tapes and disks. 2025-01-20 15:51:01 -05:00
Thomas Harte
55d59a1854 Separate chunk parsing. 2025-01-19 18:16:33 -05:00
Thomas Harte
beb9f38514 Eliminate std::shared_ptr. 2025-01-18 23:25:08 -05:00
Thomas Harte
00b1865fc8 Fix boundary condition. 2025-01-17 21:46:43 -05:00
Thomas Harte
0f545608c4 Fix serialiser ownership, Commodore analyser. 2025-01-17 21:43:11 -05:00
Thomas Harte
bde2047184 Provide target platform where serialiser will accept it. 2025-01-17 17:09:47 -05:00
Thomas Harte
0a22d8fb9e Add TODO on final dangling issue. 2025-01-17 17:06:03 -05:00
Thomas Harte
1bef37d504 Test data only once. 2025-01-17 17:04:25 -05:00
Thomas Harte
7f5d290b66 Promote validation. 2025-01-17 17:01:09 -05:00
Thomas Harte
9461e6f285 Move validation up a level. 2025-01-17 16:59:30 -05:00
Thomas Harte
3f59a03f29 Parse Commodore .tap header only once. 2025-01-17 16:54:54 -05:00
Thomas Harte
062b581b55 Move .cas and ZX .tap initial parsing out of serialiser. 2025-01-17 16:45:09 -05:00
Thomas Harte
58d3fdc1c2 Separate stateful serialisation from tapes. 2025-01-17 16:39:21 -05:00
Thomas Harte
2f546842a7 Wire TAPs and similar directly to their targets. 2025-01-16 21:21:15 -05:00
Thomas Harte
f089a85908 Zoom out to a more likely TV cropping. 2025-01-15 22:52:20 -05:00
Thomas Harte
a6e453a452 Introdice alternative tape timings for the +4. 2025-01-15 22:11:26 -05:00
Thomas Harte
3adf3dc547 Merge pull request #1457 from TomHarte/BadlinePriority
Give priority to initial bad lines.
2025-01-13 20:40:17 -05:00
Thomas Harte
1d0ea96ae9 This hasn't been true for a while. 2025-01-13 17:38:29 -05:00
Thomas Harte
a4cb17a1cb First bad lines take priority over second ones. 2025-01-13 17:31:18 -05:00
Thomas Harte
733da3161b Merge pull request #1456 from TomHarte/CounterSets
Correct shift on hcount write.
2025-01-12 22:32:46 -05:00
Thomas Harte
1b1a0f553d Keep three least bits. 2025-01-12 22:07:56 -05:00
Thomas Harte
972619c1fe Correct shift on hcount write. 2025-01-12 21:59:22 -05:00
Thomas Harte
61086d5360 Merge pull request #1455 from TomHarte/MatchBefore
Restructure loop to perform events AT time, not upon reaching it.
2025-01-12 19:18:32 -05:00
Thomas Harte
37513d726c Restructure loop to perform events AT time, not upon reaching it. 2025-01-12 19:06:42 -05:00
Thomas Harte
6510bee327 Merge pull request #1454 from TomHarte/VideoTweaks
Restrict counter sizes; invert written horizontal counter.
2025-01-11 23:42:58 -05:00
Thomas Harte
cd36f3f096 Restrict counter sizes; invert written horizontal counter. 2025-01-11 23:19:01 -05:00
Thomas Harte
407a6f5e31 Merge pull request #1453 from TomHarte/AbsentBits
Correct status unset-bit masks.
2025-01-11 22:58:42 -05:00
Thomas Harte
2b28df280e Correct status unset-bit masks. 2025-01-11 22:47:56 -05:00
Thomas Harte
eb763ed82c Merge pull request #1452 from TomHarte/TapeMotorAgain
Ensure tape motor is a combination of programmed state and button.
2025-01-10 21:04:19 -05:00
Thomas Harte
755f53cce0 Ensure tape motor is a combination of programmed state and button. 2025-01-10 16:59:09 -05:00
Thomas Harte
c190ab40b0 Merge pull request #1451 from TomHarte/Plus4Joystick
Add joystick input.
2025-01-09 17:12:37 -05:00
Thomas Harte
a3ad82de42 Add joystick input. 2025-01-09 17:01:20 -05:00
Thomas Harte
0f6cd6904d Separate keyboard and joystick masks.
Based on aside in https://plus4world.powweb.com/forum/6867#6868 ; I don't yet know what the joystick bits are.
2025-01-09 16:41:21 -05:00
Thomas Harte
79c89af6ea Merge pull request #1450 from TomHarte/LatestWarnings
Resolve GCC ubuntu-latest build warnings.
2025-01-09 16:32:50 -05:00
Thomas Harte
56f10a9a52 Adjust ownership to avoid passing reference to uninitialised object. 2025-01-09 16:27:19 -05:00
Thomas Harte
c679e2c067 line_number is now unused. 2025-01-09 16:14:16 -05:00
Thomas Harte
0677987320 Ensure all paths return a value. 2025-01-08 22:30:32 -05:00
Thomas Harte
5fb6e6780c Eliminate unused variable (at least temporarily). 2025-01-08 22:30:17 -05:00
Thomas Harte
58ef91a7b1 Merge pull request #1449 from TomHarte/FullerAudio
Switch to full-clock PWM audio implementation, with noise generator.
2025-01-08 22:28:01 -05:00
Thomas Harte
e1ae65b6d1 Switch to PWM implementation, with noise. 2025-01-08 22:09:42 -05:00
Thomas Harte
65307186dc Provide full clock to audio. 2025-01-08 21:17:48 -05:00
Thomas Harte
6fa29c204b Extend PAL/NTSC selection to audio. 2025-01-08 20:27:37 -05:00
Thomas Harte
8219beeb1a Merge pull request #1448 from TomHarte/6502Macros
Eliminate macros from 6502 bus operation actions.
2025-01-08 20:19:09 -05:00
Thomas Harte
ace7e24dfb Eliminate Objective-C-style naming. 2025-01-07 22:55:19 -05:00
Thomas Harte
828c2a6883 Convert macros to functions. 2025-01-07 22:51:52 -05:00
Thomas Harte
f195dc313d Strongly type BusOperation. 2025-01-07 22:48:17 -05:00
Thomas Harte
5b8a005f41 Merge pull request #1447 from TomHarte/CounterAccess
Add programmatic access to video counters.
2025-01-07 22:33:28 -05:00
Thomas Harte
9feb75e645 Force high unwriteable bytes. 2025-01-07 22:21:42 -05:00
Thomas Harte
7f8e90bd29 Add video counter writes. 2025-01-07 21:56:04 -05:00
Thomas Harte
2fd34b649d Add missing video counter reads. 2025-01-07 21:40:20 -05:00
Thomas Harte
104054ed1a Merge pull request #1446 from TomHarte/Plus4VideoOptions
Add selectable display type.
2025-01-07 20:15:21 -05:00
Thomas Harte
457b28c22c Merge branch 'master' into Plus4VideoOptions 2025-01-07 20:08:54 -05:00
Thomas Harte
095c8dcd0c Merge pull request #1445 from TomHarte/Plus4Tapes
Improve support for C16 TAP files.
2025-01-07 20:07:38 -05:00
Thomas Harte
8463e9ed94 Add selectable display type. 2025-01-07 17:41:43 -05:00
Thomas Harte
b6278c6144 Remove debugging cruft. 2025-01-06 22:17:53 -05:00
Thomas Harte
1c1e1eee47 Double clock for all non-C16s. 2025-01-06 22:04:57 -05:00
Thomas Harte
b37ed9ec60 Take yet another stab at wave/half-waves. 2025-01-06 21:40:46 -05:00
Thomas Harte
45f3ef6920 Guess that all C16-style files are 'half wave'. 2025-01-06 17:26:51 -05:00
Thomas Harte
2cd6c4238b Quieten logging. 2025-01-05 22:52:40 -05:00
Thomas Harte
f6ed0b33eb Diagnose current scrolling colour fault; hack in graphics-mode fix. 2025-01-05 22:48:16 -05:00
Thomas Harte
c4f4ca3f90 Add asserts. 2025-01-05 22:45:09 -05:00
Thomas Harte
9a6780616b Close unpainted gaps. 2025-01-05 22:25:35 -05:00
Thomas Harte
db4eca0a42 Hack forward to a woring Mad Rally. 2025-01-05 22:08:20 -05:00
Thomas Harte
6d674edb48 Merge remote-tracking branch 'origin/master' into Plus4Tapes 2025-01-05 22:07:26 -05:00
Thomas Harte
c0469a044b Add missing address warnings. 2025-01-05 21:10:23 -05:00
Thomas Harte
b9b64eba9a Map all missing registers. 2025-01-05 21:06:46 -05:00
Thomas Harte
2d74387a00 Extend TAP support for C16. 2025-01-05 20:37:39 -05:00
Thomas Harte
f66b6fc20c Attempt support for C16 TAPs. 2025-01-05 08:51:20 -05:00
Thomas Harte
f0711a9fbc Use detection for play button; allow computer to set motor. 2025-01-04 22:54:13 -05:00
Thomas Harte
83a8c7215a Merge pull request #1444 from TomHarte/AudioQueueTransients
Treat kAudioQueueErr_CannotStart as ephemeral.
2025-01-04 22:39:56 -05:00
Thomas Harte
a86f966cb4 Treat kAudioQueueErr_CannotStart as ephemeral. 2025-01-04 22:24:34 -05:00
Thomas Harte
74db978b81 Fix automatic tape motor control. 2025-01-04 22:23:46 -05:00
Thomas Harte
1300546a52 Merge pull request #1443 from TomHarte/TypingSpeed
Improve +4 typing speed.
2025-01-04 19:15:55 -05:00
Thomas Harte
3aeb0bba71 Improve +4 typing speed. 2025-01-04 15:14:25 -05:00
Thomas Harte
03d3efa323 Merge pull request #1442 from TomHarte/38columns
Progress shifter outside of painted pixels.
2025-01-04 07:20:56 -05:00
Thomas Harte
f9c220bee0 Progress shifter outside of painted pixels. 2025-01-04 07:15:20 -05:00
Thomas Harte
114c2e2636 Merge pull request #1441 from TomHarte/OSSGuardNoMacro
Remove macros from CoreAudio handler.
2025-01-03 23:38:35 -05:00
Thomas Harte
75a0e622ad Remove macros from CoreAudio handler. 2025-01-03 23:25:38 -05:00
Thomas Harte
8e2de4ee30 Merge pull request #1440 from TomHarte/MenuTweak
Improve menu wording.
2025-01-03 23:23:50 -05:00
Thomas Harte
b1602261cf Remove redundant adjective. 2025-01-03 23:23:02 -05:00
Thomas Harte
e5ed11f8ec Take another swing at menu item naming. 2025-01-03 23:21:55 -05:00
Thomas Harte
c1ecfd289e Merge pull request #1438 from TomHarte/Plus4UI
Add Plus 4 to Mac UI.
2025-01-03 23:10:45 -05:00
Thomas Harte
c5cca15b4e Extend window size. 2025-01-03 23:01:33 -05:00
Thomas Harte
fa978315e6 Add Plus 4 option to Mac UI. 2025-01-03 22:59:39 -05:00
Thomas Harte
c5bffc38f4 Switch typedefs to usings. 2025-01-03 21:35:34 -05:00
Thomas Harte
88b5f6b148 Merge pull request #1437 from TomHarte/Plus4Typer
Add TED typer.
2025-01-03 21:31:56 -05:00
Thomas Harte
fc04742151 Pull input from the typer. 2025-01-03 21:03:56 -05:00
Thomas Harte
c618d18d46 Allow typers to be attached. 2025-01-03 20:29:19 -05:00
Thomas Harte
33bc7c00df Eliminate long-ago use of typedef. 2025-01-03 20:29:05 -05:00
Thomas Harte
1ed550d7f9 Merge pull request #1434 from TomHarte/Plus4Startup
Add a simulacrum of C16+4 emulation.
2025-01-03 20:11:08 -05:00
Thomas Harte
18b87f2c80 Keep a little more state outside the main loop. 2025-01-03 20:05:43 -05:00
Thomas Harte
fad503ca80 Use correct source for bitmap address. 2025-01-03 17:31:27 -05:00
Thomas Harte
37ec3e4605 Simplify flash/inversion handling. 2025-01-03 17:27:43 -05:00
Thomas Harte
70e3d23f26 Add note to self. 2025-01-02 23:10:17 -05:00
Thomas Harte
6ebf415a52 Improve invert and flash support. 2025-01-02 23:04:35 -05:00
Thomas Harte
5c31104d0e Simplify control flow, half-obey 256-character flag. 2025-01-02 22:39:23 -05:00
Thomas Harte
aed8b65e2b Mark extra constexprs. 2025-01-02 22:01:51 -05:00
Thomas Harte
906e8aa2b2 Move nullptr check to bottom of pipeline. 2025-01-02 21:02:11 -05:00
Thomas Harte
d0703f95af Normalise adjective/noun. 2025-01-02 16:01:47 -05:00
Thomas Harte
538b00797d Flatten structure. 2025-01-02 16:00:47 -05:00
Thomas Harte
985c555518 Support multicolour text. 2025-01-02 15:56:39 -05:00
Thomas Harte
5ef26a25ee Fix shift timing. 2025-01-02 15:52:20 -05:00
Thomas Harte
3db0e30d12 Factor out 1bpp and 2bpp pixel generation. 2025-01-02 15:39:45 -05:00
Thomas Harte
a666cabae9 Support extended colour text mode. 2025-01-02 15:32:44 -05:00
Thomas Harte
2e8d9018ef Add other address modes. 2025-01-02 15:09:37 -05:00
Thomas Harte
ae49505e67 Attempt multicolour bitmap mode. 2025-01-02 15:07:22 -05:00
Thomas Harte
09bd5503b4 Fetch pixels earlier for a mostly-working high-resolution output. 2025-01-02 14:42:49 -05:00
Thomas Harte
dbe733524c Reintroduce RDY control. 2025-01-02 13:49:24 -05:00
Thomas Harte
1625f5c0f9 Take a stab at high-resolution bitmap mode. 2025-01-02 13:46:35 -05:00
Thomas Harte
7cd49d07f2 Collapse to a single function. 2025-01-02 13:39:50 -05:00
Thomas Harte
a542345456 Iterate towards supporting all video modes. 2025-01-01 22:34:47 -05:00
Thomas Harte
0b98f21443 Enable extra functionality. 2025-01-01 22:34:30 -05:00
Thomas Harte
c42e231e99 Attempt fully to support x scroll. 2025-01-01 21:47:59 -05:00
Thomas Harte
ab653af4b3 Introduce pixel-level shifter. 2025-01-01 20:58:06 -05:00
Thomas Harte
8653f572c8 Move static_assert. 2025-01-01 15:06:00 -05:00
Thomas Harte
39b431fb19 Rejig marginally. 2024-12-31 22:14:02 -05:00
Thomas Harte
e158c5bc30 Extend shifting to final column of screen. 2024-12-31 20:33:27 -05:00
Thomas Harte
d0fdfda4cb Set volume peak, count up rather than down. 2024-12-31 11:45:32 -05:00
Thomas Harte
668a5ca041 Make a real attempt at some degree of audio. 2024-12-31 10:25:11 -05:00
Thomas Harte
5e3947b8bc Evaluate address lazily. 2024-12-31 08:28:42 -05:00
Thomas Harte
233a627c9f Correct longstanding confusion over character fetch. 2024-12-31 08:25:05 -05:00
Thomas Harte
6197486d49 Use increment_video_counter_ to trigger fetch. 2024-12-31 08:06:04 -05:00
Thomas Harte
60856b974b Add wiring for audio. 2024-12-30 22:56:29 -05:00
Thomas Harte
d1eca5dc21 Expand mask. 2024-12-30 21:29:36 -05:00
Thomas Harte
24b281d625 Use namespace; attempt to avoid false characters. 2024-12-30 09:14:27 -05:00
Thomas Harte
b0d1dee38b Add missing header. 2024-12-29 22:36:14 -05:00
Thomas Harte
0751c51803 Dispatch warning. 2024-12-29 22:34:32 -05:00
Thomas Harte
0005229c1e Improve header. 2024-12-29 22:21:38 -05:00
Thomas Harte
33c2353107 Alter motor control detection. 2024-12-29 22:21:02 -05:00
Thomas Harte
cb98297bb5 Add consts. 2024-12-29 22:14:48 -05:00
Thomas Harte
0e663e1da8 Add C1541 activity indicator. 2024-12-29 21:30:53 -05:00
Thomas Harte
918a8c5f8b Fix 1541 clocking, invert levels again. 2024-12-29 08:41:37 -05:00
Thomas Harte
34938e8c62 Fully connect serial port. 2024-12-28 23:07:01 -05:00
Thomas Harte
da6efe52ff Accept implicit bool, eliminate rom name repetition. 2024-12-28 22:22:28 -05:00
Thomas Harte
570f1caa8f Attempt also to integrate a C1541. 2024-12-28 21:49:04 -05:00
Thomas Harte
6f638805f7 Further eliminate std::shared_ptr connections. 2024-12-28 20:52:31 -05:00
Thomas Harte
c92b0dc886 Start normalising Commodore serial bus interface. 2024-12-28 20:11:27 -05:00
Thomas Harte
b4b216de84 Attempt press-play feedback. 2024-12-27 21:43:41 -05:00
Thomas Harte
80f5d7c735 Attempt full tape input. 2024-12-27 21:19:41 -05:00
Thomas Harte
01aeb46664 Bump version. 2024-12-27 20:59:24 -05:00
Thomas Harte
2cfd2ff624 Start adding tape player. 2024-12-27 20:59:07 -05:00
Thomas Harte
ff12bbbdb6 Simplify delay state. 2024-12-27 17:10:25 -05:00
Thomas Harte
e19fe5d0e2 Reintroduce colour burst. 2024-12-27 09:25:36 -05:00
Thomas Harte
9670d5f4de Add cursor, proving things generally to be off by one. 2024-12-27 09:20:12 -05:00
Thomas Harte
863b09c39b Increase key bindings. 2024-12-27 09:14:23 -05:00
Thomas Harte
6b90de539e Add data delays. 2024-12-26 22:39:16 -05:00
Thomas Harte
4bb53ed6ba Start trending towards an FPGA-inspired implementation. 2024-12-26 22:33:09 -05:00
Thomas Harte
e6523f3ec1 Shuffle colour conversion moment; move ownership of clock rate. 2024-12-20 09:17:40 -05:00
Thomas Harte
c8ad8c79bd Factor in x_scroll_. 2024-12-18 22:14:57 -05:00
Thomas Harte
b08cc9cb49 Use attributes, attempt real cursor. 2024-12-18 22:07:37 -05:00
Thomas Harte
4f93dc0adf Support attribute bytes. 2024-12-18 22:02:05 -05:00
Thomas Harte
096f48be33 Fix top line of cursor, add pretend cursor, page video separately. 2024-12-18 21:48:03 -05:00
Thomas Harte
81398d58a2 Improve get_rect_for_area, use in C16. 2024-12-18 20:53:03 -05:00
Thomas Harte
7466da5651 Add Keyboard. 2024-12-18 07:04:17 -05:00
Thomas Harte
c8fdde4c5e Clarify clock rates. 2024-12-17 07:08:04 -05:00
Thomas Harte
15583e7975 Avoid risk of unbounded memory consumption. 2024-12-16 22:29:23 -05:00
Thomas Harte
5acdf39566 Use a normative, unique_ptr-based cache. 2024-12-16 22:12:12 -05:00
Thomas Harte
2240ada5db Avoid going out of bounds below. 2024-12-16 22:11:49 -05:00
Thomas Harte
9d5c10d440 Edge towards realistic video collection. 2024-12-16 22:11:06 -05:00
Thomas Harte
709f350d60 Begin usage of RDY. 2024-12-16 07:18:07 -05:00
Thomas Harte
3d7e016b42 Name horizontal events. 2024-12-15 08:46:07 -05:00
Thomas Harte
b76104d145 Start edging towards proper video timing. 2024-12-14 22:06:18 -05:00
Thomas Harte
702b6d6567 Add extra note to self. 2024-12-14 11:56:13 -05:00
Thomas Harte
3e93004db6 Double nominal clock, to hit normative values. 2024-12-14 11:55:10 -05:00
Thomas Harte
589903c43c Add safety rail. 2024-12-13 23:14:00 -05:00
Thomas Harte
f41b54de21 Make a close-enough guess at chrominances. 2024-12-13 22:25:23 -05:00
Thomas Harte
700b848f26 Add overt nils to aid with debugging. 2024-12-13 21:25:01 -05:00
Thomas Harte
a1f6e93e22 Add most of the keyboard. 2024-12-13 21:24:11 -05:00
Thomas Harte
1628af2ffc Provide a stuck down key 'a'. 2024-12-13 17:56:47 -05:00
Thomas Harte
1b5d446635 Fix: writes to interrupt status _clear_. 2024-12-13 17:22:05 -05:00
Thomas Harte
83a9ef772a Add TODO explaining all currently-unhandled writes. 2024-12-13 14:02:33 -05:00
Thomas Harte
1d9c3fb827 Hack in some text output. 2024-12-13 13:56:12 -05:00
Thomas Harte
ff92bdb324 Add buffer for pixels, output _something_. 2024-12-13 13:31:15 -05:00
Thomas Harte
363ad7342a Add memory fuzzing, some text output. 2024-12-12 22:59:20 -05:00
Thomas Harte
663acd3810 Map initial border colour, white and black. 2024-12-12 22:35:50 -05:00
Thomas Harte
c2fc26089e Add background colour reading, fix writing. 2024-12-12 22:15:15 -05:00
Thomas Harte
58b464bdfc Attempt to add interrupts. 2024-12-12 22:07:51 -05:00
Thomas Harte
ed766c74e6 Add some paging. 2024-12-12 21:17:28 -05:00
Thomas Harte
1d07b8238c Add a crop rectangle. 2024-12-12 17:36:44 -05:00
Thomas Harte
41c6ed7c5a Further restrict 'active' area of the display. 2024-12-12 17:33:11 -05:00
Thomas Harte
f7750af3d0 Provide bus visibility to video; mark vertical portion of display. 2024-12-11 22:32:14 -05:00
Thomas Harte
8854ffddee Include possible clock divider. 2024-12-11 21:57:31 -05:00
Thomas Harte
a487619578 Track basic frame events. 2024-12-11 21:54:03 -05:00
Thomas Harte
0eab6146fc Introduce a CRT. 2024-12-11 21:38:32 -05:00
Thomas Harte
389ba95e5a Template out the usual repetitive stuff of segment finding. 2024-12-11 21:30:58 -05:00
Thomas Harte
84d178c0ca Transcribe event times into [mostly] non-action. 2024-12-11 17:32:51 -05:00
Thomas Harte
aed8f8efa8 Transcribe some timing numbers. 2024-12-10 22:56:14 -05:00
Thomas Harte
38325741de Forward address information to a video stub. 2024-12-10 21:29:17 -05:00
Thomas Harte
891d5c2066 Separate out TED calls, to aid with logging. 2024-12-10 18:07:07 -05:00
Thomas Harte
6b7edac6e4 Add timers. 2024-12-10 18:04:10 -05:00
Thomas Harte
ab2a576e1b Merge branch 'master' into Plus4Startup 2024-12-09 22:23:24 -05:00
Thomas Harte
5a3e4dd47b Merge pull request #1431 from TomHarte/UniqueSectors
Eliminate use of std::shared_ptr for tracks on both sides of DiskImageHolder.
2024-12-09 22:23:01 -05:00
Thomas Harte
064c4b4312 Add some logging. 2024-12-09 22:22:20 -05:00
Thomas Harte
cbde504057 Add a memory map of sorts and a 6502. 2024-12-09 17:46:31 -05:00
Thomas Harte
949cfcfa69 Load ROMs. 2024-12-09 17:31:00 -05:00
Thomas Harte
06a005321e Merge pull request #1433 from TomHarte/DeclareFieldsAfresh
Use `std::once` in preference to home-rolled solution.
2024-12-08 22:46:21 -05:00
Thomas Harte
d3587f595f Merge pull request #1432 from TomHarte/Plus4ROMs
Add definitions for some of the Plus 4 ROMs.
2024-12-08 22:42:02 -05:00
Thomas Harte
b0158ed7ce Use std::once in preference to home-rolled solution. 2024-12-08 22:35:41 -05:00
Thomas Harte
e5f4300e54 Add definitions for some of the Plus 4 ROMs. 2024-12-08 22:03:44 -05:00
Thomas Harte
7cc6f8604e Eliminate std::shared_ptr outside of DiskImageHolder. 2024-12-08 21:49:34 -05:00
Thomas Harte
657960e7d0 Eliminate use of std::shared_ptr at DiskImage and below. 2024-12-08 21:26:03 -05:00
Thomas Harte
aecd7f9283 Merge pull request #1427 from TomHarte/CommodoreAnalyser
Improve analysis of Commodore BASIC
2024-12-08 18:59:03 -06:00
Thomas Harte
6f1b30cd24 Include Plus 4 in test target. 2024-12-07 11:56:16 -06:00
Thomas Harte
a6ba549b67 Don't repeat constant. 2024-12-07 11:55:38 -06:00
Thomas Harte
84ea04f61d Improve comments. 2024-12-07 11:54:55 -06:00
Thomas Harte
0d52cf5f97 Improve constiness. 2024-12-07 11:50:18 -06:00
Thomas Harte
b15a083a15 Switch to a non-macro route for startup declarations. 2024-12-07 10:15:38 -06:00
Thomas Harte
a128247ef5 Improve comments. 2024-12-07 09:32:45 -06:00
Thomas Harte
590bd934c0 Use built-in paralel for. 2024-12-07 09:32:32 -06:00
Thomas Harte
e9826d2e7e Use launch-time declarations. 2024-12-06 16:03:46 -05:00
Thomas Harte
58ed63cd18 Consciously uglify. These shouldn't look like functions. 2024-12-06 16:03:24 -05:00
Thomas Harte
fd1bd3032f Attempt to move towards at-launch field declaration.
This avoids any need for overt thread safety in mutations.
2024-12-06 16:00:03 -05:00
Thomas Harte
d7206096ea Attempt to parallelise. 2024-12-06 15:59:47 -05:00
Thomas Harte
f43e594eca Improve style: indentation, constness, names. 2024-12-06 15:29:49 -05:00
Thomas Harte
ea4fe5e809 Propagate Plus 4 to other project files. 2024-12-06 15:20:58 -05:00
Thomas Harte
9fcb634510 Route +4 software into a non-functional +4. 2024-12-06 15:17:49 -05:00
Thomas Harte
c14a4515ce Add consts widely. 2024-12-06 15:08:21 -05:00
Thomas Harte
8e71180cd2 Add an empty shell of a C16+4 class. 2024-12-06 13:53:08 -05:00
Thomas Harte
08f98aa32f Decrease indentation. 2024-12-06 13:52:42 -05:00
Thomas Harte
e8aa9b9eb2 Avoid overrun on empty file. 2024-12-06 13:37:06 -05:00
Thomas Harte
19f815eeff Infer more from first file starting address; reduce reallocations. 2024-12-06 13:34:35 -05:00
Thomas Harte
a508f7a463 Process all files if provided with a disk or tape. 2024-12-06 13:24:15 -05:00
Thomas Harte
e58d3ee060 Remove file. 2024-12-05 22:13:02 -05:00
Thomas Harte
268842681a Adjust move semantics. 2024-12-05 22:09:07 -05:00
Thomas Harte
9b357a9fbf Reduce copying. 2024-12-05 22:05:03 -05:00
Thomas Harte
6f80018b6e Reintroduce argument. 2024-12-05 22:04:39 -05:00
Thomas Harte
7a1153be65 Improve loop detection. 2024-12-05 17:30:30 -05:00
Thomas Harte
85d4c24aba Restore parameter name. 2024-12-05 17:29:05 -05:00
Thomas Harte
48c0ae8fe4 Avoid being thrown by looping BASIC. 2024-12-05 17:28:47 -05:00
Thomas Harte
e835b2c68c Merge branch 'master' into CommodoreAnalyser 2024-12-04 22:56:05 -05:00
Thomas Harte
10d20f5d09 Merge pull request #1429 from TomHarte/FarewellMacOS12
Remove deprecated macos-12 from CI; add macos-15.
2024-12-04 22:55:06 -05:00
Thomas Harte
88b31ea940 Merge pull request #1428 from TomHarte/MoreIndentation
Adjust more dangling indentation changes.
2024-12-04 22:40:30 -05:00
Thomas Harte
9cb28d23a3 Remove deprecated macos-12; add macos-15. 2024-12-04 22:39:29 -05:00
Thomas Harte
ce5aae3f7d Adjust more dangling indentation changes. 2024-12-04 22:29:08 -05:00
Thomas Harte
e7f0eb6746 Avoid invalid accesses. 2024-12-04 22:04:00 -05:00
Thomas Harte
65a118d1f3 Attempt to locate and disassemble machine code. 2024-12-04 21:41:05 -05:00
Thomas Harte
3d2eefc7e7 Merge pull request #1426 from TomHarte/C16Plus4Analysis
Begin Plus 4 analyser work, triggering clean-up of tape file classes.
2024-12-03 23:16:10 -05:00
Thomas Harte
f804c32eee Opportunistically const. 2024-12-03 22:57:38 -05:00
Thomas Harte
b89ecadc3a Improve interface. 2024-12-03 22:54:29 -05:00
Thomas Harte
6d4ff0b89a Finally eliminate all that virtual_ nonsense. 2024-12-03 22:28:57 -05:00
Thomas Harte
598003ea39 Continue marking override. 2024-12-03 21:18:26 -05:00
Thomas Harte
6ef63790a9 Mark overrides, improve constiness. 2024-12-03 17:33:09 -05:00
Thomas Harte
3ffd986a1c Start building Commodore analyser tests. 2024-12-03 09:25:58 -05:00
Thomas Harte
0b5cd4c665 Lock all tape classes down to read-only. 2024-12-03 09:21:13 -05:00
Thomas Harte
0371b0507a Avoid potential extending run-out-of-bounds. 2024-12-03 09:19:23 -05:00
Thomas Harte
9fa71231c4 Support zero-length files; further fix bounds checks. 2024-12-02 17:23:50 -05:00
Thomas Harte
32beafc12d Test Plus 4 detectionl; add shout for additional start address. 2024-12-02 15:27:37 -05:00
Thomas Harte
09e2ef334b Fix sign of bounds check. 2024-12-02 15:27:03 -05:00
Thomas Harte
c0ce62ed2b Merge pull request #1425 from TomHarte/MoreIndentation
Take another big swing at indentation, some `const`s.
2024-12-01 22:02:25 -05:00
Thomas Harte
d3ed485e7a Take another big swing at indentation, some consts. 2024-12-01 21:44:14 -05:00
Thomas Harte
31c878b654 Merge pull request #1424 from TomHarte/InstructionSetFormatting
Improve formatting, `const`ness in instruction sets.
2024-12-01 20:24:55 -05:00
Thomas Harte
3a0f4a0bfc Improve constness, formatting. 2024-12-01 18:09:19 -05:00
Thomas Harte
8b88d1294d Remove errant spaces. 2024-12-01 09:04:32 -05:00
Thomas Harte
43fcf46d69 Limit line lengths. 2024-12-01 09:00:29 -05:00
Thomas Harte
394fe0f1f1 Improve formatting, constness in 68k and ARM instruction set implementations. 2024-12-01 08:20:24 -05:00
Thomas Harte
872921f635 Merge pull request #1423 from TomHarte/InputsFormatting
Roll formatting and `const` tweaks into Inputs.
2024-11-30 19:25:50 -05:00
Thomas Harte
7248470950 Roll formatting and const tweaks into Inputs. 2024-11-30 18:57:56 -05:00
Thomas Harte
9d87296316 Merge pull request #1422 from TomHarte/MutableLevels
Correct improper application of `const`.
2024-11-30 17:53:56 -05:00
Thomas Harte
23c67f7e38 Correct improper application of const. 2024-11-30 17:32:16 -05:00
Thomas Harte
bd98d95dbf Merge pull request #1421 from TomHarte/FurtherFormatting
Further improve formatting.
2024-11-30 17:22:00 -05:00
Thomas Harte
3addb8d72b Finish updating components. 2024-11-30 17:21:00 -05:00
Thomas Harte
5545906063 Adopt new indentation, improve constness. 2024-11-30 15:53:58 -05:00
Thomas Harte
36edfe9715 Merge pull request #1420 from TomHarte/NewIcon
Import new icons.
2024-11-29 23:10:31 -05:00
Thomas Harte
030b54a2b6 Import new icons. 2024-11-29 23:04:28 -05:00
Thomas Harte
f332613922 Merge pull request #1419 from TomHarte/Reformatting
Begin a general reformatting.
2024-11-29 22:52:29 -05:00
Thomas Harte
088bc14b11 Begin a reformatting of components. 2024-11-29 22:43:54 -05:00
Thomas Harte
86fa8da8c5 Reformat ClockReceiver. 2024-11-29 22:12:57 -05:00
Thomas Harte
abfc73299e Update remainder of 'Analyser'. 2024-11-29 21:08:35 -05:00
Thomas Harte
bd97fd5973 Improve indentation, constness of 'Activity' and dynamic analyser. 2024-11-29 17:23:05 -05:00
Thomas Harte
f00e7c4a80 Merge pull request #1413 from TomHarte/ShakerScanTarget
Avoid taking an out-of-range pointer.
2024-10-19 10:15:30 -04:00
Thomas Harte
49c811b5f5 Avoid taking an out-of-range pointer.
(Even though it was safe)
2024-10-19 10:12:51 -04:00
Thomas Harte
b6c21e071d Update version number. 2024-10-19 09:19:59 -04:00
Thomas Harte
e68129e47e Merge pull request #1412 from TomHarte/CRTCType
Specify correct 6845; experiment with vsync.
2024-10-18 20:31:45 -04:00
Thomas Harte
72d7917415 Specify correct 6845; experiment with vsync. 2024-10-16 21:02:58 -04:00
Thomas Harte
53837fe132 Merge pull request #1411 from TomHarte/CMakeWarnings
Resolve GCC/Ubuntu CI warnings.
2024-10-15 22:25:06 -04:00
Thomas Harte
08d094c786 Use appropriate std::array semantics. 2024-10-15 22:14:29 -04:00
Thomas Harte
a1634ab496 Reduce uninitialised usages. 2024-10-15 22:10:16 -04:00
Thomas Harte
d35165bd8e Correct parameter usage. 2024-10-15 21:54:04 -04:00
Thomas Harte
b701ce9721 Shuffle construction order. 2024-10-15 21:51:23 -04:00
Thomas Harte
f3e18da416 Use custom type for deleter. 2024-10-15 21:49:42 -04:00
Thomas Harte
131ab00304 Merge pull request #1410 from TomHarte/CPCLatency
Further improve the CPC side of the CPC:CRTC relationship.
2024-10-15 21:30:39 -04:00
Thomas Harte
26d7d58a5f Add TODO. 2024-10-15 21:16:07 -04:00
Thomas Harte
02f92a7818 Handle runs that don't cross a pixel boundary.
`
2024-10-15 21:15:30 -04:00
Thomas Harte
b6fff521e4 Allow new interrupts to override the end of previous. 2024-10-15 12:27:30 -04:00
Thomas Harte
23f1308231 Experiment with reads/writes earlier in the transaction. 2024-10-15 12:10:36 -04:00
Thomas Harte
947e890c59 Adjust mode latch time, timer hsync signalling. 2024-10-15 11:53:00 -04:00
Thomas Harte
0f1714de7c Merge pull request #1409 from TomHarte/68000Constness
68000: `Const` as many arguments as possible.
2024-10-13 21:58:02 -04:00
Thomas Harte
a7d2b0f63b Const as many arguments as possible. 2024-10-13 21:40:39 -04:00
Thomas Harte
9c550a8154 Merge pull request #1408 from TomHarte/M50740ExecutorStyle
Eliminate majority of M50740 macros
2024-10-10 13:46:34 -04:00
Thomas Harte
49012a21c8 Convert index macro. 2024-10-09 21:50:03 -04:00
Thomas Harte
f136151064 Transcribe op_X macros. 2024-10-09 21:46:30 -04:00
Thomas Harte
4838728521 Eliminate nibble macros. 2024-10-09 21:04:32 -04:00
Thomas Harte
95fac5dc13 Begin macro elimination. 2024-10-09 14:27:35 -04:00
Thomas Harte
ac1f7884b5 Merge pull request #1407 from TomHarte/OptionalCPMData
Reduce costs of CPC disk analysis by not loading unused contents.
2024-10-09 14:16:53 -04:00
Thomas Harte
ab411512d4 Merge pull request #1405 from TomHarte/CRTCFixes
Redraft CRTC closer to raw logic.
2024-10-09 14:14:43 -04:00
Thomas Harte
704495ff42 Made reading of data optional. 2024-10-09 12:27:51 -04:00
Thomas Harte
9acc80260f Eliminate phases due to lack of evidence. 2024-10-09 11:59:27 -04:00
Thomas Harte
7759fb7e68 Add TODO. 2024-10-09 11:48:08 -04:00
Thomas Harte
0d71724598 Eliminate extra-scanline flag. 2024-10-09 11:45:32 -04:00
Thomas Harte
ae436f7a51 Fix conflicting usages of EOF. 2024-10-09 11:16:12 -04:00
Thomas Harte
43ac20cbd2 Fix non-interlaced frame length. 2024-10-07 21:50:56 -04:00
Thomas Harte
2d90868f5c Reinstitute cursor. 2024-10-07 21:13:44 -04:00
Thomas Harte
60987ae4a7 Round out interlaced output. 2024-10-07 20:53:41 -04:00
Thomas Harte
65c1d99120 Add, disable some logging. 2024-10-05 22:30:53 -04:00
Thomas Harte
35acf88847 Take a swing at adding an adjustment period. 2024-10-03 22:07:46 -04:00
Thomas Harte
45549b5fcd Switch CRTC type. 2024-10-03 22:07:12 -04:00
Thomas Harte
2eb9fb6a08 Add faulty attempt at adjustment period. 2024-09-30 23:47:27 -04:00
Thomas Harte
0d0e1083e6 Fix potential out-of-bounds access. 2024-09-30 13:37:44 -04:00
Thomas Harte
e650f3772a Limit vertical visibility. 2024-09-30 13:35:28 -04:00
Thomas Harte
e5ff4c65b7 Fix accidental skew, off-by-one end of line. 2024-09-30 13:20:18 -04:00
Thomas Harte
276809f76a Stabilise image, albeit incorrectly. 2024-09-30 13:16:03 -04:00
Thomas Harte
5e3840c5f1 Attempt to skirt with coherence. 2024-09-29 23:08:39 -04:00
Thomas Harte
6eace2a3ef Improve address counting. 2024-09-27 21:27:56 -04:00
Thomas Harte
7817b23857 Take a swing at vertical sync. 2024-09-27 21:14:57 -04:00
Thomas Harte
432854aeb5 Restore some form of visuals. 2024-09-26 22:08:22 -04:00
Thomas Harte
433c8f9c3c Make negligible progress. 2024-09-25 19:30:08 -04:00
Thomas Harte
ea25dbfd1e Begin CRTC rejig. 2024-09-23 21:11:54 -04:00
Thomas Harte
10f8318e79 Merge pull request #1404 from TomHarte/65816SquareD
65816: correct emulation-mode `[d], y`, `PEI` and `PLB`.
2024-09-21 21:46:00 -04:00
Thomas Harte
17ff0c4f65 Fix PLD/PLB sizes. 2024-09-21 21:28:38 -04:00
Thomas Harte
9abd653fb9 Avoid impossible clamps. 2024-09-21 21:25:49 -04:00
Thomas Harte
ff6753fcdf PEI: don't page wrap. 2024-09-21 21:12:04 -04:00
Thomas Harte
a65551f652 Give PLB the same stack behaviour as PLD. 2024-09-21 21:08:02 -04:00
Thomas Harte
f0d807a0fe Fix [d], y page-wrapping behaviour. 2024-09-21 20:49:59 -04:00
Thomas Harte
dfcdbe5b6a Merge pull request #1402 from TomHarte/CPCInterruptTiming
Pull CPC interrupt to start of hsync.
2024-09-12 21:12:02 -04:00
Thomas Harte
53e73238fd Merge pull request #1403 from TomHarte/OricVSync
Extend Oric vsync to four lines.
2024-09-12 21:08:51 -04:00
Thomas Harte
581454db69 Tweak mode latch time too. 2024-09-12 20:47:27 -04:00
Thomas Harte
63d501b629 Pull interrupt to start of hsync. 2024-09-12 20:45:28 -04:00
Thomas Harte
60bd877ed9 Merge pull request #1401 from TomHarte/OricVSync
Add the Oric's v-sync hardware hack.
2024-09-10 21:18:03 -04:00
Thomas Harte
44574465c5 Extend vsync to four lines. 2024-09-10 21:06:49 -04:00
Thomas Harte
2b7382a014 Loop in vsync as a potential tape input. 2024-09-10 20:59:05 -04:00
Thomas Harte
584b6df40d Tweak 60Hz period. 2024-09-10 20:43:01 -04:00
Thomas Harte
e55f61deb2 Add vsync getter. 2024-09-10 20:31:35 -04:00
Thomas Harte
a6c6a1c6da Eliminate macros. 2024-09-10 20:29:34 -04:00
Thomas Harte
bdb5abe47b Record updated version number. 2024-09-08 21:34:02 -04:00
Thomas Harte
dbe0ebc93e Merge pull request #1400 from TomHarte/DelegateOrderTest
Fix order of `if` tests.
2024-09-08 21:30:44 -04:00
Thomas Harte
1c2f66e855 Fix order of if tests. 2024-09-08 21:23:58 -04:00
Thomas Harte
7eee3f9e5e Merge pull request #1399 from TomHarte/ElectronULARedux
Replace Electron graphics generation with FPGA transcription.
2024-09-08 21:23:09 -04:00
Thomas Harte
b7f069e1bd Add a colour burst. 2024-09-08 21:12:45 -04:00
Thomas Harte
51c8396e32 Fix faulty centring. 2024-09-08 21:06:59 -04:00
Thomas Harte
0efe649ca5 Post pixel clock. 2024-09-08 20:57:43 -04:00
Thomas Harte
75db0018bc Add note on provenance. 2024-09-08 20:20:03 -04:00
Thomas Harte
2a9e1ea045 Use normal member naming convention. 2024-09-08 20:16:43 -04:00
Thomas Harte
8feb8aaadc Reintroduce cropping, even if faulty. 2024-09-06 22:12:19 -04:00
Thomas Harte
b8f4385501 Fix palette generation. 2024-09-06 21:47:13 -04:00
Thomas Harte
d8b6d87a1c Attempt colour. 2024-09-06 21:36:05 -04:00
Thomas Harte
f10702b3ca Edge towards proper serialisation. 2024-09-06 21:01:30 -04:00
Thomas Harte
88248d7062 Fix base address, delays. 2024-09-06 20:55:26 -04:00
Thomas Harte
5ca1659bcc Do just enough to get 1bpp fixed-palette pixels. 2024-09-06 20:36:27 -04:00
Thomas Harte
59530a12fd Sub in basic transliteration of hoglet's FPGA. 2024-09-06 20:21:46 -04:00
Thomas Harte
aab2dd68b6 Substitute in a real-time video generator. 2024-09-06 20:18:29 -04:00
Thomas Harte
83f5065642 Update version. 2024-08-26 21:38:49 -04:00
Thomas Harte
7e3a331eba Merge pull request #1394 from TomHarte/ElectronFlicker
Electron: don't miss interrupts early in the frame.
2024-08-26 21:28:53 -04:00
Thomas Harte
b5932edff3 Avoid missed interrupts on wraparound. 2024-08-26 21:13:49 -04:00
Thomas Harte
12846317cb Short-circuit non-interrupts. 2024-08-26 21:13:25 -04:00
Thomas Harte
051f0546c7 Merge pull request #1393 from TomHarte/ZXAnalysis
Improve Spectrum +3 disk analysis.
2024-08-24 21:45:45 -04:00
Thomas Harte
eece8c54a4 Factgor out and reuse is-ZX test. 2024-08-22 21:17:35 -04:00
Thomas Harte
69ba94e379 Add some CP/M smarts to +3 disk analysis. 2024-08-20 21:43:31 -04:00
Thomas Harte
0de7057d6f Use standard algorithm. 2024-08-20 20:45:43 -04:00
Thomas Harte
3dcbb40c55 Merge pull request #1391 from TomHarte/SSLandCSL
Treat second argument to key_delay as optional.
2024-08-14 19:56:18 -05:00
Thomas Harte
91b263f0cf Treat second argument as optional. 2024-08-14 20:55:33 -04:00
Thomas Harte
bcd558867d Merge pull request #1387 from TomHarte/SSLandCSL
CPC: implement CSL and SSM to run Shaker tests.
2024-08-14 19:55:18 -05:00
Thomas Harte
a9c8ef642c Correct original author's typo. 2024-08-14 18:55:35 -04:00
Thomas Harte
43887b42b1 Allow vsync on line 0. 2024-08-07 23:05:26 -04:00
Thomas Harte
30b1b36e63 Test digits individually; CSLs autolink. 2024-08-07 22:44:48 -04:00
Thomas Harte
ef11262721 Expand test membership. 2024-08-07 22:15:43 -04:00
Thomas Harte
2d049f5fdc Implement reset, correct file names. 2024-08-07 22:00:24 -04:00
Thomas Harte
05f0a122f4 Blank out border. 2024-08-05 22:06:23 -04:00
Thomas Harte
1977675a73 Add some measure of graphics output. 2024-08-05 21:48:40 -04:00
Thomas Harte
4ceaab7c26 Merge branch 'master' into SSLandCSL 2024-07-26 22:08:11 -04:00
Thomas Harte
6c33177548 Merge pull request #1389 from TomHarte/6502JAM
Correct 6502 JAM bus activity.
2024-07-26 22:07:40 -04:00
Thomas Harte
76ca607021 Add a graceful end for JAM. 2024-07-26 21:45:17 -04:00
Thomas Harte
59e1a5e5f6 Correct 6502 JAM behaviour. 2024-07-26 21:43:54 -04:00
Thomas Harte
4f55b2a554 Merge branch 'SSLandCSL' of github.com:TomHarte/CLK into SSLandCSL 2024-07-08 00:24:22 +02:00
Thomas Harte
78b2a89554 Add header for std::vector. 2024-07-08 00:20:54 +02:00
Thomas Harte
1e84a735e6 Add header for std::vector. 2024-07-08 00:18:53 +02:00
Thomas Harte
9e8801d867 Add header for std::variant. 2024-07-08 00:17:39 +02:00
Thomas Harte
0e58f7fa69 Merge branch 'master' into SSLandCSL 2024-07-05 14:54:47 -04:00
Thomas Harte
94058d498c Merge pull request #1388 from TomHarte/6502BBSBBR
Correct 65c02 BBS/BBR bus activity.
2024-07-05 14:51:31 -04:00
Thomas Harte
2621bcc005 Switch to 5/6/7 BBS/BBR timing. 2024-07-05 13:44:31 -04:00
Thomas Harte
e750866ab6 Remove phoney mid-BBR/BBS access. 2024-07-02 22:01:02 -04:00
Thomas Harte
00b3007b9f Switch byte order. 2024-07-02 21:51:00 -04:00
Thomas Harte
dbc0ecde31 Catch SSM events. 2024-06-30 21:26:16 -04:00
Thomas Harte
0e30e2d865 Add CSL side of execution. 2024-06-30 20:19:02 -04:00
Thomas Harte
ba1879ef78 Add URL credit. 2024-06-28 21:53:18 -04:00
Thomas Harte
7a145d72f9 Start Shaker test case. 2024-06-28 21:52:04 -04:00
Thomas Harte
f742266177 Add SSM code capture to CPC. 2024-06-26 21:53:11 -04:00
Thomas Harte
63737c09aa Improve handling of compound sequences. 2024-06-20 22:13:19 -04:00
Thomas Harte
09e8d4ba0a Do enough to parse sample files. 2024-06-18 22:16:23 -04:00
Thomas Harte
7d728c37ee Fix comment, both grammar and content. 2024-06-18 12:56:25 -04:00
Thomas Harte
e46b12e359 Start parsing CSL. 2024-06-16 14:27:48 -04:00
Thomas Harte
b3012bd89e Update version number. 2024-06-02 22:29:25 -04:00
Thomas Harte
f521c12d85 Merge pull request #1385 from TomHarte/VicBorders
CRT: accept data during retrace.
2024-06-02 22:18:25 -04:00
Thomas Harte
58f04848a9 Fix: allow allocations on invisible areas. 2024-06-02 21:59:27 -04:00
Thomas Harte
6488f46850 Normalise variable names. 2024-06-02 21:58:49 -04:00
Thomas Harte
5f4b798cff Clarify scope of this_state. 2024-06-01 20:05:51 -04:00
Thomas Harte
ffa8f1db04 Merge pull request #1384 from TomHarte/QtArchimedes
Add Archimedes Qt UI options.
2024-05-31 21:25:49 -04:00
Thomas Harte
cf2711f6dd Add Archimedes Qt UI options. 2024-05-31 21:17:56 -04:00
Thomas Harte
25eded1895 Merge pull request #1382 from TomHarte/QtRepair
Qt: Correct Electron target name.
2024-05-29 22:24:52 -04:00
Thomas Harte
a8ac8f4a23 Correct Electron target name. 2024-05-29 22:24:15 -04:00
Thomas Harte
c67a53e95b Merge pull request #1381 from TomHarte/MemoryOrder
Avoid `std::memory_order::memory_order_X` in favour of `std::memory_order_X`.
2024-05-29 22:01:20 -04:00
Thomas Harte
edf4ba2533 Merge pull request #1380 from TomHarte/NoPairs
Eliminate various unnecessary uses of `std::make_pair`.
2024-05-29 21:59:59 -04:00
Thomas Harte
71d337c10e Avoid std::memory_order::. 2024-05-29 21:51:07 -04:00
Thomas Harte
eb9e5fb727 Eliminate various unnecessary uses of std::make_pair. 2024-05-29 21:46:33 -04:00
Thomas Harte
f133000656 Update version number. 2024-05-27 15:05:47 -04:00
Thomas Harte
71361638bb Merge pull request #1379 from TomHarte/UnambiguousRejection
Don't move cursor near disk to folder if not about to load something.
2024-05-27 15:05:04 -04:00
Thomas Harte
edc7fe9c72 Simplify actions. 2024-05-27 14:54:09 -04:00
Thomas Harte
3110041a06 Don't seem to move near disk folder if not loading. 2024-05-27 14:45:37 -04:00
Thomas Harte
ff78e4172d Merge pull request #1378 from TomHarte/FastArchimedesDisks
Support FDC overclocking as 'fast loading'.
2024-05-26 22:19:40 -04:00
Thomas Harte
a1c23be73d Remove development dead ends. 2024-05-26 22:03:48 -04:00
Thomas Harte
eb2b1cb093 Support FDC overclocking as 'fast loading'. 2024-05-26 22:02:40 -04:00
Thomas Harte
f2245b8066 Merge pull request #1377 from TomHarte/TidySWIs
Clean up, slightly.
2024-05-26 14:43:40 -04:00
Thomas Harte
793b6d1deb Clean up, slightly. 2024-05-26 14:42:54 -04:00
Thomas Harte
537b91fa3f Merge pull request #1374 from TomHarte/SWIAnalyser
Add Archimedes autostart behaviour.
2024-05-24 16:32:45 -04:00
Thomas Harte
b7777c9ca3 Avoid linkage warning. 2024-05-24 15:39:38 -04:00
Thomas Harte
5235262855 Add default value. 2024-05-24 15:29:11 -04:00
Thomas Harte
7b90c36463 Shorten clicks, ensure no lost actions. 2024-05-24 15:23:45 -04:00
Thomas Harte
6407ab0673 Clean up, improve application-menu response. 2024-05-24 14:32:55 -04:00
Thomas Harte
78ec9e5a60 Limit character range. 2024-05-23 22:31:43 -04:00
Thomas Harte
778ac6e6d1 Complete autoload loop. 2024-05-23 22:16:40 -04:00
Thomas Harte
5280f5aba2 Attempt to spot screen takeovers. 2024-05-23 22:03:40 -04:00
Thomas Harte
67add0da93 Use both sources. 2024-05-21 22:23:53 -04:00
Thomas Harte
a32da9a6e1 Restore preference against !Boot. 2024-05-21 22:12:55 -04:00
Thomas Harte
b6b70bb7ff Add title fallbacks, ensure 'read' costs even 0.0-weight options. 2024-05-21 22:06:09 -04:00
Thomas Harte
6d769c9e89 Use string similarity as a program differentiator. 2024-05-21 21:49:30 -04:00
Thomas Harte
0c683c2c81 Merge branch 'master' into SWIAnalyser 2024-05-21 07:38:23 -04:00
Thomas Harte
8e51bd7578 Merge branch 'master' of github.com:TomHarte/CLK 2024-05-21 07:38:10 -04:00
Thomas Harte
6d6dfa4f44 Introduce Archimedes analyser tests. 2024-05-20 22:48:20 -04:00
Thomas Harte
7d044ad0ab Merge pull request #1376 from TomHarte/Remove-macos-11
Eliminate macos11 runner.
2024-05-20 16:29:02 -04:00
Thomas Harte
826f4c1d48 Eliminate macos-11.
As per GitHub's announcement that "The macOS 11 runner image will be removed by 6/28/24"
2024-05-20 14:21:42 -04:00
Thomas Harte
3be5d60b1e Eliminate comparison costs. 2024-05-18 22:16:58 -04:00
Thomas Harte
26375dc023 Introduce named constants. 2024-05-16 22:19:26 -04:00
Thomas Harte
8d0d7abd5a Keep track of state separately from scanning. 2024-05-16 22:18:51 -04:00
Thomas Harte
ef03ddf2ae Extend to launching the target program. 2024-05-14 22:23:35 -04:00
Thomas Harte
1d8b33d7ae Attempt to improve trajectory. 2024-05-13 22:26:36 -04:00
Thomas Harte
308b3ca448 Gamely attempt to pick an Arc program to start. 2024-05-13 22:25:02 -04:00
Thomas Harte
ca67afea4c Correct some unique-ptr oddities. 2024-05-13 21:46:03 -04:00
Thomas Harte
0b11fc259b Add Archimedes-specific target class. 2024-05-13 21:42:38 -04:00
Thomas Harte
18ffb9294f Add full cursor automation. 2024-05-12 22:16:29 -04:00
Thomas Harte
c82517c9fd Add mouse position getter. 2024-05-11 13:07:12 -04:00
Thomas Harte
6d42c9aaf9 Start making leeway on interesting SWIs. 2024-05-06 22:40:00 -04:00
Thomas Harte
02ee3a7804 Turf out old debugging cruft. 2024-05-06 20:36:00 -04:00
Thomas Harte
bdf1dff976 Update version number. 2024-05-04 21:16:43 -04:00
Thomas Harte
e6724a701a Merge pull request #1373 from TomHarte/DiskReady
Further adjust RDY.
2024-04-30 22:50:17 -04:00
Thomas Harte
d90eedfc8c Adjust bit polarity, meaning. 2024-04-30 22:49:26 -04:00
Thomas Harte
63009d00b4 Merge pull request #1372 from TomHarte/DiskReady
Add Archimedes disk drive RDY signal.
2024-04-30 22:38:20 -04:00
Thomas Harte
6a2261d217 Merge branch 'master' into DiskReady 2024-04-30 22:38:07 -04:00
Thomas Harte
c3ad2154b5 Merge pull request #1371 from TomHarte/Interlacing
Support Archimedes interlaced video.
2024-04-30 22:37:48 -04:00
Thomas Harte
3d61861737 Ensure switch is complete. 2024-04-30 22:26:19 -04:00
Thomas Harte
7545786436 Ensure extra line types are used. 2024-04-30 22:22:18 -04:00
Thomas Harte
a997b6c677 Wire drives for IBM-style RDY. 2024-04-30 22:18:17 -04:00
Thomas Harte
72d4f638aa Merge branch 'master' into Interlacing 2024-04-30 22:08:57 -04:00
Thomas Harte
b15ff6d442 Support interlaced video timing. 2024-04-30 22:06:08 -04:00
Thomas Harte
cb70967971 Merge pull request #1370 from TomHarte/Zarch
Add automatic runtime frame-rate limiter.
2024-04-30 22:02:06 -04:00
Thomas Harte
42aea2663c Add automatic runtime frame-rate limiter. 2024-04-30 21:38:37 -04:00
Thomas Harte
a882faa7f6 Merge pull request #1369 from TomHarte/UnmaskedSubAddresses
Mildly reduce ARM/Archimedes hot-path costs.
2024-04-29 22:58:22 -04:00
Thomas Harte
5da01e4fd8 Add potential short-circuit. 2024-04-29 22:45:30 -04:00
Thomas Harte
71c5a1d419 Avoid repeated trans comparison. 2024-04-29 22:35:01 -04:00
Thomas Harte
03c3da7338 Bifurcate Zone enum, possibly to help compiler. 2024-04-29 22:34:46 -04:00
Thomas Harte
47b276ca0b Merge pull request #1368 from TomHarte/MinorTweaks
Fix trans for instruction fetches.
2024-04-29 22:29:25 -04:00
Thomas Harte
c7747ec5a0 Remove a conditional from the hot path. 2024-04-29 22:16:06 -04:00
Thomas Harte
5a84e98256 Fix trans for instruction fetches. 2024-04-29 21:54:59 -04:00
Thomas Harte
b66d69b60c Merge pull request #1367 from TomHarte/FloppyHeft
Slightly reduce processing heft of floppy accesses.
2024-04-28 22:49:31 -04:00
Thomas Harte
dfaea5a922 Reduce floppy access cost. 2024-04-28 22:40:54 -04:00
Thomas Harte
f4da417c3a Merge pull request #1366 from TomHarte/VIDCDelays
Add various VIDC output latencies.
2024-04-28 22:39:29 -04:00
Thomas Harte
fa7fff86eb Eject invalid specialisation. 2024-04-28 22:20:26 -04:00
Thomas Harte
d480f9eae2 Reinstate all missing video modes. 2024-04-28 21:49:04 -04:00
Thomas Harte
4f1aef90b8 Relocate pixel collection and cursor shifting. 2024-04-26 21:29:30 -04:00
Thomas Harte
24f4538eb7 Do faulty restoration of 4bpp mode. 2024-04-25 22:50:24 -04:00
Thomas Harte
38d096cad6 Begin new state machine, losing all non-cursor pixels. 2024-04-25 22:01:38 -04:00
Thomas Harte
b82af9c471 Fix vertical timing; don't miss border colour changes. 2024-04-24 20:47:11 -04:00
Thomas Harte
0bff2089c4 Merge pull request #1364 from TomHarte/SomeWarnings
Resolve various warnings.
2024-04-23 19:40:43 -07:00
Thomas Harte
36d9c40d7b Yuckily avoid warning. 2024-04-23 22:23:56 -04:00
Thomas Harte
becb6ce2e0 Fix two more not-really-an-issue warnings. 2024-04-23 22:20:13 -04:00
Thomas Harte
56b65780d2 Avoid loading nonsense value upon data abort. 2024-04-22 22:09:57 -04:00
Thomas Harte
265d151879 Fix data aborts. 2024-04-22 22:08:09 -04:00
Thomas Harte
c485097eed Fix bool combination. 2024-04-22 22:06:09 -04:00
Thomas Harte
f86e9fe086 Eliminate impossible conditional. 2024-04-22 21:58:49 -04:00
Thomas Harte
c91ce4cfea Ensure all routes return. 2024-04-22 21:57:20 -04:00
Thomas Harte
8e64a854fc Ensure all routes return; mildly decrease conditionals. 2024-04-22 21:56:53 -04:00
Thomas Harte
7c9383cd6b Update version number. 2024-04-20 14:45:21 -04:00
Thomas Harte
82d03e3980 Merge pull request #1362 from TomHarte/ThreeStepPipeline
Introduce some degree of an ARM pipeline.
2024-04-19 19:41:46 -07:00
Thomas Harte
0775e3ad58 This is an 8-bit value. 2024-04-19 22:35:43 -04:00
Thomas Harte
ea3eef3817 Put interrupts into pipeline, without delay. 2024-04-19 22:21:23 -04:00
Thomas Harte
83eac172c9 Revoke in-pipeline interrupts.
I'm unclear on what timing should apply here really.
2024-04-19 21:46:09 -04:00
Thomas Harte
5b13d3e893 Attempt the prefetch portion of a pipeline. 2024-04-19 21:30:15 -04:00
Thomas Harte
807835b9fe Merge pull request #1361 from TomHarte/Pipeline
Provide hooks for implementing pipeline prefetch.
2024-04-19 06:58:45 -07:00
Thomas Harte
4bf02122ee Fix disassembler. 2024-04-18 23:17:44 -04:00
Thomas Harte
e6c4454059 Provide a means for SWI interception. 2024-04-18 22:13:58 -04:00
Thomas Harte
d464ce831a Add did_set_pc. 2024-04-18 19:30:07 -04:00
Thomas Harte
018f0e097f Merge pull request #1358 from TomHarte/ADFS-D
Ensure ADFS-D discs are recognised.
2024-04-17 23:06:49 -04:00
Thomas Harte
2acb853021 Merge pull request #1357 from TomHarte/EasyWins
Improve MEMC speed.
2024-04-17 22:47:04 -04:00
Thomas Harte
acd477df39 Ensure ADFS-D discs are recognised. 2024-04-17 22:44:55 -04:00
Thomas Harte
da520de9ef Further appease GCC. 2024-04-17 22:38:32 -04:00
Thomas Harte
e680a973b0 Appease GCC with a 'default'. 2024-04-17 22:17:24 -04:00
Thomas Harte
07984a2f8b Resolve various warnings. 2024-04-17 22:15:05 -04:00
Thomas Harte
16532136e9 Merge branch 'master' into EasyWins 2024-04-17 21:40:01 -04:00
Thomas Harte
30c2c65b77 Eliminate hot-path switch. 2024-04-17 21:36:39 -04:00
Thomas Harte
b63178132d Move trans tests inside switch. 2024-04-17 21:29:42 -04:00
Thomas Harte
6d66c90aad Merge pull request #1356 from TomHarte/ArchimedesGUI
Add macOS route to starting empty Archimedes.
2024-04-17 21:26:03 -04:00
Thomas Harte
c807c75412 Revert version change. 2024-04-17 21:25:12 -04:00
Thomas Harte
f6feaddfe6 Add macOS route to starting empty Archimedes. 2024-04-17 20:44:45 -04:00
Thomas Harte
87d1a476a4 Merge pull request #1355 from TomHarte/Archimedes
Add an inaccurate, basic Archimedes.
2024-04-16 22:45:42 -04:00
Thomas Harte
f7337f2400 Adopt 50%:50% tables throughout. 2024-04-16 22:45:01 -04:00
Thomas Harte
fac94a5d36 Reduce MIPS. Until other performance issues can be resolved. 2024-04-16 22:32:00 -04:00
Thomas Harte
140228a936 Mildly reduce heft of scale read. 2024-04-16 22:31:40 -04:00
Thomas Harte
06fd91f002 Fix period, table lookup. 2024-04-16 22:12:10 -04:00
Thomas Harte
c3d4d0ee38 Introduce panning, threading. 2024-04-16 21:56:34 -04:00
Thomas Harte
30cca54e6c Diagnostically try for a square wave. 2024-04-13 22:10:34 -04:00
Thomas Harte
6ac6e48b95 Attempt audio output. 2024-04-13 21:54:50 -04:00
Thomas Harte
779794632e Generate volume ramp. 2024-04-13 20:23:47 -04:00
Thomas Harte
88bb16f261 Install proper filter frequency. 2024-04-13 15:34:39 -04:00
Thomas Harte
c134c7bdc2 Fix: signal is 'flyback', not sync. 2024-04-10 21:53:38 -04:00
Thomas Harte
6c6cda3db5 Use clocking hints. 2024-04-09 22:22:03 -04:00
Thomas Harte
a29f246536 Move to more natural position of ownership. 2024-04-09 22:10:07 -04:00
Thomas Harte
d9d675a74f Fix scan status scale. 2024-04-09 21:56:42 -04:00
Thomas Harte
d62ea95889 Make some intimation towards audio. 2024-04-09 21:53:40 -04:00
Thomas Harte
e2e951ad0b Fix layout. 2024-04-09 21:49:35 -04:00
Thomas Harte
a5a653d684 Factor vsync state into IO reads. 2024-04-09 21:49:00 -04:00
Thomas Harte
6123350895 Improve state guesswork. 2024-04-09 21:24:08 -04:00
Thomas Harte
ec73c00c3b Silence the routine stuff of interrupt masks. 2024-04-09 20:57:57 -04:00
Thomas Harte
dd24f5f4f3 Don't latch video addresses until almost the last minute. 2024-04-09 20:56:10 -04:00
Thomas Harte
82a2e802ea Life's too short; just do it in HTML. 2024-04-08 23:11:22 -04:00
Thomas Harte
3b75eeb70a Try two divs. 2024-04-08 22:46:45 -04:00
Thomas Harte
ee4575b70f Attempt a div. 2024-04-08 22:45:41 -04:00
Thomas Harte
46a4ec1cb1 Reshuffle images. 2024-04-08 22:42:49 -04:00
Thomas Harte
8ab77a3260 Attempt to even out columns. 2024-04-08 22:39:14 -04:00
Thomas Harte
b875e349c1 Mention the Archimedes. 2024-04-08 22:34:08 -04:00
Thomas Harte
169298af42 Plumb through disk insertion.
Surprisingly: some things now load.
2024-04-08 21:15:40 -04:00
Thomas Harte
5e502df48b Forward motor and drive selection. 2024-04-07 22:29:00 -04:00
Thomas Harte
4f58664f97 Catch interrupt enables. 2024-04-07 22:08:12 -04:00
Thomas Harte
ffd298218c Tie off initial values; fix FIQ usage. 2024-04-07 21:58:16 -04:00
Thomas Harte
d2b077c573 Start wiring in a floppy controller. 2024-04-07 21:22:35 -04:00
Thomas Harte
547dc29a60 Remove done TODOs. 2024-04-07 15:53:42 -04:00
Thomas Harte
69aeca5c0e Aggregate mouse deltas where possible. 2024-04-06 21:24:21 -04:00
Thomas Harte
ed7cd4b277 Fix 8bpp output, all-modes cursor. 2024-04-06 20:58:44 -04:00
Thomas Harte
7bf831e1a6 Add missing 'override'. 2024-04-06 13:51:33 -04:00
Thomas Harte
0092cb8c36 Route enough to be able to mess around. 2024-04-06 13:44:05 -04:00
Thomas Harte
543b1c644a Wire mouse events to the relevant class. 2024-04-06 13:32:59 -04:00
Thomas Harte
cfaea7a90c Add cursor within 4bpp pixel area. 2024-04-05 22:43:10 -04:00
Thomas Harte
b821645644 Capture cursor palette, switch horizontal field. 2024-04-05 22:01:01 -04:00
Thomas Harte
2865190499 Resolve video addressing issues. 2024-04-05 21:56:31 -04:00
Thomas Harte
3f40e409c5 Reduce debugging heft. 2024-04-04 22:16:11 -04:00
Thomas Harte
002e235d90 Force RGB mode. 2024-04-04 22:02:47 -04:00
Thomas Harte
7d8a364658 Reimplement LDM and STM. 2024-04-04 21:59:18 -04:00
Thomas Harte
41c471ca52 Add a force-user-aware accessor. 2024-04-04 20:17:44 -04:00
Thomas Harte
dd127f64fe Simplify range. 2024-04-03 07:23:14 -04:00
Thomas Harte
b19dcfd6dc Take another run at shifts. 2024-04-02 21:57:46 -04:00
Thomas Harte
55369464ad Add a by-eye crop. A better answer will come. 2024-04-01 22:10:05 -04:00
Thomas Harte
609c117267 Switch to English RISC OS. 2024-04-01 21:44:42 -04:00
Thomas Harte
3b62a2fe7a Restrict video buffer to first 512kb. 2024-04-01 21:39:10 -04:00
Thomas Harte
7c9715f00c Change mind about carry behaviour. 2024-04-01 21:38:44 -04:00
Thomas Harte
7de92a9457 Slightly clean up shift code. 2024-04-01 21:24:49 -04:00
Thomas Harte
0866caf934 Flaws remain, but acknowledge that pixel rate is double. 2024-04-01 10:48:20 -04:00
Thomas Harte
914b88d115 Fix non-debug build. 2024-03-31 19:17:55 -04:00
Thomas Harte
cc122a7a68 Add an SWI count, to aid in logging. 2024-03-31 18:18:26 -04:00
Thomas Harte
31979649c6 As it continues to swell, factor out the junk. 2024-03-31 18:15:48 -04:00
Thomas Harte
335d13d06d Mildly improve logging, define a few more ROMs. 2024-03-30 21:49:21 -04:00
Thomas Harte
ec785f3a8a Add URL as comment. 2024-03-30 20:54:17 -04:00
Thomas Harte
1f83a5425e Complete list of all currently-failing SWIs.
... a lot of which are probably failing correctly, i.e. they're appropriately signalling.
2024-03-30 20:48:47 -04:00
Thomas Harte
4882d6d0f2 Start adding SWI detail. 2024-03-30 15:16:48 -04:00
Thomas Harte
722743659b Add missing space. 2024-03-29 21:52:57 -04:00
Thomas Harte
6e64a79b52 Log failed SWIs. 2024-03-29 21:31:33 -04:00
Thomas Harte
8a6bf84cff Keyboard: log more, ignore unrecognised commands. 2024-03-29 20:54:07 -04:00
Thomas Harte
a0fdd8f4eb Resolve magic constant. 2024-03-28 22:15:27 -04:00
Thomas Harte
bda1783624 Make new guess at non-byte IOC reads. 2024-03-28 22:10:49 -04:00
Thomas Harte
2a14557478 Be more disciplined about errant accesses. 2024-03-28 21:31:07 -04:00
Thomas Harte
0ddbc67b1f Switch to default CMOS RAM obtained from RISC OS itself. 2024-03-28 21:23:49 -04:00
Thomas Harte
ffb5149890 Reinstate real CMOS RAM results. 2024-03-28 14:27:07 -04:00
Thomas Harte
bb339d619f Eliminate trace test; I don't think I'm going to work it through. 2024-03-28 14:23:00 -04:00
Thomas Harte
2ed11877e8 Determine a couple of further exclusions. 2024-03-28 14:11:41 -04:00
Thomas Harte
ea6b83815b Add a further category of exclusions. 2024-03-28 14:01:37 -04:00
Thomas Harte
740b0e35d5 Completely bypass ignored tests. 2024-03-28 11:28:37 -04:00
Thomas Harte
2e7c1acb88 Add note on confusion. 2024-03-28 10:34:46 -04:00
Thomas Harte
4fcb85d132 Cleave off most remaining reasons for failure. 2024-03-28 10:32:27 -04:00
Thomas Harte
f175dcea58 Hack in some more potential debugging help. 2024-03-27 22:37:37 -04:00
Thomas Harte
c04c708a9d Trade some depth for breadth. 2024-03-27 22:37:10 -04:00
Thomas Harte
f4cf1e5313 Attempt to cleave by broad reason. 2024-03-27 22:36:37 -04:00
Thomas Harte
0e17f382a1 Capture further detail. 2024-03-27 22:36:03 -04:00
Thomas Harte
f38bca37a2 Take another run at MEMC.
I hadn't spotted that it is valid to map different logical pages to the same physical page with different protection levels.
2024-03-27 10:44:40 -04:00
Thomas Harte
166793ebe6 Reduce I2C chatter. 2024-03-26 21:54:42 -04:00
Thomas Harte
8b04d0e3ef Enhance and better-document I2C states. 2024-03-26 21:52:29 -04:00
Thomas Harte
a3931674dc Seemingly navigate I2C correctly. 2024-03-26 21:33:46 -04:00
Thomas Harte
bd4ef5ec57 Switch to acknowledgement-after. 2024-03-26 14:06:11 -04:00
Thomas Harte
3ba12630ab Quieten. 2024-03-26 12:27:37 -04:00
Thomas Harte
342d90c929 Advance CMOS/I2C to a seemingly-valid read. 2024-03-26 12:24:24 -04:00
Thomas Harte
9078fc994b Try to formalise I2C events. 2024-03-25 22:10:52 -04:00
Thomas Harte
f46af4b702 OS 3.11 seems to be able to get into BASIC. 2024-03-25 22:10:35 -04:00
Thomas Harte
b112987556 Do well enough at other colour depths. 2024-03-25 22:09:55 -04:00
Thomas Harte
fc880ac130 Double down on trans mode. 2024-03-25 21:32:56 -04:00
Thomas Harte
a2d95cb982 Shuffle notes. 2024-03-25 21:31:59 -04:00
Thomas Harte
d2776071e4 Speed up debug mode. 2024-03-25 21:31:33 -04:00
Thomas Harte
72a645ec1e Fix trans; take further crack at MEMC permissions. 2024-03-25 15:50:59 -04:00
Thomas Harte
1154ffd072 Add a 'drive in use' indicator LED. 2024-03-25 15:03:54 -04:00
Thomas Harte
8ba9708942 Hopefully resolve the mystery of the latch writes. 2024-03-25 14:54:30 -04:00
Thomas Harte
521fca6089 Expose full bus to IOC dependents; add notes. 2024-03-25 11:07:44 -04:00
Thomas Harte
ae684edbe1 Formally decode bank/offset/type. 2024-03-25 10:16:36 -04:00
Thomas Harte
fa0a9aa611 Eliminate 'has_moved_rom_'. 2024-03-24 22:36:11 -04:00
Thomas Harte
5da9e0486a Simplify control flow. 2024-03-24 22:30:26 -04:00
Thomas Harte
6980fd760c Add further heavily-manual debugging aids. 2024-03-24 22:18:30 -04:00
Thomas Harte
3549488b7a Add round-trip test for status flags. 2024-03-24 22:18:16 -04:00
Thomas Harte
c1602cc8fe The keyboard and interrupts are currently trusted. 2024-03-23 21:49:52 -04:00
Thomas Harte
189dd176de Reguess state machine, fixing startup display. 2024-03-23 21:38:35 -04:00
Thomas Harte
3cf262d1f7 Improve terminology, add more documentation. 2024-03-23 21:12:01 -04:00
Thomas Harte
ccfc389274 Quieten where now confident. 2024-03-23 21:03:06 -04:00
Thomas Harte
0e07f802ac Use BACK state; accept other ACKs at any time. 2024-03-23 21:02:35 -04:00
Thomas Harte
55f92e2411 Adjust data abort address. 2024-03-23 20:31:47 -04:00
Thomas Harte
c720f3910a Avoid implicit sign cast. 2024-03-23 20:13:25 -04:00
Thomas Harte
4215edd11b Reduce noise. 2024-03-23 20:12:56 -04:00
Thomas Harte
09a61cf1a7 Don't expect an ACK after identifying. 2024-03-23 20:12:38 -04:00
Thomas Harte
5967ad0865 Sketch out whole protocol, albeit faulty. 2024-03-23 17:08:03 -04:00
Thomas Harte
eb34c38332 Add very faulty key input. 2024-03-23 15:58:48 -04:00
Thomas Harte
5ccb18225a Provide key states to the keyboard. 2024-03-23 15:43:04 -04:00
Thomas Harte
58bbce1a15 Avoid display errors upon back-pressure. 2024-03-22 22:01:12 -04:00
Thomas Harte
9ea3e547ee Fix IRQ/FIQ return addresses. 2024-03-22 21:42:34 -04:00
Thomas Harte
fb5fdc9f10 Actually apply video divider. 2024-03-22 10:24:24 -04:00
Thomas Harte
de7b7818f4 Add 4bpp output. 2024-03-22 10:18:25 -04:00
Thomas Harte
c4e6b18294 Manage pixel buffers. 2024-03-22 10:10:13 -04:00
Thomas Harte
ae6cf69449 Move responsibility for clock division; reinstate vsync interrupt. 2024-03-22 10:01:34 -04:00
Thomas Harte
4a2dcff028 Endeavour to map colours properly. 2024-03-21 21:53:50 -04:00
Thomas Harte
aa6acec8fa Don't hoard cycles per line value. 2024-03-21 21:47:27 -04:00
Thomas Harte
4ac4da908c Reduce TODOs, do _something_ with border colour. 2024-03-21 21:40:11 -04:00
Thomas Harte
66e62857c4 Give ostensibly clean timing to the CRT. 2024-03-21 21:29:53 -04:00
Thomas Harte
bbc0d8b050 Count time in phase correctly. 2024-03-21 21:15:25 -04:00
Thomas Harte
0f8bc416d1 Make first, faulty step into displaying a field. 2024-03-21 21:10:55 -04:00
Thomas Harte
2ec235170e Finish the thought on magic constants. 2024-03-21 20:45:17 -04:00
Thomas Harte
2de1a2dd0d Install and properly clock a CRT. 2024-03-21 20:41:24 -04:00
Thomas Harte
1f49c3b113 Give sound and video somewhere to read from. 2024-03-21 20:22:20 -04:00
Thomas Harte
5c645fb3c2 Switch to a fixed output clock; retain addresses. 2024-03-21 11:51:29 -04:00
Thomas Harte
40b5227f0b Deliver all addresses to the video outputter. 2024-03-21 11:24:47 -04:00
Thomas Harte
847dba8f07 Divide input pixel rate. 2024-03-21 11:03:28 -04:00
Thomas Harte
417c6c4629 Announce changes. 2024-03-21 10:51:52 -04:00
Thomas Harte
2d6a4d490e Add dummy retrace interrupt. 2024-03-21 10:02:56 -04:00
Thomas Harte
a6ec870872 Capture more audio detail. 2024-03-21 09:47:53 -04:00
Thomas Harte
389541be6d Pipe further sound parameters; obey divider. 2024-03-20 14:43:47 -04:00
Thomas Harte
208f3e24de Audio ticks are now included. 2024-03-20 14:30:21 -04:00
Thomas Harte
f7e36a1e03 Merge branch 'Archimedes' of github.com:TomHarte/CLK into Archimedes 2024-03-20 14:27:32 -04:00
Thomas Harte
1341816791 Break apart, switching to delegates for interrupts. 2024-03-20 14:26:56 -04:00
Thomas Harte
b986add74a Break apart, switching to delegates for interrupts. 2024-03-20 14:25:20 -04:00
Thomas Harte
08673ff021 Switch to macro blocks of execution; flail around audio. 2024-03-20 11:42:37 -04:00
Thomas Harte
3a2d9c6082 Give user access to ROM; clean up a touch. 2024-03-19 20:26:17 -04:00
Thomas Harte
43a3959b8f Don't data abort on missing low ROM. 2024-03-19 15:06:01 -04:00
Thomas Harte
85a738acff Get rigorous on exception addresses. 2024-03-19 15:03:31 -04:00
Thomas Harte
17dbdce230 Eliminate SDL/scons targets for which brew is broken. 2024-03-19 14:27:46 -04:00
Thomas Harte
9d084782ae Document. 2024-03-19 12:22:19 -04:00
Thomas Harte
106937b679 Run into the shifts wall with LDR/STR. 2024-03-19 12:19:49 -04:00
Thomas Harte
623eda7162 Output branches and nops correctly. 2024-03-19 11:42:41 -04:00
Thomas Harte
2ad6bb099b Begin foray into disassembly. 2024-03-19 11:34:10 -04:00
Thomas Harte
9d858bc61b IRQ and FIQ should also store PC+4. 2024-03-18 14:08:08 -04:00
Thomas Harte
612c9ce49a Transfer logging responsibility. 2024-03-18 11:09:29 -04:00
Thomas Harte
64e025484a Adjust means of waiting out address. 2024-03-17 22:14:07 -04:00
Thomas Harte
7b1f800387 Extend I2C state machine. 2024-03-17 21:55:19 -04:00
Thomas Harte
2712d50e05 Attempt some inspection. 2024-03-16 22:02:16 -04:00
Thomas Harte
47e9279bd4 Add a target for I2C activity. 2024-03-16 15:00:23 -04:00
Thomas Harte
635efd0212 Clear keyboard interrupts. 2024-03-15 23:19:26 -04:00
Thomas Harte
1c1d2891c7 Adjust IRQ/FIQ return addresses. 2024-03-15 21:59:38 -04:00
Thomas Harte
1979d2e5ba Don't set interrupt flags before capture. 2024-03-15 21:34:39 -04:00
Thomas Harte
c25d0e8843 Correctly capture mode upon exception. 2024-03-15 18:39:56 -04:00
Thomas Harte
3a899ea4be Add test coverage for STM descending, proving nothing. 2024-03-15 14:55:17 -04:00
Thomas Harte
9d08282e28 Add enough of a keyboard to respond to reset. 2024-03-15 10:57:18 -04:00
Thomas Harte
18154278d1 Add minor note on where next. 2024-03-14 21:54:20 -04:00
Thomas Harte
9063852857 Undo spurious text change. 2024-03-14 21:16:38 -04:00
Thomas Harte
bc27e3998d Fix downward block data transfers. 2024-03-14 21:09:51 -04:00
Thomas Harte
19fa0b8945 Shush logging, momentarily. 2024-03-14 10:53:38 -04:00
Thomas Harte
4987bdfec9 Throw less. 2024-03-14 10:43:51 -04:00
Thomas Harte
0e4615564d Make bit masks easily testable; expand logging. 2024-03-13 14:31:26 -04:00
Thomas Harte
7aeea535a1 Reduce branchiness. 2024-03-13 11:02:52 -04:00
Thomas Harte
6b18d775ab Eliminate unused variables. 2024-03-12 21:53:26 -04:00
Thomas Harte
2ed031e440 Prepare for additional devices. 2024-03-12 21:23:22 -04:00
Thomas Harte
5d6bb11eb7 Add return. 2024-03-12 11:37:15 -04:00
Thomas Harte
c6b91559e1 Attempt to wire up timer interrupts. 2024-03-12 11:34:31 -04:00
Thomas Harte
6efc41ded7 Come to conclusion on R15; fix link values. 2024-03-12 10:42:09 -04:00
Thomas Harte
e9c5582fe1 Add note on ambiguity to be resolved. 2024-03-12 10:04:02 -04:00
Thomas Harte
8b3c0abe93 Take another swing at R15 as a destination. 2024-03-12 09:13:05 -04:00
Thomas Harte
a5ebac1b29 Add RISC OS 3.11 to catalogue, while bug hunting. 2024-03-11 22:19:14 -04:00
Thomas Harte
1ccfae885c Remove extra slashes. 2024-03-11 15:06:17 -04:00
Thomas Harte
971bfb2ecb Unify subtractions. 2024-03-11 14:52:48 -04:00
Thomas Harte
e7457461ba Reduce magic constants. 2024-03-11 14:49:03 -04:00
Thomas Harte
e8c1e8fd3f Fix RSB carry; unify set_pc. 2024-03-11 14:48:43 -04:00
Thomas Harte
ca779bc841 Expand test set. 2024-03-11 14:48:18 -04:00
Thomas Harte
a28c97c0de Simplify privilege test. 2024-03-11 12:14:00 -04:00
Thomas Harte
db49146efe Figure out what's going on with TEQ. 2024-03-11 09:51:09 -04:00
Thomas Harte
830d70d3aa Trust tests on immediate-opcode ROR 0; limit shift by register. 2024-03-10 23:38:31 -04:00
Thomas Harte
336292bc49 Further correct R15 as a destination. 2024-03-10 22:56:02 -04:00
Thomas Harte
bd62228cc6 The test set doesn't seem to do word rotation. 2024-03-10 22:40:37 -04:00
Thomas Harte
ccdd340c9a Reads also may or may not be aligned. *sigh* 2024-03-10 22:34:56 -04:00
Thomas Harte
0b42f5fb30 Make further test-set allowances. 2024-03-10 22:29:40 -04:00
Thomas Harte
e9e1db7a05 Change LDR writeback to destination. 2024-03-10 22:29:19 -04:00
Thomas Harte
21278d028c Correct unaligned accesses. 2024-03-10 21:56:19 -04:00
Thomas Harte
fbc273f114 Add invented model for tests. 2024-03-10 21:45:56 -04:00
Thomas Harte
06a5df029d Summarise failures. 2024-03-10 16:56:39 -04:00
Thomas Harte
e17700b495 Permit digression for 03110002, temporarily. 2024-03-10 14:47:02 -04:00
Thomas Harte
655b1e516c Test PSR and PC. 2024-03-10 14:14:18 -04:00
Thomas Harte
4e7a63f792 Do a de minimis checking of memory accesses. 2024-03-09 15:18:35 -05:00
Thomas Harte
a2896b9bd0 Test register values. 2024-03-09 15:11:12 -05:00
Thomas Harte
a4cf86268e Provide full access to stored registers. 2024-03-09 15:11:04 -05:00
Thomas Harte
d059e7c5d8 Disallow copying. 2024-03-09 15:10:55 -05:00
Thomas Harte
d6f882a8bb Integrate PC and PSR, guarantee invisible register values. 2024-03-09 14:59:44 -05:00
Thomas Harte
08f50f3eff Box in flags. 2024-03-08 23:01:29 -05:00
Thomas Harte
47f7340dfc Start hacking in some ARM tests. 2024-03-08 22:54:42 -05:00
Thomas Harte
fdef8901ab Double down on uint32_t. 2024-03-08 14:13:34 -05:00
Thomas Harte
ca1c3dc005 Add extra comments.
To persuade myself in the future.
2024-03-08 11:36:17 -05:00
Thomas Harte
9406a97141 Add some register switch tests. 2024-03-08 11:34:10 -05:00
Thomas Harte
a46ec4cffb Up clock rate to 24Mhz. 2024-03-07 22:16:58 -05:00
Thomas Harte
9bb5dc3c2b Fix inclusive range. 2024-03-07 19:40:34 -05:00
Thomas Harte
f6ea442606 Include various debugging detritus. 2024-03-07 14:28:39 -05:00
Thomas Harte
fa8fcd2218 Take another swing at popcount. 2024-03-07 14:28:31 -05:00
Thomas Harte
2a36d0fcbc Adjust user-mode test. 2024-03-07 14:00:38 -05:00
Thomas Harte
0e92885ed5 Fix ad hoc popcount; ARM does carry 'backwards'. 2024-03-07 13:27:41 -05:00
Thomas Harte
f5225b69e5 Add note to self. 2024-03-07 11:48:44 -05:00
Thomas Harte
15ee84b2eb Fix MUL ambiguity. 2024-03-07 11:45:39 -05:00
Thomas Harte
d380cecdb7 Add timers that count. 2024-03-07 11:39:26 -05:00
Thomas Harte
ae3cd924e8 Add a 2Mhz tick for timers. 2024-03-07 11:12:40 -05:00
Thomas Harte
a0f0f73bde Fix MOV as unconditional branch. 2024-03-07 10:31:26 -05:00
Thomas Harte
7cdceb7b4f Add a specific shout-out on prefetch abort, for debugging. 2024-03-07 10:23:46 -05:00
Thomas Harte
38b5624639 Add a little more VIDC detail. 2024-03-07 10:05:22 -05:00
Thomas Harte
3405b3b287 Add power-on bit, moving problems forward. 2024-03-06 22:14:56 -05:00
Thomas Harte
173fc9329a Add a little protection logic. 2024-03-06 22:00:34 -05:00
Thomas Harte
691a42d81e Attempt some logical mapping. 2024-03-06 21:51:19 -05:00
Thomas Harte
4059905f85 Slightly reorder messaging. 2024-03-06 16:45:17 -05:00
Thomas Harte
bbb520fd12 Transcribe some notes. 2024-03-06 15:31:07 -05:00
Thomas Harte
108a056f1c Execution now runs into a prefetch abort loop. 2024-03-06 15:05:24 -05:00
Thomas Harte
ed92e98ca2 Start looking at address translation. 2024-03-06 14:56:06 -05:00
Thomas Harte
0d666f9935 Get a bit more rigorous about reporting. 2024-03-06 09:54:39 -05:00
Thomas Harte
fe467be124 Further stick to existing type. 2024-03-05 10:56:09 -05:00
Thomas Harte
ba5f142515 Take further stab at TEQ PC, etc. 2024-03-05 10:55:44 -05:00
Thomas Harte
ed586e80bc Don't write to the PC with logical operations. 2024-03-05 09:32:35 -05:00
Thomas Harte
871c5467d7 Avoid sign change. 2024-03-05 09:31:42 -05:00
Thomas Harte
387791635e Start to establish a memory map. 2024-03-04 21:43:06 -05:00
Thomas Harte
b7a1363add Add an incorrect execution loop. 2024-03-04 21:09:24 -05:00
Thomas Harte
341b705bef Remove pointless check. 2024-03-04 14:11:44 -05:00
Thomas Harte
0b65aa39cd Add explicit assignment operator. 2024-03-04 14:09:53 -05:00
Thomas Harte
1b7c3644f4 Eliinate meaningless 'const'. 2024-03-04 14:09:27 -05:00
Thomas Harte
0cdca12e06 Resolve type mismatches. 2024-03-04 13:53:46 -05:00
Thomas Harte
61d4c69e45 Fix template parameter reference. 2024-03-04 13:25:40 -05:00
Thomas Harte
79865e295b Avoid ambiguous template parameter; use standard type. 2024-03-04 12:20:40 -05:00
Thomas Harte
1f43047de8 Loop the ARM executor into the build. 2024-03-04 12:08:46 -05:00
Thomas Harte
6f0ad0ab71 Add an empty Archimedes shell. 2024-03-04 12:06:43 -05:00
Thomas Harte
447734b1e9 Merge pull request #1354 from TomHarte/Acorn
Reorganise 'Electron' under 'Acorn'.
2024-03-04 11:55:56 -05:00
Thomas Harte
3e80651a0e Collect 'Electron' under 'Acorn'. 2024-03-04 11:31:25 -05:00
Thomas Harte
692a9da2e4 Merge pull request #1353 from TomHarte/ArchmidesAnalysis
Add a through path for Archimedes disk images.
2024-03-04 10:57:19 -05:00
Thomas Harte
e27312c980 Add to machine lists. 2024-03-04 10:19:06 -05:00
Thomas Harte
eae92a0cdb Add a through path for Archimedes disk images. 2024-03-04 10:13:57 -05:00
Thomas Harte
95cc34ba23 Merge pull request #1352 from TomHarte/ByeByeActive
Obscure storage for active registers.
2024-03-03 22:09:34 -05:00
Thomas Harte
7532b461cd Merge pull request #1351 from TomHarte/PositiveExpression
Express offset test as positive logic.
2024-03-03 22:03:37 -05:00
Thomas Harte
230e9c6327 Obscure active. 2024-03-03 21:43:30 -05:00
Thomas Harte
11c4d2f09e Add further exposition. 2024-03-03 21:38:27 -05:00
Thomas Harte
f2db1b4aae Merge branch 'TiedDown' into PositiveExpression 2024-03-03 21:31:26 -05:00
Thomas Harte
b42a6e447d Tie down more corners. 2024-03-03 21:29:53 -05:00
Thomas Harte
8a83d71560 Fix condition. 2024-03-03 14:40:05 -05:00
Thomas Harte
9fd7d5c10f Switch test and meaning. 2024-03-03 14:34:21 -05:00
Thomas Harte
7a5ed6c427 Merge pull request #1350 from TomHarte/ArchimedesROM
Add RISC OS catalogue entry; do some basic ARM debugging.
2024-03-03 14:32:25 -05:00
Thomas Harte
4e7963ee81 Clarify PC semantics; remove faulty underscore. 2024-03-03 14:11:02 -05:00
Thomas Harte
945b7e90da Add just enough to persuade self that execution is broadly sane. 2024-03-03 14:03:08 -05:00
Thomas Harte
99f0233b76 Fix immediate offset and data processing operation. 2024-03-02 23:27:37 -05:00
Thomas Harte
62da0dee7f Unify reads. 2024-03-02 23:15:17 -05:00
Thomas Harte
1663d3d9d1 Introduce disaster of an attempted test run. 2024-03-02 22:40:12 -05:00
Thomas Harte
37499d493a Fix model name. 2024-03-02 21:47:09 -05:00
Thomas Harte
c0dd96eb7c Add a catalogue entry for RISC OS. 2024-03-02 21:44:27 -05:00
Thomas Harte
2abae4c8bf Merge pull request #1349 from TomHarte/BarrelShifterTests
Introduce barrel-shifter tests.
2024-03-02 15:24:06 -05:00
Thomas Harte
c865da67e0 Introduce further barrel-shifter tests. 2024-03-02 15:12:03 -05:00
Thomas Harte
e6f77a9b80 Add logical right-shift tests. 2024-03-01 18:06:54 -05:00
Thomas Harte
7b28b3d634 Merge pull request #1343 from TomHarte/ARM2Ops
Attempt an implementation of the ARM2 instruction set.
2024-03-01 15:20:28 -05:00
Thomas Harte
42ba6d1281 Relocate execution code appropriately. 2024-03-01 15:02:47 -05:00
Thomas Harte
85b7afd530 Attempt a complete block data transfer. 2024-03-01 14:48:36 -05:00
Thomas Harte
f2f59a4de5 Attempt to deal with data aborts. 2024-03-01 10:38:08 -05:00
Thomas Harte
5759798ad7 Deal with downward write order. 2024-02-29 14:34:20 -05:00
Thomas Harte
ab1dd7f57e Implement a little of block data transfer. 2024-02-29 11:33:40 -05:00
Thomas Harte
53a2ea3a57 Add address exception. 2024-02-29 10:49:11 -05:00
Thomas Harte
1f1e7236be Add rotation. 2024-02-29 10:47:41 -05:00
Thomas Harte
fd2c5b6679 Make a quick first attempt at memory accesses. 2024-02-29 10:18:09 -05:00
Thomas Harte
0b287c55d5 Edge towards single data transfer. 2024-02-29 10:02:57 -05:00
Thomas Harte
0de8240238 Merge branch 'master' into ARM2Ops 2024-02-28 22:21:31 -05:00
Thomas Harte
1449b2a2a6 Merge pull request #1347 from TomHarte/AppleIIFlashRate
Double Apple II flash rate.
2024-02-28 22:21:05 -05:00
Thomas Harte
0f691766ee Double flash rate. 2024-02-28 22:13:22 -05:00
Thomas Harte
3ce05e9de1 Merge pull request #1346 from TomHarte/AppleIIReset
Propagate reset to the auxiliary switches.
2024-02-28 22:02:08 -05:00
Thomas Harte
98f5d0cdb7 Propagate reset to the auxiliary switches. 2024-02-28 21:36:55 -05:00
Thomas Harte
93b4008f81 Localise flags, detect improper carry write. 2024-02-28 21:28:19 -05:00
Thomas Harte
904462b881 Regularise data transfers. 2024-02-28 21:23:57 -05:00
Thomas Harte
3b320bcdef Update coprocessor interface. 2024-02-28 14:43:31 -05:00
Thomas Harte
3368bdb99f Document exceptions, partly for my future self. 2024-02-28 14:34:31 -05:00
Thomas Harte
4d400c3cb7 Add easy exceptions. 2024-02-28 14:25:12 -05:00
Thomas Harte
474f9da3c2 Add banked registers. 2024-02-28 14:09:05 -05:00
Thomas Harte
c49b26701f Relocate and clarify barrel shifts.
With a view to independent testing.
2024-02-28 13:53:13 -05:00
Thomas Harte
9b42d35d56 Update interface. 2024-02-28 11:42:33 -05:00
Thomas Harte
645152a1fd Implement branch. 2024-02-28 11:33:28 -05:00
Thomas Harte
487ade56ed Add basic multiply. 2024-02-28 11:27:27 -05:00
Thomas Harte
60d1b36e9a Implement registers side. 2024-02-28 10:25:14 -05:00
Thomas Harte
5a48c15e46 Add scheduler side of PC writeback. 2024-02-28 10:15:23 -05:00
Thomas Harte
d6bf1808f9 Take a swing at PC-as-input. 2024-02-28 09:33:05 -05:00
Thomas Harte
b676153d21 State intention to merge status with other registers. 2024-02-27 15:36:34 -05:00
Thomas Harte
a3339cf882 Fix indentation. 2024-02-27 15:30:51 -05:00
Thomas Harte
b4e0b46bac Add notes on R15. 2024-02-27 10:04:30 -05:00
Thomas Harte
09c1b2d7db Add missing shifts. 2024-02-27 09:55:24 -05:00
Thomas Harte
4255283e33 Deal with conditionality up front. 2024-02-26 21:36:23 -05:00
Thomas Harte
16e827bb2c Add basic arithmetics. 2024-02-26 21:27:58 -05:00
Thomas Harte
def69ce6d5 Add notes on R15. 2024-02-26 15:12:39 -05:00
Thomas Harte
054a799699 Fill in the easy 50% of operations. 2024-02-26 15:10:00 -05:00
Thomas Harte
580f402bb6 Muddle further towards data processing. 2024-02-26 14:50:45 -05:00
Thomas Harte
030dda34f0 Start poking at implementation. 2024-02-26 14:30:26 -05:00
Thomas Harte
cd21b39f44 Merge pull request #1342 from TomHarte/ARM2Status
Add some degree of ARM 2 status flags.
2024-02-26 10:48:24 -05:00
Thomas Harte
481b6d0e69 Sketch out some status flags. 2024-02-25 22:01:51 -05:00
Thomas Harte
a88d41bf00 List the flags. 2024-02-25 15:21:54 -05:00
Thomas Harte
0ee3b628e8 Merge pull request #1341 from TomHarte/AYEnvelopePeriod
Correct envelope period for internal double-resolution.
2024-02-24 15:38:17 -05:00
Thomas Harte
45628ba9df Merge pull request #1337 from TomHarte/ArchimedesADFs
Add some support for Archimedes ADF files.
2024-02-24 15:32:08 -05:00
Thomas Harte
c843c395ea Correct envelope period for internal double-resolution. 2024-02-24 15:16:33 -05:00
Thomas Harte
9bdaf31d04 Add missing #include. 2024-02-24 15:09:40 -05:00
Thomas Harte
4ac2baeb9d Merge pull request #1340 from ryandesign/patch-1
Mention Macintosh 128K and 512K in README.
2024-02-24 15:08:16 -05:00
Thomas Harte
c56e82207a Extend .ADF support as far as my knowledge currently goes. 2024-02-24 15:07:45 -05:00
Thomas Harte
82abebec6e Add missing #include. 2024-02-23 16:13:26 -05:00
Ryan Carsten Schmidt
60286c3a15 Mention Macintosh 128K and 512K in README. 2024-02-23 06:32:15 -06:00
Thomas Harte
8460fe2118 Flounder around file contents. 2024-02-22 22:19:19 -05:00
Thomas Harte
4b5456c9ba Add Hugo/Nick checks. 2024-02-22 22:19:10 -05:00
Thomas Harte
ddf136556d Add an Archimedes enum, start looking at analysis. 2024-02-22 13:51:44 -05:00
Thomas Harte
4c45f4468e Merge pull request #1335 from TomHarte/ARMDecoding
Add ARM2 operation mapper.
2024-02-22 11:44:03 -05:00
Thomas Harte
73d2acca12 Moderately improve comments. 2024-02-22 11:20:22 -05:00
Thomas Harte
56a5df3783 Do the least possible manual test. 2024-02-22 10:48:19 -05:00
Thomas Harte
d205e538e1 Accept the C++ I'm in; clarify and simplify interface. 2024-02-22 10:16:54 -05:00
Thomas Harte
f9cbec668b Add empty shell for tests. 2024-02-21 15:43:24 -05:00
Thomas Harte
6577f68efc Complete instruction set; consolidate mapper. 2024-02-21 15:32:27 -05:00
Thomas Harte
e986ae2878 Add coprocessor data operations and register transfers. 2024-02-21 15:25:57 -05:00
Thomas Harte
b2696450d5 Bring forwards single data transfers. 2024-02-21 14:51:51 -05:00
Thomas Harte
2bbaf73aa2 Delete was is now duplicated. 2024-02-21 14:18:41 -05:00
Thomas Harte
0fe2c1406b Start mutating towards a form that owns the switch. 2024-02-21 14:17:01 -05:00
Thomas Harte
954d920b9e Extend what's held in the operation enum. 2024-02-20 14:14:18 -05:00
Thomas Harte
57b45076c5 Start dealing with per-instruction fields. 2024-02-17 22:13:51 -05:00
Thomas Harte
d639dc8bcb Hit up some more = default opportunities. 2024-02-17 15:42:31 -05:00
Thomas Harte
9a74ab6a8e Switch to actual mnenomics, temporarily(?) shrink table. 2024-02-17 15:41:57 -05:00
Thomas Harte
4c53414cc3 Merge branch 'master' into ARMDecoding 2024-02-17 08:14:18 -05:00
Thomas Harte
c36288dd6b Merge pull request #1334 from TomHarte/EqualsDefault
Switch to `= default`.
2024-02-17 08:13:53 -05:00
Thomas Harte
bc5727af14 Switch to = default. 2024-02-16 21:50:15 -05:00
Thomas Harte
bd0a15c054 Start working on ARM2 decoding. 2024-02-16 21:36:07 -05:00
Thomas Harte
a758112084 Merge pull request #1333 from TomHarte/DeferredSwitches
Apple II: Apply deferred video actions before getting vapour value.
2024-02-16 10:08:23 -05:00
Thomas Harte
3981f3a874 Merge branch 'master' into DeferredSwitches 2024-02-16 09:19:54 -05:00
Thomas Harte
e8036127fe Add some commentary. 2024-02-16 09:19:22 -05:00
Thomas Harte
17abd87791 Remove further !!s. 2024-02-16 08:57:43 -05:00
Thomas Harte
35545451fe Apply applicable deferred actions before lookahead. 2024-02-16 08:56:01 -05:00
Thomas Harte
64bec0cc3d Merge pull request #1332 from TomHarte/NoPrintf
Trim some printfs.
2024-02-15 21:18:43 -05:00
Thomas Harte
fadd3bc6fc Eliminate 'unused' error. 2024-02-15 13:57:11 -05:00
Thomas Harte
d9ec11c62e Use logger instead of printf. 2024-02-15 13:55:46 -05:00
Thomas Harte
093a029b8c Further reduce printf footprint. 2024-02-15 13:41:35 -05:00
Thomas Harte
b4a3b23571 Eliminate use of printf. 2024-02-15 13:32:49 -05:00
Thomas Harte
be99183f1d Remove outdated TODO. 2024-02-15 13:26:03 -05:00
Thomas Harte
dda5f41487 Merge pull request #1331 from TomHarte/IODeviceSel 2024-02-15 11:16:15 -05:00
Thomas Harte
a09457dab5 Fix IOSEL and DEVSEL assignments. 2024-02-15 10:29:30 -05:00
Thomas Harte
ac171d166e Merge pull request #1321 from TomHarte/Mockingboard
Add Mockingboard support to the Apple II.
2024-02-15 10:24:39 -05:00
Thomas Harte
51de1892c0 With minor infrastructure fixes, switch Mockingboard to stereo. 2024-02-15 09:42:33 -05:00
Thomas Harte
e1fdda928a Add Mockingboard to Qt UI. 2024-02-15 09:13:17 -05:00
Thomas Harte
1c8261dc09 Add Mockingboard to macOS UI. 2024-02-15 09:10:19 -05:00
Thomas Harte
cb22278c7f Switch meaning of bit 2. 2024-02-15 08:54:52 -05:00
Thomas Harte
809bc9d6a8 Add TODO. 2024-02-14 22:46:57 -05:00
Thomas Harte
be11f31d5d Support reset. 2024-02-14 22:22:42 -05:00
Thomas Harte
0103761b7b Corrects AY audio tone. 2024-02-14 22:16:37 -05:00
Thomas Harte
3ac5fdafab Enables AY audio, albeit underclocked. 2024-02-14 22:15:21 -05:00
Thomas Harte
1e877c7563 Add a clock to the 6522s, enable interrupts. 2024-02-14 22:01:03 -05:00
Thomas Harte
07c11e8268 Begin 6522 wiring. 2024-02-14 15:18:19 -05:00
Thomas Harte
0dcceff410 There's actually two AYs. 2024-02-14 14:31:38 -05:00
Thomas Harte
2a684ab302 Include a single AY in the mix if appropriate. 2024-02-14 10:55:53 -05:00
Thomas Harte
27059233b3 Use sample source to simplify stretching AY. 2024-02-13 22:38:18 -05:00
Thomas Harte
7f84d5ac6f Merge branch 'master' into Mockingboard 2024-02-13 14:46:59 -05:00
Thomas Harte
d43f050922 Merge pull request #1330 from TomHarte/SampleProducingAY
Convert AY to a SampleSource.
2024-02-13 14:45:31 -05:00
Thomas Harte
3ba2618547 Fix formatting, add comment. 2024-02-13 13:48:31 -05:00
Thomas Harte
a3e104f8e2 Clean up commentary. 2024-02-13 13:46:27 -05:00
Thomas Harte
1bb82189e9 Add better exposition. 2024-02-13 10:57:22 -05:00
Thomas Harte
e06a66644c Eliminate a macro. 2024-02-13 10:54:53 -05:00
Thomas Harte
6dcc13921f Make first sweep at converting AY to a SampleSource. 2024-02-13 10:51:33 -05:00
Thomas Harte
fd45745600 Merge pull request #1328 from TomHarte/PerSampleAudio
Improve SampleSource infrastructure.
2024-02-12 16:38:01 -05:00
Thomas Harte
507c3da927 Sometimes avoid unnecessary zero-fills. 2024-02-12 14:33:55 -05:00
Thomas Harte
f14e45f93e Remove various instances of ';;'. 2024-02-12 14:23:54 -05:00
Thomas Harte
3d2d9ac45e Remove default set_sample_volume_range implementation too. 2024-02-12 14:00:08 -05:00
Thomas Harte
1895b4ee5d Remove empty implementation, the better for debugging. 2024-02-12 13:59:03 -05:00
Thomas Harte
d49c07687c Unify [get_/skip_]samples, adding a third option for in-place mixing. 2024-02-12 10:55:52 -05:00
Thomas Harte
3a208460e2 Reintroduce mono to stereo conversion. 2024-02-10 21:53:12 -05:00
Thomas Harte
472297e411 Merge pull request #1324 from ryandesign/cmake
Add CMake build system
2024-02-09 14:36:00 -05:00
Thomas Harte
25085cb5af Require good ordering. 2024-02-09 14:34:59 -05:00
Thomas Harte
9909146c59 Fix typo. 2024-02-09 14:26:02 -05:00
Thomas Harte
609d81d75d Distinguish sources of samples and of whole buffers. 2024-02-09 14:25:40 -05:00
Thomas Harte
c105acf1c7 Adopt a full type for stereo samples, gaining + and +=. 2024-02-09 10:48:42 -05:00
Thomas Harte
f3d0827d14 Introduce [Mono/Stereo]Sample types. 2024-02-09 09:15:48 -05:00
Thomas Harte
a4a983eb81 Promote stereo status to template parameter. 2024-02-08 15:21:47 -05:00
Thomas Harte
48be7c677e Avoid inheritance. 2024-02-08 12:07:12 -05:00
Thomas Harte
147d817977 Use fold expression for final-answer is_stereo. 2024-02-08 11:10:08 -05:00
Thomas Harte
d481f335b8 Switch to another std::fill. 2024-02-08 10:47:05 -05:00
Thomas Harte
228012cd0c Make a further deployment of std::fill. 2024-02-01 22:03:13 -05:00
Thomas Harte
f4d8c04f3c Without yet much exposition, draft sample-by-sample interface. 2024-02-01 21:56:33 -05:00
Thomas Harte
c6c9be0b08 Adopt CRTP for SampleSource. 2024-02-01 21:47:44 -05:00
Thomas Harte
3827929a15 Merge branch 'master' into PerSampleAudio 2024-02-01 21:33:25 -05:00
Thomas Harte
ca7e4b3a0e Merge pull request #1327 from ryandesign/macos-ci
Update CI to build on macOS 11, 12, 13, and 14.
2024-02-01 21:33:11 -05:00
Thomas Harte
fd73c24fc3 Use std::fill; update volume with slider. 2024-02-01 21:32:16 -05:00
Thomas Harte
ce0d53b277 Clean up SampleSource's getters. 2024-02-01 21:29:00 -05:00
Ryan Carsten Schmidt
7dc3b5ba06 Update CI to build on macOS 11, 12, 13, and 14. 2024-01-31 06:27:11 -06:00
Thomas Harte
17cad73177 Attempt an implementation of StretchedAudioSource. 2024-01-29 16:45:20 -05:00
Thomas Harte
b28e3eb419 Merge pull request #1326 from ryandesign/MacDown
Compatibility fixes in Markdown files.
2024-01-28 17:35:41 -05:00
Ryan Carsten Schmidt
d811501421 Compatibility fixes in Markdown files.
Improve compatibility with some Markdown readers like MacDown by adding
blank lines before lists. Blank lines around headers were added for
consistency. One header level was fixed. One code block was fixed.
2024-01-27 13:24:35 -06:00
Thomas Harte
c68dd50fde Merge pull request #1323 from ryandesign/BUILD.md
Rename BUILD.txt to BUILD.md and rewrite
2024-01-25 20:38:12 -05:00
Ryan Carsten Schmidt
ad8abf2e05 Add CMake SDL builds to CI workflow. 2024-01-25 10:15:11 -06:00
Ryan Carsten Schmidt
01d9455897 Exclude *AllRAM*.cpp from CMake program sources.
These files serve as documentation and are used in tests.
2024-01-25 10:15:11 -06:00
Ryan Carsten Schmidt
cbf8849004 Add CMake build system, initially for SDL version.
See #1275
2024-01-25 10:15:05 -06:00
Ryan Carsten Schmidt
f3a7d82dc1 Update build instructions with more specifics.
Mention macOS version requirement; see #1179.
2024-01-25 09:10:36 -06:00
Ryan Carsten Schmidt
017674de35 Rename BUILD.txt to BUILD.md. 2024-01-25 08:52:06 -06:00
Thomas Harte
4f211334b5 Merge pull request #1322 from ryandesign/cstring
Add missing include of cstring for memcpy.
2024-01-24 20:53:57 -05:00
Ryan Carsten Schmidt
31e261f7e5 Add missing include of cstring for memcpy. 2024-01-24 09:00:10 -06:00
Thomas Harte
15b5a62e01 Mockingboard: start sketching out intermediate clocking. 2024-01-23 22:05:30 -05:00
Thomas Harte
f5800aa004 Merge pull request #1320 from TomHarte/MoreTemplateElimination
Apply more macro elimination.
2024-01-22 21:46:19 -05:00
Thomas Harte
584aa78695 Avoid macro. 2024-01-22 21:37:04 -05:00
Thomas Harte
030f49db83 Eliminate macro. 2024-01-22 21:33:39 -05:00
Thomas Harte
cc165b65be Switch to lambda. 2024-01-22 21:22:56 -05:00
Thomas Harte
cb125e6336 Use constexpr functions rather than macros. 2024-01-22 21:17:00 -05:00
Thomas Harte
a3337ea90f Remove macro. 2024-01-22 21:15:44 -05:00
Thomas Harte
ae31f85f0c Eliminate macro. 2024-01-22 21:11:15 -05:00
Thomas Harte
5e9f484662 Avoid macro. 2024-01-22 21:09:13 -05:00
Thomas Harte
f2e29357bf Merge pull request #1318 from TomHarte/MorePragmas
Switch trailing files to #pragma once.
2024-01-22 14:00:51 -05:00
Thomas Harte
8a1a14ba4c Switch trailing files to #pragma once. 2024-01-21 21:49:59 -05:00
Thomas Harte
31cbcb206f Commit new version number. 2024-01-21 21:25:27 -05:00
Thomas Harte
bf9e913a7b Merge pull request #1317 from TomHarte/IIgsIncludes
Add missing include of cstdint.
2024-01-21 21:24:43 -05:00
Thomas Harte
d3cea4a10f Note that arguments may be unused. 2024-01-21 21:19:51 -05:00
Thomas Harte
a6df20ff84 Eliminate printf. 2024-01-21 21:19:38 -05:00
Thomas Harte
7122a9ee16 Add missing include of cstdint. 2024-01-21 21:08:04 -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
497ae935d6 Bump version number. 2023-12-26 10:43:47 -05:00
Thomas Harte
acee513cd3 Merge pull request #1287 from TomHarte/ResettingKeyboard
Treat XT keyboard reset as a continuing state.
2023-12-25 19:01:41 -05:00
Thomas Harte
14e9ae014c Remove caveman log. 2023-12-25 18:44:11 -05:00
Thomas Harte
16b646ad2e Treat reset as a continuing state. 2023-12-25 18:43:35 -05:00
Thomas Harte
35f000f93c Merge pull request #1286 from TomHarte/CMOSRAM
Adds RAM to the PC RTC.
2023-12-25 15:06:28 -05:00
Thomas Harte
fc9bea5b32 Iterate forwards. 2023-12-25 14:58:01 -05:00
Thomas Harte
0537e59486 Add RAM. 2023-12-25 14:35:24 -05:00
Thomas Harte
a15d4610f7 Merge pull request #1285 from TomHarte/24HourRTC
Default to 24-hour mode.
2023-12-24 18:11:40 -05:00
Thomas Harte
f58ab0d00d Default to 24-hour mode. 2023-12-24 17:37:52 -05:00
Thomas Harte
e0a07ad22f Merge pull request #1284 from TomHarte/SomeWarnings
Resolve outstanding x86-related warnings.
2023-12-24 15:48:17 -05:00
Thomas Harte
795529ef97 Resolve sizing types. 2023-12-24 14:26:15 -05:00
Thomas Harte
cbd4f7965b Acknowledge one further 16-bit assumption. 2023-12-24 14:22:26 -05:00
Thomas Harte
bf9743cb38 Keep as regular int. 2023-12-24 14:16:12 -05:00
Thomas Harte
13631fb7bc Resolve various 32->16 conversion warnings. 2023-12-24 14:14:53 -05:00
Thomas Harte
3e328bed61 Be overt about jump size, albeit without internal rigour. 2023-12-24 14:11:41 -05:00
Thomas Harte
a3e4d38be3 Merge pull request #1283 from TomHarte/RedundantMove
Remove pointless — and damaging — `std::move`.
2023-12-23 22:09:11 -05:00
Thomas Harte
62410a04ef Remove pointless — and damaging — std::move. 2023-12-23 21:44:10 -05:00
Thomas Harte
8b4cabd228 Merge pull request #1280 from TomHarte/More68000Op
Move fact of fixed operations into type.
2023-12-22 19:59:00 -05:00
Thomas Harte
54f1c31c94 Apply changes on trailing edges only. 2023-12-22 18:38:43 -05:00
Thomas Harte
66bc1fd6fd Don't mix constructor delegation and variable instantiation. 2023-12-22 12:29:27 -05:00
Thomas Harte
c07f8d8ef8 Switch ordering. 2023-12-22 10:50:49 -05:00
Thomas Harte
e6ed45cb71 Merge pull request #1281 from ryandesign/TargetConditionals
Include TargetConditionals.h where needed
2023-12-22 10:49:23 -05:00
Thomas Harte
dbb14467ec Remove redundant using, add extra comment. 2023-12-22 10:48:35 -05:00
Thomas Harte
c266639a0c Improve commentary; use specialised types for TAS. 2023-12-22 10:46:10 -05:00
Ryan Carsten Schmidt
5e87692102 Include TargetConditionals.h where needed
Fixes build failure "error: 'TARGET_OS_IPHONE' is not defined, evaluates
to 0" on macOS with newer versions of clang.
2023-12-21 23:33:58 -06:00
Thomas Harte
5b43ea82f3 Lock down interrupt cycle types. 2023-12-21 23:12:14 -05:00
Thomas Harte
7c28a77b2b Fill in assignment operator. 2023-12-21 23:09:42 -05:00
Thomas Harte
85f814c632 Attempt to build fixed operations into type.
This simplifies callees and should make all helper functions automatically able to optimise themselves for fixed operations.
2023-12-21 23:08:18 -05:00
Thomas Harte
213dfe037d Shift operation stuff into its own namespace, making data_select_active a free function. 2023-12-21 16:03:53 -05:00
Thomas Harte
6c4905d961 Merge pull request #1279 from TomHarte/NoMoreEmuTOS
Eliminate use of EmuTOS.
2023-12-21 15:43:34 -05:00
Thomas Harte
160fec2439 Eliminate trace. 2023-12-21 15:31:09 -05:00
Thomas Harte
faaa89bb67 Eliminate all reference to EmuTOS. 2023-12-21 15:28:45 -05:00
Thomas Harte
3616a943a5 Merge pull request #1278 from TomHarte/AdmitToPC
Formalise the PC in macOS and under SDL.
2023-12-21 13:31:28 -05:00
Thomas Harte
98be6e690f Fully expose the PC to SDL, etc. 2023-12-21 13:01:41 -05:00
Thomas Harte
09867e1e6d Unhide the PC. 2023-12-21 12:59:53 -05:00
Thomas Harte
dc03b2c03b Merge pull request #1226 from TomHarte/65c02STAAbsX
Adjust 65c02 STA abs,x behaviour.
2023-12-21 12:31:39 -05:00
Thomas Harte
1f2fbccf1f Update documentation. 2023-12-20 22:05:45 -05:00
Thomas Harte
356d8f469a Correct various throaway -> throwaway. 2023-12-20 22:02:51 -05:00
Thomas Harte
60bd81c4cc Use X. 2023-12-20 22:02:51 -05:00
Thomas Harte
38c3d302a3 Restore JMP (abs, x) length. 2023-12-20 22:02:51 -05:00
Thomas Harte
24c80060c8 Revise guess on JMP (abs, x). 2023-12-20 22:02:51 -05:00
Thomas Harte
d33deb676f Adjust (abs, y) addressing. 2023-12-20 22:02:19 -05:00
Thomas Harte
bf5ed98f35 Generalise 65c02 behaviour.
Partly to convince myself:
1. this change alters behaviour of `CycleAddXToAddressLowRead`
2. which affects only `AbsoluteXw` and the 65c02-specific `JMP (abs, x)`;
3. `AbsoluteXw` is then used only by `AbsoluteXWrite` and `AbsoluteXReadModifyWrite`;
4. `AbsoluteXWrite` is used for abs, x addressing by `SHY`, `STA` and `STZ`;
5. `AbsoluteXReadModifyWrite` is used for `ASL`, `ASO`, `ROL`, `RLA`, `LSR`, `LSE`, `ROR`, `RRA`, `DEC`, `DCP`, `INC` and `INS`.

... though many of the latter are replaced by instance of `FastAbsoluteXReadModifyWrite` for the 65c02 which don't include a dummy
access at all if the page boundary is crossed so the issue is moot.
2023-12-20 22:02:14 -05:00
Thomas Harte
abea3d10cc Merge pull request #1270 from ryandesign/MacSDL
SDL build improvements
2023-12-18 21:58:30 -05:00
Thomas Harte
a779b4668e Merge pull request #1269 from ryandesign/typos
Fix typos
2023-12-18 21:56:23 -05:00
Thomas Harte
be7e776fa4 Merge pull request #1276 from TomHarte/AppleIIColourText
Don't disable the colour burst in mixed mode.
2023-12-18 21:53:07 -05:00
Thomas Harte
08287edd61 Don't disable the colour burst in mixed mode. 2023-12-18 16:26:02 -05:00
Ryan Carsten Schmidt
5ef6b190af Fix typos 2023-12-16 03:53:07 -06:00
Ryan Carsten Schmidt
d12316dfcf Change phase from int to uint8_t
output_colour_burst expects a uint8_t so may as well make that clear.
2023-12-15 04:49:13 -06:00
Ryan Carsten Schmidt
81ad864659 Fix OpenGL Apple II colors
Adjust phase by 90 degress.

Closes #872
2023-12-15 04:48:32 -06:00
Ryan Carsten Schmidt
cd4498a36a Improve macOS SDL Macintosh video & Apple II colors
Hacks in AppleII/Video.cpp, AppleII/Video.hpp, and Macintosh/Video.cpp
assume that building on macOS means building for Metal unless
IGNORE_APPLE is defined. By defining this in the macOS SDL build,
Macintosh video is now sized and positioned correctly and Apple II
colors are now just as wrong as they are on other OpenGL builds instead
of being wrong in a unique way.

See #872
2023-12-15 01:27:28 -06:00
Ryan Carsten Schmidt
d31ecd8986 Link with OpenGL framework on macOS
Fixes "ld: library not found for -lGL"
2023-12-15 01:27:28 -06:00
Ryan Carsten Schmidt
bb030fc141 Silence macOS OpenGL deprecation warnings 2023-12-15 01:27:28 -06:00
Ryan Carsten Schmidt
778544b36e Link with Accelerate framework on macOS
Fixes "Undefined symbols for architecture x86_64: '_vDSP_dotpr_s1_15'"
2023-12-15 01:27:28 -06:00
Ryan Carsten Schmidt
dc657bdd51 Use the right include path for SDL.h
Fixes "main.cpp:22:10: fatal error: 'SDL2/SDL.h' file not found" when
SDL2 is not in a standard system include directory.
2023-12-15 01:27:28 -06:00
Ryan Carsten Schmidt
2352b4e6d8 Import PATH into scons environment
Fixes "/bin/sh: sdl2-config: command not found" when sdl2-config is not
in a standard system bin directory.
2023-12-15 01:27:28 -06:00
Ryan Carsten Schmidt
8256500877 Update GitHub workflow: also build SDL UI on macOS 2023-12-15 01:27:28 -06:00
Thomas Harte
def1f90d86 Merge pull request #1268 from TomHarte/EOI
Support auto-EOI.
2023-12-13 10:52:00 -05:00
Thomas Harte
5033d2046a Support auto-EOI. 2023-12-12 14:02:46 -05:00
Thomas Harte
b12ae263a3 Merge pull request #1267 from TomHarte/EOI
Support 8259 PIC specific EOIs.
2023-12-12 12:42:34 -05:00
Thomas Harte
a49a3da21c Merge branch 'master' into EOI 2023-12-12 12:15:13 -05:00
Thomas Harte
02b2b9d47e Merge pull request #1265 from TomHarte/PCHD
Introduce high-density tracks.
2023-12-12 12:14:48 -05:00
Thomas Harte
2db04eb671 Add TODO list. 2023-12-12 10:59:43 -05:00
Thomas Harte
0c98a78bb5 Support specific EOIs. 2023-12-12 10:55:49 -05:00
Thomas Harte
d523242e08 Add TODO. 2023-12-12 09:35:05 -05:00
Thomas Harte
070f8d8bc3 Simplify control flow. 2023-12-12 09:29:28 -05:00
Thomas Harte
add3257258 Switch to using a Parser rather than duplicating one. 2023-12-11 19:13:37 -05:00
Thomas Harte
bfd6543067 Defaults can now be private. 2023-12-11 19:12:49 -05:00
Thomas Harte
50b4132db7 Merge pull request #1259 from TomHarte/NIBSlipBits
NIB: switch to a strategy supporting non-standard formats.
2023-12-11 10:33:22 -05:00
Thomas Harte
e79727d30d Enhance to support 'try-any' density. 2023-12-11 10:32:13 -05:00
Thomas Harte
a40ae08248 Be const correct; drop get_. 2023-12-11 09:58:24 -05:00
Thomas Harte
05bfab47d2 Merge branch 'master' into PCHD 2023-12-10 23:15:33 -05:00
Thomas Harte
44a19e8306 Merge pull request #1266 from TomHarte/DayOfMonth
Fix RTC day of the month, turbo keyboard resets.
2023-12-10 23:11:57 -05:00
Thomas Harte
ad6fe75296 Add yucky disk speed coupling. 2023-12-10 23:07:02 -05:00
Thomas Harte
d658e00f26 Add exposition, expand recorded data. 2023-12-10 22:59:50 -05:00
Thomas Harte
7b9cc2332e Extend amount of time it takes keyboard to reset. 2023-12-10 22:44:24 -05:00
Thomas Harte
04d75a3ab8 Return proper day-of-the-month value. 2023-12-10 22:44:08 -05:00
Thomas Harte
dae8a5cda2 Fix namespace. 2023-12-10 22:40:07 -05:00
Thomas Harte
98e05fb0e3 Introduce high-density tracks. 2023-12-10 22:17:23 -05:00
Thomas Harte
ada627d027 Decline to try to surface tracks past the end of the disk. 2023-12-09 15:36:47 -05:00
Thomas Harte
cbe5e69aa1 Add exposition. 2023-12-08 23:56:43 -05:00
Thomas Harte
39f2c8097e Remove second semicolon. 2023-12-08 23:55:27 -05:00
Thomas Harte
28cb0ad029 Try permitting a single sync section only. 2023-12-08 23:44:26 -05:00
Thomas Harte
371f109a84 Fix mark locations. 2023-12-08 23:41:14 -05:00
Thomas Harte
3c3cff568a Remove dead variable. 2023-12-08 23:25:56 -05:00
Thomas Harte
c481577f9f Simplify, and attempt to avoid reconversions. 2023-12-08 23:12:41 -05:00
Thomas Harte
0dfaca2a20 Merge branch 'master' into NIBSlipBits 2023-12-08 22:19:46 -05:00
Thomas Harte
671e59b27a Merge pull request #1263 from TomHarte/IMDFiles
Add read-only support for IMD files.
2023-12-08 16:50:19 -05:00
Thomas Harte
42291cd789 Add documentation reference. 2023-12-08 15:38:05 -05:00
Thomas Harte
9ef28da322 Add read-only support for IMD images. 2023-12-08 15:37:13 -05:00
Thomas Harte
2a0176dde6 Merge pull request #1262 from TomHarte/PCTurbo
Add turbo option for PC execution.
2023-12-08 14:47:19 -05:00
Thomas Harte
f823310fe3 Add an appropriate crop. 2023-12-08 14:29:23 -05:00
Thomas Harte
1c47c64bcb Connect option to macOS UI. 2023-12-08 14:23:27 -05:00
Thomas Harte
fbf79c142a Undo accidental build-type switch. 2023-12-08 14:03:29 -05:00
Thomas Harte
0bf453199c Default to 'fast'. 2023-12-08 12:51:55 -05:00
Thomas Harte
604fca7fb1 Revise colour burst phase guess. 2023-12-08 11:55:00 -05:00
Thomas Harte
2ee873d1a1 This isn't intended to be exact. 2023-12-08 11:07:14 -05:00
Thomas Harte
e703721271 Tie snow avoidance to avoiding DEN. 2023-12-08 11:02:41 -05:00
Thomas Harte
664890cead Expose speed as an option. 2023-12-08 10:46:59 -05:00
Thomas Harte
3a103217d1 Add a compiletime 'turbo' flag for sort-of-80286 speeds. 2023-12-08 09:38:55 -05:00
Thomas Harte
e55a09962f Merge pull request #1260 from TomHarte/QuietPC
Mostly silence PC.
2023-12-07 22:12:12 -05:00
Thomas Harte
4bfde2f30f Mostly silence PC. 2023-12-07 22:11:49 -05:00
Thomas Harte
2966a82690 Merge pull request #1258 from TomHarte/DiskWrite
Respond appropriately if a write is attempted.
2023-12-07 22:08:07 -05:00
Thomas Harte
ba91f461fa Merge pull request #1257 from TomHarte/CGABorderColour
Switch back to yellow for composite.
2023-12-07 21:56:38 -05:00
Thomas Harte
d8d33ac419 Add a backup strategy for non-standard formats. 2023-12-07 21:52:51 -05:00
Thomas Harte
d61d80afec It seems that write protection ends in not-ready. 2023-12-07 16:50:12 -05:00
Thomas Harte
1985d7da6a Do something on a write rather than nothing. 2023-12-07 16:45:21 -05:00
Thomas Harte
75b6030516 Don't lose brown upon a blink. 2023-12-07 14:53:59 -05:00
Thomas Harte
e691cc8723 Retain dark yellow for composite output. 2023-12-07 14:21:09 -05:00
Thomas Harte
ac47b93542 Merge pull request #1256 from TomHarte/CGABorderColour
CGA: reduce repetition, map dark yellow to brown, support border colour.
2023-12-07 14:13:14 -05:00
Thomas Harte
c5745f71f6 Reduce repetition, map dark yellow to brown. 2023-12-07 13:11:20 -05:00
Thomas Harte
48d1fa7eab Merge pull request #1255 from TomHarte/CGAClock
Revise CGA clock rate downward.
2023-12-07 12:28:44 -05:00
Thomas Harte
71069bef0f Correct get_scaled_scan_status. 2023-12-07 12:18:03 -05:00
Thomas Harte
8608f0f89d Adjust CGA clocking down by 1/7th. 2023-12-07 12:05:15 -05:00
Thomas Harte
d94791a82d Merge pull request #1254 from TomHarte/BordersAplenty
Unify repeated setup/execution of output_level.
2023-12-07 11:45:42 -05:00
Thomas Harte
017fd84f36 Also use output level for CRAM dots. 2023-12-07 11:05:10 -05:00
Thomas Harte
fc63fcb751 Unify usages of output_level for border. 2023-12-07 11:04:18 -05:00
Thomas Harte
eb4a8bfef9 Merge pull request #1253 from TomHarte/RTC
Add some small portion of the AT real-time clock.
2023-12-07 10:52:45 -05:00
Thomas Harte
ad78a03300 Default to CGA40 if starting a new composite PC. 2023-12-07 10:14:06 -05:00
Thomas Harte
0f22ee5de4 Add TODO. 2023-12-07 10:08:43 -05:00
Thomas Harte
83cfacc0a5 Update TODOs. 2023-12-07 10:03:52 -05:00
Thomas Harte
ef0c3549d2 Attempt but fail to indicate PM. 2023-12-06 23:28:16 -05:00
Thomas Harte
e3119a4904 Hack in read-only versions of the main registers. 2023-12-06 23:25:34 -05:00
Thomas Harte
5fde3b8d5d Wire up a stub RTC plus appropriate option ROM. 2023-12-06 22:56:09 -05:00
Thomas Harte
d696c15be5 Merge pull request #1252 from TomHarte/CGAAddresses
Revise guess as to CGA address wrapping.
2023-12-06 22:32:54 -05:00
Thomas Harte
b385e6edad Revise guess as to address wrapping. 2023-12-06 22:03:24 -05:00
Thomas Harte
327dc51ece Merge pull request #1250 from TomHarte/CGATarget
Add CGA emulation.
2023-12-06 16:23:10 -05:00
Thomas Harte
a44ffa769b Merge pull request #1251 from TomHarte/PCScreenshots
Add PC screenshots, mention.
2023-12-06 16:21:51 -05:00
Thomas Harte
87438a3019 Add PC screenshots, mention. 2023-12-06 16:20:31 -05:00
Thomas Harte
1f976b8ccb Complete loop for macOS display selection. 2023-12-06 14:49:34 -05:00
Thomas Harte
8645a4b7b1 Walk further towards user display configuration. 2023-12-06 14:44:59 -05:00
Thomas Harte
ff000a5792 Support remainder of colour control. 2023-12-06 14:38:43 -05:00
Thomas Harte
1c7f8841f4 Avoid potential lengthy startup; work towards display option. 2023-12-06 13:55:41 -05:00
Thomas Harte
fd298ffbe9 Remove dead TODO. 2023-12-06 13:15:36 -05:00
Thomas Harte
987a5dbfbf Honour monochrome flag. 2023-12-06 13:15:17 -05:00
Thomas Harte
0bb74f405f Ensure lines are in-phase with the NTSC colour subcarrier. 2023-12-06 13:12:58 -05:00
Thomas Harte
1aa168054e Add a phoney colour burst. 2023-12-06 13:10:28 -05:00
Thomas Harte
6d7c6de32f Fix flush_pixels for 640px mode. 2023-12-06 11:50:16 -05:00
Thomas Harte
d3021e8c90 Attempt _something_ for 640px mode. 2023-12-06 11:42:35 -05:00
Thomas Harte
6adaf89934 Make first attempt at palette support. 2023-12-06 11:19:04 -05:00
Thomas Harte
bf49f745bf Attempt to distinguish clocks. 2023-12-06 10:41:20 -05:00
Thomas Harte
c5aa3fc75c Start mangling towards pixel output. 2023-12-06 10:30:30 -05:00
Thomas Harte
d88c7ae148 Switch to CGA as default. 2023-12-06 09:59:21 -05:00
Thomas Harte
f455f07ba2 Support half-clocked mode. 2023-12-06 09:59:14 -05:00
Thomas Harte
561e50a24d Implement most of CGA text mode. 2023-12-06 09:42:22 -05:00
Thomas Harte
2216fc37a1 Add CGA font. 2023-12-06 09:34:25 -05:00
Thomas Harte
23bdf0c2a2 Add CGA font references. 2023-12-06 09:34:04 -05:00
Thomas Harte
24eaf95e9d Limit to eight pixels per fetch, to produce stable video. 2023-12-06 09:13:47 -05:00
Thomas Harte
e43f960934 Produce incorrect output from proper clock; capture mode. 2023-12-05 23:01:08 -05:00
Thomas Harte
fdd599e71a Unify CRTC routing. 2023-12-05 23:00:43 -05:00
Thomas Harte
84ee683ad3 Remove redundant, false comment. 2023-12-05 23:00:21 -05:00
Thomas Harte
b2b05b590f Clone the MDA class to CGA. 2023-12-05 22:37:33 -05:00
Thomas Harte
c5ec9ae171 Adjust MDA clock; it's slightly slower than my guess. 2023-12-05 22:31:37 -05:00
Thomas Harte
5576588c2d Fix drive enables, go back to FF for non-existent ports. 2023-12-05 22:02:41 -05:00
Thomas Harte
084efdeb2d Resolve further type conversion warnings. 2023-12-05 16:54:11 -05:00
Thomas Harte
fd8afb6668 Devolve memory location and font ROM decision. 2023-12-05 16:46:39 -05:00
Thomas Harte
dd04909d58 Resolve some further warnings. 2023-12-05 16:43:55 -05:00
Thomas Harte
736a3841ce Wire up adaptor selection. 2023-12-05 16:42:55 -05:00
Thomas Harte
bdf9c4765b Loosen the assumption of MDA. 2023-12-05 16:38:09 -05:00
Thomas Harte
6659a1dec5 Exit on EOP. 2023-12-05 15:37:25 -05:00
Thomas Harte
f97e6095df Adjust option name. 2023-12-05 15:26:32 -05:00
Thomas Harte
23c60ae9bc Supply video adaptor type. 2023-12-05 15:19:58 -05:00
Thomas Harte
dc7ba11dff Merge pull request #1246 from ryandesign/DidNotLoad
Disk II: Don't overwrite data bus when not asked to
2023-12-05 15:01:23 -05:00
Thomas Harte
6c0a746470 Merge pull request #1248 from TomHarte/FAT12Analyser
Add something of a FAT12 analyser.
2023-12-05 14:58:18 -05:00
Thomas Harte
c78a2c71d7 Merge pull request #1247 from ryandesign/ci
CI improvements
2023-12-05 14:57:56 -05:00
Thomas Harte
4265455c31 Unify DMA interface. 2023-12-05 14:52:14 -05:00
Thomas Harte
0bcb17985b Eliminate further warnings. 2023-12-05 14:44:20 -05:00
Thomas Harte
711575bf69 Avoid having two PC targets. 2023-12-05 14:18:10 -05:00
Ryan Carsten Schmidt
2ee062ea9e Rename workflow to Build 2023-12-05 12:11:22 -06:00
Ryan Carsten Schmidt
452e32ca4e Add macOS build job to workflow
Closes #1244
2023-12-05 12:10:35 -06:00
Ryan Carsten Schmidt
54f25b3e4e Split workflow step commands onto two lines 2023-12-05 12:10:35 -06:00
Ryan Carsten Schmidt
b1b4404b48 Use checkout@v4 in workflow 2023-12-05 12:10:35 -06:00
Ryan Carsten Schmidt
d1bfbac59e Rename workflow job step to Checkout 2023-12-05 12:10:34 -06:00
Ryan Carsten Schmidt
0a45e26c50 Rename workflow job to Build SDL UI 2023-12-05 12:10:34 -06:00
Thomas Harte
40de0189d9 Add some notes to self (now and future). 2023-12-05 12:50:53 -05:00
Thomas Harte
7ca9a0841f Add a text search to recognise common boot sectors. 2023-12-05 12:24:53 -05:00
Ryan Carsten Schmidt
01cf7462d5 Disk II: Don't overwrite data bus when not asked to
Return DidNotLoad rather than 0xff from read_address on odd-numbered
addresses so that the data bus is not overwritten with 0xff on those
accesses.
2023-12-05 10:03:52 -06:00
Thomas Harte
2d75fbe1bf Add nonfunctional FAT12 analyser. 2023-12-05 10:46:06 -05:00
Thomas Harte
e9420fc48d Merge pull request #1245 from TomHarte/MDANoCursor
MDA: implement no cursor, blink attribute.
2023-12-04 22:10:12 -05:00
Thomas Harte
9601c69e12 Implement blinking text. 2023-12-04 22:02:38 -05:00
Thomas Harte
790e744bde Merge pull request #1239 from ryandesign/sense-write-protect
Fix Disk II sense-write-protect clocking preference
2023-12-04 21:47:26 -05:00
Thomas Harte
9f65587a1d Correct scan status scaling; rearrange FDC marginally. 2023-12-04 21:46:03 -05:00
Thomas Harte
b0d1dedb65 Support MDA control: display enable. 2023-12-04 16:34:46 -05:00
Thomas Harte
8103f8e682 Switch interpretation to support cursor on/off. 2023-12-04 15:54:56 -05:00
Thomas Harte
3523278057 Merge pull request #1243 from TomHarte/FDCInfiniteLoop
Avoid potential FDC infinite loop; clear cache on disk change.
2023-12-04 13:03:42 -05:00
Thomas Harte
bf8a4b7efe Ensure sector cache is cleared upon disk change. 2023-12-04 12:28:29 -05:00
Thomas Harte
edef0732ac Avoid potential infinite read loops. 2023-12-04 12:19:21 -05:00
Thomas Harte
9cbc991510 Merge pull request #1240 from ryandesign/patch-1
Remove invalid uef.gz file type from Info.plist
2023-12-04 12:12:27 -05:00
Thomas Harte
d476a17275 Merge pull request #1241 from ryandesign/patch-2
Fix typos in comments
2023-12-04 12:12:16 -05:00
Ryan Carsten Schmidt
896632b9b6 Fix typos in comments 2023-12-04 10:39:03 -06:00
Ryan Carsten Schmidt
5ccd232541 Remove invalid uef.gz file type from Info.plist
Closes #1194
2023-12-04 10:25:35 -06:00
Thomas Harte
9b23984d35 Merge pull request #1238 from TomHarte/MissingIncludes
Add 6845/MDA cursor.
2023-12-04 10:36:44 -05:00
Ryan Carsten Schmidt
b91a791e01 Fix Disk II sense-write-protect clocking preference
Ensure we're actually in the sense-write-protect loop before deciding
that we don't need to process anymore.

Closes #1218
2023-12-04 09:19:52 -06:00
Thomas Harte
5845ce0a39 Ameliorate for race condition. 2023-12-04 09:56:06 -05:00
Thomas Harte
646c6b08f7 Make cursor blink. 2023-12-04 09:52:46 -05:00
Thomas Harte
0d7646d42a Add a cursor-type template parameter. 2023-12-04 09:45:32 -05:00
Ryan Carsten Schmidt
ab608178f3 Consider Disk II state machine state C to be a NOP
Continuation of #1224
2023-12-04 08:13:32 -06:00
Thomas Harte
606a04b0b8 Merge pull request #1236 from TomHarte/MissingIncludes
Add missing <array> #includes
2023-12-03 18:07:35 -05:00
Thomas Harte
15868eea24 Merge branch 'master' into MissingIncludes 2023-12-03 18:07:11 -05:00
Thomas Harte
881f9bc824 Merge pull request #1235 from TomHarte/MissingKeys
Add missing key mappings, queue, cursor
2023-12-03 18:06:53 -05:00
Thomas Harte
37c46d579d Add missing array imports. 2023-12-03 18:06:09 -05:00
Thomas Harte
5d8666b837 Enable the cursor signal; no blink action yet. 2023-12-03 17:57:19 -05:00
Thomas Harte
4957ae7de1 Support cursor at point of output. 2023-12-02 22:44:26 -05:00
Thomas Harte
e77f4457c2 Map various missing keys. 2023-12-02 22:40:05 -05:00
Thomas Harte
c6b989d85b Add an input queue, to avoid key drops. 2023-12-02 22:29:49 -05:00
Thomas Harte
41bd5298b7 Signal only changes in modifiers. 2023-12-02 22:25:19 -05:00
Thomas Harte
596267f62d Merge pull request #1232 from TomHarte/8237TC
Improves 8237 TC/EOP support enough for some multisector reads
2023-12-02 22:24:58 -05:00
Thomas Harte
92913b7455 Fix mapping of Z. 2023-12-02 18:46:22 -05:00
Thomas Harte
208846a166 Attempt proper EOP semantics; multisector reads. 2023-12-02 18:38:26 -05:00
Thomas Harte
c31ee968df TC: start tending towards meaning. 2023-12-02 15:24:47 -05:00
Thomas Harte
ad9e0b664a Merge pull request #1231 from TomHarte/DiskClassification
Improve format support; log more.
2023-12-02 15:11:24 -05:00
Thomas Harte
ef134e13a1 Merge pull request #1230 from TomHarte/Warnings
Avoid illegal reads in Enterprise Nick
2023-12-02 13:29:12 -05:00
Thomas Harte
1b7e109047 Remove nonsense comment. 2023-12-02 13:25:08 -05:00
Thomas Harte
6c10611150 Avoid potential out-of-bounds read. 2023-12-02 13:23:48 -05:00
Thomas Harte
0bae14be8f Merge pull request #1229 from TomHarte/DiskClassification
Appropriately route 180kb non-FAT12 PC booters.
2023-12-02 10:42:51 -05:00
Thomas Harte
dde58faaf1 Add additional 8-sector format. 2023-12-02 00:00:57 -05:00
Thomas Harte
aa15fd1fff Comment more. 2023-12-02 00:00:44 -05:00
Thomas Harte
691d1cce9e Simplify and fix track caching. 2023-12-01 23:35:11 -05:00
Thomas Harte
7072a1661c Flag floppy as present. 2023-12-01 22:44:21 -05:00
Thomas Harte
ebe1d53220 Expand range of recognised formats. 2023-12-01 22:44:13 -05:00
Thomas Harte
bc89cb7d06 Hack attack: ignore TC. 2023-12-01 17:30:32 -05:00
Thomas Harte
b16e3de170 Accept what look like raw booters. 2023-12-01 17:23:13 -05:00
Thomas Harte
5693b3add3 Merge pull request #1228 from TomHarte/PCDiskImages 2023-12-01 16:11:01 -05:00
Thomas Harte
f50c45cc1a Treat 'invalid' as a silent failure. 2023-12-01 15:35:51 -05:00
Thomas Harte
33a0c40c02 Support HLT. 2023-12-01 13:15:01 -05:00
Thomas Harte
365b62b4a7 Add TODO. 2023-12-01 09:50:11 -05:00
Thomas Harte
4d1e976b55 Flag drive as interrupting. 2023-12-01 09:49:50 -05:00
Thomas Harte
4429448815 Make some effort at terminating appropriate if no sector. 2023-12-01 09:47:52 -05:00
Thomas Harte
88e67d9ad6 Return some status after reading. Seemingly wrong. 2023-12-01 09:37:30 -05:00
Thomas Harte
d101483714 Hack in enough that disk contents end up in RAM. 2023-12-01 09:34:31 -05:00
Thomas Harte
5feac8ef14 Avoid duplicate symbol. 2023-12-01 07:36:12 -05:00
Thomas Harte
a96cb1ebd6 Decommit debugging hook. 2023-12-01 06:46:00 -05:00
Thomas Harte
2da2240d34 Remove errant break. 2023-12-01 06:45:29 -05:00
Thomas Harte
ef37b09a78 Seed all transfers as complete. 2023-11-30 22:47:38 -05:00
Thomas Harte
9fc0d411fd Further flesh out DMA, breaking POST. 2023-11-30 22:45:40 -05:00
Thomas Harte
0dc44e8efd Adjust audio formulation.
Probably still not right, but less wrong with the current input.
2023-11-30 14:37:13 -05:00
Thomas Harte
c076636df1 Fix typo. 2023-11-30 14:26:26 -05:00
Thomas Harte
c397da3e5a Add TODOs. 2023-11-30 12:52:08 -05:00
Thomas Harte
5f6bbec741 Capture DMA high bytes, add actor for accesses. 2023-11-30 12:47:50 -05:00
Thomas Harte
ec39c4a5f0 Merge pull request #1225 from TomHarte/PCDiskImages
Add enough for FAT12 IMA images to get to the PC.
2023-11-29 16:11:33 -05:00
Thomas Harte
edc36bf3f4 Include the PC target and analyser. 2023-11-29 15:59:42 -05:00
Thomas Harte
f7acecfbff Protect set_geometry. 2023-11-29 15:56:07 -05:00
Thomas Harte
07b32844af Remove outdated comment. 2023-11-29 15:55:51 -05:00
Thomas Harte
7f0bb716f7 Grab sector contents, ready for more FDC work. 2023-11-29 15:55:37 -05:00
Thomas Harte
f25aaf2bb3 Adjust 65c02 STA abs,x behaviour. 2023-11-29 15:32:02 -05:00
Thomas Harte
b7d3633b38 Log slightly more. 2023-11-29 15:30:47 -05:00
Thomas Harte
05504c8389 Accept and keep hold of disk images. 2023-11-29 15:20:14 -05:00
Thomas Harte
ddf38595ff Add enough for FAT12 IMA images to get to the PC. 2023-11-29 14:54:33 -05:00
Thomas Harte
66b95a8b54 Merge pull request #1217 from TomHarte/PCFDC
Sketch the outline of a high-level emulation of the PC FDC
2023-11-29 12:48:55 -05:00
Thomas Harte
ab586b9965 Merge pull request #1224 from ryandesign/patch-3
Handle C, E, F operations in Disk II state machine
2023-11-29 12:48:39 -05:00
Thomas Harte
cd2567d868 Merge pull request #1222 from ryandesign/patch-1
Fix typo in comment in AppleDSK.hpp
2023-11-29 12:48:10 -05:00
Thomas Harte
c07ae43980 Merge pull request #1221 from TomHarte/More68000TemplateActions
Enable further compile-time optimisations.
2023-11-29 12:47:48 -05:00
Thomas Harte
4e10ef2816 Merge pull request #1223 from ryandesign/patch-2
Fix typo in comment in WOZ.cpp
2023-11-29 12:40:22 -05:00
Thomas Harte
8d01829fa7 Adopt PC-style naming, limit to one drive. 2023-11-29 11:35:21 -05:00
Thomas Harte
be842ee2f1 Add drive indicator lights. 2023-11-29 11:31:37 -05:00
Thomas Harte
e034daa6c8 Capture motor state. 2023-11-29 09:52:16 -05:00
Thomas Harte
ce4bcf9064 Improve comment. 2023-11-29 09:50:08 -05:00
Thomas Harte
a992ae37b1 Mildly rearrange, to match enum order. 2023-11-29 09:49:15 -05:00
Thomas Harte
439104c73a Add missing space. 2023-11-29 09:49:05 -05:00
Thomas Harte
fbbe3ab7f1 Include seek ended flag. 2023-11-29 09:45:45 -05:00
Thomas Harte
6e2e67fd46 Sculpt out enough to get to a read data command. 2023-11-29 09:42:43 -05:00
Ryan Carsten Schmidt
3293ab48ce Handle C, E, F operations in Disk II state machine
This shouldn't matter since these operations are not requested by the
state machine but this is what those operations should do according to
Understanding the Apple II, Table 9.3, page 9-15.
2023-11-29 05:50:20 -06:00
Ryan Carsten Schmidt
2e314e7a08 Fix typo in comment in WOZ.cpp 2023-11-29 03:42:39 -06:00
Thomas Harte
3827a084ad Code to GlaBIOS expectations. 2023-11-28 23:18:22 -05:00
Ryan Carsten Schmidt
afc62f3d94 Fix typo in comment in AppleDSK.hpp 2023-11-28 22:09:35 -06:00
Thomas Harte
301442a0b1 Fix meaning of flag, use correctly. 2023-11-28 22:34:34 -05:00
Thomas Harte
dd4bcf68bf Load up on debugging logs. 2023-11-28 15:09:57 -05:00
Thomas Harte
b860fba0a3 Make an attempt at providing varied sense interrupt statuses. 2023-11-28 14:12:39 -05:00
Thomas Harte
7171e24ccf Enable further compile-time optimisations. 2023-11-28 13:50:53 -05:00
Thomas Harte
c19c356c10 Add disabled longer serialisation. 2023-11-27 23:23:00 -05:00
Thomas Harte
8fec9bef11 Attempt IRQ logic. 2023-11-27 23:16:24 -05:00
Thomas Harte
bffe3ffa25 Add an 8272 results phase. 2023-11-27 23:05:37 -05:00
Thomas Harte
993366ac5a Merge branch 'master' into PCFDC 2023-11-27 22:16:30 -05:00
Thomas Harte
b07cc5c2ec Merge pull request #1219 from TomHarte/68000TemplatedPerform
Sometimes provide 68000 bus operations at compile time.
2023-11-27 21:54:24 -05:00
Thomas Harte
36a4629ce0 Explain new semantics. 2023-11-27 21:49:57 -05:00
Thomas Harte
87eec47b79 Mildly reduce cost of 8-byte ROM overlay. 2023-11-27 15:48:30 -05:00
Thomas Harte
2a0375e9c2 Mildly adjust layout of inner loop. 2023-11-27 15:16:22 -05:00
Thomas Harte
032eeb4757 Eliminate runtime switch. 2023-11-27 14:57:41 -05:00
Thomas Harte
5c7f94d2ef Introduce the possibility of operation type as a template parameter.
It's already proven possible to provide this for instruction fetch, so I think it'll immediately be a win. But more importantly it opens a path forwards for further improvement.
2023-11-27 11:48:34 -05:00
Thomas Harte
291723e85e Insert notes to self, trying to tie down FloppyController interface. 2023-11-27 10:27:36 -05:00
Thomas Harte
d2203484cc Avoid name duplication. 2023-11-26 15:29:08 -05:00
Thomas Harte
003c494aac Factor out a large number of status-related facts. 2023-11-26 15:04:10 -05:00
Thomas Harte
a6a464c240 Add printed TODO. 2023-11-25 21:40:13 -05:00
Thomas Harte
9bd75464b5 Proceed to receiving a sense interrupt status. 2023-11-25 18:15:37 -05:00
Thomas Harte
0bb048e24b Start formalising/extracting 8272 status. 2023-11-25 18:10:49 -05:00
Thomas Harte
8c70317d31 Introduce interrupt. 2023-11-24 23:06:52 -05:00
Thomas Harte
dd135bf3fe Start experimenting with a possible end-of-reset interrupt? 2023-11-24 22:41:33 -05:00
Thomas Harte
2efb5236f7 Add an agent for floppy control. 2023-11-24 22:19:39 -05:00
Thomas Harte
af70c8847d Factor out the stuff of accumulating and dissecting commands. 2023-11-24 18:24:58 -05:00
Thomas Harte
d5c30e3175 Add enough keyboard support to be able to bypass the initial FDC BIOS failure report. 2023-11-24 13:38:06 -05:00
Thomas Harte
ed31cfd80a Merge pull request #1216 from TomHarte/ReduceNoise
Limit extraneous printing.
2023-11-23 23:05:46 -05:00
Thomas Harte
89423f28ef Limit extraneous printing. 2023-11-23 22:47:31 -05:00
Thomas Harte
593c32f621 Merge pull request #1215 from TomHarte/PCKeyboard
Attempt to implement the XT keyboard controller.
2023-11-23 22:26:09 -05:00
Thomas Harte
019d987623 Clear buffer on read. 2023-11-23 22:16:08 -05:00
Thomas Harte
7e8020df59 Avoid a spurious initial interrupt. 2023-11-23 22:15:20 -05:00
Thomas Harte
44d602e0f6 Seriously attempt a keyboard controller. 2023-11-23 22:10:51 -05:00
Thomas Harte
0674da0325 Flip IRQ priority. 2023-11-23 15:41:24 -05:00
Thomas Harte
113fc9f757 Add further TODO. 2023-11-23 15:29:43 -05:00
Thomas Harte
2c31452629 Add TODO, as exposition. 2023-11-23 15:19:31 -05:00
Thomas Harte
505df78108 Add column duplication, switch to green. 2023-11-23 15:18:28 -05:00
Thomas Harte
d92d0e87ac Honour MDA attributes. 2023-11-23 14:51:32 -05:00
Thomas Harte
df9e9c2c4d Start accumulating notes. 2023-11-22 15:21:45 -05:00
Thomas Harte
b3c07b76ee Merge pull request #1214 from TomHarte/MDAOutput
Add basic MDA text output.
2023-11-22 15:04:21 -05:00
Thomas Harte
e0f72f2048 Tidy up. 2023-11-22 14:18:58 -05:00
Thomas Harte
825f3184eb Explain provenance. 2023-11-22 14:18:50 -05:00
Thomas Harte
a293a3a816 Document the future. 2023-11-22 14:14:53 -05:00
Thomas Harte
b22b489380 Mask into 4kb; I don't know whether hardware scrolling is in use. 2023-11-22 14:12:57 -05:00
Thomas Harte
231de8440e Add text display. 2023-11-22 14:11:22 -05:00
Thomas Harte
8993a9c4c1 Import MDA font. 2023-11-22 14:04:26 -05:00
Thomas Harte
381537fde9 Get as far as MDA being able to fetch. 2023-11-22 13:52:28 -05:00
Thomas Harte
f249e4ada6 Maintain an actual pixel buffer. 2023-11-22 13:40:50 -05:00
Thomas Harte
12179e486f Create a solid white rectangle. 2023-11-22 13:18:39 -05:00
Thomas Harte
80b2ccd418 Attempt to wire in a CRTC. 2023-11-22 12:53:09 -05:00
Thomas Harte
2af6259963 Merge pull request #1213 from TomHarte/PITClock
Standardise on the PIT clock as the definition of time.
2023-11-21 22:51:14 -05:00
Thomas Harte
24d0caf8e7 Fix Swift conditionality. 2023-11-21 22:48:26 -05:00
Thomas Harte
1828a10885 Use less branchy inner loop. 2023-11-21 22:42:53 -05:00
Thomas Harte
bcd4a2216a Improve clocking. 2023-11-21 22:36:11 -05:00
Thomas Harte
3da3401125 Attempt full audio output. 2023-11-21 22:28:33 -05:00
Thomas Harte
972d1d1ddd Add audio pipeline. 2023-11-21 22:11:32 -05:00
Thomas Harte
0344af986c Try to avoid having to edit this constantly. 2023-11-21 22:02:36 -05:00
Thomas Harte
6329a1208a Adopt PIT-centric timing. 2023-11-21 22:02:24 -05:00
Thomas Harte
c11d3b61d6 Merge pull request #1209 from TomHarte/SupportChipsAplenty
Add various other PC chips into the mix.
2023-11-21 21:53:29 -05:00
Thomas Harte
375a9f9ff5 Pull out the PIC, DMA. 2023-11-21 15:50:38 -05:00
Thomas Harte
a1e118a1ff Do some interrupt work. 2023-11-21 15:46:31 -05:00
Thomas Harte
83ca9b3af5 Hack in some MDA text logging. Boot seems to complete? 2023-11-21 11:37:36 -05:00
Thomas Harte
acdf32e820 Handle low/high switches. 2023-11-21 11:25:53 -05:00
Thomas Harte
931e6e7a56 Add, disable, logging detritus. 2023-11-21 11:19:47 -05:00
Thomas Harte
058080f6de Prove to my caveman self that no text is being written. 2023-11-20 23:11:27 -05:00
Thomas Harte
c4e9f75709 Edge towards but don't quite reach interrupt. 2023-11-20 22:52:20 -05:00
Thomas Harte
695282b838 PIT output now reaches the PIC. 2023-11-20 22:36:05 -05:00
Thomas Harte
f0e2ef5e28 Attempt to implement square-wave mode. 2023-11-20 22:19:18 -05:00
Thomas Harte
ee6012f6e9 Evict the PIT. 2023-11-20 19:00:16 -05:00
Thomas Harte
d3e90ce006 Capture some basics.
BIOS now seems to get as far as expecting channel 0 to trigger an interrupt, which never comes.
2023-11-20 15:36:52 -05:00
Thomas Harte
18ddc2c83a Route traffic. 2023-11-20 15:11:22 -05:00
Thomas Harte
abf0eead7a Add a functionless PIC. 2023-11-20 13:53:44 -05:00
Thomas Harte
a689f2b63e Relocate comment. 2023-11-20 12:22:30 -05:00
Thomas Harte
a3066fc040 Advance to the missing PIC. 2023-11-20 12:21:37 -05:00
Thomas Harte
7eed254de9 Bring an 8255 into the mix. 2023-11-20 12:13:42 -05:00
Thomas Harte
55f466f2fa Add enough of the DMA subsystem to trip over in PPI world. 2023-11-19 22:55:29 -05:00
Thomas Harte
119c83eb18 Fix field decoding. 2023-11-19 21:51:27 -05:00
Thomas Harte
4e077701c9 Exit without further modification upon latch. 2023-11-19 16:37:47 -05:00
Thomas Harte
a26bfd938e Merge pull request #1210 from ryandesign/patch-1
Fix typos in Apple II ROM images readme.txt
2023-11-19 16:12:08 -05:00
Thomas Harte
8844812910 Merge branch 'SupportChipsAplenty' of github.com:TomHarte/CLK into SupportChipsAplenty 2023-11-19 16:08:38 -05:00
Thomas Harte
a8f1c72f5c Take a caveman run at debugging. 2023-11-19 16:05:44 -05:00
Thomas Harte
05e93f0eb3 Implementing counting for a couple of PIT modes. 2023-11-19 15:52:32 -05:00
Thomas Harte
af885ccf08 Decode PIT mode writes. 2023-11-19 15:01:21 -05:00
Thomas Harte
56aa9d101a Decode PIT mode writes. 2023-11-19 14:59:52 -05:00
Thomas Harte
2b69081fff Start sketching the PIT. 2023-11-19 07:15:30 -05:00
Ryan Carsten Schmidt
c0eed0fe78 Fix typos in Apple II ROM images readme.txt 2023-11-19 04:59:43 -06:00
Thomas Harte
a91449555f Add link for future self. 2023-11-17 17:38:17 -05:00
Thomas Harte
afc0ca3f1b Add XT roadmap. 2023-11-17 17:35:11 -05:00
Thomas Harte
9bc33c716e Merge pull request #1208 from TomHarte/80286BIOS
Add an 80286 BIOS, for later.
2023-11-17 17:19:57 -05:00
Thomas Harte
f0ac62566c Add an 80286 BIOS, for later. 2023-11-17 17:15:57 -05:00
Thomas Harte
3843102609 Merge pull request #1207 from TomHarte/PhoneyPC
Start sketching out a PC compatible machine.
2023-11-17 17:12:10 -05:00
Thomas Harte
d202cfc2ca Add TODO. 2023-11-17 17:09:20 -05:00
Thomas Harte
ec2d878e3f End run around the template.
I have yet to get any insight whatsoever on the reason for GCC's failure here and won't have access to a suitable test
machine for a while so all I have for testing is the arduous CI cycle.
2023-11-17 17:02:46 -05:00
Thomas Harte
626e4fe6b3 Just pull requests will do. 2023-11-17 10:45:32 -05:00
Thomas Harte
ac12b256d4 Tweak syntax. 2023-11-17 10:44:52 -05:00
Thomas Harte
f4b1279342 Try a different GCC version. 2023-11-17 10:43:50 -05:00
Thomas Harte
a0ca5e6cdc Remove outdated comment. 2023-11-17 10:38:11 -05:00
Thomas Harte
83c8f9996e Switch back to the natural type. 2023-11-17 10:27:38 -05:00
Thomas Harte
f2fdfe86ec Reduce repetition. 2023-11-17 09:13:45 -05:00
Thomas Harte
3f27338b2c New guess: the definition of size_t varies? 2023-11-16 23:46:22 -05:00
Thomas Harte
fbe02e3ad5 Randomly try a different explicit instantiation. 2023-11-16 23:37:37 -05:00
Thomas Harte
effddcaf65 Hide PC option by default. 2023-11-16 23:33:42 -05:00
Thomas Harte
4b730c26d0 Satisfy GCC warning. 2023-11-16 23:31:51 -05:00
Thomas Harte
8af173c4bc Remove hopeful hit. 2023-11-16 15:48:27 -05:00
Thomas Harte
e1541543c3 Play hit and hope. 2023-11-16 15:40:47 -05:00
Thomas Harte
33486e69bf Remove CI trap. 2023-11-16 15:30:43 -05:00
Thomas Harte
1c7bb6d759 Add CI diagnosis trap. 2023-11-16 15:25:42 -05:00
Thomas Harte
99e7de5a8b Colocate memory. 2023-11-16 15:24:35 -05:00
Thomas Harte
095359017f Log first unhandled port. 2023-11-16 13:02:35 -05:00
Thomas Harte
25f0a373f3 Don't sign-extend ports (!). 2023-11-16 11:17:12 -05:00
Thomas Harte
233ec7b818 Soften some warnings. 2023-11-16 10:57:17 -05:00
Thomas Harte
832e31f7e5 Add note to self. 2023-11-16 10:34:24 -05:00
Thomas Harte
164a7fe848 Log port IO. 2023-11-16 06:48:24 -05:00
Thomas Harte
62b6219763 Install BIOS, albeit in writeable storage. 2023-11-15 22:02:53 -05:00
Thomas Harte
2bc9dfbef9 Albeit with no BIOS present, execute. 2023-11-15 16:10:37 -05:00
Thomas Harte
3b84299a05 Edge closer to PCCompatible doing _something_. 2023-11-15 15:58:49 -05:00
Thomas Harte
6f48ffba16 Add enough of a ScanProducer to run. 2023-11-15 14:30:30 -05:00
Thomas Harte
1a3b2b0620 Add necessary wiring for File -> New... 2023-11-15 14:27:04 -05:00
Thomas Harte
af7069ac21 Include and fetch a BIOS. 2023-11-15 11:32:23 -05:00
Thomas Harte
7323af0b41 Avoid shadowing template parameter. 2023-11-15 11:10:01 -05:00
Thomas Harte
1676ed9850 Add to SDL and Qt builds. 2023-11-15 11:02:44 -05:00
Thomas Harte
e927fd00d8 Do just enough to include x86 code in the main build. 2023-11-15 11:01:28 -05:00
Thomas Harte
70a4d59517 Merge pull request #1205 from TomHarte/80286Preparation
Clear a path towards implementing the 80286
2023-11-15 10:41:26 -05:00
Thomas Harte
f83d2a8740 Take a swing at ENTER. 2023-11-14 16:23:24 -05:00
Thomas Harte
a22ac2f88b Move towards privacy. 2023-11-14 11:39:44 -05:00
Thomas Harte
aafa7de536 Implement LEAVE, almost. 2023-11-14 11:39:36 -05:00
Thomas Harte
2533fd2da9 Fix segment comparisons. 2023-11-14 11:14:28 -05:00
Thomas Harte
29169ffed7 Merge pull request #1203 from ryandesign/apple-ii-floating-bus-3
Fix Apple II/II+/IIe floating bus first eight non-hbl vbl bytes
2023-11-14 10:59:29 -05:00
Thomas Harte
d2187a0442 Merge pull request #1206 from ryandesign/gui-wording
Minor Mac UI wording changes
2023-11-14 10:57:21 -05:00
Thomas Harte
ac826f90c3 Formalise a separate manager of segments. 2023-11-14 10:56:00 -05:00
Thomas Harte
6c405680f2 Implement PUSHA, POPA. 2023-11-14 10:42:06 -05:00
Ryan Carsten Schmidt
39df6daf3e Add ellipsis at end of New menu item
Menu items that elicit a dialog box in which further choices must be
made should end with an ellipsis.
2023-11-14 02:13:23 -06:00
Ryan Carsten Schmidt
480b5bef95 Add period at end of sentence 2023-11-14 02:11:00 -06:00
Ryan Carsten Schmidt
6bb85c98ba Change "Exit" button to "Quit" 2023-11-14 02:10:55 -06:00
Thomas Harte
1552500b10 Implement BOUND. 2023-11-13 22:33:46 -05:00
Thomas Harte
60cec9fc67 Expand commentary. 2023-11-13 11:45:17 -05:00
Ryan Carsten Schmidt
234292f163 Fix Apple II/II+/IIe first eight non-hbl vbl bytes
Closes #1196
2023-11-13 00:51:34 -06:00
Thomas Harte
03a2d4df80 Merge pull request #1202 from TomHarte/8088SegmentRegisters
Add means for tracking segment register changes.
2023-11-10 23:07:37 -05:00
Thomas Harte
08d9cc3bd3 Restore permitted IDIV miss. 2023-11-10 23:02:32 -05:00
Thomas Harte
47fc276afc Add note to future self. 2023-11-10 23:01:46 -05:00
Thomas Harte
3a782faaf3 Ensure shoutouts upon LDS, LES and any far jump/call/int. 2023-11-10 22:58:59 -05:00
Thomas Harte
19a61f867f Eliminate final misuse of 'selector'. 2023-11-10 22:56:00 -05:00
Thomas Harte
2551e73be1 Fully test segment registers. 2023-11-10 22:54:10 -05:00
Thomas Harte
7abd4d9b38 Fix AAA/AAS carry outcome. 2023-11-10 22:47:50 -05:00
Thomas Harte
e61dc0466f Add callout for tracking segment register changes. 2023-11-10 22:22:32 -05:00
Thomas Harte
79b126e6bb Add route for tracking segment register changes. 2023-11-10 22:11:52 -05:00
Thomas Harte
a230274306 Merge pull request #1201 from TomHarte/IDIVYuck
Improve IDIV marginally; require acceptable failures to have a reason.
2023-11-09 13:38:48 -05:00
Thomas Harte
e78e5c8101 Add remaining acceptable error cases. 2023-11-09 12:26:40 -05:00
Thomas Harte
ed3922e458 Switch to accepting failures only with a reason. 2023-11-09 11:55:36 -05:00
Thomas Harte
800c76a4fe Capture and respond to IDIV_REP. 2023-11-09 11:55:04 -05:00
Thomas Harte
bf179e8933 Merge pull request #1200 from TomHarte/MoreDAA
Correct 8086 DAA and DAS; unify those and AAA/AAS.
2023-11-08 22:45:26 -05:00
Thomas Harte
9e61d3e8cf Combine AAA and AAS. 2023-11-08 22:38:52 -05:00
Thomas Harte
5f1ea6c04c Unify AAA and AAS. 2023-11-08 22:30:39 -05:00
Thomas Harte
8d2a2bcf4a Unify DAA and DAS. 2023-11-08 22:26:48 -05:00
Thomas Harte
6b666bc92a Simplify DAS. 2023-11-08 22:19:51 -05:00
Thomas Harte
38933aa079 Bring fully into 8086 conformance. 2023-11-08 22:16:12 -05:00
Thomas Harte
502b9d2023 Simplify implementation of DAA. 2023-11-08 22:06:58 -05:00
Thomas Harte
da7582d4b5 Merge pull request #1199 from TomHarte/8088Groupings
Split up the ungainly PerformImplementation.hpp.
2023-11-08 19:02:59 -05:00
Thomas Harte
ec4a60b7da Further universalise function layout. 2023-11-08 11:30:33 -05:00
Thomas Harte
d7bb1a9ee1 Tidy up and comment a little further. 2023-11-08 11:23:21 -05:00
Thomas Harte
9566a8de67 Split up the ungainly PerformImplementation.hpp. 2023-11-08 10:52:36 -05:00
Thomas Harte
0fee3ff92c Merge pull request #1198 from TomHarte/DirectWrite
Add compiler assistance on access types
2023-11-07 22:23:41 -05:00
Thomas Harte
b927cf4159 Resolve new decoding errors. 2023-11-07 22:08:44 -05:00
Thomas Harte
f608153c1a Don't bother prepropulating for writes. 2023-11-07 14:38:23 -05:00
Thomas Harte
413e7b7de1 Switch Memory to using accessors. 2023-11-07 14:03:20 -05:00
Thomas Harte
91b7d55871 Get strict about writeables. 2023-11-07 10:13:18 -05:00
Thomas Harte
e56e49a318 Fix SUB/SBB writes. 2023-11-07 10:09:04 -05:00
Thomas Harte
0262875088 Claw back to building. 2023-11-07 09:58:42 -05:00
Thomas Harte
2bed2c2c5c Further simplify syntax. 2023-11-07 09:14:42 -05:00
Thomas Harte
2af774601f Temporarily disentangle Memory and access internals; start to be overt in PerformImplementation. 2023-11-06 16:04:31 -05:00
Thomas Harte
797c9fe129 Temporarily avoid use of Writeable. 2023-11-05 21:47:52 -05:00
Thomas Harte
009915f4de Start promotion of ReturnType. 2023-11-05 21:42:22 -05:00
Thomas Harte
f96c33102a Add documentation. 2023-11-04 22:22:50 -04:00
Thomas Harte
5739862dbb Add specific entryway for preauthorised writes. 2023-11-03 15:36:30 -04:00
Thomas Harte
7f4fa914dd Merge pull request #1195 from TomHarte/8088Flags
Commute: Status -> Flags as per usual x86 naming.
2023-11-02 17:05:13 -04:00
Thomas Harte
ebdf10525c Fix parameter case. 2023-11-02 17:00:22 -04:00
Thomas Harte
83850d7596 Commute: Status -> Flags as per usual x86 naming. 2023-11-02 16:55:38 -04:00
Thomas Harte
18820644b0 Merge pull request #1193 from TomHarte/8088Intentions
Work towards x86 access violations.
2023-11-02 16:46:36 -04:00
Thomas Harte
770803b073 Be more careful as to authorisation. 2023-11-02 15:37:59 -04:00
Thomas Harte
8d0deeb20e Clean up Memory. 2023-11-02 14:25:13 -04:00
Thomas Harte
e4fdf09149 Fix PUSH SP, far call. Further simplify FlowController. 2023-11-01 23:39:52 -04:00
Thomas Harte
acb55aa4e2 Subsume repetition of arguments into a single context.
Albeit that it (temporarily?) loses some context used during test validation.
2023-11-01 17:03:23 -04:00
Thomas Harte
bc095bb9ce Slim down the flow controller. 2023-11-01 14:49:30 -04:00
Thomas Harte
097b328075 Split the preauthorised tracks. 2023-11-01 14:31:42 -04:00
Thomas Harte
ef83ac855a Fix spelling of Preauthorised, think further on return types. 2023-11-01 14:11:10 -04:00
Thomas Harte
78df0d19e4 Start experimenting with varying return types. 2023-11-01 10:03:31 -04:00
Thomas Harte
430c60111e CMP doesn't write. 2023-10-31 22:42:39 -04:00
Thomas Harte
2432396eaa Fix SETMOC. 2023-10-31 22:04:26 -04:00
Thomas Harte
da2aea94e3 Fix CMPS. 2023-10-31 21:58:32 -04:00
Thomas Harte
9538491ee9 Fix pushes and pops. 2023-10-31 21:55:30 -04:00
Thomas Harte
8be03be529 Add test of ::Write mode. 2023-10-31 20:28:37 -04:00
Thomas Harte
724e08d4f1 Update commentary on semantics. 2023-10-31 15:09:21 -04:00
Thomas Harte
1d479ec2d7 Ensure that reads can only read, accept that source is sometimes written to. E.g. XCHG. 2023-10-31 15:06:19 -04:00
Thomas Harte
02af08ffd2 Fix counts. 2023-10-30 12:32:44 -04:00
Thomas Harte
3dc9b625a1 Partly dodge British/American spelling issue; slightly tighten otherwise. 2023-10-30 11:43:07 -04:00
Thomas Harte
444c5b94b9 Add summary of accepted failures. 2023-10-29 16:55:07 -04:00
Thomas Harte
1cd1bbd26c Make a first pass of access types. 2023-10-29 16:19:10 -04:00
Thomas Harte
8ecc9835f8 Merge branch 'master' into 8088Intentions 2023-10-29 16:10:21 -04:00
Thomas Harte
39e803aa71 Commit updated macOS version. 2023-10-29 14:47:09 -04:00
Thomas Harte
7a886f938a Propagate access types, even if incorrect. 2023-10-29 14:33:39 -04:00
Thomas Harte
8153cec455 Merge branch 'master' into 8088Intentions 2023-10-28 15:57:05 -04:00
Thomas Harte
3ee0fcaaeb Hatch an appropriate enum. 2023-10-28 15:56:37 -04:00
Thomas Harte
b98f54545f Merge pull request #1182 from ryandesign/apple-ii-floating-bus-2
Fix Apple II/II+/IIe floating bus issues
2023-10-28 15:46:35 -04:00
Thomas Harte
0a5c24be19 Merge pull request #1192 from ryandesign/ryandesign-rpath
Fix LD_RUNPATH_SEARCH_PATHS for High Sierra
2023-10-28 15:41:10 -04:00
Ryan Carsten Schmidt
764a7b60f4 Fix LD_RUNPATH_SEARCH_PATHS for High Sierra
See #1118
See #1143
Closes #1191
2023-10-28 08:42:26 -05:00
Thomas Harte
b9891d25ee Merge pull request #1184 from TomHarte/CompactInstruction
Compact normalised x86 instructions.
2023-10-27 16:40:11 -04:00
Thomas Harte
6da0add100 Permit 1654 failures, the current amount. 2023-10-27 16:30:30 -04:00
Thomas Harte
f9d1a4dd8f Add Repetition::Rep to unify repeat logic. 2023-10-27 16:27:24 -04:00
Thomas Harte
66cee41b99 Fix port. 2023-10-27 14:04:23 -04:00
Thomas Harte
a30cad5e8a Rearrange class for clarity. 2023-10-27 14:02:53 -04:00
Thomas Harte
f9d98ed219 Fix packing_size. 2023-10-27 13:46:14 -04:00
Thomas Harte
2d70b44303 Boil down segment ahead of time. 2023-10-27 12:54:42 -04:00
Thomas Harte
5b0d2d754f Update comments. 2023-10-26 23:27:56 -04:00
Thomas Harte
11b032fb06 Eliminate length extension. 2023-10-26 23:19:31 -04:00
Thomas Harte
8e35a56ff7 Include repetition in operation; simplify Instruction constructor. 2023-10-26 23:08:07 -04:00
Thomas Harte
167b52c4ff Merge pull request #1171 from TomHarte/8088Execution
Add first seeds of x86 execution.
2023-10-26 22:20:38 -04:00
Thomas Harte
dafb134cdc Eliminate dead detour. 2023-10-25 22:27:44 -04:00
Thomas Harte
6ac66dad0c Remove stale notes. 2023-10-25 22:22:20 -04:00
Thomas Harte
de230fb6be Resolve for work factored out. 2023-10-25 22:21:23 -04:00
Thomas Harte
29a921f764 Remove TODO, add exposition. 2023-10-25 16:15:08 -04:00
Thomas Harte
a2826cdee5 Propagate address size. 2023-10-25 16:00:01 -04:00
Thomas Harte
3b62638b30 Remove dead DataPointerResolver and extra-conditional version of source(). 2023-10-25 14:43:58 -04:00
Thomas Harte
0c09c14baa Incorporate instruction length into offsets. 2023-10-25 13:02:43 -04:00
Thomas Harte
6dd5628dd6 Provide full pair for string conversion. 2023-10-25 11:21:11 -04:00
Thomas Harte
6cecb84878 Add #include. 2023-10-25 09:09:51 -04:00
Ryan Schmidt
18ed36d090 Update get_last_read_value source documentation 2023-10-25 03:25:52 -05:00
Ryan Schmidt
c206c7e2cb Fix Apple II/II+ text/lores hbl read addresses
Closes #1181
2023-10-25 03:25:48 -05:00
Ryan Schmidt
98730f1f90 Fix Apple II/II+/IIe first hbl byte read addresses
Closes #1180
2023-10-25 03:21:22 -05:00
Ryan Schmidt
c272632b5a Fix Apple II/II+/IIe hbl row < 64 read addresses
See #1180
2023-10-25 03:21:17 -05:00
Ryan Schmidt
577b01e80b Fix Apple II/II+/IIe vbl rows read addresses
See #1180
2023-10-25 03:21:06 -05:00
Thomas Harte
239ce75db6 Fix IN and OUT conversion. 2023-10-24 22:35:13 -04:00
Thomas Harte
cc9e8117ab Add note. 2023-10-24 16:43:22 -04:00
Thomas Harte
26c2a29b99 Fix int3 mapping. 2023-10-24 15:09:25 -04:00
Thomas Harte
e36274e5c2 Add segment prefix for MOVS, LODS, etc. 2023-10-24 15:07:53 -04:00
Thomas Harte
0e027445d4 Don't offer repne for reps; print far CALLs and JMPs as h-suffix rather than 0x prefix. 2023-10-24 11:01:38 -04:00
Thomas Harte
20d7079006 Start adaptation to new test disassembly form. 2023-10-23 16:37:27 -04:00
Thomas Harte
49d87c9f27 Fix 16-bit accesses that overlap memory's end.
1654 failures remaining.
2023-10-23 10:41:58 -04:00
Thomas Harte
7a4d74b8e4 Correct copy and paste error: 0x27 is DAA. 2023-10-23 10:07:57 -04:00
Thomas Harte
82c66e7433 Fix far jump with immediate operand.
1655 failures remaining.
2023-10-23 10:07:19 -04:00
Thomas Harte
569cf8bf34 Focus on remaining files with issues. 2023-10-23 10:02:13 -04:00
Thomas Harte
817a30332c Take a swing at LEA r16, r16. 2023-10-22 22:15:27 -04:00
Thomas Harte
599c123b36 Reenable all tests. 2023-10-21 22:55:10 -04:00
Thomas Harte
e3cdf113d1 Implement INS, OUTS. 2023-10-21 22:52:50 -04:00
Thomas Harte
aade91f043 Implement IN, OUT. 2023-10-21 22:37:25 -04:00
Thomas Harte
bf6fd8e5e4 Shuffle down TODO. 2023-10-20 21:57:03 -04:00
Thomas Harte
c2ebbe5ad9 Implement STOS with one failure. 2023-10-20 21:54:30 -04:00
Thomas Harte
4efc181f07 Fix memory handler, STOS. 2023-10-20 21:49:34 -04:00
Thomas Harte
93e90b09a0 Implement MOVS, STOS, revealing an issue in the memory handler. 2023-10-20 21:46:47 -04:00
Thomas Harte
dab3dcaafb Fix LODS: REP is not REPE. 2023-10-20 21:36:50 -04:00
Thomas Harte
8caad8b99d Document slightly. 2023-10-20 17:25:27 -04:00
Thomas Harte
bee094eba1 Add LODS; somehow manage to fail some of its tests. 2023-10-20 17:13:56 -04:00
Thomas Harte
bcebb2e520 Further reduce repetition overhead. 2023-10-20 17:08:11 -04:00
Thomas Harte
0f5e0e17a4 Fix address manipulation. 2023-10-20 17:03:23 -04:00
Thomas Harte
49ac2d8e0c Improve error reporting, remove some dead TODOs. 2023-10-20 17:00:32 -04:00
Thomas Harte
a71db54212 Simplify flow slightly; uncover issues in CMPSW. 2023-10-20 16:52:47 -04:00
Thomas Harte
efb854ddfa Fix repetition. Sufficient for tests. 2023-10-19 14:40:03 -04:00
Thomas Harte
387a952328 Reduce repetition. 2023-10-19 14:21:08 -04:00
Thomas Harte
f715cd89a9 Attempt CMPS, changing storage of direction; add flags check. 2023-10-19 14:07:59 -04:00
Thomas Harte
14851f407c Merge pull request #1177 from omimakhare/patch-1
Remove Typo
2023-10-18 22:52:36 -04:00
Thomas Harte
617be7cba7 Implement PUSHes and POPs. 2023-10-18 15:59:39 -04:00
Thomas Harte
02cea3047e Implement LOOP, LOOPE, LOOPNE. 2023-10-18 14:04:21 -04:00
Thomas Harte
a8c7871b0c Implement JCXZ. 2023-10-18 13:20:28 -04:00
Thomas Harte
90f49a6e73 Implement JMP. 2023-10-18 13:15:00 -04:00
OMKAR MAKHARE
47c535414b Update README.md
Corrected "generlaly" to "generally" in the README.md file.
2023-10-17 23:35:19 +05:30
Thomas Harte
440f3bdb10 Further improve error reporting. 2023-10-16 15:47:06 -04:00
Thomas Harte
89743f0ba0 Implement RET, IRET. 2023-10-16 15:40:24 -04:00
Thomas Harte
f1779e6067 Implement SHR. 2023-10-16 12:34:11 -04:00
Thomas Harte
e38fe7dffc Implement SAL, SAR. 2023-10-14 21:42:33 -04:00
Thomas Harte
f1cba4eb78 Implement remaining rolls. 2023-10-13 22:03:54 -04:00
Thomas Harte
f45d8bcbdb Implement RCR. 2023-10-13 21:44:48 -04:00
Thomas Harte
6f7991f54a Avoid loop. 2023-10-13 21:32:35 -04:00
Thomas Harte
6ec291d96f Move ownership of mask test. 2023-10-13 15:34:06 -04:00
Thomas Harte
1a0f848b21 Implement RCL. 2023-10-13 14:44:22 -04:00
Thomas Harte
bf832768e6 Implement XLAT. 2023-10-12 21:12:03 -04:00
Thomas Harte
d35377c776 Implement SALC, SETMO, SETMOC. 2023-10-12 15:52:05 -04:00
Thomas Harte
97d3a9fa78 Implement MOV. 2023-10-12 15:34:46 -04:00
Thomas Harte
da029ee344 Implement LEA. 2023-10-12 14:31:25 -04:00
Thomas Harte
cf846f501a Implement LDS, LES. 2023-10-12 14:24:28 -04:00
Thomas Harte
e948a67814 Implement SAHF, LAHF. 2023-10-12 13:54:51 -04:00
Thomas Harte
56e639e09a Add INT (including INT3), INTO. 2023-10-11 16:01:09 -04:00
Thomas Harte
e75ef70c96 Further generalise. 2023-10-11 15:08:04 -04:00
Thomas Harte
a768b101f8 Further clean up copy-and-paste mess. 2023-10-11 14:36:42 -04:00
Thomas Harte
7159366360 Collapse all flags accesses behind setters and getters. 2023-10-11 12:35:17 -04:00
Thomas Harte
033ba75376 Standardise repetitive sign/zero/parity sets. 2023-10-11 11:15:59 -04:00
Thomas Harte
fbd647080d Start factoring out useful ALU stuff. 2023-10-11 11:06:20 -04:00
Thomas Harte
4a803e2d43 Reduce ADD/ADC/SUB/SBB repetition. 2023-10-10 22:43:06 -04:00
Thomas Harte
7753497a93 Add header for std::swap. 2023-10-10 22:35:25 -04:00
Thomas Harte
a83b43a1ae Implement XCHG. 2023-10-10 22:34:42 -04:00
Thomas Harte
5125907048 Implement TEST. 2023-10-10 22:28:10 -04:00
Thomas Harte
08867f4970 Implement CMP. 2023-10-10 22:15:33 -04:00
Thomas Harte
d0a9b5cb81 Implement NEG, NOT. 2023-10-10 22:09:10 -04:00
Thomas Harte
0ecc319ee6 Add OR, XOR. 2023-10-10 17:12:06 -04:00
Thomas Harte
de95026076 Implement Jcc. 2023-10-10 16:27:06 -04:00
Thomas Harte
ec982444f7 Add getters to obscure internal flag storage. 2023-10-10 16:14:20 -04:00
Thomas Harte
f083eab011 Implement INC, DEC. 2023-10-10 15:57:33 -04:00
Thomas Harte
3d08953103 Add TODO. 2023-10-10 12:43:41 -04:00
Thomas Harte
dbf7d07609 Add DIV, faulty IDIV. 2023-10-10 10:34:18 -04:00
Thomas Harte
b420d4cbd7 Collect TODOs. 2023-10-09 22:22:06 -04:00
Thomas Harte
0412890923 Add STC, STD, STI. 2023-10-09 22:16:37 -04:00
Thomas Harte
5e830781cc Implement IMUL, improve test memory footprint. 2023-10-09 22:12:15 -04:00
Thomas Harte
ff6573dd02 Implement MUL. 2023-10-09 21:50:17 -04:00
Thomas Harte
e46e42d896 This is the same test either way around. 2023-10-09 16:47:02 -04:00
Thomas Harte
1cb26cb141 Pull add/sub distinction into templates. 2023-10-09 16:40:50 -04:00
Thomas Harte
f74ca8aee1 Fix SBB. 2023-10-09 16:32:01 -04:00
Thomas Harte
58aa1da649 Fix SUB. SBB still failing. 2023-10-09 16:30:47 -04:00
Thomas Harte
67d364cc89 Add faulty SUB, SBB. 2023-10-09 16:21:04 -04:00
Thomas Harte
d24fa381c7 'Implement' ESC, NOP. 2023-10-09 15:03:01 -04:00
Thomas Harte
fe6e2eb0a1 Generalise CBW. 2023-10-09 15:00:04 -04:00
Thomas Harte
08aed3bac5 Implement CWD. 2023-10-09 14:54:14 -04:00
Thomas Harte
6bbd896c34 Add DAS with a manageable number of failures. 2023-10-09 14:47:39 -04:00
Thomas Harte
0bf2099a70 Improve DAA. 2023-10-09 14:42:32 -04:00
Thomas Harte
1b9e6e8c8e Add DAA, which doesn't yet pass all tests. 2023-10-09 14:27:02 -04:00
Thomas Harte
59521f9d38 Implement CBW, CLC, CLD, CLI, CMC. 2023-10-09 11:59:38 -04:00
Thomas Harte
769aed10ea Reduce repetition. 2023-10-09 11:49:38 -04:00
Thomas Harte
5a77f0c93c Implement CALL. 2023-10-09 11:46:59 -04:00
Thomas Harte
4f14210ee0 Remove ideas discarded. 2023-10-08 22:27:01 -04:00
Thomas Harte
f618ca6046 Implement, test AND. 2023-10-08 22:18:40 -04:00
Thomas Harte
0a0d53103d Enable tests for all implemented operations.
Only the various AAM 00hs are failing, which I've yet to understand.
2023-10-08 22:12:22 -04:00
Thomas Harte
e3b18708c7 Handle segment-boundary word accesses.
With all ADDs and ADCs enabled, no remaining failures.
2023-10-08 22:11:05 -04:00
Thomas Harte
bd0b62232f Consider that displacements may always be signed.
Down to 1 failure.
2023-10-08 21:41:36 -04:00
Thomas Harte
dbfaef632a Fix DataPointer reference.
Down from 4521 to 1248 failures within 00.json.gz
2023-10-08 15:59:30 -04:00
Thomas Harte
6808f2c778 Attempt to catch illegal accesses ahead of time. 2023-10-08 15:44:11 -04:00
Thomas Harte
0d2af80f7f Avoid access issues if there's no index. 2023-10-08 13:50:36 -04:00
Thomas Harte
6f768d9a3d Start climbing towards address resolution. 2023-10-08 13:47:43 -04:00
Thomas Harte
dd3cc1f510 Fix ADD and ADC sign flags. 2023-10-08 13:39:46 -04:00
Thomas Harte
a4b1d2b00a Float out data resolution. 2023-10-08 13:34:28 -04:00
Thomas Harte
a5523c9feb Fail at scale.
108,645 current failures (!)
2023-10-07 14:37:12 -04:00
Thomas Harte
6e465b9159 Merge branch 'master' into 8088Execution 2023-10-07 14:31:09 -04:00
Thomas Harte
90f0e937e8 Merge pull request #1172 from TomHarte/AddNeskellBinaries
Import Neskell binaries.
2023-10-07 14:30:56 -04:00
Thomas Harte
6d1dd218d4 Import Neskell binaries. 2023-10-07 14:29:53 -04:00
Thomas Harte
6abc3b6cd7 Collate all failures for printing at the end. 2023-10-07 14:28:44 -04:00
Thomas Harte
7d093d71b3 Avoid allocating and reallocating per test. 2023-10-07 14:23:47 -04:00
Thomas Harte
ade5828035 Add a clear, in the hope of not recreating Memory every test.
It's a big allocation, and therefore likely the bottleneck on test running.
2023-10-07 13:39:23 -04:00
Thomas Harte
5c62606154 Simplify parity logic. 2023-10-07 13:38:36 -04:00
Thomas Harte
16bf7c6f26 Fix include guard. 2023-10-07 13:31:35 -04:00
Thomas Harte
cf4603cb33 Attempt to check defined flags only. 2023-10-06 16:32:35 -04:00
Thomas Harte
b6d000ac5e Add enough wiring to consolidate failure on lazy handling of flags. 2023-10-06 13:22:35 -04:00
Thomas Harte
82f0cd790f Find first failing execution, note reason. 2023-10-06 11:43:18 -04:00
Thomas Harte
2d17d9d316 Execute some tests at some facile level. 2023-10-06 11:31:45 -04:00
Thomas Harte
a0ca0bb3c0 Mark non-templates as inline. 2023-10-06 11:11:29 -04:00
Thomas Harte
c6b311b84a Explain source of comments. 2023-10-06 11:10:54 -04:00
Thomas Harte
28c7d27cac Establish some proportion of state, ready to execute _something_. 2023-10-06 11:07:33 -04:00
Thomas Harte
90a8999b4b Fix typo. 2023-10-05 22:29:15 -04:00
Thomas Harte
6d392852d2 Hack on through to something that builds. 2023-10-05 22:27:52 -04:00
Thomas Harte
f7d9116811 Merge branch 'master' into 8088Execution 2023-10-05 17:13:50 -04:00
Thomas Harte
451c687441 Merge pull request #1168 from TomHarte/8088Tests
Verify and correct 8086 instruction decoding.
2023-10-05 17:13:22 -04:00
Thomas Harte
f411a961a3 Create a central location for avoiding segment conditionality. 2023-10-05 17:12:38 -04:00
Thomas Harte
ada411c0d8 It's differing mildly from DataPointResolver, but segue towards a world of real data. 2023-10-05 17:06:00 -04:00
Thomas Harte
eb100e3b29 Start reforming; data size plus register aren't independent in finding a source. 2023-10-05 16:49:02 -04:00
Thomas Harte
15acb1fc7c Add ADC and ADD. 2023-10-05 15:49:07 -04:00
Thomas Harte
09b2cfad8a Add AAM and AAS. 2023-10-05 14:52:24 -04:00
Thomas Harte
059f300500 Start fleshing out x86 performance. 2023-10-05 14:37:58 -04:00
Thomas Harte
524e4ae65c Tidy up just slightly more. 2023-10-05 11:26:52 -04:00
Thomas Harte
488fceb42b Clean up, add a TODO. 2023-10-05 11:23:58 -04:00
Thomas Harte
01851874ea I guess this is what a perform looks like. 2023-10-05 11:23:41 -04:00
Thomas Harte
7f6e3cf8b7 Define the available flags. 2023-10-05 10:51:55 -04:00
Thomas Harte
2d20175472 Explain absence. 2023-10-05 09:27:02 -04:00
Thomas Harte
6597283c34 Simplify roll/shift case. 2023-10-05 09:26:12 -04:00
Thomas Harte
f6fd49d950 Relocate all text wrangling; this isn't really test-specific. 2023-10-04 22:35:52 -04:00
Thomas Harte
40af162214 Be overt about what's here to aid with printing only. 2023-10-04 22:15:13 -04:00
Thomas Harte
92c46faf84 Add SETMO and SETMOC. 2023-09-29 22:28:23 -04:00
Thomas Harte
ff9237be9f Decode SALC. 2023-09-29 22:06:42 -04:00
Thomas Harte
6cbb434482 Deal with all dangling aliases.
Leaves just five undocumented instructions.
2023-09-29 15:36:34 -04:00
Thomas Harte
9fe6e354a6 Determine what I'm up against re: outstanding unofficial opcodes. 2023-09-29 15:29:35 -04:00
Thomas Harte
103f42f0b0 Introduce FF.7 alias. 2023-09-29 15:26:25 -04:00
Thomas Harte
f2732962d0 Add 6x 8086 aliases. 2023-09-29 15:22:05 -04:00
Thomas Harte
ef5ee8cf94 Include missing context on JMP/CALL far.
Zero failing tests amongst official opcodes.
2023-09-29 14:57:08 -04:00
Thomas Harte
1a6c8a2aed Add outputters for IN and OUT.
2 failures remaining.
2023-09-29 09:39:51 -04:00
Thomas Harte
b76899f2bc Undo broken extension-word DS assumption.
8 failures.
2023-09-28 22:17:14 -04:00
Thomas Harte
a24e17c320 Simplify debugging hook; remove outdated notes. 2023-09-28 22:04:59 -04:00
Thomas Harte
245919e67d Resolve REPNE and whitespace issues. 2023-09-28 22:01:12 -04:00
Thomas Harte
6936cf1819 Handle special case of INT3.
10 failures.
2023-09-28 15:34:33 -04:00
Thomas Harte
ae4a588de3 Adjust semantics to avoid culling end of relevant RETs. 2023-09-28 15:24:15 -04:00
Thomas Harte
960cca163e Make better guess at CALL/JMP size; apply same sizing-logic as offset for disassembly matching.
13 failures.
2023-09-28 14:52:42 -04:00
Thomas Harte
86f12f4d4c Adopt test-set's preferred pointer type for LES and LDS.
15 failures.
2023-09-28 14:16:47 -04:00
Thomas Harte
249da884a7 Trim trailing space. 2023-09-28 13:59:41 -04:00
Thomas Harte
035a1265f6 Map invalid reg numbers properly for the 8086.
17 failures.
2023-09-28 13:11:15 -04:00
Thomas Harte
ff4d79e77e Add test synonym, fix operand size.
19 failures.
2023-09-28 09:43:26 -04:00
Thomas Harte
95df9bcb1e Accept SHL as a synonym of SAL.
20 failures.
2023-09-28 09:31:10 -04:00
Thomas Harte
78cb39ad67 Also fix AddrReg.
24 failures.
2023-09-27 22:47:14 -04:00
Thomas Harte
9207de4164 Fix RegAddr macro.
26 failures.
2023-09-27 22:44:10 -04:00
Thomas Harte
c20e7ed9b6 Fix TEST.
28 failures.
2023-09-27 22:30:40 -04:00
Thomas Harte
11c747e3c4 Defer worrying about immediate sign extensions. 2023-09-27 22:18:05 -04:00
Thomas Harte
02aeec0173 Prepare for greater nuance on testing sign extensions by text. 2023-09-27 17:06:34 -04:00
Thomas Harte
2d882d2153 Switch shift/roll semantics to reduce extension words and for sanity generally.
37 failures.
2023-09-27 16:40:46 -04:00
Thomas Harte
638f3d3a53 Add special case for shifts and rolls. 2023-09-27 11:10:21 -04:00
Thomas Harte
b59eae3676 Adopt normative ESC decoding.
55 failures.
2023-09-27 10:32:22 -04:00
Thomas Harte
2cc60563e0 Resolve rep vs repe.
63 failures.
2023-09-26 17:36:22 -04:00
Thomas Harte
5368f789f6 Shuffle list slightly. 2023-09-26 17:30:27 -04:00
Thomas Harte
b03b408984 Give the decoder responsibility for sanity-checking repetitions.
This may avoid some spurious extension words.
2023-09-26 17:29:20 -04:00
Thomas Harte
cd072e1b57 LEA implies a word. Otherwise add TODOs.
So that's now 69 failures.
2023-09-26 15:41:51 -04:00
Thomas Harte
f16ac603f2 Deal with printing segment:offset.
70 failing files remaining.
2023-09-26 15:28:51 -04:00
Thomas Harte
0a0051eb59 I've just been inconsistent with POP. Stop being so.
71 failures from 288 tests.
2023-09-26 15:16:41 -04:00
Thomas Harte
92c8e1ca93 Add missing #include. 2023-09-26 14:52:08 -04:00
Thomas Harte
4a38e6b4b5 Take si/di confusion and offset length off the table.
Now 74 failures of 288 tests.
2023-09-26 13:21:24 -04:00
Thomas Harte
e56a5899bd Ensure test order is deterministic. 2023-09-25 12:28:34 -04:00
Thomas Harte
87097c44b9 Curate list of known failures; apply easiest fixes.
Now at 157 failures of 288 applicable tests.
2023-09-25 11:39:12 -04:00
Thomas Harte
7fadf01e4e BP in isolation acts as a base. 2023-09-24 18:06:53 -04:00
Thomas Harte
0d65bf0c1f Take offset length off the table as a spurious cause of failures. 2023-09-24 15:26:58 -04:00
Thomas Harte
d2b9c435e5 Allow for non-sign-extended offsets/displacements. 2023-09-24 15:00:16 -04:00
Thomas Harte
d36f785428 Include file name in error. 2023-09-22 23:04:26 -04:00
Thomas Harte
5fd98e9833 Add an ignore list.
Leaves 180 failures amongst the valid 306 instructions.
2023-09-22 22:56:33 -04:00
Thomas Harte
787e9e770e Retain baseless addresses correctly. 2023-09-22 17:27:27 -04:00
Thomas Harte
c8c0c3ca6d Default segment is ::DS if there was no base. 2023-09-22 17:03:40 -04:00
Thomas Harte
5a5f71e703 JMPs imply their size. 2023-09-22 17:00:10 -04:00
Thomas Harte
587ec81900 Improve string output, better to find actual errors.
Still at 194/324 failures, but a lot of them seem reasonable.
2023-09-22 11:24:33 -04:00
Thomas Harte
9f63db991c Capture default segments, fix base/index confusion. 2023-09-22 11:07:09 -04:00
Thomas Harte
13f49fe8bf Merge branch 'master' into 8088Tests 2023-09-22 10:45:55 -04:00
Thomas Harte
5f95b32799 Merge pull request #1170 from TomHarte/NeskellTests
6502: fix SH[S/X/Y/A]
2023-09-21 21:35:33 -04:00
Thomas Harte
873b1122ab Correct SHA, SHX, SHY, SHS when page boundary crossed. 2023-09-21 15:31:04 -04:00
Thomas Harte
4c32fc9b11 These tests appear to be against a real 6502. 2023-09-21 10:22:04 -04:00
Thomas Harte
4a87aa06a5 Add use of AHX/TAS/SHX/SHY pagecross test. Which fails. 2023-09-21 10:07:09 -04:00
Thomas Harte
5731ab75a6 Test stack result, pass first test. 2023-09-21 10:00:26 -04:00
Thomas Harte
797ce89a26 Correct test trailer. 2023-09-21 09:52:38 -04:00
Thomas Harte
4dc7b1840c Start attempting to digest Neskell's NES 6502 tests. 2023-09-21 09:47:29 -04:00
Thomas Harte
3db21b0bed Merge pull request #1169 from TomHarte/NESARR
Don't necessarily apply D for ARR.
2023-09-20 22:09:20 -04:00
Thomas Harte
74b5ad93c4 Don't necessarily apply D for ARR. 2023-09-20 10:17:00 -04:00
Thomas Harte
7ebecd2f41 Add notes to self, finally figuring out segment issue. 2023-09-19 23:27:42 -04:00
Thomas Harte
406c838c39 Attempt better to print DirectAddresss. 2023-09-19 22:46:53 -04:00
Thomas Harte
6f5fcf23dc Add missing substitutions. 2023-09-19 14:00:27 -04:00
Thomas Harte
02fcaf0dbd JCXZ seems to be preferred over JPCX. 2023-09-19 13:56:48 -04:00
Thomas Harte
a7cf7d3183 Resolve LOOPNE, LOOPE, etc. 2023-09-19 13:55:19 -04:00
Thomas Harte
9b3199d97b Reduce failures to 205/324. 2023-09-19 13:45:19 -04:00
Thomas Harte
e5dfc882cb Agree that JZ/JNZ are clearer (for me) of the synonyms. 2023-09-19 13:38:08 -04:00
Thomas Harte
2d928199d6 Clean up, add extra breakpoint points. 2023-09-18 17:10:09 -04:00
Thomas Harte
3582d2c9e3 Start to beef up operand count list. 2023-09-18 16:34:52 -04:00
Thomas Harte
da953fdf0d Complete 8086 operation list; standardise enum order. 2023-09-18 16:25:04 -04:00
Thomas Harte
710017ada2 Largely resolve the operation-name problem. 2023-09-18 15:57:26 -04:00
Thomas Harte
9d9194f194 Improve dumped information on a mismatch. 2023-09-17 17:09:40 -04:00
Thomas Harte
f8dc5b8ebc Attempt to get close on index + base addresses. 2023-09-17 17:05:19 -04:00
Thomas Harte
2ee028d74f Bluff through a few more simple cases. 2023-09-17 16:29:04 -04:00
Thomas Harte
2d2eda6f8c Bodge my way into passing some comparisons. 2023-09-17 16:22:17 -04:00
Thomas Harte
5b9c5e250d Increase version number. 2023-09-17 16:04:19 -04:00
Thomas Harte
c95df3cb6c Move a little towards string formation. 2023-09-15 22:28:30 -04:00
Thomas Harte
f039d44ee3 Fully handle rm = 6, mod = 0. 2023-09-15 22:08:20 -04:00
Thomas Harte
7ee5adc481 Forcing a displacement upon BP reduces to 29 failures.
(At the current limited fidelity of testing)
2023-09-15 16:09:04 -04:00
Thomas Harte
8d4393275c Add optional allow list, for ephemeral whittling. 2023-09-15 15:50:59 -04:00
Thomas Harte
9417996280 Also dump hex form of the instruction. 2023-09-14 15:40:40 -04:00
Thomas Harte
804f80d23c Provide sorted output. 2023-09-14 12:29:49 -04:00
Thomas Harte
28027385bc Attempt further to cheer via statistics.
Current opcode failure count: 164 out of 324. Just a shade more than 50%.
2023-09-14 09:33:45 -04:00
Thomas Harte
53d8322b46 Contort further for testing. 2023-09-13 16:45:39 -04:00
Thomas Harte
39840feae7 Added text to cheer myself up. 2023-09-13 16:09:58 -04:00
Thomas Harte
57087cc7c6 Provide feedback on prima facie failure. 2023-09-13 16:08:12 -04:00
Thomas Harte
a6abe3a51d Attempt actually to decode. No comparison yet. 2023-09-13 16:00:16 -04:00
Thomas Harte
aa127d9a9f Add an empty 8088 suite test class. 2023-09-13 15:53:38 -04:00
Thomas Harte
49ec6d19a5 Merge pull request #1167 from TomHarte/NextSequencePoint
Simplify 'get_next_sequence_point' -> 'next_sequence_point'.
2023-09-10 18:08:11 -04:00
Thomas Harte
8efb6a9226 Simplify 'get_next_sequence_point' -> 'next_sequence_point'. 2023-09-10 18:00:49 -04:00
Thomas Harte
211a6e5114 Merge pull request #1166 from TomHarte/6502Exhaustive 2023-09-10 17:02:20 -04:00
Thomas Harte
e42a2578da Enable 6502 for 'exhaustive' disassembly. 2023-09-10 14:30:39 -04:00
Thomas Harte
34c631ed3b Avoid ranges entirely in favour of implicit entries. 2023-09-10 14:25:28 -04:00
Thomas Harte
2f5d710441 Keep map small. 2023-09-07 11:09:33 -04:00
Thomas Harte
b7a27fbc6b Merge pull request #1165 from TomHarte/MSX2Detection
Improve MSX cartridge type detection.
2023-09-06 22:50:53 -04:00
Thomas Harte
e98f78316b Accept a paging scheme if it becomes 60% likely. 2023-09-06 22:40:39 -04:00
Thomas Harte
8c3ebe23f6 Use ranges properly to apply address mapping. 2023-09-06 22:26:15 -04:00
Thomas Harte
251b8e69ad Attempt to support 'exhaustive' disassemblies (i.e. ones that chase every byte). 2023-09-04 15:13:06 -04:00
Thomas Harte
a21fe92b7a Merge pull request #1164 from TomHarte/MacOS1013
Add manual rpath for macOS 10.13.
2023-09-04 14:45:53 -04:00
Thomas Harte
3d5a351306 Add manual rpath for macOS 10.13. 2023-09-03 15:46:35 -04:00
Thomas Harte
43dfb729d3 Explain even better. 2023-09-02 14:45:53 -04:00
Thomas Harte
ecec9ff6dc Merge pull request #1162 from TomHarte/65C02BCDTest
Extend BCD testing to the 65C02; clean up implementation
2023-09-02 11:45:35 -04:00
Thomas Harte
543be49cf8 Merge branch 'master' into 65C02BCDTest 2023-09-01 16:39:18 -04:00
Thomas Harte
4f0adc4d5d Merge pull request #1163 from TomHarte/AbsoluteNOPs
Fix abs,x NOP length.
2023-09-01 16:38:54 -04:00
Thomas Harte
1fb278c9f1 Fix abs,x NOP length. 2023-09-01 14:31:21 -04:00
Thomas Harte
19ec63b4fb Add exposition, slightly simplify, unbreak INS. 2023-09-01 09:29:35 -04:00
Thomas Harte
4d6ffa7a2e With some degree of hit and hope, correct 65C02 results. 2023-08-31 15:28:59 -04:00
Thomas Harte
39ee75d94a Clean up decimal SBC implementation. 2023-08-31 15:02:17 -04:00
Thomas Harte
13be247495 Comment. 2023-08-30 23:08:42 -04:00
Thomas Harte
cdcac7c11c Simplify top nibble handling. 2023-08-30 23:07:54 -04:00
Thomas Harte
67cd5dd63b Simplify top nibble decision. 2023-08-30 23:06:00 -04:00
Thomas Harte
139a1a2acc Clean up decimal ADC. 2023-08-30 23:04:38 -04:00
Thomas Harte
7b569b1a6c Merge branch 'master' into 65C02BCDTest 2023-08-29 21:32:25 -04:00
Thomas Harte
3e666a08ae Merge pull request #1161 from TomHarte/6502Idling
6502: add final read cycle to illegal NOPs.
2023-08-29 21:24:04 -04:00
Thomas Harte
74b416f985 Clean up output. 2023-08-29 17:07:35 -04:00
Thomas Harte
c160482b0a Exploit test's 65C02 abilities. 2023-08-29 17:04:52 -04:00
Thomas Harte
ec8f1b0fe0 Vary seed between processors. 2023-08-29 16:55:39 -04:00
Thomas Harte
5dae726857 Differentiate non-fetching and fetching NOPs. 2023-08-29 16:50:39 -04:00
Thomas Harte
598a889c6d Merge pull request #1160 from TomHarte/ADBKeyboard
Avoid flurry of startup events, repeats.
2023-08-22 09:42:03 -04:00
Thomas Harte
e5d3140cd1 Avoid flurry of startup events, repeats. 2023-08-22 09:28:57 -04:00
Thomas Harte
525e5ce8b0 Merge pull request #1159 from TomHarte/PixelOrder
Flip order of byte usage in double high res mono.
2023-08-21 22:21:18 -04:00
Thomas Harte
79e9de34b6 Flip order of byte usage in double high res mono. 2023-08-21 22:20:42 -04:00
Thomas Harte
0a547355db Merge pull request #1158 from TomHarte/FasterMouse
Switch to maximal signalling rate.
2023-08-21 22:13:39 -04:00
Thomas Harte
2b58f64161 Switch to maximal signalling rate. 2023-08-21 22:12:55 -04:00
Thomas Harte
6cbd152ff5 Merge pull request #1157 from TomHarte/ADBRate
Add basic ADB controller interrupts.
2023-08-21 20:22:51 -04:00
Thomas Harte
a5038259bc Add admission. 2023-08-21 19:30:34 -04:00
Thomas Harte
bb84a5a474 Enable various ADB-controller interrupts. 2023-08-21 15:35:13 -04:00
Thomas Harte
b5dc84c431 Merge pull request #1156 from TomHarte/IIgsMouseMystery
Without rhythm or rhyme, fix IIgs GSOS mouse movement.
2023-08-20 16:19:04 -04:00
Thomas Harte
357a324e87 Add exposition. 2023-08-20 15:34:40 -04:00
Thomas Harte
fa82fb46b9 Acknowledge ever-revolving earth. 2023-08-20 15:33:47 -04:00
Thomas Harte
b8e7c2b8ac Remove printf. 2023-08-20 15:33:30 -04:00
Thomas Harte
3e2a82b638 Add delta capper. 2023-08-20 15:32:48 -04:00
Thomas Harte
1125286b96 Add note to self. 2023-08-20 15:03:28 -04:00
Thomas Harte
17f1f05064 Hit and hope appears to have fixed mouse input. 2023-08-20 15:02:25 -04:00
Thomas Harte
ae56da2b0d Merge pull request #1155 from TomHarte/Templates
Show failing operations in human form.
2023-08-19 15:58:15 -04:00
Thomas Harte
90f16026bc Merge branch 'master' into Templates 2023-08-19 15:57:37 -04:00
Thomas Harte
d0284917cf Merge pull request #1154 from TomHarte/65816StackAgain
Clarify SH=1 upon TCS.
2023-08-19 15:56:30 -04:00
Thomas Harte
7815d18676 Merge branch 'master' into 65816StackAgain 2023-08-19 15:55:45 -04:00
Thomas Harte
222f6e92fb Merge pull request #1153 from TomHarte/IIgsInterrupts
IIgS: abstract VGC interrupt register; fix clearing bug.
2023-08-18 22:14:13 -04:00
Thomas Harte
b34403164e Abstract out VGC interrupt register; fix clearing bug. 2023-08-18 14:30:40 -04:00
Thomas Harte
3bd931937f Merge pull request #1152 from TomHarte/New6502TestGenerator
Generalise 65816 test generator to handle all 6502esques.
2023-08-18 11:28:57 -04:00
Thomas Harte
d207c13b6b Merge pull request #1151 from TomHarte/STopByteAgain
Fix S top byte overwrite.
2023-08-18 11:28:51 -04:00
Thomas Harte
ca75822dbe Fix restart_operation_fetch. 2023-08-17 15:42:34 -04:00
Thomas Harte
d9df568dab Add faulty restart_operation_fetch. 2023-08-17 15:38:28 -04:00
Thomas Harte
26343148ae Use simplified control lines when appropriate. 2023-08-17 15:32:02 -04:00
Thomas Harte
fd0fe66851 Omit unsupported registers and flags. 2023-08-17 15:24:08 -04:00
Thomas Harte
c41ed191dc Fix S top byte overwrite. 2023-08-17 14:51:13 -04:00
Thomas Harte
833613b68a Fix S top byte overwrite. 2023-08-17 14:50:55 -04:00
Thomas Harte
0a336baae2 Perform minor generalisation. 2023-08-17 14:50:43 -04:00
Thomas Harte
b9bd3f9b8c Merge pull request #1150 from TomHarte/65816Setter
Don't allow setting of an invalid S.
2023-08-07 09:19:59 -04:00
Thomas Harte
42024c1573 Don't allow setting of an invalid S. 2023-08-07 09:19:20 -04:00
Thomas Harte
0222dcf5ce Merge pull request #1149 from TomHarte/65816StackAgain
Add a between-instructions enforcement of SH = 1.
2023-08-05 15:14:53 -04:00
Thomas Harte
54103f1f34 Fix SH=1 reset; appropriate TCS. 2023-08-05 15:06:18 -04:00
Thomas Harte
c0eb401d04 Add a between-instructions enforcement of SH = 1. 2023-08-05 14:57:43 -04:00
Thomas Harte
ad5047dbd5 Show failing operations as strings. 2022-10-19 22:25:09 -04:00
897 changed files with 73178 additions and 39834 deletions

137
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,137 @@
name: Build
on: [pull_request]
jobs:
build-mac-xcodebuild:
name: Mac UI / xcodebuild / ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest] #[macos-13, macos-14, macos-15]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Make
working-directory: OSBindings/Mac
run: xcodebuild CODE_SIGN_IDENTITY=-
build-sdl-cmake:
name: SDL UI / cmake / ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies
shell: bash
run: |
case $RUNNER_OS in
Linux)
sudo apt-get --allow-releaseinfo-change update
sudo apt-get --fix-missing install cmake gcc-10 libsdl2-dev
;;
macOS)
brew uninstall cmake
brew install cmake sdl2
;;
esac
- name: Make
shell: bash
run: |
case $RUNNER_OS in
Linux)
jobs=$(nproc --all)
;;
macOS)
jobs=$(sysctl -n hw.activecpu)
;;
*)
jobs=1
esac
cmake -S. -Bbuild -DCLK_UI=SDL -DCMAKE_BUILD_TYPE=Release
cmake --build build -v -j"$jobs"
build-sdl-scons:
name: SDL UI / scons / ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies
shell: bash
run: |
case $RUNNER_OS in
Linux)
sudo apt-get --allow-releaseinfo-change update
sudo apt-get --fix-missing install gcc-10 libsdl2-dev scons
;;
macOS)
brew install scons sdl2
;;
esac
- name: Make
working-directory: OSBindings/SDL
shell: bash
run: |
case $RUNNER_OS in
Linux)
jobs=$(nproc --all)
;;
macOS)
jobs=$(sysctl -n hw.activecpu)
;;
*)
jobs=1
esac
scons -j"$jobs"
build-qt5:
name: Qt 5 / ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies
uses: jurplel/install-qt-action@v3
with:
version: '5.15.2'
archives: 'qtbase qtmultimedia qtx11extras icu'
- name: Make
working-directory: OSBindings/Qt
shell: bash
run: |
qmake -o Makefile clksignal.pro
make
# build-qt6:
# name: Qt 6 / ${{ matrix.os }}
# strategy:
# matrix:
# os: [ubuntu-latest]
# runs-on: ${{ matrix.os }}
# steps:
# - name: Checkout
# uses: actions/checkout@v4
# - name: Install dependencies
# uses: jurplel/install-qt-action@v4
# with:
# version: '6.8'
# archives: qtbase
# - name: Make
# working-directory: OSBindings/Qt
# shell: bash
# run: |
# qmake -o Makefile clksignal.pro
# make

View File

@@ -1,16 +0,0 @@
name: SDL/Ubuntu
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: sudo apt-get --allow-releaseinfo-change update && sudo apt-get --fix-missing install libsdl2-dev scons
- name: Make
working-directory: OSBindings/SDL
run: scons -j$(nproc --all)

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>
@@ -23,38 +22,38 @@ namespace Activity {
and/or to show or unshow status indicators.
*/
class Observer {
public:
/// 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.
/// If this flag is absent then the LED describes an ephemeral state, such as media access.
Persistent = (1 << 0),
};
public:
virtual ~Observer() = default;
/// Announces to the receiver that there is an LED of name @c name.
virtual void register_led([[maybe_unused]] const std::string &name, [[maybe_unused]] uint8_t presentation = 0) {}
/// 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.
/// If this flag is absent then the LED describes an ephemeral state, such as media access.
Persistent = (1 << 0),
};
/// Announces to the receiver that there is a drive of name @c name.
///
/// If a drive has the same name as an LED, that LED goes with this drive.
virtual void register_drive([[maybe_unused]] const std::string &name) {}
/// Announces to the receiver that there is an LED of name @c name.
virtual void register_led([[maybe_unused]] const std::string &name, [[maybe_unused]] uint8_t presentation = 0) {}
/// Informs the receiver of the new state of the LED with name @c name.
virtual void set_led_status([[maybe_unused]] const std::string &name, [[maybe_unused]] bool lit) {}
/// Announces to the receiver that there is a drive of name @c name.
///
/// If a drive has the same name as an LED, that LED goes with this drive.
virtual void register_drive([[maybe_unused]] const std::string &name) {}
enum class DriveEvent {
StepNormal,
StepBelowZero,
StepBeyondMaximum
};
/// Informs the receiver of the new state of the LED with name @c name.
virtual void set_led_status([[maybe_unused]] const std::string &name, [[maybe_unused]] bool lit) {}
/// Informs the receiver that the named event just occurred for the drive with name @c name.
virtual void announce_drive_event([[maybe_unused]] const std::string &name, [[maybe_unused]] DriveEvent event) {}
enum class DriveEvent {
StepNormal,
StepBelowZero,
StepBeyondMaximum
};
/// Informs the receiver of the motor-on status of the drive with name @c name.
virtual void set_drive_motor_status([[maybe_unused]] const std::string &name, [[maybe_unused]] bool is_on) {}
/// Informs the receiver that the named event just occurred for the drive with name @c name.
virtual void announce_drive_event([[maybe_unused]] const std::string &name, [[maybe_unused]] DriveEvent event) {}
/// Informs the receiver of the motor-on status of the drive with name @c name.
virtual void set_drive_motor_status([[maybe_unused]] const std::string &name, [[maybe_unused]] bool is_on) {}
};
}
#endif /* ActivityObserver_h */

View File

@@ -6,19 +6,15 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef ActivitySource_h
#define ActivitySource_h
#pragma once
#include "Observer.hpp"
namespace Activity {
class Source {
public:
virtual void set_activity_observer(Observer *observer) = 0;
public:
virtual void set_activity_observer(Observer *) = 0;
};
}
#endif /* ActivitySource_h */

View File

@@ -10,7 +10,7 @@
using namespace Analyser::Dynamic;
float ConfidenceCounter::get_confidence() {
float ConfidenceCounter::confidence() const {
return float(hits_) / float(hits_ + misses_);
}

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef ConfidenceCounter_hpp
#define ConfidenceCounter_hpp
#pragma once
#include "ConfidenceSource.hpp"
@@ -19,27 +18,25 @@ namespace Analyser::Dynamic {
The initial value of the confidence counter is 0.5.
*/
class ConfidenceCounter: public ConfidenceSource {
public:
/*! @returns The computed probability, based on the history of events. */
float get_confidence() final;
public:
/*! @returns The computed probability, based on the history of events. */
float confidence() const final;
/*! Records an event that implies this is the appropriate class: pushes probability up towards 1.0. */
void add_hit();
/*! Records an event that implies this is the appropriate class: pushes probability up towards 1.0. */
void add_hit();
/*! Records an event that implies this is not the appropriate class: pushes probability down towards 0.0. */
void add_miss();
/*! Records an event that implies this is not the appropriate class: pushes probability down towards 0.0. */
void add_miss();
/*!
Records an event that could be correct but isn't necessarily so; which can push probability
down towards 0.5, but will never push it upwards.
*/
void add_equivocal();
/*!
Records an event that could be correct but isn't necessarily so; which can push probability
down towards 0.5, but will never push it upwards.
*/
void add_equivocal();
private:
int hits_ = 1;
int misses_ = 1;
private:
int hits_ = 1;
int misses_ = 1;
};
}
#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 {
@@ -18,9 +17,7 @@ namespace Analyser::Dynamic {
program is handed to an Atari 2600 then its confidence should grow towards 1.0.
*/
struct ConfidenceSource {
virtual float get_confidence() = 0;
virtual float confidence() const = 0;
};
}
#endif /* ConfidenceSource_hpp */

View File

@@ -13,16 +13,19 @@
using namespace Analyser::Dynamic;
ConfidenceSummary::ConfidenceSummary(const std::vector<ConfidenceSource *> &sources, const std::vector<float> &weights) :
ConfidenceSummary::ConfidenceSummary(
const std::vector<ConfidenceSource *> &sources,
const std::vector<float> &weights
) :
sources_(sources), weights_(weights) {
assert(weights.size() == sources.size());
weight_sum_ = std::accumulate(weights.begin(), weights.end(), 0.0f);
}
float ConfidenceSummary::get_confidence() {
float ConfidenceSummary::confidence() const {
float result = 0.0f;
for(std::size_t index = 0; index < sources_.size(); ++index) {
result += sources_[index]->get_confidence() * weights_[index];
result += sources_[index]->confidence() * weights_[index];
}
return result / weight_sum_;
}

View File

@@ -6,8 +6,7 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef ConfidenceSummary_hpp
#define ConfidenceSummary_hpp
#pragma once
#include "ConfidenceSource.hpp"
@@ -19,26 +18,24 @@ namespace Analyser::Dynamic {
Summaries a collection of confidence sources by calculating their weighted sum.
*/
class ConfidenceSummary: public ConfidenceSource {
public:
/*!
Instantiates a summary that will produce the weighted sum of
@c sources, each using the corresponding entry of @c weights.
public:
/*!
Instantiates a summary that will produce the weighted sum of
@c sources, each using the corresponding entry of @c weights.
Requires that @c sources and @c weights are of the same length.
*/
ConfidenceSummary(
const std::vector<ConfidenceSource *> &sources,
const std::vector<float> &weights);
Requires that @c sources and @c weights are of the same length.
*/
ConfidenceSummary(
const std::vector<ConfidenceSource *> &sources,
const std::vector<float> &weights);
/*! @returns The weighted sum of all sources. */
float get_confidence() final;
/*! @returns The weighted sum of all sources. */
float confidence() const final;
private:
const std::vector<ConfidenceSource *> sources_;
const std::vector<float> weights_;
float weight_sum_;
private:
const std::vector<ConfidenceSource *> sources_;
const std::vector<float> weights_;
float weight_sum_;
};
}
#endif /* ConfidenceSummary_hpp */

View File

@@ -15,90 +15,90 @@ using namespace Analyser::Dynamic;
namespace {
class MultiStruct: public Reflection::Struct {
public:
MultiStruct(const std::vector<Configurable::Device *> &devices) : devices_(devices) {
for(auto device: devices) {
options_.emplace_back(device->get_options());
public:
MultiStruct(const std::vector<Configurable::Device *> &devices) : devices_(devices) {
for(auto device: devices) {
options_.emplace_back(device->get_options());
}
}
void apply() {
auto options = options_.begin();
for(auto device: devices_) {
device->set_options(*options);
++options;
}
}
std::vector<std::string> all_keys() const final {
std::set<std::string> keys;
for(auto &options: options_) {
const auto new_keys = options->all_keys();
keys.insert(new_keys.begin(), new_keys.end());
}
return std::vector<std::string>(keys.begin(), keys.end());
}
std::vector<std::string> values_for(const std::string &name) const final {
std::set<std::string> values;
for(auto &options: options_) {
const auto new_values = options->values_for(name);
values.insert(new_values.begin(), new_values.end());
}
return std::vector<std::string>(values.begin(), values.end());
}
const std::type_info *type_of(const std::string &name) const final {
for(auto &options: options_) {
auto info = options->type_of(name);
if(info) return info;
}
return nullptr;
}
size_t count_of(const std::string &name) const final {
for(auto &options: options_) {
auto info = options->type_of(name);
if(info) return options->count_of(name);
}
return 0;
}
const void *get(const std::string &name) const final {
for(auto &options: options_) {
auto value = options->get(name);
if(value) return value;
}
return nullptr;
}
void *get(const std::string &name) final {
for(auto &options: options_) {
auto value = options->get(name);
if(value) return value;
}
return nullptr;
}
void set(const std::string &name, const void *value, const size_t offset) final {
const auto safe_type = type_of(name);
if(!safe_type) return;
// Set this property only where the child's type is the same as that
// which was returned from here for type_of.
for(auto &options: options_) {
const auto type = options->type_of(name);
if(!type) continue;
if(*type == *safe_type) {
options->set(name, value, offset);
}
}
}
void apply() {
auto options = options_.begin();
for(auto device: devices_) {
device->set_options(*options);
++options;
}
}
std::vector<std::string> all_keys() const final {
std::set<std::string> keys;
for(auto &options: options_) {
const auto new_keys = options->all_keys();
keys.insert(new_keys.begin(), new_keys.end());
}
return std::vector<std::string>(keys.begin(), keys.end());
}
std::vector<std::string> values_for(const std::string &name) const final {
std::set<std::string> values;
for(auto &options: options_) {
const auto new_values = options->values_for(name);
values.insert(new_values.begin(), new_values.end());
}
return std::vector<std::string>(values.begin(), values.end());
}
const std::type_info *type_of(const std::string &name) const final {
for(auto &options: options_) {
auto info = options->type_of(name);
if(info) return info;
}
return nullptr;
}
size_t count_of(const std::string &name) const final {
for(auto &options: options_) {
auto info = options->type_of(name);
if(info) return options->count_of(name);
}
return 0;
}
const void *get(const std::string &name) const final {
for(auto &options: options_) {
auto value = options->get(name);
if(value) return value;
}
return nullptr;
}
void *get(const std::string &name) final {
for(auto &options: options_) {
auto value = options->get(name);
if(value) return value;
}
return nullptr;
}
void set(const std::string &name, const void *value, size_t offset) final {
const auto safe_type = type_of(name);
if(!safe_type) return;
// Set this property only where the child's type is the same as that
// which was returned from here for type_of.
for(auto &options: options_) {
const auto type = options->type_of(name);
if(!type) continue;
if(*type == *safe_type) {
options->set(name, value, offset);
}
}
}
private:
const std::vector<Configurable::Device *> &devices_;
std::vector<std::unique_ptr<Reflection::Struct>> options_;
private:
const std::vector<Configurable::Device *> &devices_;
std::vector<std::unique_ptr<Reflection::Struct>> options_;
};
}
@@ -115,6 +115,6 @@ void MultiConfigurable::set_options(const std::unique_ptr<Reflection::Struct> &s
options->apply();
}
std::unique_ptr<Reflection::Struct> MultiConfigurable::get_options() {
std::unique_ptr<Reflection::Struct> MultiConfigurable::get_options() const {
return std::make_unique<MultiStruct>(devices_);
}

View File

@@ -6,11 +6,10 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiConfigurable_hpp
#define MultiConfigurable_hpp
#pragma once
#include "../../../../Machines/DynamicMachine.hpp"
#include "../../../../Configurable/Configurable.hpp"
#include "Machines/DynamicMachine.hpp"
#include "Configurable/Configurable.hpp"
#include <memory>
#include <vector>
@@ -24,17 +23,15 @@ namespace Analyser::Dynamic {
order of delivered messages.
*/
class MultiConfigurable: public Configurable::Device {
public:
MultiConfigurable(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines);
public:
MultiConfigurable(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &);
// Below is the standard Configurable::Device interface; see there for documentation.
void set_options(const std::unique_ptr<Reflection::Struct> &options) final;
std::unique_ptr<Reflection::Struct> get_options() final;
// Below is the standard Configurable::Device interface; see there for documentation.
void set_options(const std::unique_ptr<Reflection::Struct> &) final;
std::unique_ptr<Reflection::Struct> get_options() const final;
private:
std::vector<Configurable::Device *> devices_;
private:
std::vector<Configurable::Device *> devices_;
};
}
#endif /* MultiConfigurable_hpp */

View File

@@ -15,52 +15,52 @@ using namespace Analyser::Dynamic;
namespace {
class MultiJoystick: public Inputs::Joystick {
public:
MultiJoystick(std::vector<MachineTypes::JoystickMachine *> &machines, std::size_t index) {
for(const auto &machine: machines) {
const auto &joysticks = machine->get_joysticks();
if(joysticks.size() >= index) {
joysticks_.push_back(joysticks[index].get());
}
public:
MultiJoystick(std::vector<MachineTypes::JoystickMachine *> &machines, const std::size_t index) {
for(const auto &machine: machines) {
const auto &joysticks = machine->get_joysticks();
if(joysticks.size() > index) {
joysticks_.push_back(joysticks[index].get());
}
}
}
const std::vector<Input> &get_inputs() final {
if(inputs.empty()) {
for(const auto &joystick: joysticks_) {
std::vector<Input> joystick_inputs = joystick->get_inputs();
for(const auto &input: joystick_inputs) {
if(std::find(inputs.begin(), inputs.end(), input) != inputs.end()) {
inputs.push_back(input);
}
const std::vector<Input> &get_inputs() final {
if(inputs.empty()) {
for(const auto &joystick: joysticks_) {
std::vector<Input> joystick_inputs = joystick->get_inputs();
for(const auto &input: joystick_inputs) {
if(std::find(inputs.begin(), inputs.end(), input) != inputs.end()) {
inputs.push_back(input);
}
}
}
return inputs;
}
void set_input(const Input &digital_input, bool is_active) final {
for(const auto &joystick: joysticks_) {
joystick->set_input(digital_input, is_active);
}
}
return inputs;
}
void set_input(const Input &digital_input, float value) final {
for(const auto &joystick: joysticks_) {
joystick->set_input(digital_input, value);
}
void set_input(const Input &digital_input, const bool is_active) final {
for(const auto &joystick: joysticks_) {
joystick->set_input(digital_input, is_active);
}
}
void reset_all_inputs() final {
for(const auto &joystick: joysticks_) {
joystick->reset_all_inputs();
}
void set_input(const Input &digital_input, const float value) final {
for(const auto &joystick: joysticks_) {
joystick->set_input(digital_input, value);
}
}
private:
std::vector<Input> inputs;
std::vector<Inputs::Joystick *> joysticks_;
void reset_all_inputs() final {
for(const auto &joystick: joysticks_) {
joystick->reset_all_inputs();
}
}
private:
std::vector<Input> inputs;
std::vector<Inputs::Joystick *> joysticks_;
};
}

View File

@@ -6,10 +6,9 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiJoystickMachine_hpp
#define MultiJoystickMachine_hpp
#pragma once
#include "../../../../Machines/DynamicMachine.hpp"
#include "Machines/DynamicMachine.hpp"
#include <memory>
#include <vector>
@@ -23,16 +22,14 @@ namespace Analyser::Dynamic {
order of delivered messages.
*/
class MultiJoystickMachine: public MachineTypes::JoystickMachine {
public:
MultiJoystickMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines);
public:
MultiJoystickMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &);
// Below is the standard JoystickMachine::Machine interface; see there for documentation.
const std::vector<std::unique_ptr<Inputs::Joystick>> &get_joysticks() final;
// Below is the standard JoystickMachine::Machine interface; see there for documentation.
const std::vector<std::unique_ptr<Inputs::Joystick>> &get_joysticks() final;
private:
std::vector<std::unique_ptr<Inputs::Joystick>> joysticks_;
private:
std::vector<std::unique_ptr<Inputs::Joystick>> joysticks_;
};
}
#endif /* MultiJoystickMachine_hpp */

View File

@@ -24,7 +24,7 @@ void MultiKeyboardMachine::clear_all_keys() {
}
}
void MultiKeyboardMachine::set_key_state(uint16_t key, bool is_pressed) {
void MultiKeyboardMachine::set_key_state(const uint16_t key, const bool is_pressed) {
for(const auto &machine: machines_) {
machine->set_key_state(key, is_pressed);
}
@@ -36,7 +36,7 @@ void MultiKeyboardMachine::type_string(const std::string &string) {
}
}
bool MultiKeyboardMachine::can_type(char c) const {
bool MultiKeyboardMachine::can_type(const char c) const {
bool can_type = true;
for(const auto &machine: machines_) {
can_type &= machine->can_type(c);
@@ -51,15 +51,23 @@ Inputs::Keyboard &MultiKeyboardMachine::get_keyboard() {
MultiKeyboardMachine::MultiKeyboard::MultiKeyboard(const std::vector<::MachineTypes::KeyboardMachine *> &machines)
: machines_(machines) {
for(const auto &machine: machines_) {
observed_keys_.insert(machine->get_keyboard().observed_keys().begin(), machine->get_keyboard().observed_keys().end());
observed_keys_.insert(
machine->get_keyboard().observed_keys().begin(),
machine->get_keyboard().observed_keys().end()
);
is_exclusive_ |= machine->get_keyboard().is_exclusive();
}
}
bool MultiKeyboardMachine::MultiKeyboard::set_key_pressed(Key key, char value, bool is_pressed) {
bool MultiKeyboardMachine::MultiKeyboard::set_key_pressed(
const Key key,
const char value,
const bool is_pressed,
const 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,11 +6,10 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiKeyboardMachine_hpp
#define MultiKeyboardMachine_hpp
#pragma once
#include "../../../../Machines/DynamicMachine.hpp"
#include "../../../../Machines/KeyboardMachine.hpp"
#include "Machines/DynamicMachine.hpp"
#include "Machines/KeyboardMachine.hpp"
#include <memory>
#include <vector>
@@ -24,36 +23,34 @@ namespace Analyser::Dynamic {
order of delivered messages.
*/
class MultiKeyboardMachine: public MachineTypes::KeyboardMachine {
private:
std::vector<MachineTypes::KeyboardMachine *> machines_;
class MultiKeyboard: public Inputs::Keyboard {
public:
MultiKeyboard(const std::vector<MachineTypes::KeyboardMachine *> &machines);
bool set_key_pressed(Key key, char value, bool is_pressed) final;
void reset_all_keys() final;
const std::set<Key> &observed_keys() const final;
bool is_exclusive() const final;
private:
const std::vector<MachineTypes::KeyboardMachine *> &machines_;
std::set<Key> observed_keys_;
bool is_exclusive_ = false;
};
std::unique_ptr<MultiKeyboard> keyboard_;
private:
std::vector<MachineTypes::KeyboardMachine *> machines_;
class MultiKeyboard: public Inputs::Keyboard {
public:
MultiKeyboardMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines);
MultiKeyboard(const std::vector<MachineTypes::KeyboardMachine *> &);
// Below is the standard KeyboardMachine::Machine interface; see there for documentation.
void clear_all_keys() final;
void set_key_state(uint16_t key, bool is_pressed) final;
void type_string(const std::string &) final;
bool can_type(char c) const final;
Inputs::Keyboard &get_keyboard() 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;
private:
const std::vector<MachineTypes::KeyboardMachine *> &machines_;
std::set<Key> observed_keys_;
bool is_exclusive_ = false;
};
std::unique_ptr<MultiKeyboard> keyboard_;
public:
MultiKeyboardMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines);
// Below is the standard KeyboardMachine::Machine interface; see there for documentation.
void clear_all_keys() final;
void set_key_state(uint16_t key, bool is_pressed) final;
void type_string(const std::string &) final;
bool can_type(char c) const final;
Inputs::Keyboard &get_keyboard() final;
};
}
#endif /* MultiKeyboardMachine_hpp */

View File

@@ -7,6 +7,7 @@
//
#include "MultiMediaTarget.hpp"
#include <unordered_set>
using namespace Analyser::Dynamic;
@@ -18,9 +19,38 @@ MultiMediaTarget::MultiMediaTarget(const std::vector<std::unique_ptr<::Machine::
}
bool MultiMediaTarget::insert_media(const Analyser::Static::Media &media) {
// TODO: copy media afresh for each target machine; media
// generally has mutable state.
bool inserted = false;
for(const auto &target : targets_) {
inserted |= target->insert_media(media);
}
return inserted;
}
MultiMediaChangeObserver::MultiMediaChangeObserver(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines) {
for(const auto &machine: machines) {
auto media_change_observer = machine->media_change_observer();
if(media_change_observer) targets_.push_back(media_change_observer);
}
}
using ChangeEffect = MachineTypes::MediaChangeObserver::ChangeEffect;
ChangeEffect MultiMediaChangeObserver::effect_for_file_did_change(const std::string &name) const {
if(targets_.empty()) {
return ChangeEffect::None;
}
std::unordered_set<ChangeEffect> effects;
for(const auto &target: targets_) {
effects.insert(target->effect_for_file_did_change(name));
}
// No agreement => restart.
if(effects.size() > 1) {
return ChangeEffect::RestartMachine;
}
return *effects.begin();
}

View File

@@ -6,11 +6,10 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiMediaTarget_hpp
#define MultiMediaTarget_hpp
#pragma once
#include "../../../../Machines/MediaTarget.hpp"
#include "../../../../Machines/DynamicMachine.hpp"
#include "Machines/MediaTarget.hpp"
#include "Machines/DynamicMachine.hpp"
#include <memory>
#include <vector>
@@ -24,16 +23,25 @@ namespace Analyser::Dynamic {
order of delivered messages.
*/
struct MultiMediaTarget: public MachineTypes::MediaTarget {
public:
MultiMediaTarget(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines);
public:
MultiMediaTarget(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &);
// Below is the standard MediaTarget::Machine interface; see there for documentation.
bool insert_media(const Analyser::Static::Media &media) final;
// Below is the standard MediaTarget::Machine interface; see there for documentation.
bool insert_media(const Analyser::Static::Media &) final;
private:
std::vector<MachineTypes::MediaTarget *> targets_;
private:
std::vector<MachineTypes::MediaTarget *> targets_;
};
struct MultiMediaChangeObserver: public MachineTypes::MediaChangeObserver {
public:
MultiMediaChangeObserver(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &);
// Below is the standard MediaTarget::Machine interface; see there for documentation.
ChangeEffect effect_for_file_did_change(const std::string &) const final;
private:
std::vector<MachineTypes::MediaChangeObserver *> targets_;
};
}
#endif /* MultiMediaTarget_hpp */

View File

@@ -19,7 +19,7 @@ template <typename MachineType>
void MultiInterface<MachineType>::perform_parallel(const std::function<void(MachineType *)> &function) {
// Apply a blunt force parallelisation of the machines; each run_for is dispatched
// to a separate queue and this queue will block until all are done.
volatile std::size_t outstanding_machines;
std::size_t outstanding_machines;
std::condition_variable condition;
std::mutex mutex;
{
@@ -33,7 +33,7 @@ void MultiInterface<MachineType>::perform_parallel(const std::function<void(Mach
if(machine) function(machine);
std::lock_guard lock(mutex);
outstanding_machines--;
--outstanding_machines;
condition.notify_all();
});
}
@@ -53,7 +53,7 @@ void MultiInterface<MachineType>::perform_serial(const std::function<void(Machin
}
// MARK: - MultiScanProducer
void MultiScanProducer::set_scan_target(Outputs::Display::ScanTarget *scan_target) {
void MultiScanProducer::set_scan_target(Outputs::Display::ScanTarget *const scan_target) {
scan_target_ = scan_target;
std::lock_guard machines_lock(machines_mutex_);
@@ -80,7 +80,12 @@ void MultiScanProducer::did_change_machine_order() {
}
// MARK: - MultiAudioProducer
MultiAudioProducer::MultiAudioProducer(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines, std::recursive_mutex &machines_mutex) : MultiInterface(machines, machines_mutex) {
MultiAudioProducer::MultiAudioProducer(
const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines,
std::recursive_mutex &machines_mutex
) :
MultiInterface(machines, machines_mutex)
{
speaker_ = MultiSpeaker::create(machines);
}
@@ -96,10 +101,10 @@ void MultiAudioProducer::did_change_machine_order() {
// MARK: - MultiTimedMachine
void MultiTimedMachine::run_for(Time::Seconds duration) {
void MultiTimedMachine::run_for(const Time::Seconds duration) {
perform_parallel([duration](::MachineTypes::TimedMachine *machine) {
if(machine->get_confidence() >= 0.01f) machine->run_for(duration);
});
if(delegate_) delegate_->did_run_machines(this);
if(delegate_) delegate_->did_run_machines(*this);
}

View File

@@ -6,12 +6,11 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiProducer_hpp
#define MultiProducer_hpp
#pragma once
#include "../../../../Concurrency/AsyncTaskQueue.hpp"
#include "../../../../Machines/MachineTypes.hpp"
#include "../../../../Machines/DynamicMachine.hpp"
#include "Concurrency/AsyncTaskQueue.hpp"
#include "Machines/MachineTypes.hpp"
#include "Machines/DynamicMachine.hpp"
#include "MultiSpeaker.hpp"
@@ -22,88 +21,91 @@
namespace Analyser::Dynamic {
template <typename MachineType> class MultiInterface {
public:
MultiInterface(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines, std::recursive_mutex &machines_mutex) :
machines_(machines), machines_mutex_(machines_mutex), queues_(machines.size()) {}
public:
MultiInterface(
const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines,
std::recursive_mutex &machines_mutex
) :
machines_(machines), machines_mutex_(machines_mutex), queues_(machines.size()) {}
protected:
/*!
Performs a parallel for operation across all machines, performing the supplied
function on each and returning only once all applications have completed.
protected:
/*!
Performs a parallel for operation across all machines, performing the supplied
function on each and returning only once all applications have completed.
No guarantees are extended as to which thread operations will occur on.
*/
void perform_parallel(const std::function<void(MachineType *)> &);
No guarantees are extended as to which thread operations will occur on.
*/
void perform_parallel(const std::function<void(MachineType *)> &);
/*!
Performs a serial for operation across all machines, performing the supplied
function on each on the calling thread.
*/
void perform_serial(const std::function<void(MachineType *)> &);
/*!
Performs a serial for operation across all machines, performing the supplied
function on each on the calling thread.
*/
void perform_serial(const std::function<void(MachineType *)> &);
protected:
const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines_;
std::recursive_mutex &machines_mutex_;
protected:
const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines_;
std::recursive_mutex &machines_mutex_;
private:
std::vector<Concurrency::AsyncTaskQueue<true>> queues_;
private:
std::vector<Concurrency::AsyncTaskQueue<true>> queues_;
};
class MultiTimedMachine: public MultiInterface<MachineTypes::TimedMachine>, public MachineTypes::TimedMachine {
public:
using MultiInterface::MultiInterface;
public:
using MultiInterface::MultiInterface;
/*!
Provides a mechanism by which a delegate can be informed each time a call to run_for has
been received.
*/
struct Delegate {
virtual void did_run_machines(MultiTimedMachine *) = 0;
};
/// Sets @c delegate as the receiver of delegate messages.
void set_delegate(Delegate *delegate) {
delegate_ = delegate;
}
/*!
Provides a mechanism by which a delegate can be informed each time a call to run_for has
been received.
*/
struct Delegate {
virtual void did_run_machines(MultiTimedMachine &) = 0;
};
/// Sets @c delegate as the receiver of delegate messages.
void set_delegate(Delegate *const delegate) {
delegate_ = delegate;
}
void run_for(Time::Seconds duration) final;
void run_for(Time::Seconds duration) final;
private:
void run_for(const Cycles) final {}
Delegate *delegate_ = nullptr;
private:
void run_for(Cycles) final {}
Delegate *delegate_ = nullptr;
};
class MultiScanProducer: public MultiInterface<MachineTypes::ScanProducer>, public MachineTypes::ScanProducer {
public:
using MultiInterface::MultiInterface;
public:
using MultiInterface::MultiInterface;
/*!
Informs the MultiScanProducer that the order of machines has changed; it
uses this as an opportunity to synthesis any CRTMachine::Machine::Delegate messages that
are necessary to bridge the gap between one machine and the next.
*/
void did_change_machine_order();
/*!
Informs the MultiScanProducer that the order of machines has changed; it
uses this as an opportunity to synthesis any CRTMachine::Machine::Delegate messages that
are necessary to bridge the gap between one machine and the next.
*/
void did_change_machine_order();
void set_scan_target(Outputs::Display::ScanTarget *scan_target) final;
Outputs::Display::ScanStatus get_scan_status() const final;
void set_scan_target(Outputs::Display::ScanTarget *) final;
Outputs::Display::ScanStatus get_scan_status() const final;
private:
Outputs::Display::ScanTarget *scan_target_ = nullptr;
private:
Outputs::Display::ScanTarget *scan_target_ = nullptr;
};
class MultiAudioProducer: public MultiInterface<MachineTypes::AudioProducer>, public MachineTypes::AudioProducer {
public:
MultiAudioProducer(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines, std::recursive_mutex &machines_mutex);
public:
MultiAudioProducer(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &, std::recursive_mutex &);
/*!
Informs the MultiAudio that the order of machines has changed; it
uses this as an opportunity to switch speaker delegates as appropriate.
*/
void did_change_machine_order();
/*!
Informs the MultiAudio that the order of machines has changed; it
uses this as an opportunity to switch speaker delegates as appropriate.
*/
void did_change_machine_order();
Outputs::Speaker::Speaker *get_speaker() final;
Outputs::Speaker::Speaker *get_speaker() final;
private:
MultiSpeaker *speaker_ = nullptr;
private:
MultiSpeaker *speaker_ = nullptr;
};
/*!
@@ -115,5 +117,3 @@ class MultiAudioProducer: public MultiInterface<MachineTypes::AudioProducer>, pu
*/
}
#endif /* MultiProducer_hpp */

View File

@@ -28,7 +28,7 @@ MultiSpeaker::MultiSpeaker(const std::vector<Outputs::Speaker::Speaker *> &speak
}
}
float MultiSpeaker::get_ideal_clock_rate_in_range(float minimum, float maximum) {
float MultiSpeaker::get_ideal_clock_rate_in_range(const float minimum, const float maximum) {
float ideal = 0.0f;
for(const auto &speaker: speakers_) {
ideal += speaker->get_ideal_clock_rate_in_range(minimum, maximum);
@@ -37,7 +37,7 @@ float MultiSpeaker::get_ideal_clock_rate_in_range(float minimum, float maximum)
return ideal / float(speakers_.size());
}
void MultiSpeaker::set_computed_output_rate(float cycles_per_second, int buffer_size, bool stereo) {
void MultiSpeaker::set_computed_output_rate(const float cycles_per_second, const int buffer_size, const bool stereo) {
stereo_output_ = stereo;
for(const auto &speaker: speakers_) {
speaker->set_computed_output_rate(cycles_per_second, buffer_size, stereo);
@@ -54,39 +54,39 @@ bool MultiSpeaker::get_is_stereo() {
return false;
}
void MultiSpeaker::set_output_volume(float volume) {
void MultiSpeaker::set_output_volume(const float volume) {
for(const auto &speaker: speakers_) {
speaker->set_output_volume(volume);
}
}
void MultiSpeaker::speaker_did_complete_samples(Speaker *speaker, const std::vector<int16_t> &buffer) {
auto delegate = delegate_.load(std::memory_order::memory_order_relaxed);
void MultiSpeaker::speaker_did_complete_samples(Speaker &speaker, const std::vector<int16_t> &buffer) {
auto delegate = delegate_.load(std::memory_order_relaxed);
if(!delegate) return;
{
std::lock_guard lock_guard(front_speaker_mutex_);
if(speaker != front_speaker_) return;
if(&speaker != front_speaker_) return;
}
did_complete_samples(this, buffer, stereo_output_);
}
void MultiSpeaker::speaker_did_change_input_clock(Speaker *speaker) {
auto delegate = delegate_.load(std::memory_order::memory_order_relaxed);
void MultiSpeaker::speaker_did_change_input_clock(Speaker &speaker) {
auto delegate = delegate_.load(std::memory_order_relaxed);
if(!delegate) return;
{
std::lock_guard lock_guard(front_speaker_mutex_);
if(speaker != front_speaker_) return;
if(&speaker != front_speaker_) return;
}
delegate->speaker_did_change_input_clock(this);
delegate->speaker_did_change_input_clock(*this);
}
void MultiSpeaker::set_new_front_machine(::Machine::DynamicMachine *machine) {
void MultiSpeaker::set_new_front_machine(::Machine::DynamicMachine *const machine) {
{
std::lock_guard lock_guard(front_speaker_mutex_);
front_speaker_ = machine->audio_producer()->get_speaker();
}
auto delegate = delegate_.load(std::memory_order::memory_order_relaxed);
auto delegate = delegate_.load(std::memory_order_relaxed);
if(delegate) {
delegate->speaker_did_change_input_clock(this);
delegate->speaker_did_change_input_clock(*this);
}
}

View File

@@ -6,11 +6,10 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiSpeaker_hpp
#define MultiSpeaker_hpp
#pragma once
#include "../../../../Machines/DynamicMachine.hpp"
#include "../../../../Outputs/Speaker/Speaker.hpp"
#include "Machines/DynamicMachine.hpp"
#include "Outputs/Speaker/Speaker.hpp"
#include <memory>
#include <mutex>
@@ -26,34 +25,32 @@ namespace Analyser::Dynamic {
abreast of the current frontmost machine.
*/
class MultiSpeaker: public Outputs::Speaker::Speaker, Outputs::Speaker::Speaker::Delegate {
public:
/*!
Provides a construction mechanism that may return nullptr, in the case that all included
machines return nullptr as their speaker.
*/
static MultiSpeaker *create(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines);
public:
/*!
Provides a construction mechanism that may return nullptr, in the case that all included
machines return nullptr as their speaker.
*/
static MultiSpeaker *create(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &);
/// This class requires the caller to nominate changes in the frontmost machine.
void set_new_front_machine(::Machine::DynamicMachine *machine);
/// This class requires the caller to nominate changes in the frontmost machine.
void set_new_front_machine(::Machine::DynamicMachine *);
// Below is the standard Outputs::Speaker::Speaker interface; see there for documentation.
float get_ideal_clock_rate_in_range(float minimum, float maximum) override;
void set_computed_output_rate(float cycles_per_second, int buffer_size, bool stereo) override;
bool get_is_stereo() override;
void set_output_volume(float) override;
// Below is the standard Outputs::Speaker::Speaker interface; see there for documentation.
float get_ideal_clock_rate_in_range(float minimum, float maximum) override;
void set_computed_output_rate(float cycles_per_second, int buffer_size, bool stereo) override;
bool get_is_stereo() override;
void set_output_volume(float) override;
private:
void speaker_did_complete_samples(Speaker *speaker, const std::vector<int16_t> &buffer) final;
void speaker_did_change_input_clock(Speaker *speaker) final;
MultiSpeaker(const std::vector<Outputs::Speaker::Speaker *> &speakers);
private:
void speaker_did_complete_samples(Speaker &, const std::vector<int16_t> &buffer) final;
void speaker_did_change_input_clock(Speaker &) final;
MultiSpeaker(const std::vector<Outputs::Speaker::Speaker *> &speakers);
std::vector<Outputs::Speaker::Speaker *> speakers_;
Outputs::Speaker::Speaker *front_speaker_ = nullptr;
std::mutex front_speaker_mutex_;
std::vector<Outputs::Speaker::Speaker *> speakers_;
Outputs::Speaker::Speaker *front_speaker_ = nullptr;
std::mutex front_speaker_mutex_;
bool stereo_output_ = false;
bool stereo_output_ = false;
};
}
#endif /* MultiSpeaker_hpp */

View File

@@ -7,10 +7,16 @@
//
#include "MultiMachine.hpp"
#include "../../../Outputs/Log.hpp"
#include "Outputs/Log.hpp"
#include <algorithm>
namespace {
Log::Logger<Log::Source::MultiMachine> logger;
}
using namespace Analyser::Dynamic;
MultiMachine::MultiMachine(std::vector<std::unique_ptr<DynamicMachine>> &&machines) :
@@ -21,7 +27,9 @@ MultiMachine::MultiMachine(std::vector<std::unique_ptr<DynamicMachine>> &&machin
audio_producer_(machines_, machines_mutex_),
joystick_machine_(machines_),
keyboard_machine_(machines_),
media_target_(machines_) {
media_target_(machines_),
media_change_observer_(machines_)
{
timed_machine_.set_delegate(this);
}
@@ -29,13 +37,13 @@ Activity::Source *MultiMachine::activity_source() {
return nullptr; // TODO
}
#define Provider(type, name, member) \
type *MultiMachine::name() { \
if(has_picked_) { \
#define Provider(type, name, member) \
type *MultiMachine::name() { \
if(has_picked_) { \
return machines_.front()->name(); \
} else { \
return &member; \
} \
} else { \
return &member; \
} \
}
Provider(Configurable::Device, configurable_device, configurable_)
@@ -45,6 +53,7 @@ Provider(MachineTypes::AudioProducer, audio_producer, audio_producer_)
Provider(MachineTypes::JoystickMachine, joystick_machine, joystick_machine_)
Provider(MachineTypes::KeyboardMachine, keyboard_machine, keyboard_machine_)
Provider(MachineTypes::MediaTarget, media_target, media_target_)
Provider(MachineTypes::MediaChangeObserver, media_change_observer, media_change_observer_)
MachineTypes::MouseMachine *MultiMachine::mouse_machine() {
// TODO.
@@ -59,15 +68,16 @@ bool MultiMachine::would_collapse(const std::vector<std::unique_ptr<DynamicMachi
(machines.front()->timed_machine()->get_confidence() >= 2.0f * machines[1]->timed_machine()->get_confidence());
}
void MultiMachine::did_run_machines(MultiTimedMachine *) {
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.InfoEnabled) {
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,17 +6,16 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef MultiMachine_hpp
#define MultiMachine_hpp
#pragma once
#include "../../../Machines/DynamicMachine.hpp"
#include "Machines/DynamicMachine.hpp"
#include "Implementation/MultiProducer.hpp"
#include "Implementation/MultiConfigurable.hpp"
#include "Implementation/MultiProducer.hpp"
#include "Implementation/MultiJoystickMachine.hpp"
#include "Implementation/MultiKeyboardMachine.hpp"
#include "Implementation/MultiMediaTarget.hpp"
#include "Analyser/Dynamic/MultiMachine/Implementation/MultiProducer.hpp"
#include "Analyser/Dynamic/MultiMachine/Implementation/MultiConfigurable.hpp"
#include "Analyser/Dynamic/MultiMachine/Implementation/MultiProducer.hpp"
#include "Analyser/Dynamic/MultiMachine/Implementation/MultiJoystickMachine.hpp"
#include "Analyser/Dynamic/MultiMachine/Implementation/MultiKeyboardMachine.hpp"
#include "Analyser/Dynamic/MultiMachine/Implementation/MultiMediaTarget.hpp"
#include <memory>
#include <mutex>
@@ -39,46 +38,46 @@ namespace Analyser::Dynamic {
the others in the set, that machine stops running.
*/
class MultiMachine: public ::Machine::DynamicMachine, public MultiTimedMachine::Delegate {
public:
/*!
Allows a potential MultiMachine creator to enquire as to whether there's any benefit in
requesting this class as a proxy.
public:
/*!
Allows a potential MultiMachine creator to enquire as to whether there's any benefit in
requesting this class as a proxy.
@returns @c true if the multimachine would discard all but the first machine in this list;
@c false otherwise.
*/
static bool would_collapse(const std::vector<std::unique_ptr<DynamicMachine>> &machines);
MultiMachine(std::vector<std::unique_ptr<DynamicMachine>> &&machines);
@returns @c true if the multimachine would discard all but the first machine in this list;
@c false otherwise.
*/
static bool would_collapse(const std::vector<std::unique_ptr<DynamicMachine>> &);
MultiMachine(std::vector<std::unique_ptr<DynamicMachine>> &&);
Activity::Source *activity_source() final;
Configurable::Device *configurable_device() final;
MachineTypes::TimedMachine *timed_machine() final;
MachineTypes::ScanProducer *scan_producer() final;
MachineTypes::AudioProducer *audio_producer() final;
MachineTypes::JoystickMachine *joystick_machine() final;
MachineTypes::KeyboardMachine *keyboard_machine() final;
MachineTypes::MouseMachine *mouse_machine() final;
MachineTypes::MediaTarget *media_target() final;
void *raw_pointer() final;
Activity::Source *activity_source() final;
Configurable::Device *configurable_device() final;
MachineTypes::TimedMachine *timed_machine() final;
MachineTypes::ScanProducer *scan_producer() final;
MachineTypes::AudioProducer *audio_producer() final;
MachineTypes::JoystickMachine *joystick_machine() final;
MachineTypes::KeyboardMachine *keyboard_machine() final;
MachineTypes::MouseMachine *mouse_machine() final;
MachineTypes::MediaTarget *media_target() final;
MachineTypes::MediaChangeObserver *media_change_observer() final;
void *raw_pointer() final;
private:
void did_run_machines(MultiTimedMachine *) final;
private:
void did_run_machines(MultiTimedMachine &) final;
std::vector<std::unique_ptr<DynamicMachine>> machines_;
std::recursive_mutex machines_mutex_;
std::vector<std::unique_ptr<DynamicMachine>> machines_;
std::recursive_mutex machines_mutex_;
MultiConfigurable configurable_;
MultiTimedMachine timed_machine_;
MultiScanProducer scan_producer_;
MultiAudioProducer audio_producer_;
MultiJoystickMachine joystick_machine_;
MultiKeyboardMachine keyboard_machine_;
MultiMediaTarget media_target_;
MultiConfigurable configurable_;
MultiTimedMachine timed_machine_;
MultiScanProducer scan_producer_;
MultiAudioProducer audio_producer_;
MultiJoystickMachine joystick_machine_;
MultiKeyboardMachine keyboard_machine_;
MultiMediaTarget media_target_;
MultiMediaChangeObserver media_change_observer_;
void pick_first();
bool has_picked_ = false;
void pick_first();
bool has_picked_ = false;
};
}
#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 {
@@ -18,6 +17,7 @@ enum class Machine {
Atari2600,
AtariST,
Amiga,
Archimedes,
ColecoVision,
Electron,
Enterprise,
@@ -25,11 +25,11 @@ enum class Machine {
MasterSystem,
MSX,
Oric,
Plus4,
PCCompatible,
Vic20,
ZX8081,
ZXSpectrum,
};
}
#endif /* Machines_h */

View File

@@ -8,21 +8,22 @@
#include "Disk.hpp"
#include "../../../Storage/Disk/Controller/DiskController.hpp"
#include "../../../Storage/Disk/Encodings/MFM/Parser.hpp"
#include "../../../Numeric/CRC.hpp"
#include "Storage/Disk/Controller/DiskController.hpp"
#include "Storage/Disk/Encodings/MFM/Parser.hpp"
#include "Numeric/CRC.hpp"
#include <algorithm>
#include <cstring>
using namespace Analyser::Static::Acorn;
std::unique_ptr<Catalogue> Analyser::Static::Acorn::GetDFSCatalogue(const std::shared_ptr<Storage::Disk::Disk> &disk) {
// c.f. http://beebwiki.mdfs.net/Acorn_DFS_disc_format
auto catalogue = std::make_unique<Catalogue>();
Storage::Encodings::MFM::Parser parser(false, disk);
Storage::Encodings::MFM::Parser parser(Storage::Encodings::MFM::Density::Single, disk);
const Storage::Encodings::MFM::Sector *const names = parser.get_sector(0, 0, 0);
const Storage::Encodings::MFM::Sector *const details = parser.get_sector(0, 0, 1);
const Storage::Encodings::MFM::Sector *const names = parser.sector(0, 0, 0);
const Storage::Encodings::MFM::Sector *const details = parser.sector(0, 0, 1);
if(!names || !details) return nullptr;
if(names->samples.empty() || details->samples.empty()) return nullptr;
@@ -48,27 +49,39 @@ std::unique_ptr<Catalogue> Analyser::Static::Acorn::GetDFSCatalogue(const std::s
char name[10];
snprintf(name, 10, "%c.%.7s", names->samples[0][file_offset + 7] & 0x7f, &names->samples[0][file_offset]);
new_file.name = name;
new_file.load_address = uint32_t(details->samples[0][file_offset] | (details->samples[0][file_offset+1] << 8) | ((details->samples[0][file_offset+6]&0x0c) << 14));
new_file.execution_address = uint32_t(details->samples[0][file_offset+2] | (details->samples[0][file_offset+3] << 8) | ((details->samples[0][file_offset+6]&0xc0) << 10));
new_file.load_address = uint32_t(
details->samples[0][file_offset] |
(details->samples[0][file_offset+1] << 8) |
((details->samples[0][file_offset+6]&0x0c) << 14)
);
new_file.execution_address = uint32_t(
details->samples[0][file_offset+2] |
(details->samples[0][file_offset+3] << 8) |
((details->samples[0][file_offset+6]&0xc0) << 10)
);
if(names->samples[0][file_offset + 7] & 0x80) {
// File is locked; it may not be altered or deleted.
new_file.flags |= File::Flags::Locked;
}
long data_length = long(details->samples[0][file_offset+4] | (details->samples[0][file_offset+5] << 8) | ((details->samples[0][file_offset+6]&0x30) << 12));
auto data_length = long(
details->samples[0][file_offset+4] |
(details->samples[0][file_offset+5] << 8) |
((details->samples[0][file_offset+6]&0x30) << 12)
);
int start_sector = details->samples[0][file_offset+7] | ((details->samples[0][file_offset+6]&0x03) << 8);
new_file.data.reserve(size_t(data_length));
if(start_sector < 2) continue;
while(data_length > 0) {
uint8_t sector = uint8_t(start_sector % 10);
uint8_t track = uint8_t(start_sector / 10);
start_sector++;
const uint8_t sector = uint8_t(start_sector % 10);
const uint8_t track = uint8_t(start_sector / 10);
++start_sector;
Storage::Encodings::MFM::Sector *next_sector = parser.get_sector(0, track, sector);
const Storage::Encodings::MFM::Sector *next_sector = parser.sector(0, track, sector);
if(!next_sector) break;
long length_from_sector = std::min(data_length, 256l);
const long length_from_sector = std::min(data_length, 256l);
new_file.data.insert(new_file.data.end(), next_sector->samples[0].begin(), next_sector->samples[0].begin() + length_from_sector);
data_length -= length_from_sector;
}
@@ -84,36 +97,59 @@ std::unique_ptr<Catalogue> Analyser::Static::Acorn::GetDFSCatalogue(const std::s
*/
std::unique_ptr<Catalogue> Analyser::Static::Acorn::GetADFSCatalogue(const std::shared_ptr<Storage::Disk::Disk> &disk) {
auto catalogue = std::make_unique<Catalogue>();
Storage::Encodings::MFM::Parser parser(true, disk);
Storage::Encodings::MFM::Parser parser(Storage::Encodings::MFM::Density::Double, disk);
Storage::Encodings::MFM::Sector *free_space_map_second_half = parser.get_sector(0, 0, 1);
// Grab the second half of the free-space map because it has the boot option in it.
const Storage::Encodings::MFM::Sector *free_space_map_second_half = parser.sector(0, 0, 1);
if(!free_space_map_second_half) return nullptr;
catalogue->has_large_sectors = free_space_map_second_half->samples[0].size() == 1024;
// Possibility: this is a large-sector disk with an old-style free space map. In which
// case the above just read the start of the root directory.
uint8_t first_directory_sector = 2;
if(catalogue->has_large_sectors && !memcmp(&free_space_map_second_half->samples[0][1], "Hugo", 4)) {
free_space_map_second_half = parser.sector(0, 0, 0);
if(!free_space_map_second_half) return nullptr;
first_directory_sector = 1;
}
std::vector<uint8_t> root_directory;
root_directory.reserve(5 * 256);
for(uint8_t c = 2; c < 7; c++) {
const Storage::Encodings::MFM::Sector *const sector = parser.get_sector(0, 0, c);
root_directory.reserve(catalogue->has_large_sectors ? 2*1024 : 5*256);
for(uint8_t c = first_directory_sector; c < first_directory_sector + (catalogue->has_large_sectors ? 2 : 5); c++) {
const Storage::Encodings::MFM::Sector *const sector = parser.sector(0, 0, c);
if(!sector) return nullptr;
root_directory.insert(root_directory.end(), sector->samples[0].begin(), sector->samples[0].end());
}
// Quick sanity checks.
if(root_directory[0x4cb]) return nullptr;
if(root_directory[1] != 'H' || root_directory[2] != 'u' || root_directory[3] != 'g' || root_directory[4] != 'o') return nullptr;
if(root_directory[0x4FB] != 'H' || root_directory[0x4FC] != 'u' || root_directory[0x4FD] != 'g' || root_directory[0x4FE] != 'o') return nullptr;
// Check for end of directory marker.
if(root_directory[catalogue->has_large_sectors ? 0x7d7 : 0x4cb]) return nullptr;
switch(free_space_map_second_half->samples[0][0xfd]) {
default: catalogue->bootOption = Catalogue::BootOption::None; break;
case 1: catalogue->bootOption = Catalogue::BootOption::LoadBOOT; break;
case 2: catalogue->bootOption = Catalogue::BootOption::RunBOOT; break;
case 3: catalogue->bootOption = Catalogue::BootOption::ExecBOOT; break;
// Check for both directory identifiers.
const uint8_t *const start_id = &root_directory[1];
const uint8_t *const end_id = &root_directory[root_directory.size() - 5];
catalogue->is_hugo = !memcmp(start_id, "Hugo", 4) && !memcmp(end_id, "Hugo", 4);
const bool is_nick = !memcmp(start_id, "Nick", 4) && !memcmp(end_id, "Nick", 4);
if(!catalogue->is_hugo && !is_nick) {
return nullptr;
}
if(!catalogue->has_large_sectors) {
// TODO: I don't know where the boot option rests with large sectors.
switch(free_space_map_second_half->samples[0][0xfd]) {
default: catalogue->bootOption = Catalogue::BootOption::None; break;
case 1: catalogue->bootOption = Catalogue::BootOption::LoadBOOT; break;
case 2: catalogue->bootOption = Catalogue::BootOption::RunBOOT; break;
case 3: catalogue->bootOption = Catalogue::BootOption::ExecBOOT; break;
}
}
// Parse the root directory, at least.
for(std::size_t file_offset = 0x005; file_offset < 0x4cb; file_offset += 0x1a) {
const std::size_t directory_extent = catalogue->has_large_sectors ? 0x7d7 : 0x4cb;
for(std::size_t file_offset = 0x005; file_offset < directory_extent; file_offset += 0x1a) {
// Obtain the name, which will be at most ten characters long, and will
// be terminated by either a NULL character or a \r.
char name[11];
char name[11]{};
std::size_t c = 0;
for(; c < 10; c++) {
const char next = root_directory[file_offset + c] & 0x7f;
@@ -122,8 +158,9 @@ std::unique_ptr<Catalogue> Analyser::Static::Acorn::GetADFSCatalogue(const std::
}
name[c] = '\0';
// Skip if the name is empty.
if(name[0] == '\0') continue;
// An empty name implies the directory has ended; files are always listed in case-insensitive
// sorted order, with that list being terminated by a '\0'.
if(name[0] == '\0') break;
// Populate a file then.
File new_file;
@@ -166,16 +203,36 @@ std::unique_ptr<Catalogue> Analyser::Static::Acorn::GetADFSCatalogue(const std::
new_file.data.reserve(size);
while(new_file.data.size() < size) {
const Storage::Encodings::MFM::Sector *const sector = parser.get_sector(start_sector / (80 * 16), (start_sector / 16) % 80, start_sector % 16);
const Storage::Encodings::MFM::Sector *const sector =
parser.sector(start_sector / (80 * 16), (start_sector / 16) % 80, start_sector % 16);
if(!sector) break;
const auto length_from_sector = std::min(size - new_file.data.size(), sector->samples[0].size());
new_file.data.insert(new_file.data.end(), sector->samples[0].begin(), sector->samples[0].begin() + ssize_t(length_from_sector));
new_file.data.insert(
new_file.data.end(),
sector->samples[0].begin(),
sector->samples[0].begin() + ssize_t(length_from_sector)
);
++start_sector;
}
catalogue->files.push_back(std::move(new_file));
}
// Include the directory title.
const char *title, *name;
if(catalogue->has_large_sectors) {
title = reinterpret_cast<const char *>(&root_directory[0x7dd]);
name = reinterpret_cast<const char *>(&root_directory[0x7f0]);
} else {
title = reinterpret_cast<const char *>(&root_directory[0x4d9]);
name = reinterpret_cast<const char *>(&root_directory[0x4cc]);
}
catalogue->name = std::string(title, strnlen(title, 19));
if(catalogue->name.empty() || catalogue->name == "$") {
catalogue->name = std::string(name, strnlen(name, 10));
}
return catalogue;
}

View File

@@ -6,16 +6,17 @@
// 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"
#include "Storage/Disk/Disk.hpp"
namespace Analyser::Static::Acorn {
/// Describes a DFS- or ADFS-format catalogue(/directory): the list of files available and the catalogue's boot option.
struct Catalogue {
bool is_hugo = false;
bool has_large_sectors = false;
std::string name;
std::vector<File> files;
enum class BootOption {
@@ -26,9 +27,7 @@ struct Catalogue {
} bootOption;
};
std::unique_ptr<Catalogue> GetDFSCatalogue(const std::shared_ptr<Storage::Disk::Disk> &disk);
std::unique_ptr<Catalogue> GetADFSCatalogue(const std::shared_ptr<Storage::Disk::Disk> &disk);
std::unique_ptr<Catalogue> GetDFSCatalogue(const std::shared_ptr<Storage::Disk::Disk> &);
std::unique_ptr<Catalogue> GetADFSCatalogue(const std::shared_ptr<Storage::Disk::Disk> &);
}
#endif /* Disk_hpp */

View File

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

View File

@@ -12,25 +12,28 @@
#include "Tape.hpp"
#include "Target.hpp"
#include "Numeric/StringSimilarity.hpp"
#include <algorithm>
#include <map>
using namespace Analyser::Static::Acorn;
static std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
AcornCartridgesFrom(const std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges) {
AcornCartridgesFrom(const std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges) {
std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>> acorn_cartridges;
for(const auto &cartridge : cartridges) {
const auto &segments = cartridge->get_segments();
// only one mapped item is allowed
// Only one mapped item is allowed.
if(segments.size() != 1) continue;
// which must be 8 or 16 kb in size
// Cartridges must be 8 or 16 kb in size.
const Storage::Cartridge::Cartridge::Segment &segment = segments.front();
if(segment.data.size() != 0x4000 && segment.data.size() != 0x2000) continue;
// is a copyright string present?
// Check copyright string.
const uint8_t copyright_offset = segment.data[7];
if(
segment.data[copyright_offset] != 0x00 ||
@@ -39,16 +42,16 @@ static std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
segment.data[copyright_offset+3] != 0x29
) continue;
// is the language entry point valid?
// Check language entry point.
if(!(
(segment.data[0] == 0x00 && segment.data[1] == 0x00 && segment.data[2] == 0x00) ||
(segment.data[0] != 0x00 && segment.data[2] >= 0x80 && segment.data[2] < 0xc0)
)) continue;
// is the service entry point valid?
// Check service entry point.
if(!(segment.data[5] >= 0x80 && segment.data[5] < 0xc0)) continue;
// probability of a random binary blob that isn't an Acorn ROM proceeding to here:
// Probability of a random binary blob that isn't an Acorn ROM proceeding to here:
// 1/(2^32) *
// ( ((2^24)-1)/(2^24)*(1/4) + 1/(2^24) ) *
// 1/4
@@ -59,65 +62,78 @@ static std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
return acorn_cartridges;
}
Analyser::Static::TargetList Analyser::Static::Acorn::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
auto target = std::make_unique<Target>();
Analyser::Static::TargetList Analyser::Static::Acorn::GetTargets(
const Media &media,
const std::string &file_name,
TargetPlatform::IntType,
bool
) {
auto target8bit = std::make_unique<ElectronTarget>();
auto targetArchimedes = std::make_unique<ArchimedesTarget>();
// strip out inappropriate cartridges
target->media.cartridges = AcornCartridgesFrom(media.cartridges);
// Copy appropriate cartridges to the 8-bit target.
target8bit->media.cartridges = AcornCartridgesFrom(media.cartridges);
// if there are any tapes, attempt to get data from the first
// If there are tapes, attempt to get data from the first.
if(!media.tapes.empty()) {
std::shared_ptr<Storage::Tape::Tape> tape = media.tapes.front();
std::vector<File> files = GetFiles(tape);
tape->reset();
auto serialiser = tape->serialiser();
std::vector<File> files = GetFiles(*serialiser);
// continue if there are any files
if(!files.empty()) {
bool is_basic = true;
// If a file is execute-only, that means *RUN.
if(files.front().flags & File::Flags::ExecuteOnly) is_basic = false;
if(files.front().flags & File::Flags::ExecuteOnly) {
is_basic = false;
}
// check also for a continuous threading of BASIC lines; if none then this probably isn't BASIC code,
// so that's also justification to *RUN
std::size_t pointer = 0;
uint8_t *const data = &files.front().data[0];
const std::size_t data_size = files.front().data.size();
while(1) {
if(pointer >= data_size-1 || data[pointer] != 13) {
is_basic = false;
break;
// Check also for a continuous threading of BASIC lines; if none then this probably isn't BASIC code,
// so that's also justification to *RUN.
if(is_basic) {
std::size_t pointer = 0;
uint8_t *const data = &files.front().data[0];
const std::size_t data_size = files.front().data.size();
while(true) {
if(pointer >= data_size-1 || data[pointer] != 0x0d) {
is_basic = false;
break;
}
if((data[pointer+1]&0x7f) == 0x7f) break;
pointer += data[pointer+3];
}
if((data[pointer+1]&0x7f) == 0x7f) break;
pointer += data[pointer+3];
}
// Inspect first file. If it's protected or doesn't look like BASIC
// then the loading command is *RUN. Otherwise it's CHAIN"".
target->loading_command = is_basic ? "CHAIN\"\"\n" : "*RUN\n";
target->media.tapes = media.tapes;
target8bit->loading_command = is_basic ? "CHAIN\"\"\n" : "*RUN\n";
target8bit->media.tapes = media.tapes;
}
}
if(!media.disks.empty()) {
std::shared_ptr<Storage::Disk::Disk> disk = media.disks.front();
std::unique_ptr<Catalogue> dfs_catalogue, adfs_catalogue;
// Get any sort of catalogue that can be found.
dfs_catalogue = GetDFSCatalogue(disk);
if(dfs_catalogue == nullptr) adfs_catalogue = GetADFSCatalogue(disk);
if(dfs_catalogue || adfs_catalogue) {
// 8-bit options: DFS and Hugo-style ADFS.
if(dfs_catalogue || (adfs_catalogue && !adfs_catalogue->has_large_sectors && adfs_catalogue->is_hugo)) {
// Accept the disk and determine whether DFS or ADFS ROMs are implied.
// Use the Pres ADFS if using an ADFS, as it leaves Page at &EOO.
target->media.disks = media.disks;
target->has_dfs = bool(dfs_catalogue);
target->has_pres_adfs = bool(adfs_catalogue);
target8bit->media.disks = media.disks;
target8bit->has_dfs = bool(dfs_catalogue);
target8bit->has_pres_adfs = bool(adfs_catalogue);
// Check whether a simple shift+break will do for loading this disk.
Catalogue::BootOption bootOption = (dfs_catalogue ?: adfs_catalogue)->bootOption;
const auto bootOption = (dfs_catalogue ?: adfs_catalogue)->bootOption;
if(bootOption != Catalogue::BootOption::None) {
target->should_shift_restart = true;
target8bit->should_shift_restart = true;
} else {
target->loading_command = "*CAT\n";
target8bit->loading_command = "*CAT\n";
}
// Check whether adding the AP6 ROM is justified.
@@ -133,39 +149,79 @@ Analyser::Static::TargetList Analyser::Static::Acorn::GetTargets(const Media &me
"VERIFY", "ZERO"
}) {
if(std::search(file.data.begin(), file.data.end(), command, command+strlen(command)) != file.data.end()) {
target->has_ap6_rom = true;
target->has_sideways_ram = true;
target8bit->has_ap6_rom = true;
target8bit->has_sideways_ram = true;
}
}
}
} else if(adfs_catalogue) {
// Archimedes options, implicitly: ADFS, non-Hugo.
targetArchimedes->media.disks = media.disks;
// Also look for the best possible startup program name, if it can be discerned.
std::multimap<double, std::string, std::greater<double>> options;
for(const auto &file: adfs_catalogue->files) {
// Skip non-Pling files.
if(file.name[0] != '!') continue;
// Take whatever else comes with a preference for things that don't
// have 'boot' or 'read' in them (the latter of which will tend to be
// read_me or read_this or similar).
static constexpr char read[] = "read";
static constexpr char boot[] = "boot";
const auto has = [&](const char *begin, const char *end) {
return std::search(
file.name.begin(), file.name.end(),
begin, end - 1, // i.e. don't compare the trailing NULL.
[](char lhs, char rhs) {
return std::tolower(lhs) == rhs;
}
) != file.name.end();
};
const auto has_read = has(std::begin(read), std::end(read));
const auto has_boot = has(std::begin(boot), std::end(boot));
const auto probability =
Numeric::similarity(file.name, adfs_catalogue->name) +
Numeric::similarity(file.name, file_name) -
((has_read || has_boot) ? 0.2 : 0.0);
options.emplace(probability, file.name);
}
if(!options.empty()) {
targetArchimedes->main_program = options.begin()->second;
}
}
}
// Enable the Acorn ADFS if a mass-storage device is attached;
// unlike the Pres ADFS it retains SCSI logic.
if(!media.mass_storage_devices.empty()) {
target->has_pres_adfs = false; // To override a floppy selection, if one was made.
target->has_acorn_adfs = true;
target8bit->has_pres_adfs = false; // To override a floppy selection, if one was made.
target8bit->has_acorn_adfs = true;
// Assume some sort of later-era Acorn work is likely to happen;
// so ensure *TYPE, etc are present.
target->has_ap6_rom = true;
target->has_sideways_ram = true;
target8bit->has_ap6_rom = true;
target8bit->has_sideways_ram = true;
target->media.mass_storage_devices = media.mass_storage_devices;
target8bit->media.mass_storage_devices = media.mass_storage_devices;
// Check for a boot option.
const auto sector = target->media.mass_storage_devices.front()->get_block(1);
const auto sector = target8bit->media.mass_storage_devices.front()->get_block(1);
if(sector[0xfd]) {
target->should_shift_restart = true;
target8bit->should_shift_restart = true;
} else {
target->loading_command = "*CAT\n";
target8bit->loading_command = "*CAT\n";
}
}
TargetList targets;
if(!target->media.empty()) {
targets.push_back(std::move(target));
if(!target8bit->media.empty()) {
targets.push_back(std::move(target8bit));
}
if(!targetArchimedes->media.empty()) {
targets.push_back(std::move(targetArchimedes));
}
return targets;
}

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::Acorn {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* AcornAnalyser_hpp */

View File

@@ -10,70 +10,68 @@
#include <deque>
#include "../../../Numeric/CRC.hpp"
#include "../../../Storage/Tape/Parsers/Acorn.hpp"
#include "Numeric/CRC.hpp"
#include "Storage/Tape/Parsers/Acorn.hpp"
using namespace Analyser::Static::Acorn;
static std::unique_ptr<File::Chunk> GetNextChunk(const std::shared_ptr<Storage::Tape::Tape> &tape, Storage::Tape::Acorn::Parser &parser) {
static std::unique_ptr<File::Chunk> GetNextChunk(
Storage::Tape::TapeSerialiser &serialiser,
Storage::Tape::Acorn::Parser &parser
) {
auto new_chunk = std::make_unique<File::Chunk>();
int shift_register = 0;
// TODO: move this into the parser
#define shift() shift_register = (shift_register >> 1) | (parser.get_next_bit(tape) << 9)
// find next area of high tone
while(!tape->is_at_end() && (shift_register != 0x3ff)) {
shift();
}
// find next 0x2a (swallowing stop bit)
while(!tape->is_at_end() && (shift_register != 0x254)) {
shift();
}
#undef shift
// TODO: move this into the parser
const auto find = [&](int target) {
while(!serialiser.is_at_end() && (shift_register != target)) {
shift_register = (shift_register >> 1) | (parser.get_next_bit(serialiser) << 9);
}
};
// Find first sync byte that follows high tone.
find(0x3ff);
find(0x254); // i.e. 0x2a wrapped in a 1 start bit and a 0 stop bit.
parser.reset_crc();
parser.reset_error_flag();
// read out name
char name[11];
// Read name.
char name[11]{};
std::size_t name_ptr = 0;
while(!tape->is_at_end() && name_ptr < sizeof(name)) {
name[name_ptr] = char(parser.get_next_byte(tape));
while(!serialiser.is_at_end() && name_ptr < sizeof(name)) {
name[name_ptr] = char(parser.get_next_byte(serialiser));
if(!name[name_ptr]) break;
++name_ptr;
}
name[sizeof(name)-1] = '\0';
new_chunk->name = name;
// addresses
new_chunk->load_address = uint32_t(parser.get_next_word(tape));
new_chunk->execution_address = uint32_t(parser.get_next_word(tape));
new_chunk->block_number = uint16_t(parser.get_next_short(tape));
new_chunk->block_length = uint16_t(parser.get_next_short(tape));
new_chunk->block_flag = uint8_t(parser.get_next_byte(tape));
new_chunk->next_address = uint32_t(parser.get_next_word(tape));
// Read rest of header fields.
new_chunk->load_address = uint32_t(parser.get_next_word(serialiser));
new_chunk->execution_address = uint32_t(parser.get_next_word(serialiser));
new_chunk->block_number = uint16_t(parser.get_next_short(serialiser));
new_chunk->block_length = uint16_t(parser.get_next_short(serialiser));
new_chunk->block_flag = uint8_t(parser.get_next_byte(serialiser));
new_chunk->next_address = uint32_t(parser.get_next_word(serialiser));
uint16_t calculated_header_crc = parser.get_crc();
uint16_t stored_header_crc = uint16_t(parser.get_next_short(tape));
stored_header_crc = uint16_t((stored_header_crc >> 8) | (stored_header_crc << 8));
new_chunk->header_crc_matched = stored_header_crc == calculated_header_crc;
const auto matched_crc = [&]() {
const uint16_t calculated_crc = parser.get_crc();
uint16_t stored_crc = uint16_t(parser.get_next_short(serialiser));
stored_crc = uint16_t((stored_crc >> 8) | (stored_crc << 8));
return stored_crc == calculated_crc;
};
new_chunk->header_crc_matched = matched_crc();
if(!new_chunk->header_crc_matched) return nullptr;
parser.reset_crc();
new_chunk->data.reserve(new_chunk->block_length);
for(int c = 0; c < new_chunk->block_length; c++) {
new_chunk->data.push_back(uint8_t(parser.get_next_byte(tape)));
}
// Bit 6 of the block flag means 'empty block'; allow it to override declared block length.
if(new_chunk->block_length && !(new_chunk->block_flag&0x40)) {
uint16_t calculated_data_crc = parser.get_crc();
uint16_t stored_data_crc = uint16_t(parser.get_next_short(tape));
stored_data_crc = uint16_t((stored_data_crc >> 8) | (stored_data_crc << 8));
new_chunk->data_crc_matched = stored_data_crc == calculated_data_crc;
parser.reset_crc();
new_chunk->data.reserve(new_chunk->block_length);
for(int c = 0; c < new_chunk->block_length; c++) {
new_chunk->data.push_back(uint8_t(parser.get_next_byte(serialiser)));
}
new_chunk->data_crc_matched = matched_crc();
} else {
new_chunk->data_crc_matched = true;
}
@@ -82,67 +80,62 @@ static std::unique_ptr<File::Chunk> GetNextChunk(const std::shared_ptr<Storage::
}
static std::unique_ptr<File> GetNextFile(std::deque<File::Chunk> &chunks) {
// find next chunk with a block number of 0
while(chunks.size() && chunks.front().block_number) {
// Find next chunk with a block number of 0.
while(!chunks.empty() && chunks.front().block_number) {
chunks.pop_front();
}
if(chunks.empty()) return nullptr;
if(!chunks.size()) return nullptr;
// accumulate chunks for as long as block number is sequential and the end-of-file bit isn't set
// Accumulate sequential blocks until end-of-file bit is set.
auto file = std::make_unique<File>();
uint16_t block_number = 0;
while(chunks.size()) {
while(!chunks.empty()) {
if(chunks.front().block_number != block_number) return nullptr;
bool was_last = chunks.front().block_flag & 0x80;
const bool was_last = chunks.front().block_flag & 0x80;
file->chunks.push_back(chunks.front());
chunks.pop_front();
block_number++;
++block_number;
if(was_last) break;
}
// accumulate total data, copy flags appropriately
// Grab metadata flags.
file->name = file->chunks.front().name;
file->load_address = file->chunks.front().load_address;
file->execution_address = file->chunks.front().execution_address;
// I think the final chunk's flags are the ones that count; TODO: check.
if(file->chunks.back().block_flag & 0x01) {
// File is locked, which in more generalised terms means it is
// for execution only.
// File is locked i.e. for execution only.
file->flags |= File::Flags::ExecuteOnly;
}
// copy all data into a single big block
for(File::Chunk chunk : file->chunks) {
// Copy data into a single big block.
file->data.reserve(file->chunks.size() * 256);
for(auto &chunk : file->chunks) {
file->data.insert(file->data.end(), chunk.data.begin(), chunk.data.end());
}
return file;
}
std::vector<File> Analyser::Static::Acorn::GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape) {
std::vector<File> Analyser::Static::Acorn::GetFiles(Storage::Tape::TapeSerialiser &serialiser) {
Storage::Tape::Acorn::Parser parser;
// populate chunk list
// Read all chunks.
std::deque<File::Chunk> chunk_list;
while(!tape->is_at_end()) {
std::unique_ptr<File::Chunk> chunk = GetNextChunk(tape, parser);
while(!serialiser.is_at_end()) {
const std::unique_ptr<File::Chunk> chunk = GetNextChunk(serialiser, parser);
if(chunk) {
chunk_list.push_back(*chunk);
chunk_list.push_back(std::move(*chunk));
}
}
// decompose into file list
// Convert to files.
std::vector<File> file_list;
while(chunk_list.size()) {
std::unique_ptr<File> next_file = GetNextFile(chunk_list);
while(!chunk_list.empty()) {
const std::unique_ptr<File> next_file = GetNextFile(chunk_list);
if(next_file) {
file_list.push_back(*next_file);
file_list.push_back(std::move(*next_file));
}
}

View File

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

View File

@@ -6,16 +6,15 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Reflection/Struct.hpp"
#include <string>
namespace Analyser::Static::Acorn {
struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<Target> {
struct ElectronTarget: public ::Analyser::Static::Target, public Reflection::StructImpl<ElectronTarget> {
bool has_acorn_adfs = false;
bool has_pres_adfs = false;
bool has_dfs = false;
@@ -24,17 +23,27 @@ struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<
bool should_shift_restart = false;
std::string loading_command;
Target() : Analyser::Static::Target(Machine::Electron) {
if(needs_declare()) {
DeclareField(has_pres_adfs);
DeclareField(has_acorn_adfs);
DeclareField(has_dfs);
DeclareField(has_ap6_rom);
DeclareField(has_sideways_ram);
}
ElectronTarget() : Analyser::Static::Target(Machine::Electron) {}
private:
friend Reflection::StructImpl<ElectronTarget>;
void declare_fields() {
DeclareField(has_pres_adfs);
DeclareField(has_acorn_adfs);
DeclareField(has_dfs);
DeclareField(has_ap6_rom);
DeclareField(has_sideways_ram);
}
};
}
struct ArchimedesTarget: public ::Analyser::Static::Target, public Reflection::StructImpl<ArchimedesTarget> {
std::string main_program;
#endif /* Analyser_Static_Acorn_Target_h */
ArchimedesTarget() : Analyser::Static::Target(Machine::Archimedes) {}
private:
friend Reflection::StructImpl<ArchimedesTarget>;
void declare_fields() {}
};
}

View File

@@ -9,9 +9,14 @@
#include "StaticAnalyser.hpp"
#include "Target.hpp"
Analyser::Static::TargetList Analyser::Static::Amiga::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::Amiga::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
bool is_confident
) {
// This analyser can comprehend disks and mass-storage devices only.
if(media.disks.empty()) return {};
if(media.disks.empty() && !is_confident) return {};
// As there is at least one usable media image, wave it through.
Analyser::Static::TargetList targets;

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::Amiga {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* Analyser_Static_Amiga_StaticAnalyser_hpp */

View File

@@ -6,11 +6,10 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Reflection/Struct.hpp"
namespace Analyser::Static::Amiga {
@@ -29,16 +28,16 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
ChipRAM chip_ram = ChipRAM::FiveHundredAndTwelveKilobytes;
FastRAM fast_ram = FastRAM::EightMegabytes;
Target() : Analyser::Static::Target(Machine::Amiga) {
if(needs_declare()) {
DeclareField(fast_ram);
DeclareField(chip_ram);
AnnounceEnum(FastRAM);
AnnounceEnum(ChipRAM);
}
Target() : Analyser::Static::Target(Machine::Amiga) {}
private:
friend Reflection::StructImpl<Target>;
void declare_fields() {
DeclareField(fast_ram);
DeclareField(chip_ram);
AnnounceEnum(FastRAM);
AnnounceEnum(ChipRAM);
}
};
}
#endif /* Analyser_Static_Amiga_Target_h */

View File

@@ -8,15 +8,15 @@
#include "StaticAnalyser.hpp"
#include <algorithm>
#include <cstring>
#include "../../../Storage/Disk/Parsers/CPM.hpp"
#include "../../../Storage/Disk/Encodings/MFM/Parser.hpp"
#include "../../../Storage/Tape/Parsers/Spectrum.hpp"
#include "Storage/Disk/Parsers/CPM.hpp"
#include "Storage/Disk/Encodings/MFM/Parser.hpp"
#include "Storage/Tape/Parsers/Spectrum.hpp"
#include "Target.hpp"
#include <algorithm>
#include <cstring>
namespace {
bool strcmp_insensitive(const char *a, const char *b) {
@@ -63,8 +63,8 @@ std::string RunCommandFor(const Storage::Disk::CPM::File &file) {
void InspectCatalogue(
const Storage::Disk::CPM::Catalogue &catalogue,
const std::unique_ptr<Analyser::Static::AmstradCPC::Target> &target) {
const std::unique_ptr<Analyser::Static::AmstradCPC::Target> &target
) {
std::vector<const Storage::Disk::CPM::File *> candidate_files;
candidate_files.reserve(catalogue.files.size());
for(const auto &file : catalogue.files) {
@@ -158,9 +158,12 @@ void InspectCatalogue(
target->loading_command = "cat\n";
}
bool CheckBootSector(const std::shared_ptr<Storage::Disk::Disk> &disk, const std::unique_ptr<Analyser::Static::AmstradCPC::Target> &target) {
Storage::Encodings::MFM::Parser parser(true, disk);
Storage::Encodings::MFM::Sector *boot_sector = parser.get_sector(0, 0, 0x41);
bool CheckBootSector(
const std::shared_ptr<Storage::Disk::Disk> &disk,
const std::unique_ptr<Analyser::Static::AmstradCPC::Target> &target
) {
Storage::Encodings::MFM::Parser parser(Storage::Encodings::MFM::Density::Double, disk);
const Storage::Encodings::MFM::Sector *boot_sector = parser.sector(0, 0, 0x41);
if(boot_sector != nullptr && !boot_sector->samples.empty() && boot_sector->samples[0].size() == 512) {
// Check that the first 64 bytes of the sector aren't identical; if they are then probably
// this disk was formatted and the filler byte never replaced.
@@ -182,7 +185,7 @@ bool CheckBootSector(const std::shared_ptr<Storage::Disk::Disk> &disk, const std
return false;
}
bool IsAmstradTape(const std::shared_ptr<Storage::Tape::Tape> &tape) {
bool IsAmstradTape(Storage::Tape::TapeSerialiser &serialiser) {
// Limited sophistication here; look for a CPC-style file header, that is
// any Spectrum-esque block with a synchronisation character of 0x2c.
//
@@ -191,7 +194,7 @@ bool IsAmstradTape(const std::shared_ptr<Storage::Tape::Tape> &tape) {
Parser parser(Parser::MachineType::AmstradCPC);
while(true) {
const auto block = parser.find_block(tape);
const auto block = parser.find_block(serialiser);
if(!block) break;
if(block->type == 0x2c) {
@@ -204,7 +207,12 @@ bool IsAmstradTape(const std::shared_ptr<Storage::Tape::Tape> &tape) {
} // namespace
Analyser::Static::TargetList Analyser::Static::AmstradCPC::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::AmstradCPC::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
bool
) {
TargetList destination;
auto target = std::make_unique<Target>();
target->confidence = 0.5;
@@ -214,7 +222,8 @@ Analyser::Static::TargetList Analyser::Static::AmstradCPC::GetTargets(const Medi
if(!media.tapes.empty()) {
bool has_cpc_tape = false;
for(auto &tape: media.tapes) {
has_cpc_tape |= IsAmstradTape(tape);
const auto serialiser = tape->serialiser();
has_cpc_tape |= IsAmstradTape(*serialiser);
}
if(has_cpc_tape) {
@@ -228,26 +237,14 @@ Analyser::Static::TargetList Analyser::Static::AmstradCPC::GetTargets(const Medi
}
if(!media.disks.empty()) {
Storage::Disk::CPM::ParameterBlock data_format;
data_format.sectors_per_track = 9;
data_format.tracks = 40;
data_format.block_size = 1024;
data_format.first_sector = 0xc1;
data_format.catalogue_allocation_bitmap = 0xc000;
data_format.reserved_tracks = 0;
Storage::Disk::CPM::ParameterBlock system_format;
system_format.sectors_per_track = 9;
system_format.tracks = 40;
system_format.block_size = 1024;
system_format.first_sector = 0x41;
system_format.catalogue_allocation_bitmap = 0xc000;
system_format.reserved_tracks = 2;
const auto data_format = Storage::Disk::CPM::ParameterBlock::cpc_data_format();
const auto system_format = Storage::Disk::CPM::ParameterBlock::cpc_system_format();
for(auto &disk: media.disks) {
// Check for an ordinary catalogue.
std::unique_ptr<Storage::Disk::CPM::Catalogue> data_catalogue = Storage::Disk::CPM::GetCatalogue(disk, data_format);
if(data_catalogue) {
// Check for an ordinary catalogue, making sure this isn't actually a ZX Spectrum disk.
std::unique_ptr<Storage::Disk::CPM::Catalogue> data_catalogue =
Storage::Disk::CPM::GetCatalogue(disk, data_format, false);
if(data_catalogue && !data_catalogue->is_zx_spectrum_booter()) {
InspectCatalogue(*data_catalogue, target);
target->media.disks.push_back(disk);
continue;
@@ -260,8 +257,9 @@ Analyser::Static::TargetList Analyser::Static::AmstradCPC::GetTargets(const Medi
}
// Failing that check for a system catalogue.
std::unique_ptr<Storage::Disk::CPM::Catalogue> system_catalogue = Storage::Disk::CPM::GetCatalogue(disk, system_format);
if(system_catalogue) {
std::unique_ptr<Storage::Disk::CPM::Catalogue> system_catalogue =
Storage::Disk::CPM::GetCatalogue(disk, system_format, false);
if(system_catalogue && !system_catalogue->is_zx_spectrum_booter()) {
InspectCatalogue(*system_catalogue, target);
target->media.disks.push_back(disk);
continue;

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::AmstradCPC {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* Analyser_Static_AmstradCPC_StaticAnalyser_hpp */

View File

@@ -6,12 +6,11 @@
// 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"
#include "../StaticAnalyser.hpp"
#include "Reflection/Enum.hpp"
#include "Reflection/Struct.hpp"
#include "Analyser/Static/StaticAnalyser.hpp"
#include <string>
namespace Analyser::Static::AmstradCPC {
@@ -21,14 +20,22 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
Model model = Model::CPC464;
std::string loading_command;
Target() : Analyser::Static::Target(Machine::AmstradCPC) {
if(needs_declare()) {
DeclareField(model);
AnnounceEnum(Model);
}
ReflectableEnum(CRTCType, Type0, Type1, Type2, Type3);
CRTCType crtc_type = CRTCType::Type2;
// This is used internally for testing; it therefore isn't exposed reflectively.
bool catch_ssm_codes = false;
Target() : Analyser::Static::Target(Machine::AmstradCPC) {}
private:
friend Reflection::StructImpl<Target>;
void declare_fields() {
DeclareField(model);
DeclareField(crtc_type);
AnnounceEnum(Model);
AnnounceEnum(CRTCType);
}
};
}
#endif /* Analyser_Static_AmstradCPC_Target_h */

View File

@@ -9,7 +9,12 @@
#include "StaticAnalyser.hpp"
#include "Target.hpp"
Analyser::Static::TargetList Analyser::Static::AppleII::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::AppleII::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
bool
) {
auto target = std::make_unique<Target>();
target->media = media;

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::AppleII {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* Analyser_Static_AppleII_StaticAnalyser_hpp */

View File

@@ -6,12 +6,11 @@
// 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"
#include "../StaticAnalyser.hpp"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Reflection/Enum.hpp"
#include "Reflection/Struct.hpp"
namespace Analyser::Static::AppleII {
@@ -35,20 +34,26 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
Model model = Model::IIe;
DiskController disk_controller = DiskController::None;
SCSIController scsi_controller = SCSIController::None;
bool has_mockingboard = true;
Target() : Analyser::Static::Target(Machine::AppleII) {
if(needs_declare()) {
DeclareField(model);
DeclareField(disk_controller);
DeclareField(scsi_controller);
Target() : Analyser::Static::Target(Machine::AppleII) {}
AnnounceEnum(Model);
AnnounceEnum(DiskController);
AnnounceEnum(SCSIController);
}
private:
friend Reflection::StructImpl<Target>;
void declare_fields() {
DeclareField(model);
DeclareField(disk_controller);
DeclareField(scsi_controller);
DeclareField(has_mockingboard);
AnnounceEnum(Model);
AnnounceEnum(DiskController);
AnnounceEnum(SCSIController);
}
};
constexpr bool is_iie(const Target::Model model) {
return model == Target::Model::IIe || model == Target::Model::EnhancedIIe;
}
#endif /* Analyser_Static_AppleII_Target_h */
}

View File

@@ -9,7 +9,12 @@
#include "StaticAnalyser.hpp"
#include "Target.hpp"
Analyser::Static::TargetList Analyser::Static::AppleIIgs::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::AppleIIgs::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
bool
) {
auto target = std::make_unique<Target>();
target->media = media;

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::AppleIIgs {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* Analyser_Static_AppleIIgs_StaticAnalyser_hpp */

View File

@@ -6,12 +6,11 @@
// 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"
#include "../StaticAnalyser.hpp"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Reflection/Enum.hpp"
#include "Reflection/Struct.hpp"
namespace Analyser::Static::AppleIIgs {
@@ -30,16 +29,16 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
Model model = Model::ROM01;
MemoryModel memory_model = MemoryModel::EightMB;
Target() : Analyser::Static::Target(Machine::AppleIIgs) {
if(needs_declare()) {
DeclareField(model);
DeclareField(memory_model);
AnnounceEnum(Model);
AnnounceEnum(MemoryModel);
}
Target() : Analyser::Static::Target(Machine::AppleIIgs) {}
private:
friend Reflection::StructImpl<Target>;
void declare_fields() {
DeclareField(model);
DeclareField(memory_model);
AnnounceEnum(Model);
AnnounceEnum(MemoryModel);
}
};
}
#endif /* Analyser_Static_AppleIIgs_Target_h */

View File

@@ -10,7 +10,7 @@
#include "Target.hpp"
#include "../Disassembler/6502.hpp"
#include "Analyser/Static/Disassembler/6502.hpp"
using namespace Analyser::Static::Atari2600;
using Target = Analyser::Static::Atari2600::Target;
@@ -33,11 +33,13 @@ static void DeterminePagingFor2kCartridge(Target &target, const Storage::Cartrid
// Assume that any kind of store that looks likely to be intended for large amounts of memory implies
// large amounts of memory.
bool has_wide_area_store = false;
for(std::map<uint16_t, Analyser::Static::MOS6502::Instruction>::value_type &entry : high_location_disassembly.instructions_by_address) {
for(const auto &entry : high_location_disassembly.instructions_by_address) {
using Instruction = Analyser::Static::MOS6502::Instruction;
if(entry.second.operation == Analyser::Static::MOS6502::Instruction::STA) {
has_wide_area_store |= entry.second.addressing_mode == Analyser::Static::MOS6502::Instruction::Indirect;
has_wide_area_store |= entry.second.addressing_mode == Analyser::Static::MOS6502::Instruction::IndexedIndirectX;
has_wide_area_store |= entry.second.addressing_mode == Analyser::Static::MOS6502::Instruction::IndirectIndexedY;
has_wide_area_store |=
entry.second.addressing_mode == Instruction::Indirect ||
entry.second.addressing_mode == Instruction::IndexedIndirectX ||
entry.second.addressing_mode == Instruction::IndirectIndexedY;
if(has_wide_area_store) break;
}
@@ -50,13 +52,21 @@ static void DeterminePagingFor2kCartridge(Target &target, const Storage::Cartrid
if(has_wide_area_store) target.paging_model = Target::PagingModel::CommaVid;
}
static void DeterminePagingFor8kCartridge(Target &target, const Storage::Cartridge::Cartridge::Segment &segment, const Analyser::Static::MOS6502::Disassembly &disassembly) {
static void DeterminePagingFor8kCartridge(
Target &target,
const Storage::Cartridge::Cartridge::Segment &segment,
const Analyser::Static::MOS6502::Disassembly &disassembly
) {
// Activision stack titles have their vectors at the top of the low 4k, not the top, and
// always list 0xf000 as both vectors; they do not repeat them, and, inexplicably, they all
// issue an SEI as their first instruction (maybe some sort of relic of the development environment?).
if(
segment.data[4095] == 0xf0 && segment.data[4093] == 0xf0 && segment.data[4094] == 0x00 && segment.data[4092] == 0x00 &&
(segment.data[8191] != 0xf0 || segment.data[8189] != 0xf0 || segment.data[8190] != 0x00 || segment.data[8188] != 0x00) &&
segment.data[4095] == 0xf0 && segment.data[4093] == 0xf0 &&
segment.data[4094] == 0x00 && segment.data[4092] == 0x00 &&
(
segment.data[8191] != 0xf0 || segment.data[8189] != 0xf0 ||
segment.data[8190] != 0x00 || segment.data[8188] != 0x00
) &&
segment.data[0] == 0x78
) {
target.paging_model = Target::PagingModel::ActivisionStack;
@@ -88,7 +98,11 @@ static void DeterminePagingFor8kCartridge(Target &target, const Storage::Cartrid
else if(tigervision_access_count > atari_access_count) target.paging_model = Target::PagingModel::Tigervision;
}
static void DeterminePagingFor16kCartridge(Target &target, const Storage::Cartridge::Cartridge::Segment &, const Analyser::Static::MOS6502::Disassembly &disassembly) {
static void DeterminePagingFor16kCartridge(
Target &target,
const Storage::Cartridge::Cartridge::Segment &,
const Analyser::Static::MOS6502::Disassembly &disassembly
) {
// Make an assumption that this is the Atari paging model.
target.paging_model = Target::PagingModel::Atari16k;
@@ -108,7 +122,11 @@ static void DeterminePagingFor16kCartridge(Target &target, const Storage::Cartri
if(mnetwork_access_count > atari_access_count) target.paging_model = Target::PagingModel::MNetwork;
}
static void DeterminePagingFor64kCartridge(Target &target, const Storage::Cartridge::Cartridge::Segment &, const Analyser::Static::MOS6502::Disassembly &disassembly) {
static void DeterminePagingFor64kCartridge(
Target &target,
const Storage::Cartridge::Cartridge::Segment &,
const Analyser::Static::MOS6502::Disassembly &disassembly
) {
// Make an assumption that this is a Tigervision if there is a write to 3F.
target.paging_model =
(disassembly.external_stores.find(0x3f) != disassembly.external_stores.end()) ?
@@ -121,8 +139,12 @@ static void DeterminePagingForCartridge(Target &target, const Storage::Cartridge
return;
}
const uint16_t entry_address = uint16_t(segment.data[segment.data.size() - 4] | (segment.data[segment.data.size() - 3] << 8));
const uint16_t break_address = uint16_t(segment.data[segment.data.size() - 2] | (segment.data[segment.data.size() - 1] << 8));
const auto word = [](const uint8_t low, const uint8_t high) {
return uint16_t(low | (high << 8));
};
const auto entry_address = word(segment.data[segment.data.size() - 4], segment.data[segment.data.size() - 3]);
const auto break_address = word(segment.data[segment.data.size() - 2], segment.data[segment.data.size() - 1]);
std::function<std::size_t(uint16_t address)> address_mapper = [](uint16_t address) {
if(!(address & 0x1000)) return size_t(-1);
@@ -130,27 +152,16 @@ static void DeterminePagingForCartridge(Target &target, const Storage::Cartridge
};
const std::vector<uint8_t> final_4k(segment.data.end() - 4096, segment.data.end());
Analyser::Static::MOS6502::Disassembly disassembly = Analyser::Static::MOS6502::Disassemble(final_4k, address_mapper, {entry_address, break_address});
const auto disassembly =
Analyser::Static::MOS6502::Disassemble(final_4k, address_mapper, {entry_address, break_address});
switch(segment.data.size()) {
case 8192:
DeterminePagingFor8kCartridge(target, segment, disassembly);
break;
case 10495:
target.paging_model = Target::PagingModel::Pitfall2;
break;
case 12288:
target.paging_model = Target::PagingModel::CBSRamPlus;
break;
case 16384:
DeterminePagingFor16kCartridge(target, segment, disassembly);
break;
case 32768:
target.paging_model = Target::PagingModel::Atari32k;
break;
case 65536:
DeterminePagingFor64kCartridge(target, segment, disassembly);
break;
case 8192: DeterminePagingFor8kCartridge(target, segment, disassembly); break;
case 10495: target.paging_model = Target::PagingModel::Pitfall2; break;
case 12288: target.paging_model = Target::PagingModel::CBSRamPlus; break;
case 16384: DeterminePagingFor16kCartridge(target, segment, disassembly); break;
case 32768: target.paging_model = Target::PagingModel::Atari32k; break;
case 65536: DeterminePagingFor64kCartridge(target, segment, disassembly); break;
default:
break;
}
@@ -177,7 +188,12 @@ static void DeterminePagingForCartridge(Target &target, const Storage::Cartridge
}
}
Analyser::Static::TargetList Analyser::Static::Atari2600::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::Atari2600::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
bool
) {
// TODO: sanity checking; is this image really for an Atari 2600?
auto target = std::make_unique<Target>();
target->confidence = 0.5;

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::Atari2600 {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* StaticAnalyser_hpp */

View File

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

View File

@@ -9,7 +9,12 @@
#include "StaticAnalyser.hpp"
#include "Target.hpp"
Analyser::Static::TargetList Analyser::Static::AtariST::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::AtariST::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
bool
) {
// This analyser can comprehend disks and mass-storage devices only.
if(media.disks.empty()) return {};

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::AtariST {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* Analyser_Static_AtariST_StaticAnalyser_hpp */

View File

@@ -6,11 +6,10 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Reflection/Struct.hpp"
namespace Analyser::Static::AtariST {
@@ -21,14 +20,14 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
FourMegabytes);
MemorySize memory_size = MemorySize::OneMegabyte;
Target() : Analyser::Static::Target(Machine::AtariST) {
if(needs_declare()) {
DeclareField(memory_size);
AnnounceEnum(MemorySize);
}
Target() : Analyser::Static::Target(Machine::AtariST) {}
private:
friend Reflection::StructImpl<Target>;
void declare_fields() {
DeclareField(memory_size);
AnnounceEnum(MemorySize);
}
};
}
#endif /* Analyser_Static_AtariST_Target_h */

View File

@@ -9,7 +9,7 @@
#include "StaticAnalyser.hpp"
static std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
ColecoCartridgesFrom(const std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges) {
ColecoCartridgesFrom(const std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges) {
std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>> coleco_cartridges;
for(const auto &cartridge : cartridges) {
@@ -52,11 +52,20 @@ static std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
return coleco_cartridges;
}
Analyser::Static::TargetList Analyser::Static::Coleco::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::Coleco::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
const bool is_confident
) {
TargetList targets;
auto target = std::make_unique<Target>(Machine::ColecoVision);
target->confidence = 1.0f - 1.0f / 32768.0f;
target->media.cartridges = ColecoCartridgesFrom(media.cartridges);
if(is_confident) {
target->media = media;
} else {
target->media.cartridges = ColecoCartridgesFrom(media.cartridges);
}
if(!target->media.empty())
targets.push_back(std::move(target));
return targets;

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::Coleco {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* StaticAnalyser_hpp */

View File

@@ -7,166 +7,168 @@
//
#include "Disk.hpp"
#include "../../../Storage/Disk/Controller/DiskController.hpp"
#include "../../../Storage/Disk/Encodings/CommodoreGCR.hpp"
#include "../../../Storage/Data/Commodore.hpp"
#include "Storage/Disk/Controller/DiskController.hpp"
#include "Storage/Disk/Encodings/CommodoreGCR.hpp"
#include "Storage/Data/Commodore.hpp"
#include <limits>
#include <vector>
#include <array>
#include <limits>
#include <unordered_map>
#include <vector>
using namespace Analyser::Static::Commodore;
class CommodoreGCRParser: public Storage::Disk::Controller {
public:
CommodoreGCRParser() : Storage::Disk::Controller(4000000), shift_register_(0), track_(1) {
emplace_drive(4000000, 300, 2);
set_drive(1);
get_drive().set_motor_on(true);
}
public:
CommodoreGCRParser() : Storage::Disk::Controller(4000000), shift_register_(0), track_(1) {
emplace_drive(4000000, 300, 2);
set_drive(1);
get_drive().set_motor_on(true);
}
struct Sector {
uint8_t sector, track;
std::array<uint8_t, 256> data;
bool header_checksum_matched;
bool data_checksum_matched;
};
struct Sector {
uint8_t sector, track;
std::array<uint8_t, 256> data;
bool header_checksum_matched;
bool data_checksum_matched;
};
/*!
Attempts to read the sector located at @c track and @c sector.
/*!
Attempts to read the sector located at @c track and @c sector.
@returns a sector if one was found; @c nullptr otherwise.
*/
std::shared_ptr<Sector> get_sector(uint8_t track, uint8_t sector) {
int difference = int(track) - int(track_);
track_ = track;
@returns a sector if one was found; @c nullptr otherwise.
*/
const Sector *sector(const uint8_t track, const uint8_t sector) {
int difference = int(track) - int(track_);
track_ = track;
if(difference) {
int direction = difference < 0 ? -1 : 1;
difference *= direction;
if(difference) {
const int direction = difference < 0 ? -1 : 1;
difference *= direction;
for(int c = 0; c < difference; c++) {
get_drive().step(Storage::Disk::HeadPosition(direction));
}
unsigned int zone = 3;
if(track >= 18) zone = 2;
else if(track >= 25) zone = 1;
else if(track >= 31) zone = 0;
set_expected_bit_length(Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(zone));
for(int c = 0; c < difference; c++) {
get_drive().step(Storage::Disk::HeadPosition(direction));
}
return get_sector(sector);
unsigned int zone = 3;
if(track >= 18) zone = 2;
else if(track >= 25) zone = 1;
else if(track >= 31) zone = 0;
set_expected_bit_length(Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(zone));
}
void set_disk(const std::shared_ptr<Storage::Disk::Disk> &disk) {
get_drive().set_disk(disk);
return get_sector(sector);
}
void set_disk(const std::shared_ptr<Storage::Disk::Disk> &disk) {
get_drive().set_disk(disk);
}
private:
unsigned int shift_register_;
int index_count_;
int bit_count_;
uint8_t track_;
std::unordered_map<uint16_t, std::unique_ptr<Sector>> sector_cache_;
void process_input_bit(const int value) override {
shift_register_ = ((shift_register_ << 1) | unsigned(value)) & 0x3ff;
bit_count_++;
}
unsigned int proceed_to_next_block(const int max_index_count) {
// find GCR lead-in
proceed_to_shift_value(0x3ff);
if(shift_register_ != 0x3ff) return 0xff;
// find end of lead-in
while(shift_register_ == 0x3ff && index_count_ < max_index_count) {
run_for(Cycles(1));
}
private:
unsigned int shift_register_;
int index_count_;
int bit_count_;
uint8_t track_;
std::shared_ptr<Sector> sector_cache_[65536];
void process_input_bit(int value) {
shift_register_ = ((shift_register_ << 1) | unsigned(value)) & 0x3ff;
bit_count_++;
// continue for a further nine bits
bit_count_ = 0;
while(bit_count_ < 9 && index_count_ < max_index_count) {
run_for(Cycles(1));
}
unsigned int proceed_to_next_block(int max_index_count) {
// find GCR lead-in
proceed_to_shift_value(0x3ff);
if(shift_register_ != 0x3ff) return 0xff;
return Storage::Encodings::CommodoreGCR::decoding_from_dectet(shift_register_);
}
// find end of lead-in
while(shift_register_ == 0x3ff && index_count_ < max_index_count) {
run_for(Cycles(1));
}
unsigned int get_next_byte() {
bit_count_ = 0;
while(bit_count_ < 10) run_for(Cycles(1));
return Storage::Encodings::CommodoreGCR::decoding_from_dectet(shift_register_);
}
// continue for a further nine bits
bit_count_ = 0;
while(bit_count_ < 9 && index_count_ < max_index_count) {
run_for(Cycles(1));
}
return Storage::Encodings::CommodoreGCR::decoding_from_dectet(shift_register_);
void proceed_to_shift_value(const unsigned int shift_value) {
const int max_index_count = index_count_ + 2;
while(shift_register_ != shift_value && index_count_ < max_index_count) {
run_for(Cycles(1));
}
}
unsigned int get_next_byte() {
bit_count_ = 0;
while(bit_count_ < 10) run_for(Cycles(1));
return Storage::Encodings::CommodoreGCR::decoding_from_dectet(shift_register_);
void process_index_hole() override {
index_count_++;
}
const Sector *get_sector(const uint8_t sector) {
const uint16_t sector_address = uint16_t((track_ << 8) | sector);
auto existing = sector_cache_.find(sector_address);
if(existing != sector_cache_.end()) return existing->second.get();
const auto first_sector = get_next_sector();
if(!first_sector) return first_sector;
if(first_sector->sector == sector) return first_sector;
while(true) {
const auto next_sector = get_next_sector();
if(next_sector->sector == first_sector->sector) return nullptr;
if(next_sector->sector == sector) return next_sector;
}
}
void proceed_to_shift_value(unsigned int shift_value) {
const int max_index_count = index_count_ + 2;
while(shift_register_ != shift_value && index_count_ < max_index_count) {
run_for(Cycles(1));
}
}
void process_index_hole() {
index_count_++;
}
std::shared_ptr<Sector> get_sector(uint8_t sector) {
const uint16_t sector_address = uint16_t((track_ << 8) | sector);
if(sector_cache_[sector_address]) return sector_cache_[sector_address];
const std::shared_ptr<Sector> first_sector = get_next_sector();
if(!first_sector) return first_sector;
if(first_sector->sector == sector) return first_sector;
const Sector *get_next_sector() {
auto sector = std::make_unique<Sector>();
const int max_index_count = index_count_ + 2;
while(index_count_ < max_index_count) {
// look for a sector header
while(1) {
const std::shared_ptr<Sector> next_sector = get_next_sector();
if(next_sector->sector == first_sector->sector) return nullptr;
if(next_sector->sector == sector) return next_sector;
if(proceed_to_next_block(max_index_count) == 0x08) break;
if(index_count_ >= max_index_count) return nullptr;
}
// get sector details, skip if this looks malformed
uint8_t checksum = uint8_t(get_next_byte());
sector->sector = uint8_t(get_next_byte());
sector->track = uint8_t(get_next_byte());
uint8_t disk_id[2];
disk_id[0] = uint8_t(get_next_byte());
disk_id[1] = uint8_t(get_next_byte());
if(checksum != (sector->sector ^ sector->track ^ disk_id[0] ^ disk_id[1])) continue;
// look for the following data
while(1) {
if(proceed_to_next_block(max_index_count) == 0x07) break;
if(index_count_ >= max_index_count) return nullptr;
}
checksum = 0;
for(std::size_t c = 0; c < 256; c++) {
sector->data[c] = uint8_t(get_next_byte());
checksum ^= sector->data[c];
}
if(checksum == get_next_byte()) {
uint16_t sector_address = uint16_t((sector->track << 8) | sector->sector);
auto pair = sector_cache_.emplace(sector_address, std::move(sector));
return pair.first->second.get();
}
}
std::shared_ptr<Sector> get_next_sector() {
auto sector = std::make_shared<Sector>();
const int max_index_count = index_count_ + 2;
while(index_count_ < max_index_count) {
// look for a sector header
while(1) {
if(proceed_to_next_block(max_index_count) == 0x08) break;
if(index_count_ >= max_index_count) return nullptr;
}
// get sector details, skip if this looks malformed
uint8_t checksum = uint8_t(get_next_byte());
sector->sector = uint8_t(get_next_byte());
sector->track = uint8_t(get_next_byte());
uint8_t disk_id[2];
disk_id[0] = uint8_t(get_next_byte());
disk_id[1] = uint8_t(get_next_byte());
if(checksum != (sector->sector ^ sector->track ^ disk_id[0] ^ disk_id[1])) continue;
// look for the following data
while(1) {
if(proceed_to_next_block(max_index_count) == 0x07) break;
if(index_count_ >= max_index_count) return nullptr;
}
checksum = 0;
for(std::size_t c = 0; c < 256; c++) {
sector->data[c] = uint8_t(get_next_byte());
checksum ^= sector->data[c];
}
if(checksum == get_next_byte()) {
uint16_t sector_address = uint16_t((sector->track << 8) | sector->sector);
sector_cache_[sector_address] = sector;
return sector;
}
}
return nullptr;
}
return nullptr;
}
};
std::vector<File> Analyser::Static::Commodore::GetFiles(const std::shared_ptr<Storage::Disk::Disk> &disk) {
@@ -174,20 +176,26 @@ std::vector<File> Analyser::Static::Commodore::GetFiles(const std::shared_ptr<St
CommodoreGCRParser parser;
parser.set_disk(disk);
// find any sector whatsoever to establish the current track
std::shared_ptr<CommodoreGCRParser::Sector> sector;
// assemble directory
// Assemble directory.
std::vector<uint8_t> directory;
uint8_t next_track = 18;
uint8_t next_sector = 1;
while(1) {
sector = parser.get_sector(next_track, next_sector);
directory.reserve(20 * 1024); // Probably more than plenty.
std::set<std::pair<uint8_t, uint8_t>> visited;
while(true) {
// Don't be fooled by disks that are encoded with a looping directory.
const auto key = std::make_pair(next_track, next_sector);
if(visited.find(key) != visited.end()) break;
visited.insert(key);
// Append sector to directory and follow next link.
const auto sector = parser.sector(next_track, next_sector);
if(!sector) break;
directory.insert(directory.end(), sector->data.begin(), sector->data.end());
next_track = sector->data[0];
next_sector = sector->data[1];
// Check for end-of-directory.
if(!next_track) break;
}
@@ -216,24 +224,36 @@ std::vector<File> Analyser::Static::Commodore::GetFiles(const std::shared_ptr<St
}
new_file.name = Storage::Data::Commodore::petscii_from_bytes(&new_file.raw_name[0], 16, false);
std::size_t number_of_sectors = size_t(directory[header_pointer + 0x1e]) + (size_t(directory[header_pointer + 0x1f]) << 8);
new_file.data.reserve((number_of_sectors - 1) * 254 + 252);
const std::size_t number_of_sectors =
size_t(directory[header_pointer + 0x1e]) +
(size_t(directory[header_pointer + 0x1f]) << 8);
if(number_of_sectors) {
new_file.data.reserve((number_of_sectors - 1) * 254 + 252);
bool is_first_sector = true;
while(next_track) {
sector = parser.get_sector(next_track, next_sector);
if(!sector) break;
bool is_first_sector = true;
while(next_track) {
const auto sector = parser.sector(next_track, next_sector);
if(!sector) break;
next_track = sector->data[0];
next_sector = sector->data[1];
next_track = sector->data[0];
next_sector = sector->data[1];
if(is_first_sector) new_file.starting_address = uint16_t(sector->data[2]) | uint16_t(sector->data[3] << 8);
if(next_track)
new_file.data.insert(new_file.data.end(), sector->data.begin() + (is_first_sector ? 4 : 2), sector->data.end());
else
new_file.data.insert(new_file.data.end(), sector->data.begin() + 2, sector->data.begin() + next_sector);
if(is_first_sector) new_file.starting_address = uint16_t(sector->data[2]) | uint16_t(sector->data[3] << 8);
if(next_track)
new_file.data.insert(
new_file.data.end(),
sector->data.begin() + (is_first_sector ? 4 : 2),
sector->data.end()
);
else
new_file.data.insert(
new_file.data.end(),
sector->data.begin() + 2,
sector->data.begin() + next_sector
);
is_first_sector = false;
is_first_sector = false;
}
}
if(!next_track) files.push_back(new_file);

View File

@@ -6,18 +6,15 @@
// 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 "Storage/Disk/Disk.hpp"
#include "File.hpp"
#include <vector>
namespace Analyser::Static::Commodore {
std::vector<File> GetFiles(const std::shared_ptr<Storage::Disk::Disk> &disk);
std::vector<File> GetFiles(const std::shared_ptr<Storage::Disk::Disk> &);
}
#endif /* Disk_hpp */

View File

@@ -1,47 +0,0 @@
//
// File.cpp
// Clock Signal
//
// Created by Thomas Harte on 10/09/2016.
// Copyright 2016 Thomas Harte. All rights reserved.
//
#include "File.hpp"
bool Analyser::Static::Commodore::File::is_basic() {
// BASIC files are always relocatable (?)
if(type != File::RelocatableProgram) return false;
uint16_t line_address = starting_address;
int line_number = -1;
// decide whether this is a BASIC file based on the proposition that:
// (1) they're always relocatable; and
// (2) they have a per-line structure of:
// [4 bytes: address of start of next line]
// [4 bytes: this line number]
// ... null-terminated code ...
// (with a next line address of 0000 indicating end of program)
while(1) {
if(size_t(line_address - starting_address) >= data.size() + 2) break;
uint16_t next_line_address = data[line_address - starting_address];
next_line_address |= data[line_address - starting_address + 1] << 8;
if(!next_line_address) {
return true;
}
if(next_line_address < line_address + 5) break;
if(size_t(line_address - starting_address) >= data.size() + 5) break;
uint16_t next_line_number = data[line_address - starting_address + 2];
next_line_number |= data[line_address - starting_address + 3] << 8;
if(next_line_number <= line_number) break;
line_number = uint16_t(next_line_number);
line_address = next_line_address;
}
return false;
}

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>
@@ -30,10 +29,6 @@ struct File {
Relative
} type;
std::vector<uint8_t> data;
bool is_basic();
};
}
#endif /* File_hpp */

View File

@@ -12,26 +12,33 @@
#include "File.hpp"
#include "Tape.hpp"
#include "Target.hpp"
#include "../../../Storage/Cartridge/Encodings/CommodoreROM.hpp"
#include "../../../Outputs/Log.hpp"
#include "Storage/Cartridge/Encodings/CommodoreROM.hpp"
#include "Outputs/Log.hpp"
#include "Analyser/Static/Disassembler/6502.hpp"
#include "Analyser/Static/Disassembler/AddressMapper.hpp"
#include <algorithm>
#include <cstring>
#include <optional>
#include <sstream>
#include <unordered_set>
using namespace Analyser::Static::Commodore;
static std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
Vic20CartridgesFrom(const std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges) {
namespace {
std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
Vic20CartridgesFrom(const std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges) {
std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>> vic20_cartridges;
for(const auto &cartridge : cartridges) {
const auto &segments = cartridge->get_segments();
// only one mapped item is allowed
// Only one mapped item is allowed ...
if(segments.size() != 1) continue;
// which must be 16 kb in size
// ... which must be 16 kb in size.
Storage::Cartridge::Cartridge::Segment segment = segments.front();
if(segment.start_address != 0xa000) continue;
if(!Storage::Cartridge::Encodings::CommodoreROM::isROM(segment.data)) continue;
@@ -39,126 +46,312 @@ static std::vector<std::shared_ptr<Storage::Cartridge::Cartridge>>
vic20_cartridges.push_back(cartridge);
}
// TODO: other machines?
return vic20_cartridges;
}
Analyser::Static::TargetList Analyser::Static::Commodore::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType) {
TargetList destination;
struct BASICAnalysis {
enum class Version {
NotBASIC,
BASIC2,
BASIC4,
BASIC3_5,
} minimum_version = Version::NotBASIC;
std::vector<uint16_t> machine_code_addresses;
};
auto target = std::make_unique<Target>();
target->machine = Machine::Vic20; // TODO: machine estimation
target->confidence = 0.5; // TODO: a proper estimation
std::optional<BASICAnalysis> analyse(const File &file) {
BASICAnalysis analysis;
switch(file.type) {
// For 'program' types, proceed with analysis below.
case File::RelocatableProgram:
case File::NonRelocatableProgram:
break;
// For sequential and relative data stop right now.
case File::DataSequence:
case File::Relative:
return std::nullopt;
// For user data, try decoding from the starting point.
case File::User:
analysis.machine_code_addresses.push_back(file.starting_address);
return analysis;
}
// Don't form an opinion if file is empty.
if(file.data.empty()) {
return std::nullopt;
}
uint16_t line_address = file.starting_address;
// int previous_line_number = -1;
const auto byte = [&](uint16_t address) {
return file.data[address - file.starting_address];
};
const auto word = [&](uint16_t address) {
return uint16_t(byte(address) | byte(address + 1) << 8);
};
// BASIC programs have a per-line structure of:
// [2 bytes: address of start of next line]
// [2 bytes: this line number]
// ... null-terminated code ...
// (with a next line address of 0000 indicating end of program)
//
// If a SYS is encountered that jumps into the BASIC program then treat that as
// a machine code entry point.
std::unordered_set<uint16_t> visited_lines;
while(true) {
// Analysis has failed if there isn't at least one complete BASIC line from here.
// Fall back on guessing the start address as a machine code entrypoint.
if(size_t(line_address - file.starting_address) + 5 >= file.data.size() || line_address < file.starting_address) {
analysis.machine_code_addresses.push_back(file.starting_address);
break;
}
const auto next_line_address = word(line_address);
// const auto line_number = word(line_address + 2);
uint16_t code = line_address + 4;
const auto next = [&]() -> uint8_t {
if(code >= file.starting_address + file.data.size()) {
return 0;
}
return byte(code++);
};
// TODO: sanity check on apparent line contents.
// TODO: observe token set (and possibly parameters?) to guess BASIC version.
while(true) {
const auto token = next();
if(!token || token == 0x8f) break;
switch(token) {
case 0x9e: { // SYS; parse following ASCII argument.
uint16_t address = 0;
while(true) {
const auto c = next();
if(c < '0' || c > '9') {
break;
}
address = (address * 10) + (c - '0');
};
analysis.machine_code_addresses.push_back(address);
} break;
}
}
// Exit if a formal end of the program has been declared or if, as some copy protections do,
// the linked list of line contents has been made circular.
visited_lines.insert(line_address);
if(!next_line_address || visited_lines.find(next_line_address) != visited_lines.end()) {
break;
}
// previous_line_number = line_number;
line_address = next_line_address;
}
return analysis;
}
template <typename TargetT>
void set_loading_command(TargetT &target) {
if(target.media.disks.empty()) {
target.loading_command = "LOAD\"\",1,1\nRUN\n";
} else {
target.loading_command = "LOAD\"*\",8,1\nRUN\n";
}
}
bool obviously_uses_ted(const File &file) {
const auto analysis = analyse(file);
if(!analysis) return false;
// Disassemble.
const auto disassembly = Analyser::Static::MOS6502::Disassemble(
file.data,
Analyser::Static::Disassembler::OffsetMapper(file.starting_address),
analysis->machine_code_addresses
);
// Check for interrupt status and paging touches.
for(const auto address: {0xff3e, 0xff3f, 0xff09}) {
for(const auto &collection: {
disassembly.external_loads,
disassembly.external_stores,
disassembly.external_modifies
}) {
if(collection.find(uint16_t(address)) != collection.end()) {
return true;
}
}
}
return false;
}
struct FileAnalysis {
int device = 0;
std::vector<File> files;
bool is_disk = false;
Analyser::Static::Media media;
};
// strip out inappropriate cartridges
target->media.cartridges = Vic20CartridgesFrom(media.cartridges);
template <TargetPlatform::Type platform>
FileAnalysis analyse_files(const Analyser::Static::Media &media) {
FileAnalysis analysis;
// check disks
// Find all valid Commodore files on disks.
for(auto &disk : media.disks) {
std::vector<File> disk_files = GetFiles(disk);
if(!disk_files.empty()) {
is_disk = true;
files.insert(files.end(), disk_files.begin(), disk_files.end());
target->media.disks.push_back(disk);
if(!device) device = 8;
analysis.is_disk = true;
analysis.files.insert(
analysis.files.end(),
std::make_move_iterator(disk_files.begin()),
std::make_move_iterator(disk_files.end())
);
analysis.media.disks.push_back(disk);
if(!analysis.device) analysis.device = 8;
}
}
// check tapes
// Find all valid Commodore files on tapes.
for(auto &tape : media.tapes) {
std::vector<File> tape_files = GetFiles(tape);
tape->reset();
auto serialiser = tape->serialiser();
std::vector<File> tape_files = GetFiles(*serialiser, platform);
if(!tape_files.empty()) {
files.insert(files.end(), tape_files.begin(), tape_files.end());
target->media.tapes.push_back(tape);
if(!device) device = 1;
analysis.files.insert(
analysis.files.end(),
std::make_move_iterator(tape_files.begin()),
std::make_move_iterator(tape_files.end())
);
analysis.media.tapes.push_back(tape);
if(!analysis.device) analysis.device = 1;
}
}
if(!files.empty()) {
auto memory_model = Target::MemoryModel::Unexpanded;
std::ostringstream string_stream;
string_stream << "LOAD\"" << (is_disk ? "*" : "") << "\"," << device << ",";
if(files.front().is_basic()) {
string_stream << "0";
} else {
string_stream << "1";
return analysis;
}
std::string loading_command(const FileAnalysis &file_analysis) {
std::ostringstream string_stream;
string_stream << "LOAD\"" << (file_analysis.is_disk ? "*" : "") << "\"," << file_analysis.device;
const auto analysis = analyse(file_analysis.files[0]);
if(analysis && !analysis->machine_code_addresses.empty()) {
string_stream << ",1";
}
string_stream << "\nRUN\n";
return string_stream.str();
}
std::pair<TargetPlatform::IntType, std::optional<Vic20Target::MemoryModel>>
analyse_starting_address(uint16_t starting_address) {
switch(starting_address) {
case 0x1c01:
// TODO: assume C128.
default:
Log::Logger<Log::Source::CommodoreStaticAnalyser>().error().append(
"Unrecognised loading address for Commodore program: %04x", starting_address);
[[fallthrough]];
case 0x1001:
return std::make_pair(TargetPlatform::Vic20 | TargetPlatform::Plus4, Vic20Target::MemoryModel::Unexpanded);
case 0x1201: return std::make_pair(TargetPlatform::Vic20, Vic20Target::MemoryModel::ThirtyTwoKB);
case 0x0401: return std::make_pair(TargetPlatform::Vic20, Vic20Target::MemoryModel::EightKB);
case 0x0801: return std::make_pair(TargetPlatform::C64, std::nullopt);
}
}
template <TargetPlatform::IntType platform>
std::unique_ptr<Analyser::Static::Target> get_target(
const Analyser::Static::Media &media,
const std::string &file_name,
bool is_confident
);
template<>
std::unique_ptr<Analyser::Static::Target> get_target<TargetPlatform::Plus4>(
const Analyser::Static::Media &media,
const std::string &,
bool is_confident
) {
auto target = std::make_unique<Plus4Target>();
if(is_confident) {
target->media = media;
set_loading_command(*target);
} else {
const auto files = analyse_files<TargetPlatform::Plus4>(media);
if(!files.files.empty()) {
target->loading_command = loading_command(files);
}
string_stream << "\nRUN\n";
target->loading_command = string_stream.str();
// 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);
[[fallthrough]];
case 0x1001:
memory_model = Target::MemoryModel::Unexpanded;
break;
case 0x1201:
memory_model = Target::MemoryModel::ThirtyTwoKB;
break;
case 0x0401:
memory_model = Target::MemoryModel::EightKB;
break;
}
target->set_memory_model(memory_model);
// General approach: increase memory size conservatively such that the largest file found will fit.
// for(File &file : files) {
// std::size_t file_size = file.data.size();
// bool is_basic = file.is_basic();
/*if(is_basic)
{
// BASIC files may be relocated, so the only limit is size.
//
// An unexpanded machine has 3583 bytes free for BASIC;
// a 3kb expanded machine has 6655 bytes free.
if(file_size > 6655)
target->vic20.memory_model = Vic20MemoryModel::ThirtyTwoKB;
else if(target->vic20.memory_model == Vic20MemoryModel::Unexpanded && file_size > 3583)
target->vic20.memory_model = Vic20MemoryModel::EightKB;
}
else
{*/
// if(!file.type == File::NonRelocatableProgram)
// {
// Non-BASIC files may be relocatable but, if so, by what logic?
// Given that this is unknown, take starting address as literal
// and check against memory windows.
//
// (ignoring colour memory...)
// An unexpanded Vic has memory between 0x0000 and 0x0400; and between 0x1000 and 0x2000.
// A 3kb expanded Vic fills in the gap and has memory between 0x0000 and 0x2000.
// A 32kb expanded Vic has memory in the entire low 32kb.
// uint16_t starting_address = file.starting_address;
// If anything above the 8kb mark is touched, mark as a 32kb machine; otherwise if the
// region 0x0400 to 0x1000 is touched and this is an unexpanded machine, mark as 3kb.
// if(starting_address + file_size > 0x2000)
// target->memory_model = Target::MemoryModel::ThirtyTwoKB;
// else if(target->memory_model == Target::MemoryModel::Unexpanded && !(starting_address >= 0x1000 || starting_address+file_size < 0x0400))
// target->memory_model = Target::MemoryModel::ThirtyTwoKB;
// }
// }
target->media.disks = media.disks;
target->media.tapes = media.tapes;
}
// Attach a 1541 if there are any disks here.
target->has_c1541 = !target->media.disks.empty();
return target;
}
template<>
std::unique_ptr<Analyser::Static::Target> get_target<TargetPlatform::Vic20>(
const Analyser::Static::Media &media,
const std::string &file_name,
bool is_confident
) {
auto target = std::make_unique<Vic20Target>();
const auto files = analyse_files<TargetPlatform::Vic20>(media);
if(!files.files.empty()) {
target->loading_command = loading_command(files);
const auto model = analyse_starting_address(files.files[0].starting_address);
if(model.second.has_value()) {
target->set_memory_model(*model.second);
}
}
if(is_confident) {
target->media = media;
set_loading_command(*target);
} else {
// Strip out inappropriate cartridges but retain all tapes and disks.
target->media.cartridges = Vic20CartridgesFrom(media.cartridges);
target->media.disks = media.disks;
target->media.tapes = media.tapes;
}
for(const auto &file : files.files) {
// The Vic-20 never has RAM after 0x8000.
if(file.ending_address >= 0x8000) {
return nullptr;
}
if(obviously_uses_ted(file)) {
return nullptr;
}
}
// Inspect filename for configuration hints.
if(!target->media.empty()) {
// Inspect filename for configuration hints.
using Region = Analyser::Static::Commodore::Vic20Target::Region;
std::string lowercase_name = file_name;
std::transform(lowercase_name.begin(), lowercase_name.end(), lowercase_name.begin(), ::tolower);
// Hint 1: 'ntsc' anywhere in the name implies America.
if(lowercase_name.find("ntsc") != std::string::npos) {
target->region = Analyser::Static::Commodore::Target::Region::American;
target->region = Region::American;
}
// Potential additional hints: check for TheC64 tags.
// Potential additional hints: check for TheC64 tags; these are Vic-20 exclusive.
auto final_underscore = lowercase_name.find_last_of('_');
if(final_underscore != std::string::npos) {
auto iterator = lowercase_name.begin() + ssize_t(final_underscore) + 1;
@@ -180,10 +373,10 @@ Analyser::Static::TargetList Analyser::Static::Commodore::GetTargets(const Media
target->enabled_ram.bank3 |= !strcmp(next_tag, "b3");
target->enabled_ram.bank5 |= !strcmp(next_tag, "b5");
if(!strcmp(next_tag, "tn")) { // i.e. NTSC.
target->region = Analyser::Static::Commodore::Target::Region::American;
target->region = Region::American;
}
if(!strcmp(next_tag, "tp")) { // i.e. PAL.
target->region = Analyser::Static::Commodore::Target::Region::European;
target->region = Region::European;
}
// Unhandled:
@@ -194,11 +387,36 @@ Analyser::Static::TargetList Analyser::Static::Commodore::GetTargets(const Media
// RO: this disk image should be treated as read-only.
}
}
}
// Attach a 1540 if there are any disks here.
target->has_c1540 = !target->media.disks.empty();
// Attach a 1540 if there are any disks here.
target->has_c1540 = !target->media.disks.empty();
return target;
}
destination.push_back(std::move(target));
}
Analyser::Static::TargetList Analyser::Static::Commodore::GetTargets(
const Media &media,
const std::string &file_name,
TargetPlatform::IntType platforms,
bool is_confident
) {
TargetList destination;
if(platforms & TargetPlatform::Vic20) {
auto vic20 = get_target<TargetPlatform::Vic20>(media, file_name, is_confident);
if(vic20) {
destination.push_back(std::move(vic20));
}
}
if(platforms & TargetPlatform::Plus4) {
auto plus4 = get_target<TargetPlatform::Plus4>(media, file_name, is_confident);
if(plus4) {
destination.push_back(std::move(plus4));
}
}
return destination;

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::Commodore {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* CommodoreAnalyser_hpp */

View File

@@ -7,26 +7,27 @@
//
#include "Tape.hpp"
#include "Storage/Tape/Parsers/Commodore.hpp"
#include "../../../Storage/Tape/Parsers/Commodore.hpp"
#include <algorithm>
using namespace Analyser::Static::Commodore;
std::vector<File> Analyser::Static::Commodore::GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape) {
Storage::Tape::Commodore::Parser parser;
std::vector<File> Analyser::Static::Commodore::GetFiles(Storage::Tape::TapeSerialiser &serialiser, TargetPlatform::Type type) {
Storage::Tape::Commodore::Parser parser(type);
std::vector<File> file_list;
std::unique_ptr<Storage::Tape::Commodore::Header> header = parser.get_next_header(tape);
std::unique_ptr<Storage::Tape::Commodore::Header> header = parser.get_next_header(serialiser);
while(!tape->is_at_end()) {
while(!serialiser.is_at_end()) {
if(!header) {
header = parser.get_next_header(tape);
header = parser.get_next_header(serialiser);
continue;
}
switch(header->type) {
case Storage::Tape::Commodore::Header::DataSequenceHeader: {
File new_file;
File &new_file = file_list.emplace_back();
new_file.name = header->name;
new_file.raw_name = header->raw_name;
new_file.starting_address = header->starting_address;
@@ -34,38 +35,36 @@ std::vector<File> Analyser::Static::Commodore::GetFiles(const std::shared_ptr<St
new_file.type = File::DataSequence;
new_file.data.swap(header->data);
while(!tape->is_at_end()) {
header = parser.get_next_header(tape);
while(!serialiser.is_at_end()) {
header = parser.get_next_header(serialiser);
if(!header) continue;
if(header->type != Storage::Tape::Commodore::Header::DataBlock) break;
std::copy(header->data.begin(), header->data.end(), std::back_inserter(new_file.data));
std::ranges::copy(header->data, std::back_inserter(new_file.data));
}
file_list.push_back(new_file);
}
break;
case Storage::Tape::Commodore::Header::RelocatableProgram:
case Storage::Tape::Commodore::Header::NonRelocatableProgram: {
std::unique_ptr<Storage::Tape::Commodore::Data> data = parser.get_next_data(tape);
std::unique_ptr<Storage::Tape::Commodore::Data> data = parser.get_next_data(serialiser);
if(data) {
File new_file;
File &new_file = file_list.emplace_back();
new_file.name = header->name;
new_file.raw_name = header->raw_name;
new_file.starting_address = header->starting_address;
new_file.ending_address = header->ending_address;
new_file.data.swap(data->data);
new_file.type = (header->type == Storage::Tape::Commodore::Header::RelocatableProgram) ? File::RelocatableProgram : File::NonRelocatableProgram;
file_list.push_back(new_file);
new_file.type =
header->type == Storage::Tape::Commodore::Header::RelocatableProgram
? File::RelocatableProgram : File::NonRelocatableProgram;
}
header = parser.get_next_header(tape);
header = parser.get_next_header(serialiser);
}
break;
default:
header = parser.get_next_header(tape);
header = parser.get_next_header(serialiser);
break;
}
}

View File

@@ -6,16 +6,14 @@
// 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 "Storage/Tape/Tape.hpp"
#include "Storage/TargetPlatforms.hpp"
#include "File.hpp"
namespace Analyser::Static::Commodore {
std::vector<File> GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape);
std::vector<File> GetFiles(Storage::Tape::TapeSerialiser &, TargetPlatform::Type);
}
#endif /* Tape_hpp */

View File

@@ -6,17 +6,30 @@
// 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"
#include "../StaticAnalyser.hpp"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Reflection/Enum.hpp"
#include "Reflection/Struct.hpp"
#include <string>
namespace Analyser::Static::Commodore {
struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Target> {
struct Plus4Target: public Analyser::Static::Target, public Reflection::StructImpl<Plus4Target> {
// TODO: region, etc.
std::string loading_command;
bool has_c1541 = false;
Plus4Target() : Analyser::Static::Target(Machine::Plus4) {}
private:
friend Reflection::StructImpl<Plus4Target>;
void declare_fields() {
DeclareField(has_c1541);
}
};
struct Vic20Target: public Analyser::Static::Target, public Reflection::StructImpl<Vic20Target> {
enum class MemoryModel {
Unexpanded,
EightKB,
@@ -55,20 +68,20 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
bool has_c1540 = false;
std::string loading_command;
Target() : Analyser::Static::Target(Machine::Vic20) {
if(needs_declare()) {
DeclareField(enabled_ram.bank0);
DeclareField(enabled_ram.bank1);
DeclareField(enabled_ram.bank2);
DeclareField(enabled_ram.bank3);
DeclareField(enabled_ram.bank5);
DeclareField(region);
DeclareField(has_c1540);
AnnounceEnum(Region);
}
Vic20Target() : Analyser::Static::Target(Machine::Vic20) {}
private:
friend Reflection::StructImpl<Vic20Target>;
void declare_fields() {
DeclareField(enabled_ram.bank0);
DeclareField(enabled_ram.bank1);
DeclareField(enabled_ram.bank2);
DeclareField(enabled_ram.bank3);
DeclareField(enabled_ram.bank5);
DeclareField(region);
DeclareField(has_c1540);
AnnounceEnum(Region);
}
};
}
#endif /* Analyser_Static_Commodore_Target_h */

View File

@@ -17,7 +17,12 @@ using PartialDisassembly = Analyser::Static::Disassembly::PartialDisassembly<Dis
struct MOS6502Disassembler {
static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<uint8_t> &memory, const std::function<std::size_t(uint16_t)> &address_mapper, uint16_t entry_point) {
static void AddToDisassembly(
PartialDisassembly &disassembly,
const std::vector<uint8_t> &memory,
const std::function<std::size_t(uint16_t)> &address_mapper,
uint16_t entry_point
) {
disassembly.disassembly.internal_calls.insert(entry_point);
uint16_t address = entry_point;
while(true) {
@@ -75,23 +80,25 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<
}
// Decode operation.
#define RM_INSTRUCTION(base, op) \
case base+0x09: case base+0x05: case base+0x15: case base+0x01: case base+0x11: case base+0x0d: case base+0x1d: case base+0x19: \
instruction.operation = op; \
#define RM_INSTRUCTION(base, op) \
case base+0x09: case base+0x05: case base+0x15: case base+0x01: \
case base+0x11: case base+0x0d: case base+0x1d: case base+0x19: \
instruction.operation = op; \
break;
#define URM_INSTRUCTION(base, op) \
#define URM_INSTRUCTION(base, op) \
case base+0x07: case base+0x17: case base+0x03: case base+0x13: case base+0x0f: case base+0x1f: case base+0x1b: \
instruction.operation = op; \
instruction.operation = op; \
break;
#define M_INSTRUCTION(base, op) \
#define M_INSTRUCTION(base, op) \
case base+0x0a: case base+0x06: case base+0x16: case base+0x0e: case base+0x1e: \
instruction.operation = op; \
instruction.operation = op; \
break;
#define IM_INSTRUCTION(base, op) \
#define IM_INSTRUCTION(base, op) \
case base: instruction.operation = op; break;
switch(operation) {
default:
instruction.operation = Instruction::KIL;
@@ -236,7 +243,7 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<
case Instruction::Relative: {
std::size_t operand_address = address_mapper(address);
if(operand_address >= memory.size()) return;
address++;
++address;
instruction.operand = memory[operand_address];
}
@@ -259,7 +266,10 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<
disassembly.disassembly.instructions_by_address[instruction.address] = instruction;
// TODO: something wider-ranging than this
if(instruction.addressing_mode == Instruction::Absolute || instruction.addressing_mode == Instruction::ZeroPage) {
if(
instruction.addressing_mode == Instruction::Absolute ||
instruction.addressing_mode == Instruction::ZeroPage
) {
const size_t mapped_address = address_mapper(instruction.operand);
const bool is_external = mapped_address >= memory.size();
@@ -272,39 +282,56 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<
case Instruction::ADC: case Instruction::SBC:
case Instruction::LAS:
case Instruction::CMP: case Instruction::CPX: case Instruction::CPY:
(is_external ? disassembly.disassembly.external_loads : disassembly.disassembly.internal_loads).insert(instruction.operand);
(is_external ? disassembly.disassembly.external_loads : disassembly.disassembly.internal_loads)
.insert(instruction.operand);
break;
case Instruction::STY: case Instruction::STX: case Instruction::STA:
case Instruction::AXS: case Instruction::AHX: case Instruction::SHX: case Instruction::SHY:
case Instruction::TAS:
(is_external ? disassembly.disassembly.external_stores : disassembly.disassembly.internal_stores).insert(instruction.operand);
(is_external ? disassembly.disassembly.external_stores : disassembly.disassembly.internal_stores)
.insert(instruction.operand);
break;
case Instruction::SLO: case Instruction::RLA: case Instruction::SRE: case Instruction::RRA:
case Instruction::DCP: case Instruction::ISC:
case Instruction::INC: case Instruction::DEC:
case Instruction::ASL: case Instruction::ROL: case Instruction::LSR: case Instruction::ROR:
(is_external ? disassembly.disassembly.external_modifies : disassembly.disassembly.internal_modifies).insert(instruction.operand);
(is_external ? disassembly.disassembly.external_modifies : disassembly.disassembly.internal_modifies)
.insert(instruction.operand);
break;
}
}
// Decide on overall flow control.
if(instruction.operation == Instruction::RTS || instruction.operation == Instruction::RTI) return;
if(instruction.operation == Instruction::BRK) return; // TODO: check whether IRQ vector is within memory range
if(instruction.operation == Instruction::JSR) {
disassembly.remaining_entry_points.push_back(instruction.operand);
}
if(instruction.operation == Instruction::JMP) {
if(instruction.addressing_mode == Instruction::Absolute)
disassembly.remaining_entry_points.push_back(instruction.operand);
return;
}
// All relative instructions are flow control.
if(instruction.addressing_mode == Instruction::Relative) {
uint16_t destination = uint16_t(address + int8_t(instruction.operand));
disassembly.remaining_entry_points.push_back(destination);
}
switch(instruction.operation) {
default: break;
case Instruction::KIL:
case Instruction::RTS:
case Instruction::RTI:
case Instruction::BRK: // TODO: check whether IRQ vector is within memory range.
disassembly.implicit_entry_points.push_back(address);
return;
case Instruction::JMP:
// Adding a new entry point for relative jumps was handled above.
if(instruction.addressing_mode == Instruction::Absolute) {
disassembly.remaining_entry_points.push_back(instruction.operand);
}
return;
case Instruction::JSR:
disassembly.remaining_entry_points.push_back(instruction.operand);
break;
}
}
}
@@ -316,5 +343,10 @@ Disassembly Analyser::Static::MOS6502::Disassemble(
const std::vector<uint8_t> &memory,
const std::function<std::size_t(uint16_t)> &address_mapper,
std::vector<uint16_t> entry_points) {
return Analyser::Static::Disassembly::Disassemble<Disassembly, uint16_t, MOS6502Disassembler>(memory, address_mapper, entry_points);
return Analyser::Static::Disassembly::Disassemble<Disassembly, uint16_t, MOS6502Disassembler>(
memory,
address_mapper,
entry_points,
false
);
}

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>
@@ -17,12 +16,10 @@ namespace Analyser::Static::Disassembler {
Provides an address mapper that relocates a chunk of memory so that it starts at
address @c start_address.
*/
template <typename T> std::function<std::size_t(T)> OffsetMapper(T start_address) {
template <typename T> std::function<std::size_t(T)> OffsetMapper(const T start_address) {
return [start_address](T argument) {
return size_t(argument - start_address);
};
}
}
#endif /* AddressMapper_hpp */

View File

@@ -6,43 +6,61 @@
// Copyright 2017 Thomas Harte. All rights reserved.
//
#ifndef Kernel_hpp
#define Kernel_hpp
#pragma once
namespace Analyser::Static::Disassembly {
template <typename D, typename S> struct PartialDisassembly {
D disassembly;
std::vector<S> remaining_entry_points;
std::vector<S> implicit_entry_points;
};
template <typename D, typename S, typename Disassembler> D Disassemble(
const std::vector<uint8_t> &memory,
const std::function<std::size_t(S)> &address_mapper,
std::vector<S> entry_points) {
std::vector<S> entry_points,
bool exhaustive)
{
PartialDisassembly<D, S> partial_disassembly;
partial_disassembly.remaining_entry_points = entry_points;
while(!partial_disassembly.remaining_entry_points.empty()) {
// pull the next entry point from the back of the vector
S next_entry_point = partial_disassembly.remaining_entry_points.back();
partial_disassembly.remaining_entry_points.pop_back();
// Do a recursive-style disassembly for all current entry points.
while(!partial_disassembly.remaining_entry_points.empty()) {
// Pull the next entry point from the back of the vector.
const S next_entry_point = partial_disassembly.remaining_entry_points.back();
partial_disassembly.remaining_entry_points.pop_back();
// if that address has already been visited, forget about it
if( partial_disassembly.disassembly.instructions_by_address.find(next_entry_point)
!= partial_disassembly.disassembly.instructions_by_address.end()) continue;
// If that address has already been visited, forget about it.
if( partial_disassembly.disassembly.instructions_by_address.find(next_entry_point)
!= partial_disassembly.disassembly.instructions_by_address.end()) continue;
// if it's outgoing, log it as such and forget about it; otherwise disassemble
std::size_t mapped_entry_point = address_mapper(next_entry_point);
if(mapped_entry_point >= memory.size())
partial_disassembly.disassembly.outward_calls.insert(next_entry_point);
else
Disassembler::AddToDisassembly(partial_disassembly, memory, address_mapper, next_entry_point);
// If it's outgoing, log it as such and forget about it; otherwise disassemble.
std::size_t mapped_entry_point = address_mapper(next_entry_point);
if(mapped_entry_point >= memory.size())
partial_disassembly.disassembly.outward_calls.insert(next_entry_point);
else
Disassembler::AddToDisassembly(partial_disassembly, memory, address_mapper, next_entry_point);
}
// If this is not an exhaustive disassembly, that's your lot.
if(!exhaustive) {
break;
}
// Otherwise, copy in the new 'implicit entry points' (i.e. all locations that are one after
// a disassembled region). There's a test above that'll ignore any which have already been
// disassembled from.
std::move(
partial_disassembly.implicit_entry_points.begin(),
partial_disassembly.implicit_entry_points.end(),
std::back_inserter(partial_disassembly.remaining_entry_points)
);
partial_disassembly.implicit_entry_points.clear();
}
return partial_disassembly.disassembly;
}
}
#endif /* Kernel_hpp */

View File

@@ -16,51 +16,55 @@ namespace {
using PartialDisassembly = Analyser::Static::Disassembly::PartialDisassembly<Disassembly, uint16_t>;
class Accessor {
public:
Accessor(const std::vector<uint8_t> &memory, const std::function<std::size_t(uint16_t)> &address_mapper, uint16_t address) :
memory_(memory), address_mapper_(address_mapper), address_(address) {}
public:
Accessor(
const std::vector<uint8_t> &memory,
const std::function<std::size_t(uint16_t)> &address_mapper,
uint16_t address
) :
memory_(memory), address_mapper_(address_mapper), address_(address) {}
uint8_t byte() {
std::size_t mapped_address = address_mapper_(address_);
address_++;
if(mapped_address >= memory_.size()) {
overrun_ = true;
return 0xff;
}
return memory_[mapped_address];
uint8_t byte() {
std::size_t mapped_address = address_mapper_(address_);
++address_;
if(mapped_address >= memory_.size()) {
overrun_ = true;
return 0xff;
}
return memory_[mapped_address];
}
uint16_t word() {
uint8_t low = byte();
uint8_t high = byte();
return uint16_t(low | (high << 8));
}
uint16_t word() {
uint8_t low = byte();
uint8_t high = byte();
return uint16_t(low | (high << 8));
}
bool overrun() {
return overrun_;
}
bool overrun() const {
return overrun_;
}
bool at_end() {
std::size_t mapped_address = address_mapper_(address_);
return mapped_address >= memory_.size();
}
bool at_end() const {
std::size_t mapped_address = address_mapper_(address_);
return mapped_address >= memory_.size();
}
uint16_t address() {
return address_;
}
uint16_t address() const {
return address_;
}
private:
const std::vector<uint8_t> &memory_;
const std::function<std::size_t(uint16_t)> &address_mapper_;
uint16_t address_;
bool overrun_ = false;
private:
const std::vector<uint8_t> &memory_;
const std::function<std::size_t(uint16_t)> &address_mapper_;
uint16_t address_;
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(const uint8_t v) { return v >> 6; }
constexpr uint8_t y(const uint8_t v) { return (v >> 3) & 7; }
constexpr uint8_t q(const uint8_t v) { return (v >> 3) & 1; }
constexpr uint8_t p(const uint8_t v) { return (v >> 4) & 3; }
constexpr uint8_t z(const uint8_t v) { return v & 7; }
Instruction::Condition condition_table[] = {
Instruction::Condition::NZ, Instruction::Condition::Z,
@@ -83,8 +87,12 @@ Instruction::Location register_pair_table2[] = {
Instruction::Location::AF
};
Instruction::Location RegisterTableEntry(int offset, Accessor &accessor, Instruction &instruction, bool needs_indirect_offset) {
Instruction::Location register_table[] = {
Instruction::Location RegisterTableEntry(
const int offset, Accessor &accessor,
Instruction &instruction,
const bool needs_indirect_offset
) {
static constexpr Instruction::Location register_table[] = {
Instruction::Location::B, Instruction::Location::C,
Instruction::Location::D, Instruction::Location::E,
Instruction::Location::H, Instruction::Location::L,
@@ -92,7 +100,7 @@ Instruction::Location RegisterTableEntry(int offset, Accessor &accessor, Instruc
Instruction::Location::A
};
Instruction::Location location = register_table[offset];
const Instruction::Location location = register_table[offset];
if(location == Instruction::Location::HL_Indirect && needs_indirect_offset) {
instruction.offset = accessor.byte() - 128;
}
@@ -100,7 +108,7 @@ Instruction::Location RegisterTableEntry(int offset, Accessor &accessor, Instruc
return location;
}
Instruction::Operation alu_table[] = {
constexpr Instruction::Operation alu_table[] = {
Instruction::Operation::ADD,
Instruction::Operation::ADC,
Instruction::Operation::SUB,
@@ -111,7 +119,7 @@ Instruction::Operation alu_table[] = {
Instruction::Operation::CP
};
Instruction::Operation rotation_table[] = {
constexpr Instruction::Operation rotation_table[] = {
Instruction::Operation::RLC,
Instruction::Operation::RRC,
Instruction::Operation::RL,
@@ -122,19 +130,32 @@ Instruction::Operation rotation_table[] = {
Instruction::Operation::SRL
};
Instruction::Operation block_table[][4] = {
{Instruction::Operation::LDI, Instruction::Operation::CPI, Instruction::Operation::INI, Instruction::Operation::OUTI},
{Instruction::Operation::LDD, Instruction::Operation::CPD, Instruction::Operation::IND, Instruction::Operation::OUTD},
{Instruction::Operation::LDIR, Instruction::Operation::CPIR, Instruction::Operation::INIR, Instruction::Operation::OTIR},
{Instruction::Operation::LDDR, Instruction::Operation::CPDR, Instruction::Operation::INDR, Instruction::Operation::OTDR},
constexpr Instruction::Operation block_table[][4] = {
{
Instruction::Operation::LDI, Instruction::Operation::CPI,
Instruction::Operation::INI, Instruction::Operation::OUTI
},
{
Instruction::Operation::LDD, Instruction::Operation::CPD,
Instruction::Operation::IND, Instruction::Operation::OUTD
},
{
Instruction::Operation::LDIR, Instruction::Operation::CPIR,
Instruction::Operation::INIR, Instruction::Operation::OTIR
},
{
Instruction::Operation::LDDR, Instruction::Operation::CPDR,
Instruction::Operation::INDR, Instruction::Operation::OTDR
},
};
void DisassembleCBPage(Accessor &accessor, Instruction &instruction, bool needs_indirect_offset) {
void DisassembleCBPage(Accessor &accessor, Instruction &instruction, const bool needs_indirect_offset) {
const uint8_t operation = accessor.byte();
if(!x(operation)) {
instruction.operation = rotation_table[y(operation)];
instruction.source = instruction.destination = RegisterTableEntry(z(operation), accessor, instruction, needs_indirect_offset);
instruction.source = instruction.destination =
RegisterTableEntry(z(operation), accessor, instruction, needs_indirect_offset);
} else {
instruction.destination = RegisterTableEntry(z(operation), accessor, instruction, needs_indirect_offset);
instruction.source = Instruction::Location::Operand;
@@ -148,7 +169,7 @@ void DisassembleCBPage(Accessor &accessor, Instruction &instruction, bool needs_
}
}
void DisassembleEDPage(Accessor &accessor, Instruction &instruction, bool needs_indirect_offset) {
void DisassembleEDPage(Accessor &accessor, Instruction &instruction, const bool needs_indirect_offset) {
const uint8_t operation = accessor.byte();
switch(x(operation)) {
@@ -170,7 +191,8 @@ void DisassembleEDPage(Accessor &accessor, Instruction &instruction, bool needs_
if(y(operation) == 6) {
instruction.destination = Instruction::Location::None;
} else {
instruction.destination = RegisterTableEntry(y(operation), accessor, instruction, needs_indirect_offset);
instruction.destination =
RegisterTableEntry(y(operation), accessor, instruction, needs_indirect_offset);
}
break;
case 1:
@@ -179,7 +201,8 @@ void DisassembleEDPage(Accessor &accessor, Instruction &instruction, bool needs_
if(y(operation) == 6) {
instruction.source = Instruction::Location::None;
} else {
instruction.source = RegisterTableEntry(y(operation), accessor, instruction, needs_indirect_offset);
instruction.source =
RegisterTableEntry(y(operation), accessor, instruction, needs_indirect_offset);
}
break;
case 2:
@@ -190,11 +213,13 @@ void DisassembleEDPage(Accessor &accessor, Instruction &instruction, bool needs_
case 3:
instruction.operation = Instruction::Operation::LD;
if(q(operation)) {
instruction.destination = RegisterTableEntry(p(operation), accessor, instruction, needs_indirect_offset);
instruction.destination =
RegisterTableEntry(p(operation), accessor, instruction, needs_indirect_offset);
instruction.source = Instruction::Location::Operand_Indirect;
} else {
instruction.destination = Instruction::Location::Operand_Indirect;
instruction.source = RegisterTableEntry(p(operation), accessor, instruction, needs_indirect_offset);
instruction.source =
RegisterTableEntry(p(operation), accessor, instruction, needs_indirect_offset);
}
instruction.operand = accessor.word();
break;
@@ -202,7 +227,8 @@ void DisassembleEDPage(Accessor &accessor, Instruction &instruction, bool needs_
instruction.operation = Instruction::Operation::NEG;
break;
case 5:
instruction.operation = (y(operation) == 1) ? Instruction::Operation::RETI : Instruction::Operation::RETN;
instruction.operation =
y(operation) == 1 ? Instruction::Operation::RETI : Instruction::Operation::RETN;
break;
case 6:
instruction.operation = Instruction::Operation::IM;
@@ -253,7 +279,7 @@ void DisassembleMainPage(Accessor &accessor, Instruction &instruction) {
} hl_substitution = None;
while(true) {
uint8_t operation = accessor.byte();
const uint8_t operation = accessor.byte();
switch(x(operation)) {
case 0:
@@ -343,15 +369,18 @@ void DisassembleMainPage(Accessor &accessor, Instruction &instruction) {
break;
case 4:
instruction.operation = Instruction::Operation::INC;
instruction.source = instruction.destination = RegisterTableEntry(y(operation), accessor, instruction, needs_indirect_offset);
instruction.source = instruction.destination =
RegisterTableEntry(y(operation), accessor, instruction, needs_indirect_offset);
break;
case 5:
instruction.operation = Instruction::Operation::DEC;
instruction.source = instruction.destination = RegisterTableEntry(y(operation), accessor, instruction, needs_indirect_offset);
instruction.source = instruction.destination =
RegisterTableEntry(y(operation), accessor, instruction, needs_indirect_offset);
break;
case 6:
instruction.operation = Instruction::Operation::LD;
instruction.destination = RegisterTableEntry(y(operation), accessor, instruction, needs_indirect_offset);
instruction.destination =
RegisterTableEntry(y(operation), accessor, instruction, needs_indirect_offset);
instruction.source = Instruction::Location::Operand;
instruction.operand = accessor.byte();
break;
@@ -374,8 +403,10 @@ void DisassembleMainPage(Accessor &accessor, Instruction &instruction) {
instruction.operation = Instruction::Operation::HALT;
} else {
instruction.operation = Instruction::Operation::LD;
instruction.source = RegisterTableEntry(z(operation), accessor, instruction, needs_indirect_offset);
instruction.destination = RegisterTableEntry(y(operation), accessor, instruction, needs_indirect_offset);
instruction.source =
RegisterTableEntry(z(operation), accessor, instruction, needs_indirect_offset);
instruction.destination =
RegisterTableEntry(y(operation), accessor, instruction, needs_indirect_offset);
}
break;
case 2:
@@ -517,10 +548,14 @@ void DisassembleMainPage(Accessor &accessor, Instruction &instruction) {
instruction.destination == Instruction::Location::HL_Indirect) {
if(instruction.source == Instruction::Location::HL_Indirect) {
instruction.source = (hl_substitution == IX) ? Instruction::Location::IX_Indirect_Offset : Instruction::Location::IY_Indirect_Offset;
instruction.source =
hl_substitution == IX ?
Instruction::Location::IX_Indirect_Offset : Instruction::Location::IY_Indirect_Offset;
}
if(instruction.destination == Instruction::Location::HL_Indirect) {
instruction.destination = (hl_substitution == IX) ? Instruction::Location::IX_Indirect_Offset : Instruction::Location::IY_Indirect_Offset;
instruction.destination =
hl_substitution == IX ?
Instruction::Location::IX_Indirect_Offset : Instruction::Location::IY_Indirect_Offset;
}
return;
}
@@ -542,7 +577,12 @@ void DisassembleMainPage(Accessor &accessor, Instruction &instruction) {
}
struct Z80Disassembler {
static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<uint8_t> &memory, const std::function<std::size_t(uint16_t)> &address_mapper, uint16_t entry_point) {
static void AddToDisassembly(
PartialDisassembly &disassembly,
const std::vector<uint8_t> &memory,
const std::function<std::size_t(uint16_t)> &address_mapper,
const uint16_t entry_point
) {
disassembly.disassembly.internal_calls.insert(entry_point);
Accessor accessor(memory, address_mapper, entry_point);
@@ -589,7 +629,7 @@ struct Z80Disassembler {
break;
}
// Add any (potentially) newly discovered entry point.
// Add any (potentially) newly-discovered entry point.
if( instruction.operation == Instruction::Operation::JP ||
instruction.operation == Instruction::Operation::JR ||
instruction.operation == Instruction::Operation::CALL ||
@@ -598,22 +638,37 @@ struct Z80Disassembler {
}
// This is it if: an unconditional RET, RETI, RETN, JP or JR is found.
if(instruction.condition != Instruction::Condition::None) continue;
switch(instruction.operation) {
default: break;
if(instruction.operation == Instruction::Operation::RET) return;
if(instruction.operation == Instruction::Operation::RETI) return;
if(instruction.operation == Instruction::Operation::RETN) return;
if(instruction.operation == Instruction::Operation::JP) return;
if(instruction.operation == Instruction::Operation::JR) return;
case Instruction::Operation::RET:
case Instruction::Operation::RETI:
case Instruction::Operation::RETN:
case Instruction::Operation::JP:
case Instruction::Operation::JR:
if(instruction.condition == Instruction::Condition::None) {
disassembly.implicit_entry_points.push_back(accessor.address());
return;
}
}
}
}
};
} // end of anonymous namespace
Disassembly Analyser::Static::Z80::Disassemble(
const std::vector<uint8_t> &memory,
const std::function<std::size_t(uint16_t)> &address_mapper,
std::vector<uint16_t> entry_points) {
return Analyser::Static::Disassembly::Disassemble<Disassembly, uint16_t, Z80Disassembler>(memory, address_mapper, entry_points);
std::vector<uint16_t> entry_points,
Approach approach)
{
return Analyser::Static::Disassembly::Disassemble<Disassembly, uint16_t, Z80Disassembler>(
memory,
address_mapper,
entry_points,
approach == Approach::Exhaustive
);
}

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>
@@ -76,11 +75,18 @@ struct Disassembly {
std::set<uint16_t> internal_stores, internal_loads, internal_modifies;
};
enum class Approach {
/// Disassemble from the supplied entry points until an indeterminate branch or return only, adding other fully-static
/// entry points as they are observed.
Recursive,
/// Disassemble all supplied bytes, regardless of what nonsense may be encountered by accidental parsing of data areas.
Exhaustive,
};
Disassembly Disassemble(
const std::vector<uint8_t> &memory,
const std::function<std::size_t(uint16_t)> &address_mapper,
std::vector<uint16_t> entry_points);
std::vector<uint16_t> entry_points,
Approach approach);
}
#endif /* StaticAnalyser_Disassembler_Z80_hpp */

View File

@@ -8,14 +8,14 @@
#include "StaticAnalyser.hpp"
#include "../AppleII/Target.hpp"
#include "../AppleIIgs/Target.hpp"
#include "../Oric/Target.hpp"
#include "../Disassembler/6502.hpp"
#include "../Disassembler/AddressMapper.hpp"
#include "Analyser/Static/AppleII/Target.hpp"
#include "Analyser/Static//AppleIIgs/Target.hpp"
#include "Analyser/Static//Oric/Target.hpp"
#include "Analyser/Static//Disassembler/6502.hpp"
#include "Analyser/Static//Disassembler/AddressMapper.hpp"
#include "../../../Storage/Disk/Track/TrackSerialiser.hpp"
#include "../../../Storage/Disk/Encodings/AppleGCR/SegmentParser.hpp"
#include "Storage/Disk/Track/TrackSerialiser.hpp"
#include "Storage/Disk/Encodings/AppleGCR/SegmentParser.hpp"
namespace {
@@ -47,7 +47,12 @@ Analyser::Static::Target *OricTarget(const Storage::Encodings::AppleGCR::Sector
}
Analyser::Static::TargetList Analyser::Static::DiskII::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::DiskII::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
bool
) {
// This analyser can comprehend disks only.
if(media.disks.empty()) return {};
@@ -55,14 +60,15 @@ Analyser::Static::TargetList Analyser::Static::DiskII::GetTargets(const Media &m
TargetList targets;
// If the disk image is too large for a 5.25" disk, map this to the IIgs.
if(disk->get_maximum_head_position() > Storage::Disk::HeadPosition(40)) {
if(disk->maximum_head_position() > Storage::Disk::HeadPosition(40)) {
targets.push_back(std::unique_ptr<Analyser::Static::Target>(AppleIIgsTarget()));
targets.back()->media = media;
return targets;
}
// Grab track 0, sector 0: the boot sector.
const auto track_zero = disk->get_track_at_position(Storage::Disk::Track::Address(0, Storage::Disk::HeadPosition(0)));
const auto track_zero =
disk->track_at_position(Storage::Disk::Track::Address(0, Storage::Disk::HeadPosition(0)));
const auto sector_map = Storage::Encodings::AppleGCR::sectors_from_segment(
Storage::Disk::track_serialisation(*track_zero, Storage::Time(1, 50000)));
@@ -89,7 +95,8 @@ Analyser::Static::TargetList Analyser::Static::DiskII::GetTargets(const Media &m
// If the boot sector looks like it's intended for the Oric, create an Oric.
// Otherwise go with the Apple II.
const auto disassembly = Analyser::Static::MOS6502::Disassemble(sector_zero->data, Analyser::Static::Disassembler::OffsetMapper(0xb800), {0xb800});
const auto disassembly = Analyser::Static::MOS6502::Disassemble(
sector_zero->data, Analyser::Static::Disassembler::OffsetMapper(0xb800), {0xb800});
bool did_read_shift_register = false;
bool is_oric = false;

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::DiskII {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* Analyser_Static_DiskII_StaticAnalyser_hpp */

View File

@@ -9,7 +9,7 @@
#include "StaticAnalyser.hpp"
#include "Target.hpp"
#include "../../../Storage/Disk/Parsers/FAT.hpp"
#include "Storage/Disk/Parsers/FAT.hpp"
#include <algorithm>
@@ -26,7 +26,12 @@ bool insensitive_equal(const std::string &lhs, const std::string &rhs) {
}
Analyser::Static::TargetList Analyser::Static::Enterprise::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::Enterprise::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
bool
) {
// This analyser can comprehend disks only.
if(media.disks.empty()) return {};
@@ -40,6 +45,8 @@ Analyser::Static::TargetList Analyser::Static::Enterprise::GetTargets(const Medi
target->basic_version = Target::BASICVersion::Any;
// Inspect any supplied disks.
//
// TODO: how best can these be discerned from MS-DOS and MSX disks?
if(!media.disks.empty()) {
// DOS will be needed.
target->dos = Target::DOS::EXDOS;
@@ -70,7 +77,8 @@ Analyser::Static::TargetList Analyser::Static::Enterprise::GetTargets(const Medi
if(!has_exdos_ini) {
if(did_pick_file) {
target->loading_command = std::string("run \"") + selected_file->name + "." + selected_file->extension + "\"\n";
target->loading_command =
std::string("run \"") + selected_file->name + "." + selected_file->extension + "\"\n";
} else {
target->loading_command = ":dir\n";
}

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::Enterprise {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* Analyser_Static_Enterprise_StaticAnalyser_hpp */

View File

@@ -6,12 +6,11 @@
// 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"
#include "../StaticAnalyser.hpp"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Reflection/Enum.hpp"
#include "Reflection/Struct.hpp"
#include <string>
@@ -31,23 +30,23 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
Speed speed = Speed::FourMHz;
std::string loading_command;
Target() : Analyser::Static::Target(Machine::Enterprise) {
if(needs_declare()) {
AnnounceEnum(Model);
AnnounceEnum(EXOSVersion);
AnnounceEnum(BASICVersion);
AnnounceEnum(DOS);
AnnounceEnum(Speed);
Target() : Analyser::Static::Target(Machine::Enterprise) {}
DeclareField(model);
DeclareField(exos_version);
DeclareField(basic_version);
DeclareField(dos);
DeclareField(speed);
}
private:
friend Reflection::StructImpl<Target>;
void declare_fields() {
AnnounceEnum(Model);
AnnounceEnum(EXOSVersion);
AnnounceEnum(BASICVersion);
AnnounceEnum(DOS);
AnnounceEnum(Speed);
DeclareField(model);
DeclareField(exos_version);
DeclareField(basic_version);
DeclareField(dos);
DeclareField(speed);
}
};
}
#endif /* Analyser_Static_Enterprise_Target_h */

View File

@@ -0,0 +1,106 @@
//
// StaticAnalyser.cpp
// Clock Signal
//
// Created by Thomas Harte on 05/12/2023.
// Copyright 2023 Thomas Harte. All rights reserved.
//
#include "StaticAnalyser.hpp"
#include "Analyser/Static/Enterprise/StaticAnalyser.hpp"
#include "Analyser/Static/PCCompatible/StaticAnalyser.hpp"
#include "Storage/Disk/Track/TrackSerialiser.hpp"
#include "Storage/Disk/Encodings/MFM/Constants.hpp"
#include "Storage/Disk/Encodings/MFM/SegmentParser.hpp"
Analyser::Static::TargetList Analyser::Static::FAT12::GetTargets(
const Media &media,
const std::string &file_name,
TargetPlatform::IntType platforms,
bool
) {
// This analyser can comprehend disks only.
if(media.disks.empty()) return {};
auto &disk = media.disks.front();
TargetList targets;
// Total list of potential platforms is:
//
// * the Enterprise (and, by extension, CP/M-targetted software);
// * the Atari ST;
// * the MSX (ditto on CP/M); and
// * the PC.
//
// (though the MSX and Atari ST don't currently call in here for now)
// If the disk image is very small or large, map it to the PC. That's the only option old enough
// to have used 5.25" media.
if(disk->maximum_head_position() <= Storage::Disk::HeadPosition(40)) {
return Analyser::Static::PCCompatible::GetTargets(media, file_name, platforms, true);
}
// Attempt to grab MFM track 0, sector 1: the boot sector.
const auto track_zero =
disk->track_at_position(Storage::Disk::Track::Address(0, Storage::Disk::HeadPosition(0)));
const auto sector_map = Storage::Encodings::MFM::sectors_from_segment(
Storage::Disk::track_serialisation(
*track_zero,
Storage::Encodings::MFM::MFMBitLength
), Storage::Encodings::MFM::Density::Double);
// If no sectors were found, assume this disk was either single density or high density, which both imply the PC.
if(sector_map.empty() || sector_map.size() > 10) {
return Analyser::Static::PCCompatible::GetTargets(media, file_name, platforms, true);
}
const Storage::Encodings::MFM::Sector *boot_sector = nullptr;
for(const auto &pair: sector_map) {
if(pair.second.address.sector == 1) {
boot_sector = &pair.second;
break;
}
}
// This shouldn't technically be possible since the disk has been identified as FAT12, but be safe.
if(!boot_sector) {
return {};
}
// Check for key phrases that imply a PC disk.
const auto &sample = boot_sector->samples[0];
const std::vector<std::string> pc_strings = {
// MS-DOS strings.
"MSDOS",
"Non-System disk or disk error",
// DOS Plus strings.
"Insert a SYSTEM disk",
};
for(const auto &string: pc_strings) {
if(
std::search(sample.begin(), sample.end(), string.begin(), string.end()) != sample.end()
) {
return Analyser::Static::PCCompatible::GetTargets(media, file_name, platforms, true);
}
}
// TODO: look for a COM, EXE or BAT, inspect. AUTOEXEC.BAT and/or CONFIG.SYS could be either PC or MSX.
// Disassembling the boot sector doesn't necessarily work, as several Enterprise titles out there in the wild seem
// to have been created by WINIMAGE which adds an x86 PC-style boot sector.
// Enterprise notes: EXOS files all start with a 16-byte header which should begin with a 0 and then have a type
// byte that will be 0xa or lower; cf http://epbas.lgb.hu/readme.html
//
// Some disks commonly passed around as Enterprise software are actually CP/M software, expecting IS-DOS (the CP/M
// clone) to be present. It's certainly possible the same could be true of MSX disks and MSX-DOS. So analysing COM
// files probably means searching for CALL 5s and/or INT 21hs, if not a more rigorous disassembly.
//
// I have not been able to locate a copy of IS-DOS so there's probably not much that can be done here; perhaps I
// could redirect to an MSX2 with MSX-DOS2? Though it'd be nicer if I had a machine that was pure CP/M.
// Being unable to prove that this is a PC disk, throw it to the Enterprise.
return Analyser::Static::Enterprise::GetTargets(media, file_name, platforms, false);
}

View File

@@ -0,0 +1,19 @@
//
// StaticAnalyser.hpp
// Clock Signal
//
// Created by Thomas Harte on 05/12/2023.
// Copyright 2023 Thomas Harte. All rights reserved.
//
#pragma once
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::FAT12 {
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}

View File

@@ -6,10 +6,9 @@
// Copyright 2018 Thomas Harte. All rights reserved.
//
#ifndef Cartridge_hpp
#define Cartridge_hpp
#pragma once
#include "../../../Storage/Cartridge/Cartridge.hpp"
#include "Storage/Cartridge/Cartridge.hpp"
namespace Analyser::Static::MSX {
@@ -27,10 +26,8 @@ struct Cartridge: public ::Storage::Cartridge::Cartridge {
};
const Type type;
Cartridge(const std::vector<Segment> &segments, Type type) :
Cartridge(const std::vector<Segment> &segments, const Type type) :
Storage::Cartridge::Cartridge(segments), type(type) {}
};
}
#endif /* Cartridge_hpp */

View File

@@ -12,8 +12,8 @@
#include "Tape.hpp"
#include "Target.hpp"
#include "../Disassembler/Z80.hpp"
#include "../Disassembler/AddressMapper.hpp"
#include "Analyser/Static/Disassembler/Z80.hpp"
#include "Analyser/Static//Disassembler/AddressMapper.hpp"
#include <algorithm>
@@ -27,7 +27,8 @@ static std::unique_ptr<Analyser::Static::Target> CartridgeTarget(
std::vector<Storage::Cartridge::Cartridge::Segment> output_segments;
if(segment.data.size() & 0x1fff) {
std::vector<uint8_t> truncated_data;
std::vector<uint8_t>::difference_type truncated_size = std::vector<uint8_t>::difference_type(segment.data.size()) & ~0x1fff;
const auto truncated_size =
std::vector<uint8_t>::difference_type(segment.data.size()) & ~0x1fff;
truncated_data.insert(truncated_data.begin(), segment.data.begin(), segment.data.begin() + truncated_size);
output_segments.emplace_back(start_address, truncated_data);
} else {
@@ -82,7 +83,7 @@ static Analyser::Static::TargetList CartridgeTargetsFrom(
if(segments.size() != 1) continue;
// Which must be no more than 63 bytes larger than a multiple of 8 kb in size.
Storage::Cartridge::Cartridge::Segment segment = segments.front();
const Storage::Cartridge::Cartridge::Segment &segment = segments.front();
const size_t data_size = segment.data.size();
if(data_size < 0x2000 || (data_size & 0x1fff) > 64) continue;
@@ -101,7 +102,7 @@ static Analyser::Static::TargetList CartridgeTargetsFrom(
// Reject cartridge if the ROM header wasn't found.
if(!found_start) continue;
uint16_t init_address = uint16_t(segment.data[2] | (segment.data[3] << 8));
const uint16_t init_address = uint16_t(segment.data[2] | (segment.data[3] << 8));
// TODO: check for a rational init address?
// If this ROM is less than 48kb in size then it's an ordinary ROM. Just emplace it and move on.
@@ -115,97 +116,16 @@ static Analyser::Static::TargetList CartridgeTargetsFrom(
// be at play; disassemble to try to figure it out.
std::vector<uint8_t> first_8k;
first_8k.insert(first_8k.begin(), segment.data.begin(), segment.data.begin() + 8192);
Analyser::Static::Z80::Disassembly disassembly =
const Analyser::Static::Z80::Disassembly disassembly =
Analyser::Static::Z80::Disassemble(
first_8k,
Analyser::Static::Disassembler::OffsetMapper(start_address),
{ init_address }
{ init_address },
Analyser::Static::Z80::Approach::Exhaustive
);
// // Look for a indirect store followed by an unconditional JP or CALL into another
// // segment, that's a fairly explicit sign where found.
using Instruction = Analyser::Static::Z80::Instruction;
std::map<uint16_t, Instruction> &instructions = disassembly.instructions_by_address;
bool is_ascii = false;
// auto iterator = instructions.begin();
// while(iterator != instructions.end()) {
// auto next_iterator = iterator;
// next_iterator++;
// if(next_iterator == instructions.end()) break;
//
// if( iterator->second.operation == Instruction::Operation::LD &&
// iterator->second.destination == Instruction::Location::Operand_Indirect &&
// (
// iterator->second.operand == 0x5000 ||
// iterator->second.operand == 0x6000 ||
// iterator->second.operand == 0x6800 ||
// iterator->second.operand == 0x7000 ||
// iterator->second.operand == 0x77ff ||
// iterator->second.operand == 0x7800 ||
// iterator->second.operand == 0x8000 ||
// iterator->second.operand == 0x9000 ||
// iterator->second.operand == 0xa000
// ) &&
// (
// next_iterator->second.operation == Instruction::Operation::CALL ||
// next_iterator->second.operation == Instruction::Operation::JP
// ) &&
// ((next_iterator->second.operand >> 13) != (0x4000 >> 13))
// ) {
// const uint16_t address = uint16_t(next_iterator->second.operand);
// switch(iterator->second.operand) {
// case 0x6000:
// if(address >= 0x6000 && address < 0x8000) {
// target.msx.cartridge_type = Analyser::Static::MSXCartridgeType::KonamiWithSCC;
// }
// break;
// case 0x6800:
// if(address >= 0x6000 && address < 0x6800) {
// target.msx.cartridge_type = Analyser::Static::MSXCartridgeType::ASCII8kb;
// }
// break;
// case 0x7000:
// if(address >= 0x6000 && address < 0x8000) {
// target.msx.cartridge_type = Analyser::Static::MSXCartridgeType::KonamiWithSCC;
// }
// if(address >= 0x7000 && address < 0x7800) {
// is_ascii = true;
// }
// break;
// case 0x77ff:
// if(address >= 0x7000 && address < 0x7800) {
// target.msx.cartridge_type = Analyser::Static::MSXCartridgeType::ASCII16kb;
// }
// break;
// case 0x7800:
// if(address >= 0xa000 && address < 0xc000) {
// target.msx.cartridge_type = Analyser::Static::MSXCartridgeType::ASCII8kb;
// }
// break;
// case 0x8000:
// if(address >= 0x8000 && address < 0xa000) {
// target.msx.cartridge_type = Analyser::Static::MSXCartridgeType::KonamiWithSCC;
// }
// break;
// case 0x9000:
// if(address >= 0x8000 && address < 0xa000) {
// target.msx.cartridge_type = Analyser::Static::MSXCartridgeType::KonamiWithSCC;
// }
// break;
// case 0xa000:
// if(address >= 0xa000 && address < 0xc000) {
// target.msx.cartridge_type = Analyser::Static::MSXCartridgeType::Konami;
// }
// break;
// case 0xb000:
// if(address >= 0xa000 && address < 0xc000) {
// target.msx.cartridge_type = Analyser::Static::MSXCartridgeType::KonamiWithSCC;
// }
// break;
// }
// }
//
// iterator = next_iterator;
const std::map<uint16_t, Instruction> &instructions = disassembly.instructions_by_address;
// Look for LD (nnnn), A instructions, and collate those addresses.
std::map<uint16_t, int> address_counts;
@@ -217,56 +137,60 @@ static Analyser::Static::TargetList CartridgeTargetsFrom(
}
}
// Weight confidences by number of observed hits.
float total_hits =
float(
address_counts[0x6000] + address_counts[0x6800] +
address_counts[0x7000] + address_counts[0x7800] +
address_counts[0x77ff] + address_counts[0x8000] +
address_counts[0xa000] + address_counts[0x5000] +
address_counts[0x9000] + address_counts[0xb000]
);
// Weight confidences by number of observed hits; if any is above 60% confidence, just use it.
const auto ascii_8kb_total =
address_counts[0x6000] + address_counts[0x6800] + address_counts[0x7000] + address_counts[0x7800];
const auto ascii_16kb_total = address_counts[0x6000] + address_counts[0x7000] + address_counts[0x77ff];
const auto konami_total = address_counts[0x6000] + address_counts[0x8000] + address_counts[0xa000];
const auto konami_with_scc_total =
address_counts[0x5000] + address_counts[0x7000] + address_counts[0x9000] + address_counts[0xb000];
targets.push_back(CartridgeTarget(
segment,
start_address,
Analyser::Static::MSX::Cartridge::ASCII8kb,
float( address_counts[0x6000] +
address_counts[0x6800] +
address_counts[0x7000] +
address_counts[0x7800]) / total_hits));
targets.push_back(CartridgeTarget(
segment,
start_address,
Analyser::Static::MSX::Cartridge::ASCII16kb,
float( address_counts[0x6000] +
address_counts[0x7000] +
address_counts[0x77ff]) / total_hits));
if(!is_ascii) {
const auto total_hits = ascii_8kb_total + ascii_16kb_total + konami_total + konami_with_scc_total;
const bool is_ascii_8kb = (ascii_8kb_total * 5) / (total_hits * 3);
const bool is_ascii_16kb = (ascii_16kb_total * 5) / (total_hits * 3);
const bool is_konami = (konami_total * 5) / (total_hits * 3);
const bool is_konami_with_scc = (konami_with_scc_total * 5) / (total_hits * 3);
if(!is_ascii_16kb && !is_konami && !is_konami_with_scc) {
targets.push_back(CartridgeTarget(
segment,
start_address,
Analyser::Static::MSX::Cartridge::ASCII8kb,
float(ascii_8kb_total) / float(total_hits)));
}
if(!is_ascii_8kb && !is_konami && !is_konami_with_scc) {
targets.push_back(CartridgeTarget(
segment,
start_address,
Analyser::Static::MSX::Cartridge::ASCII16kb,
float(ascii_16kb_total) / float(total_hits)));
}
if(!is_ascii_8kb && !is_ascii_16kb && !is_konami_with_scc) {
targets.push_back(CartridgeTarget(
segment,
start_address,
Analyser::Static::MSX::Cartridge::Konami,
float( address_counts[0x6000] +
address_counts[0x8000] +
address_counts[0xa000]) / total_hits));
float(konami_total) / float(total_hits)));
}
if(!is_ascii) {
if(!is_ascii_8kb && !is_ascii_16kb && !is_konami) {
targets.push_back(CartridgeTarget(
segment,
start_address,
Analyser::Static::MSX::Cartridge::KonamiWithSCC,
float( address_counts[0x5000] +
address_counts[0x7000] +
address_counts[0x9000] +
address_counts[0xb000]) / total_hits));
float(konami_with_scc_total) / float(total_hits)));
}
}
return targets;
}
Analyser::Static::TargetList Analyser::Static::MSX::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::MSX::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
bool
) {
TargetList destination;
// Append targets for any cartridges that look correct.
@@ -278,7 +202,7 @@ Analyser::Static::TargetList Analyser::Static::MSX::GetTargets(const Media &medi
// Check tapes for loadable files.
for(auto &tape : media.tapes) {
std::vector<File> files_on_tape = GetFiles(tape);
const std::vector<File> files_on_tape = GetFiles(tape);
if(!files_on_tape.empty()) {
switch(files_on_tape.front().type) {
case File::Type::ASCII: target->loading_command = "RUN\"CAS:\r"; break;

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::MSX {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* StaticAnalyser_MSX_StaticAnalyser_hpp */

View File

@@ -8,7 +8,7 @@
#include "Tape.hpp"
#include "../../../Storage/Tape/Parsers/MSX.hpp"
#include "Storage/Tape/Parsers/MSX.hpp"
using namespace Analyser::Static::MSX;
@@ -29,12 +29,12 @@ std::vector<File> Analyser::Static::MSX::GetFiles(const std::shared_ptr<Storage:
Storage::Tape::BinaryTapePlayer tape_player(1000000);
tape_player.set_motor_control(true);
tape_player.set_tape(tape);
tape_player.set_tape(tape, TargetPlatform::MSX);
using Parser = Storage::Tape::MSX::Parser;
// Get all recognisable files from the tape.
while(!tape->is_at_end()) {
while(!tape_player.is_at_end()) {
// Try to locate and measure a header.
std::unique_ptr<Parser::FileSpeed> file_speed = Parser::find_header(tape_player);
if(!file_speed) continue;

View File

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

View File

@@ -6,12 +6,11 @@
// 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"
#include "../StaticAnalyser.hpp"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Reflection/Enum.hpp"
#include "Reflection/Struct.hpp"
#include <string>
namespace Analyser::Static::MSX {
@@ -34,18 +33,18 @@ struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<
);
Region region = Region::USA;
Target(): Analyser::Static::Target(Machine::MSX) {
if(needs_declare()) {
DeclareField(has_disk_drive);
DeclareField(has_msx_music);
DeclareField(region);
AnnounceEnum(Region);
DeclareField(model);
AnnounceEnum(Model);
}
Target(): Analyser::Static::Target(Machine::MSX) {}
private:
friend Reflection::StructImpl<Target>;
void declare_fields() {
DeclareField(has_disk_drive);
DeclareField(has_msx_music);
DeclareField(region);
AnnounceEnum(Region);
DeclareField(model);
AnnounceEnum(Model);
}
};
}
#endif /* Analyser_Static_MSX_Target_h */

View File

@@ -9,9 +9,14 @@
#include "StaticAnalyser.hpp"
#include "Target.hpp"
Analyser::Static::TargetList Analyser::Static::Macintosh::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::Macintosh::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
bool is_confident
) {
// This analyser can comprehend disks and mass-storage devices only.
if(media.disks.empty() && media.mass_storage_devices.empty()) return {};
if(media.disks.empty() && media.mass_storage_devices.empty() && !is_confident) return {};
// As there is at least one usable media image, wave it through.
Analyser::Static::TargetList targets;
@@ -24,7 +29,7 @@ Analyser::Static::TargetList Analyser::Static::Macintosh::GetTargets(const Media
if(media.mass_storage_devices.empty()) {
bool has_800kb_disks = false;
for(const auto &disk: media.disks) {
has_800kb_disks |= disk->get_head_count() > 1;
has_800kb_disks |= disk->head_count() > 1;
}
if(!has_800kb_disks) {

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::Macintosh {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* Analyser_Static_Macintosh_StaticAnalyser_hpp */

View File

@@ -6,12 +6,11 @@
// 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"
#include "../StaticAnalyser.hpp"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Reflection/Enum.hpp"
#include "Reflection/Struct.hpp"
namespace Analyser::Static::Macintosh {
@@ -19,15 +18,14 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
ReflectableEnum(Model, Mac128k, Mac512k, Mac512ke, MacPlus);
Model model = Model::MacPlus;
Target() : Analyser::Static::Target(Machine::Macintosh) {
// Boilerplate for declaring fields and potential values.
if(needs_declare()) {
DeclareField(model);
AnnounceEnum(Model);
}
Target() : Analyser::Static::Target(Machine::Macintosh) {}
private:
friend Reflection::StructImpl<Target>;
void declare_fields() {
DeclareField(model);
AnnounceEnum(Model);
}
};
}
#endif /* Analyser_Static_Macintosh_Target_h */

View File

@@ -11,10 +11,10 @@
#include "Tape.hpp"
#include "Target.hpp"
#include "../Disassembler/6502.hpp"
#include "../Disassembler/AddressMapper.hpp"
#include "Analyser/Static/Disassembler/6502.hpp"
#include "Analyser/Static/Disassembler/AddressMapper.hpp"
#include "../../../Storage/Disk/Encodings/MFM/Parser.hpp"
#include "Storage/Disk/Encodings/MFM/Parser.hpp"
#include <cstring>
@@ -22,12 +22,22 @@ using namespace Analyser::Static::Oric;
namespace {
int score(const Analyser::Static::MOS6502::Disassembly &disassembly, const std::set<uint16_t> &rom_functions, const std::set<uint16_t> &variable_locations) {
int score(
const Analyser::Static::MOS6502::Disassembly &disassembly,
const std::set<uint16_t> &rom_functions,
const std::set<uint16_t> &variable_locations
) {
int score = 0;
for(const auto address : disassembly.outward_calls) score += (rom_functions.find(address) != rom_functions.end()) ? 1 : -1;
for(const auto address : disassembly.external_stores) score += (variable_locations.find(address) != variable_locations.end()) ? 1 : -1;
for(const auto address : disassembly.external_loads) score += (variable_locations.find(address) != variable_locations.end()) ? 1 : -1;
for(const auto address : disassembly.outward_calls) {
score += (rom_functions.find(address) != rom_functions.end()) ? 1 : -1;
}
for(const auto address : disassembly.external_stores) {
score += (variable_locations.find(address) != variable_locations.end()) ? 1 : -1;
}
for(const auto address : disassembly.external_loads) {
score += (variable_locations.find(address) != variable_locations.end()) ? 1 : -1;
}
return score;
}
@@ -35,19 +45,32 @@ int score(const Analyser::Static::MOS6502::Disassembly &disassembly, const std::
int basic10_score(const Analyser::Static::MOS6502::Disassembly &disassembly) {
const std::set<uint16_t> rom_functions = {
0x0228, 0x022b,
0xc3ca, 0xc3f8, 0xc448, 0xc47c, 0xc4b5, 0xc4e3, 0xc4e0, 0xc524, 0xc56f, 0xc5a2, 0xc5f8, 0xc60a, 0xc6a5, 0xc6de, 0xc719, 0xc738,
0xc773, 0xc824, 0xc832, 0xc841, 0xc8c1, 0xc8fe, 0xc91f, 0xc93f, 0xc941, 0xc91e, 0xc98b, 0xc996, 0xc9b3, 0xc9e0, 0xca0a, 0xca1c,
0xca1f, 0xca3e, 0xca61, 0xca78, 0xca98, 0xcad2, 0xcb61, 0xcb9f, 0xcc59, 0xcbed, 0xcc0a, 0xcc8c, 0xcc8f, 0xccba, 0xccc9, 0xccfd,
0xce0c, 0xce77, 0xce8b, 0xcfac, 0xcf74, 0xd03c, 0xd059, 0xcff0, 0xd087, 0xd0f2, 0xd0fc, 0xd361, 0xd3eb, 0xd47e, 0xd4a6, 0xd401,
0xd593, 0xd5a3, 0xd4fa, 0xd595, 0xd730, 0xd767, 0xd816, 0xd82a, 0xd856, 0xd861, 0xd8a6, 0xd8b5, 0xd80a, 0xd867, 0xd938, 0xd894,
0xd89d, 0xd8ac, 0xd983, 0xd993, 0xd9b5, 0xd93d, 0xd965, 0xda3f, 0xd9c6, 0xda16, 0xdaab, 0xdada, 0xda6b, 0xdb92, 0xdbb9, 0xdc79,
0xdd4d, 0xdda3, 0xddbf, 0xd0d0, 0xde77, 0xdef4, 0xdf0b, 0xdf0f, 0xdf04, 0xdf12, 0xdf31, 0xdf4c, 0xdf8c, 0xdfa5, 0xdfcf, 0xe076,
0xe0c1, 0xe22a, 0xe27c, 0xe2a6, 0xe313, 0xe34b, 0xe387, 0xe38e, 0xe3d7, 0xe407, 0xe43b, 0xe46f, 0xe4a8, 0xe4f2, 0xe554, 0xe57d,
0xe585, 0xe58c, 0xe594, 0xe5a4, 0xe5ab, 0xe5b6, 0xe5ea, 0xe563, 0xe5c6, 0xe630, 0xe696, 0xe6ba, 0xe6ca, 0xe725, 0xe7aa, 0xe903,
0xe7db, 0xe80d, 0xe987, 0xe9d1, 0xe87d, 0xe905, 0xe965, 0xe974, 0xe994, 0xe9a9, 0xe9bb, 0xec45, 0xeccc, 0xedc4, 0xecc7, 0xed01,
0xed09, 0xed70, 0xed81, 0xed8f, 0xe0ad, 0xeee8, 0xeef8, 0xebdf, 0xebe2, 0xebe5, 0xebeb, 0xebee, 0xebf4, 0xebf7, 0xebfa, 0xebe8,
0xf43c, 0xf4ef, 0xf523, 0xf561, 0xf535, 0xf57b, 0xf5d3, 0xf71a, 0xf73f, 0xf7e4, 0xf7e0, 0xf82f, 0xf88f, 0xf8af, 0xf8b5, 0xf920,
0xf967, 0xf960, 0xf9c9, 0xfa14, 0xfa85, 0xfa9b, 0xfab1, 0xfac7, 0xfafa, 0xfb10, 0xfb26, 0xfbb6, 0xfbfe
0xc3ca, 0xc3f8, 0xc448, 0xc47c, 0xc4b5, 0xc4e3, 0xc4e0, 0xc524,
0xc56f, 0xc5a2, 0xc5f8, 0xc60a, 0xc6a5, 0xc6de, 0xc719, 0xc738,
0xc773, 0xc824, 0xc832, 0xc841, 0xc8c1, 0xc8fe, 0xc91f, 0xc93f,
0xc941, 0xc91e, 0xc98b, 0xc996, 0xc9b3, 0xc9e0, 0xca0a, 0xca1c,
0xca1f, 0xca3e, 0xca61, 0xca78, 0xca98, 0xcad2, 0xcb61, 0xcb9f,
0xcc59, 0xcbed, 0xcc0a, 0xcc8c, 0xcc8f, 0xccba, 0xccc9, 0xccfd,
0xce0c, 0xce77, 0xce8b, 0xcfac, 0xcf74, 0xd03c, 0xd059, 0xcff0,
0xd087, 0xd0f2, 0xd0fc, 0xd361, 0xd3eb, 0xd47e, 0xd4a6, 0xd401,
0xd593, 0xd5a3, 0xd4fa, 0xd595, 0xd730, 0xd767, 0xd816, 0xd82a,
0xd856, 0xd861, 0xd8a6, 0xd8b5, 0xd80a, 0xd867, 0xd938, 0xd894,
0xd89d, 0xd8ac, 0xd983, 0xd993, 0xd9b5, 0xd93d, 0xd965, 0xda3f,
0xd9c6, 0xda16, 0xdaab, 0xdada, 0xda6b, 0xdb92, 0xdbb9, 0xdc79,
0xdd4d, 0xdda3, 0xddbf, 0xd0d0, 0xde77, 0xdef4, 0xdf0b, 0xdf0f,
0xdf04, 0xdf12, 0xdf31, 0xdf4c, 0xdf8c, 0xdfa5, 0xdfcf, 0xe076,
0xe0c1, 0xe22a, 0xe27c, 0xe2a6, 0xe313, 0xe34b, 0xe387, 0xe38e,
0xe3d7, 0xe407, 0xe43b, 0xe46f, 0xe4a8, 0xe4f2, 0xe554, 0xe57d,
0xe585, 0xe58c, 0xe594, 0xe5a4, 0xe5ab, 0xe5b6, 0xe5ea, 0xe563,
0xe5c6, 0xe630, 0xe696, 0xe6ba, 0xe6ca, 0xe725, 0xe7aa, 0xe903,
0xe7db, 0xe80d, 0xe987, 0xe9d1, 0xe87d, 0xe905, 0xe965, 0xe974,
0xe994, 0xe9a9, 0xe9bb, 0xec45, 0xeccc, 0xedc4, 0xecc7, 0xed01,
0xed09, 0xed70, 0xed81, 0xed8f, 0xe0ad, 0xeee8, 0xeef8, 0xebdf,
0xebe2, 0xebe5, 0xebeb, 0xebee, 0xebf4, 0xebf7, 0xebfa, 0xebe8,
0xf43c, 0xf4ef, 0xf523, 0xf561, 0xf535, 0xf57b, 0xf5d3, 0xf71a,
0xf73f, 0xf7e4, 0xf7e0, 0xf82f, 0xf88f, 0xf8af, 0xf8b5, 0xf920,
0xf967, 0xf960, 0xf9c9, 0xfa14, 0xfa85, 0xfa9b, 0xfab1, 0xfac7,
0xfafa, 0xfb10, 0xfb26, 0xfbb6, 0xfbfe
};
const std::set<uint16_t> variable_locations = {
0x0228, 0x0229, 0x022a, 0x022b, 0x022c, 0x022d, 0x0230
@@ -59,19 +82,32 @@ int basic10_score(const Analyser::Static::MOS6502::Disassembly &disassembly) {
int basic11_score(const Analyser::Static::MOS6502::Disassembly &disassembly) {
const std::set<uint16_t> rom_functions = {
0x0238, 0x023b, 0x023e, 0x0241, 0x0244, 0x0247,
0xc3c6, 0xc3f4, 0xc444, 0xc47c, 0xc4a8, 0xc4d3, 0xc4e0, 0xc524, 0xc55f, 0xc592, 0xc5e8, 0xc5fa, 0xc692, 0xc6b3, 0xc6ee, 0xc70d,
0xc748, 0xc7fd, 0xc809, 0xc816, 0xc82f, 0xc855, 0xc8c1, 0xc915, 0xc952, 0xc971, 0xc973, 0xc9a0, 0xc9bd, 0xc9c8, 0xc9e5, 0xca12,
0xca3c, 0xca4e, 0xca51, 0xca70, 0xca99, 0xcac2, 0xcae2, 0xcb1c, 0xcbab, 0xcbf0, 0xcc59, 0xccb0, 0xccce, 0xcd16, 0xcd19, 0xcd46,
0xcd55, 0xcd89, 0xce98, 0xcf03, 0xcf17, 0xcfac, 0xd000, 0xd03c, 0xd059, 0xd07c, 0xd113, 0xd17e, 0xd188, 0xd361, 0xd3eb, 0xd47e,
0xd4a6, 0xd4ba, 0xd593, 0xd5a3, 0xd5b5, 0xd650, 0xd730, 0xd767, 0xd816, 0xd82a, 0xd856, 0xd861, 0xd8a6, 0xd8b5, 0xd8c5, 0xd922,
0xd938, 0xd94f, 0xd958, 0xd967, 0xd983, 0xd993, 0xd9b5, 0xd9de, 0xda0c, 0xda3f, 0xda51, 0xdaa1, 0xdaab, 0xdada, 0xdaf6, 0xdb92,
0xdbb9, 0xdcaf, 0xdd51, 0xdda7, 0xddc3, 0xddd4, 0xde77, 0xdef4, 0xdf0b, 0xdf0f, 0xdf13, 0xdf21, 0xdf49, 0xdf4c, 0xdf8c, 0xdfbd,
0xdfe7, 0xe076, 0xe0c5, 0xe22e, 0xe27c, 0xe2aa, 0xe313, 0xe34f, 0xe38b, 0xe392, 0xe3db, 0xe407, 0xe43f, 0xe46f, 0xe4ac, 0xe4e0,
0xe4f2, 0xe56c, 0xe57d, 0xe585, 0xe58c, 0xe594, 0xe5a4, 0xe5ab, 0xe5b6, 0xe5ea, 0xe5f5, 0xe607, 0xe65e, 0xe6c9, 0xe735, 0xe75a,
0xe76a, 0xe7b2, 0xe85b, 0xe903, 0xe909, 0xe946, 0xe987, 0xe9d1, 0xeaf0, 0xeb78, 0xebce, 0xebe7, 0xec0c, 0xec21, 0xec33, 0xec45,
0xeccc, 0xedc4, 0xede0, 0xee1a, 0xee22, 0xee8c, 0xee9d, 0xeeab, 0xeec9, 0xeee8, 0xeef8, 0xf0c8, 0xf0fd, 0xf110, 0xf11d, 0xf12d,
0xf204, 0xf210, 0xf268, 0xf37f, 0xf495, 0xf4ef, 0xf523, 0xf561, 0xf590, 0xf5c1, 0xf602, 0xf71a, 0xf77c, 0xf7e4, 0xf816, 0xf865,
0xf88f, 0xf8af, 0xf8b5, 0xf920, 0xf967, 0xf9aa, 0xf9c9, 0xfa14, 0xfa9f, 0xfab5, 0xfacb, 0xfae1, 0xfb14, 0xfb2a, 0xfb40, 0xfbd0,
0xc3c6, 0xc3f4, 0xc444, 0xc47c, 0xc4a8, 0xc4d3, 0xc4e0, 0xc524,
0xc55f, 0xc592, 0xc5e8, 0xc5fa, 0xc692, 0xc6b3, 0xc6ee, 0xc70d,
0xc748, 0xc7fd, 0xc809, 0xc816, 0xc82f, 0xc855, 0xc8c1, 0xc915,
0xc952, 0xc971, 0xc973, 0xc9a0, 0xc9bd, 0xc9c8, 0xc9e5, 0xca12,
0xca3c, 0xca4e, 0xca51, 0xca70, 0xca99, 0xcac2, 0xcae2, 0xcb1c,
0xcbab, 0xcbf0, 0xcc59, 0xccb0, 0xccce, 0xcd16, 0xcd19, 0xcd46,
0xcd55, 0xcd89, 0xce98, 0xcf03, 0xcf17, 0xcfac, 0xd000, 0xd03c,
0xd059, 0xd07c, 0xd113, 0xd17e, 0xd188, 0xd361, 0xd3eb, 0xd47e,
0xd4a6, 0xd4ba, 0xd593, 0xd5a3, 0xd5b5, 0xd650, 0xd730, 0xd767,
0xd816, 0xd82a, 0xd856, 0xd861, 0xd8a6, 0xd8b5, 0xd8c5, 0xd922,
0xd938, 0xd94f, 0xd958, 0xd967, 0xd983, 0xd993, 0xd9b5, 0xd9de,
0xda0c, 0xda3f, 0xda51, 0xdaa1, 0xdaab, 0xdada, 0xdaf6, 0xdb92,
0xdbb9, 0xdcaf, 0xdd51, 0xdda7, 0xddc3, 0xddd4, 0xde77, 0xdef4,
0xdf0b, 0xdf0f, 0xdf13, 0xdf21, 0xdf49, 0xdf4c, 0xdf8c, 0xdfbd,
0xdfe7, 0xe076, 0xe0c5, 0xe22e, 0xe27c, 0xe2aa, 0xe313, 0xe34f,
0xe38b, 0xe392, 0xe3db, 0xe407, 0xe43f, 0xe46f, 0xe4ac, 0xe4e0,
0xe4f2, 0xe56c, 0xe57d, 0xe585, 0xe58c, 0xe594, 0xe5a4, 0xe5ab,
0xe5b6, 0xe5ea, 0xe5f5, 0xe607, 0xe65e, 0xe6c9, 0xe735, 0xe75a,
0xe76a, 0xe7b2, 0xe85b, 0xe903, 0xe909, 0xe946, 0xe987, 0xe9d1,
0xeaf0, 0xeb78, 0xebce, 0xebe7, 0xec0c, 0xec21, 0xec33, 0xec45,
0xeccc, 0xedc4, 0xede0, 0xee1a, 0xee22, 0xee8c, 0xee9d, 0xeeab,
0xeec9, 0xeee8, 0xeef8, 0xf0c8, 0xf0fd, 0xf110, 0xf11d, 0xf12d,
0xf204, 0xf210, 0xf268, 0xf37f, 0xf495, 0xf4ef, 0xf523, 0xf561,
0xf590, 0xf5c1, 0xf602, 0xf71a, 0xf77c, 0xf7e4, 0xf816, 0xf865,
0xf88f, 0xf8af, 0xf8b5, 0xf920, 0xf967, 0xf9aa, 0xf9c9, 0xfa14,
0xfa9f, 0xfab5, 0xfacb, 0xfae1, 0xfb14, 0xfb2a, 0xfb40, 0xfbd0,
0xfc18
};
const std::set<uint16_t> variable_locations = {
@@ -85,7 +121,7 @@ bool is_microdisc(Storage::Encodings::MFM::Parser &parser) {
/*
The Microdisc boot sector is sector 2 of track 0 and contains a 23-byte signature.
*/
Storage::Encodings::MFM::Sector *sector = parser.get_sector(0, 0, 2);
const Storage::Encodings::MFM::Sector *sector = parser.sector(0, 0, 2);
if(!sector) return false;
if(sector->samples.empty()) return false;
@@ -102,13 +138,13 @@ bool is_microdisc(Storage::Encodings::MFM::Parser &parser) {
return !std::memcmp(signature, first_sample.data(), sizeof(signature));
}
bool is_400_loader(Storage::Encodings::MFM::Parser &parser, uint16_t range_start, uint16_t range_end) {
bool is_400_loader(Storage::Encodings::MFM::Parser &parser, const uint16_t range_start, const uint16_t range_end) {
/*
Both the Jasmin and BD-DOS boot sectors are sector 1 of track 0 and are loaded at $400;
use disassembly to test for likely matches.
*/
Storage::Encodings::MFM::Sector *sector = parser.get_sector(0, 0, 1);
const Storage::Encodings::MFM::Sector *sector = parser.sector(0, 0, 1);
if(!sector) return false;
if(sector->samples.empty()) return false;
@@ -120,8 +156,8 @@ bool is_400_loader(Storage::Encodings::MFM::Parser &parser, uint16_t range_start
}
// Grab a disassembly.
const auto disassembly =
Analyser::Static::MOS6502::Disassemble(first_sample, Analyser::Static::Disassembler::OffsetMapper(0x400), {0x400});
const auto disassembly = Analyser::Static::MOS6502::Disassemble(
first_sample, Analyser::Static::Disassembler::OffsetMapper(0x400), {0x400});
// Check for references to the Jasmin registers.
int register_hits = 0;
@@ -145,7 +181,12 @@ bool is_bd500(Storage::Encodings::MFM::Parser &parser) {
}
Analyser::Static::TargetList Analyser::Static::Oric::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::Oric::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
bool
) {
auto target = std::make_unique<Target>();
target->confidence = 0.5;
@@ -153,14 +194,18 @@ Analyser::Static::TargetList Analyser::Static::Oric::GetTargets(const Media &med
int basic11_votes = 0;
for(auto &tape : media.tapes) {
std::vector<File> tape_files = GetFiles(tape);
tape->reset();
auto serialiser = tape->serialiser();
std::vector<File> tape_files = GetFiles(*serialiser);
if(!tape_files.empty()) {
for(const auto &file : tape_files) {
if(file.data_type == File::MachineCode) {
std::vector<uint16_t> entry_points = {file.starting_address};
const Analyser::Static::MOS6502::Disassembly disassembly =
Analyser::Static::MOS6502::Disassemble(file.data, Analyser::Static::Disassembler::OffsetMapper(file.starting_address), entry_points);
Analyser::Static::MOS6502::Disassemble(
file.data,
Analyser::Static::Disassembler::OffsetMapper(file.starting_address),
entry_points
);
if(basic10_score(disassembly) > basic11_score(disassembly)) ++basic10_votes; else ++basic11_votes;
}
@@ -175,7 +220,7 @@ Analyser::Static::TargetList Analyser::Static::Oric::GetTargets(const Media &med
// 8-DOS is recognised by a dedicated Disk II analyser, so check only for Microdisc,
// Jasmin and BD-DOS formats here.
for(auto &disk: media.disks) {
Storage::Encodings::MFM::Parser parser(true, disk);
Storage::Encodings::MFM::Parser parser(Storage::Encodings::MFM::Density::Double, disk);
if(is_microdisc(parser)) {
target->disk_interface = Target::DiskInterface::Microdisc;

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::Oric {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* StaticAnalyser_hpp */

View File

@@ -7,61 +7,61 @@
//
#include "Tape.hpp"
#include "../../../Storage/Tape/Parsers/Oric.hpp"
#include "Storage/Tape/Parsers/Oric.hpp"
using namespace Analyser::Static::Oric;
std::vector<File> Analyser::Static::Oric::GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape) {
std::vector<File> Analyser::Static::Oric::GetFiles(Storage::Tape::TapeSerialiser &serialiser) {
std::vector<File> files;
Storage::Tape::Oric::Parser parser;
while(!tape->is_at_end()) {
while(!serialiser.is_at_end()) {
// sync to next lead-in, check that it's one of three 0x16s
bool is_fast = parser.sync_and_get_encoding_speed(tape);
bool is_fast = parser.sync_and_get_encoding_speed(serialiser);
int next_bytes[2];
next_bytes[0] = parser.get_next_byte(tape, is_fast);
next_bytes[1] = parser.get_next_byte(tape, is_fast);
next_bytes[0] = parser.get_next_byte(serialiser, is_fast);
next_bytes[1] = parser.get_next_byte(serialiser, is_fast);
if(next_bytes[0] != 0x16 || next_bytes[1] != 0x16) continue;
// get the first byte that isn't a 0x16, check it was a 0x24
int byte = 0x16;
while(!tape->is_at_end() && byte == 0x16) {
byte = parser.get_next_byte(tape, is_fast);
while(!serialiser.is_at_end() && byte == 0x16) {
byte = parser.get_next_byte(serialiser, is_fast);
}
if(byte != 0x24) continue;
// skip two empty bytes
parser.get_next_byte(tape, is_fast);
parser.get_next_byte(tape, is_fast);
parser.get_next_byte(serialiser, is_fast);
parser.get_next_byte(serialiser, is_fast);
// get data and launch types
File new_file;
switch(parser.get_next_byte(tape, is_fast)) {
switch(parser.get_next_byte(serialiser, is_fast)) {
case 0x00: new_file.data_type = File::ProgramType::BASIC; break;
case 0x80: new_file.data_type = File::ProgramType::MachineCode; break;
default: new_file.data_type = File::ProgramType::None; break;
}
switch(parser.get_next_byte(tape, is_fast)) {
switch(parser.get_next_byte(serialiser, is_fast)) {
case 0x80: new_file.launch_type = File::ProgramType::BASIC; break;
case 0xc7: new_file.launch_type = File::ProgramType::MachineCode; break;
default: new_file.launch_type = File::ProgramType::None; break;
}
// read end and start addresses
new_file.ending_address = uint16_t(parser.get_next_byte(tape, is_fast) << 8);
new_file.ending_address |= uint16_t(parser.get_next_byte(tape, is_fast));
new_file.starting_address = uint16_t(parser.get_next_byte(tape, is_fast) << 8);
new_file.starting_address |= uint16_t(parser.get_next_byte(tape, is_fast));
new_file.ending_address = uint16_t(parser.get_next_byte(serialiser, is_fast) << 8);
new_file.ending_address |= uint16_t(parser.get_next_byte(serialiser, is_fast));
new_file.starting_address = uint16_t(parser.get_next_byte(serialiser, is_fast) << 8);
new_file.starting_address |= uint16_t(parser.get_next_byte(serialiser, is_fast));
// skip an empty byte
parser.get_next_byte(tape, is_fast);
parser.get_next_byte(serialiser, is_fast);
// read file name, up to 16 characters and null terminated
char file_name[17];
int name_pos = 0;
while(name_pos < 16) {
file_name[name_pos] = char(parser.get_next_byte(tape, is_fast));
file_name[name_pos] = char(parser.get_next_byte(serialiser, is_fast));
if(!file_name[name_pos]) break;
name_pos++;
}
@@ -72,11 +72,11 @@ std::vector<File> Analyser::Static::Oric::GetFiles(const std::shared_ptr<Storage
std::size_t body_length = new_file.ending_address - new_file.starting_address + 1;
new_file.data.reserve(body_length);
for(std::size_t c = 0; c < body_length; c++) {
new_file.data.push_back(uint8_t(parser.get_next_byte(tape, is_fast)));
new_file.data.push_back(uint8_t(parser.get_next_byte(serialiser, is_fast)));
}
// only one validation check: was there enough tape?
if(!tape->is_at_end()) {
if(!serialiser.is_at_end()) {
files.push_back(new_file);
}
}

View File

@@ -6,10 +6,9 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_Oric_Tape_hpp
#define StaticAnalyser_Oric_Tape_hpp
#pragma once
#include "../../../Storage/Tape/Tape.hpp"
#include "Storage/Tape/Tape.hpp"
#include <string>
#include <vector>
@@ -29,8 +28,6 @@ struct File {
std::vector<uint8_t> data;
};
std::vector<File> GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape);
std::vector<File> GetFiles(Storage::Tape::TapeSerialiser &);
}
#endif /* Tape_hpp */

View File

@@ -6,12 +6,11 @@
// 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"
#include "../StaticAnalyser.hpp"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Reflection/Enum.hpp"
#include "Reflection/Struct.hpp"
#include <string>
namespace Analyser::Static::Oric {
@@ -42,18 +41,18 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
std::string loading_command;
bool should_start_jasmin = false;
Target(): Analyser::Static::Target(Machine::Oric) {
if(needs_declare()) {
DeclareField(rom);
DeclareField(disk_interface);
DeclareField(processor);
AnnounceEnum(ROM);
AnnounceEnum(DiskInterface);
AnnounceEnum(Processor);
}
Target(): Analyser::Static::Target(Machine::Oric) {}
private:
friend Reflection::StructImpl<Target>;
void declare_fields() {
DeclareField(rom);
DeclareField(disk_interface);
DeclareField(processor);
AnnounceEnum(ROM);
AnnounceEnum(DiskInterface);
AnnounceEnum(Processor);
}
};
}
#endif /* Analyser_Static_Oric_Target_h */

View File

@@ -0,0 +1,30 @@
//
// StaticAnalyser.cpp
// Clock Signal
//
// Created by Thomas Harte on 03/10/2019.
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#include "StaticAnalyser.hpp"
#include "Target.hpp"
Analyser::Static::TargetList Analyser::Static::PCCompatible::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
bool
) {
// This analyser can comprehend disks only.
if(media.disks.empty()) return {};
// No analysis is applied yet.
Analyser::Static::TargetList targets;
using Target = Analyser::Static::PCCompatible::Target;
auto *const target = new Target();
target->media = media;
targets.push_back(std::unique_ptr<Analyser::Static::Target>(target));
return targets;
}

View File

@@ -0,0 +1,19 @@
//
// StaticAnalyser.hpp
// Clock Signal
//
// Created by Thomas Harte on 29/11/2019.
// Copyright © 2023 Thomas Harte. All rights reserved.
//
#pragma once
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::PCCompatible {
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}

View File

@@ -0,0 +1,54 @@
//
// Target.hpp
// Clock Signal
//
// Created by Thomas Harte on 29/11/2023.
// Copyright © 2023 Thomas Harte. All rights reserved.
//
#pragma once
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Reflection/Struct.hpp"
namespace Analyser::Static::PCCompatible {
ReflectableEnum(Model,
XT,
TurboXT,
AT
);
constexpr bool is_xt(const Model model) {
return model <= Model::TurboXT;
}
constexpr bool is_at(const Model model) {
return model >= Model::AT;
}
constexpr bool has_ide(const Model model) {
return model >= Model::AT;
}
struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Target> {
ReflectableEnum(VideoAdaptor,
MDA,
CGA,
);
VideoAdaptor adaptor = VideoAdaptor::CGA;
Model model = Model::TurboXT;
Target() : Analyser::Static::Target(Machine::PCCompatible) {}
private:
friend Reflection::StructImpl<Target>;
void declare_fields() {
AnnounceEnum(VideoAdaptor);
AnnounceEnum(Model);
DeclareField(adaptor);
DeclareField(model);
}
};
}

View File

@@ -13,7 +13,12 @@
#include <algorithm>
#include <cstring>
Analyser::Static::TargetList Analyser::Static::Sega::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::Sega::GetTargets(
const Media &media,
const std::string &file_name,
TargetPlatform::IntType,
bool
) {
if(media.cartridges.empty())
return {};
@@ -54,7 +59,8 @@ Analyser::Static::TargetList Analyser::Static::Sega::GetTargets(const Media &med
if(lowercase_name.find("(jp)") == std::string::npos) {
target->region =
(lowercase_name.find("(us)") == std::string::npos &&
lowercase_name.find("(ntsc)") == std::string::npos) ? Target::Region::Europe : Target::Region::USA;
lowercase_name.find("(ntsc)") == std::string::npos) ?
Target::Region::Europe : Target::Region::USA;
}
} break;
}
@@ -63,9 +69,9 @@ Analyser::Static::TargetList Analyser::Static::Sega::GetTargets(const Media &med
// If one is found, set the paging scheme appropriately.
const uint16_t inverse_checksum = uint16_t(0x10000 - (data[0x7fe6] | (data[0x7fe7] << 8)));
if(
data[0x7fe3] >= 0x87 && data[0x7fe3] < 0x96 && // i.e. game is dated between 1987 and 1996
data[0x7fe3] >= 0x87 && data[0x7fe3] < 0x96 && // i.e. game is dated between 1987 and 1996
(inverse_checksum&0xff) == data[0x7fe8] &&
(inverse_checksum >> 8) == data[0x7fe9] && // i.e. the standard checksum appears to be present
(inverse_checksum >> 8) == data[0x7fe9] && // i.e. the standard checksum appears to be present.
!data[0x7fea] && !data[0x7feb] && !data[0x7fec] && !data[0x7fed] && !data[0x7fee] && !data[0x7fef]
) {
target->paging_scheme = Target::PagingScheme::Codemasters;

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::Sega {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* StaticAnalyser_hpp */

View File

@@ -6,12 +6,11 @@
// 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"
#include "../StaticAnalyser.hpp"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Reflection/Enum.hpp"
#include "Reflection/Struct.hpp"
namespace Analyser::Static::Sega {
@@ -38,18 +37,18 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
Region region = Region::Japan;
PagingScheme paging_scheme = PagingScheme::Sega;
Target() : Analyser::Static::Target(Machine::MasterSystem) {
if(needs_declare()) {
DeclareField(region);
AnnounceEnum(Region);
}
Target() : Analyser::Static::Target(Machine::MasterSystem) {}
private:
friend Reflection::StructImpl<Target>;
void declare_fields() {
DeclareField(region);
AnnounceEnum(Region);
}
};
constexpr bool is_master_system(Analyser::Static::Sega::Target::Model model) {
constexpr bool is_master_system(const Analyser::Static::Sega::Target::Model model) {
return model >= Analyser::Static::Sega::Target::Model::MasterSystem;
}
}
#endif /* Analyser_Static_Sega_Target_h */

View File

@@ -9,81 +9,90 @@
#include "StaticAnalyser.hpp"
#include <algorithm>
#include <bit>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <iterator>
// Analysers
#include "Acorn/StaticAnalyser.hpp"
#include "Amiga/StaticAnalyser.hpp"
#include "AmstradCPC/StaticAnalyser.hpp"
#include "AppleII/StaticAnalyser.hpp"
#include "AppleIIgs/StaticAnalyser.hpp"
#include "Atari2600/StaticAnalyser.hpp"
#include "AtariST/StaticAnalyser.hpp"
#include "Coleco/StaticAnalyser.hpp"
#include "Commodore/StaticAnalyser.hpp"
#include "DiskII/StaticAnalyser.hpp"
#include "Enterprise/StaticAnalyser.hpp"
#include "Macintosh/StaticAnalyser.hpp"
#include "MSX/StaticAnalyser.hpp"
#include "Oric/StaticAnalyser.hpp"
#include "Sega/StaticAnalyser.hpp"
#include "ZX8081/StaticAnalyser.hpp"
#include "ZXSpectrum/StaticAnalyser.hpp"
#include "Analyser/Static/Acorn/StaticAnalyser.hpp"
#include "Analyser/Static/Amiga/StaticAnalyser.hpp"
#include "Analyser/Static/AmstradCPC/StaticAnalyser.hpp"
#include "Analyser/Static/AppleII/StaticAnalyser.hpp"
#include "Analyser/Static/AppleIIgs/StaticAnalyser.hpp"
#include "Analyser/Static/Atari2600/StaticAnalyser.hpp"
#include "Analyser/Static/AtariST/StaticAnalyser.hpp"
#include "Analyser/Static/Coleco/StaticAnalyser.hpp"
#include "Analyser/Static/Commodore/StaticAnalyser.hpp"
#include "Analyser/Static/DiskII/StaticAnalyser.hpp"
#include "Analyser/Static/Enterprise/StaticAnalyser.hpp"
#include "Analyser/Static/FAT12/StaticAnalyser.hpp"
#include "Analyser/Static/Macintosh/StaticAnalyser.hpp"
#include "Analyser/Static/MSX/StaticAnalyser.hpp"
#include "Analyser/Static/Oric/StaticAnalyser.hpp"
#include "Analyser/Static/PCCompatible/StaticAnalyser.hpp"
#include "Analyser/Static/Sega/StaticAnalyser.hpp"
#include "Analyser/Static/ZX8081/StaticAnalyser.hpp"
#include "Analyser/Static/ZXSpectrum/StaticAnalyser.hpp"
// Cartridges
#include "../../Storage/Cartridge/Formats/BinaryDump.hpp"
#include "../../Storage/Cartridge/Formats/PRG.hpp"
#include "Storage/Cartridge/Formats/BinaryDump.hpp"
#include "Storage/Cartridge/Formats/PRG.hpp"
// Disks
#include "../../Storage/Disk/DiskImage/Formats/2MG.hpp"
#include "../../Storage/Disk/DiskImage/Formats/AcornADF.hpp"
#include "../../Storage/Disk/DiskImage/Formats/AmigaADF.hpp"
#include "../../Storage/Disk/DiskImage/Formats/AppleDSK.hpp"
#include "../../Storage/Disk/DiskImage/Formats/CPCDSK.hpp"
#include "../../Storage/Disk/DiskImage/Formats/D64.hpp"
#include "../../Storage/Disk/DiskImage/Formats/G64.hpp"
#include "../../Storage/Disk/DiskImage/Formats/DMK.hpp"
#include "../../Storage/Disk/DiskImage/Formats/FAT12.hpp"
#include "../../Storage/Disk/DiskImage/Formats/HFE.hpp"
#include "../../Storage/Disk/DiskImage/Formats/IPF.hpp"
#include "../../Storage/Disk/DiskImage/Formats/MacintoshIMG.hpp"
#include "../../Storage/Disk/DiskImage/Formats/MSA.hpp"
#include "../../Storage/Disk/DiskImage/Formats/NIB.hpp"
#include "../../Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp"
#include "../../Storage/Disk/DiskImage/Formats/SSD.hpp"
#include "../../Storage/Disk/DiskImage/Formats/STX.hpp"
#include "../../Storage/Disk/DiskImage/Formats/WOZ.hpp"
#include "Storage/Disk/DiskImage/Formats/2MG.hpp"
#include "Storage/Disk/DiskImage/Formats/AcornADF.hpp"
#include "Storage/Disk/DiskImage/Formats/AmigaADF.hpp"
#include "Storage/Disk/DiskImage/Formats/AppleDSK.hpp"
#include "Storage/Disk/DiskImage/Formats/CPCDSK.hpp"
#include "Storage/Disk/DiskImage/Formats/D64.hpp"
#include "Storage/Disk/DiskImage/Formats/G64.hpp"
#include "Storage/Disk/DiskImage/Formats/DMK.hpp"
#include "Storage/Disk/DiskImage/Formats/FAT12.hpp"
#include "Storage/Disk/DiskImage/Formats/HFE.hpp"
#include "Storage/Disk/DiskImage/Formats/IPF.hpp"
#include "Storage/Disk/DiskImage/Formats/IMD.hpp"
#include "Storage/Disk/DiskImage/Formats/JFD.hpp"
#include "Storage/Disk/DiskImage/Formats/MacintoshIMG.hpp"
#include "Storage/Disk/DiskImage/Formats/MSA.hpp"
#include "Storage/Disk/DiskImage/Formats/NIB.hpp"
#include "Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp"
#include "Storage/Disk/DiskImage/Formats/PCBooter.hpp"
#include "Storage/Disk/DiskImage/Formats/SSD.hpp"
#include "Storage/Disk/DiskImage/Formats/STX.hpp"
#include "Storage/Disk/DiskImage/Formats/WOZ.hpp"
// Mass Storage Devices (i.e. usually, hard disks)
#include "../../Storage/MassStorage/Formats/DAT.hpp"
#include "../../Storage/MassStorage/Formats/DSK.hpp"
#include "../../Storage/MassStorage/Formats/HDV.hpp"
#include "../../Storage/MassStorage/Formats/HFV.hpp"
#include "Storage/MassStorage/Formats/DAT.hpp"
#include "Storage/MassStorage/Formats/DSK.hpp"
#include "Storage/MassStorage/Formats/HDV.hpp"
#include "Storage/MassStorage/Formats/HFV.hpp"
#include "Storage/MassStorage/Formats/VHD.hpp"
// State Snapshots
#include "../../Storage/State/SNA.hpp"
#include "../../Storage/State/SZX.hpp"
#include "../../Storage/State/Z80.hpp"
#include "Storage/State/SNA.hpp"
#include "Storage/State/SZX.hpp"
#include "Storage/State/Z80.hpp"
// Tapes
#include "../../Storage/Tape/Formats/CAS.hpp"
#include "../../Storage/Tape/Formats/CommodoreTAP.hpp"
#include "../../Storage/Tape/Formats/CSW.hpp"
#include "../../Storage/Tape/Formats/OricTAP.hpp"
#include "../../Storage/Tape/Formats/TapePRG.hpp"
#include "../../Storage/Tape/Formats/TapeUEF.hpp"
#include "../../Storage/Tape/Formats/TZX.hpp"
#include "../../Storage/Tape/Formats/ZX80O81P.hpp"
#include "../../Storage/Tape/Formats/ZXSpectrumTAP.hpp"
#include "Storage/Tape/Formats/CAS.hpp"
#include "Storage/Tape/Formats/CommodoreTAP.hpp"
#include "Storage/Tape/Formats/CSW.hpp"
#include "Storage/Tape/Formats/OricTAP.hpp"
#include "Storage/Tape/Formats/TapePRG.hpp"
#include "Storage/Tape/Formats/TapeUEF.hpp"
#include "Storage/Tape/Formats/TZX.hpp"
#include "Storage/Tape/Formats/ZX80O81P.hpp"
#include "Storage/Tape/Formats/ZXSpectrumTAP.hpp"
// Target Platform Types
#include "../../Storage/TargetPlatforms.hpp"
#include "Storage/TargetPlatforms.hpp"
template<class> inline constexpr bool always_false_v = false;
using namespace Analyser::Static;
using namespace Storage;
namespace {
@@ -97,46 +106,94 @@ 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(const 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::Distinguisher *const distinguisher =
dynamic_cast<TargetPlatform::Distinguisher *>(instance.get());
if(distinguisher) {
was_distinguished = true;
potential_platforms_ &= distinguisher->target_platforms();
}
}
/// 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(const 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(const 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(const TargetPlatform::IntType platforms, const char *extension) {
if(name_matches(extension)) {
try_insert<InstanceT>(platforms, file_name_);
}
}
bool name_matches(const char *const extension) {
return extension_ == extension;
}
Media media;
bool was_distinguished = false;
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.");
}
@@ -144,95 +201,113 @@ 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("img", result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2)
Format("image", result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2)
Format("img", result.disks, Disk::DiskImageHolder<Storage::Disk::FAT12>, TargetPlatform::Enterprise) // IMG (Enterprise/MS-DOS style)
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<Tape::ZX80O81P>(TargetPlatform::ZX8081, "80");
accumulator.try_standard<Tape::ZX80O81P>(TargetPlatform::ZX8081, "81");
// 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<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<Disk::DiskImageHolder<Disk::JFD>>(TargetPlatform::Archimedes, "jfd");
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::Commodore8bit, "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::Commodore8bit, "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(accumulator.name_matches("img")) {
try {
accumulator.insert<Disk::DiskImageHolder<Disk::FAT12>>(TargetPlatform::FAT12, file_name);
} catch(...) {
accumulator.try_standard<Disk::DiskImageHolder<Disk::PCBooter>>(TargetPlatform::PCCompatible, "img");
}
}
Format("p81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P81
accumulator.try_standard<Disk::DiskImageHolder<Disk::IPF>>(
TargetPlatform::Amiga | TargetPlatform::AtariST | TargetPlatform::AmstradCPC | TargetPlatform::ZXSpectrum,
"ipf");
// PRG
if(extension == "prg") {
// try instantiating as a ROM; failing that accept as a tape
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);
}
accumulator.try_standard<Tape::ZX80O81P>(TargetPlatform::ZX8081, "p81");
static constexpr auto PRGTargets = TargetPlatform::Vic20; //Commodore8bit; // Disabled until analysis improves.
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>(PRGTargets, file_name);
} catch(...) {
try {
Insert(result.tapes, Tape::PRG, TargetPlatform::Commodore, file_name)
accumulator.insert<Tape::PRG>(PRGTargets, 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::Commodore8bit, "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<MassStorage::VHD>(TargetPlatform::PCCompatible, "vhd");
accumulator.try_standard<Disk::DiskImageHolder<Disk::WOZ>>(TargetPlatform::DiskII, "woz");
return accumulator.media;
}
Media Analyser::Static::GetMedia(const std::string &file_name) {
@@ -241,26 +316,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:
//
@@ -269,37 +346,45 @@ TargetList Analyser::Static::GetTargets(const std::string &file_name) {
TargetPlatform::IntType potential_platforms = 0;
Media media = GetMediaAndPlatforms(file_name, potential_platforms);
int total_options = std::popcount(potential_platforms);
const bool is_confident = total_options == 1;
// i.e. This analyser `is_confident` if file analysis suggested only one potential target platform.
// The machine-specific static analyser will still run in case it can provide meaningful annotations on
// loading command, machine configuration, etc, but the flag will be passed onwards to mean "don't reject this".
// 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(Macintosh);
Append(MSX);
Append(Oric);
Append(Sega);
Append(ZX8081);
Append(ZXSpectrum);
#undef Append
// Reset any tapes to their initial position.
for(const auto &target : targets) {
for(auto &tape : target->media.tapes) {
tape->reset();
const auto append = [&](TargetPlatform::IntType platform, auto evaluator) {
if(!(potential_platforms & platform)) {
return;
}
}
auto new_targets = evaluator(media, file_name, potential_platforms, is_confident);
targets.insert(
targets.end(),
std::make_move_iterator(new_targets.begin()),
std::make_move_iterator(new_targets.end())
);
};
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::Commodore8bit, 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);
// Sort by initial confidence. Use a stable sort in case any of the machine-specific analysers
// picked their insertion order carefully.

View File

@@ -6,16 +6,16 @@
// Copyright 2016 Thomas Harte. All rights reserved.
//
#ifndef StaticAnalyser_hpp
#define StaticAnalyser_hpp
#pragma once
#include "../Machines.hpp"
#include "Analyser/Machines.hpp"
#include "../../Storage/Cartridge/Cartridge.hpp"
#include "../../Storage/Disk/Disk.hpp"
#include "../../Storage/MassStorage/MassStorageDevice.hpp"
#include "../../Storage/Tape/Tape.hpp"
#include "../../Reflection/Struct.hpp"
#include "Storage/Cartridge/Cartridge.hpp"
#include "Storage/Disk/Disk.hpp"
#include "Storage/MassStorage/MassStorageDevice.hpp"
#include "Storage/Tape/Tape.hpp"
#include "Storage/TargetPlatforms.hpp"
#include "Reflection/Struct.hpp"
#include <memory>
#include <string>
@@ -39,12 +39,15 @@ struct Media {
}
Media &operator +=(const Media &rhs) {
#define append(name) name.insert(name.end(), rhs.name.begin(), rhs.name.end());
append(disks);
append(tapes);
append(cartridges);
append(mass_storage_devices);
#undef append
const auto append = [&](auto &destination, auto &source) {
destination.insert(destination.end(), source.begin(), source.end());
};
append(disks, rhs.disks);
append(tapes, rhs.tapes);
append(cartridges, rhs.cartridges);
append(mass_storage_devices, rhs.mass_storage_devices);
return *this;
}
};
@@ -55,16 +58,16 @@ struct Media {
*/
struct Target {
Target(Machine machine) : machine(machine) {}
virtual ~Target() {}
virtual ~Target() = default;
// This field is entirely optional.
std::unique_ptr<Reflection::Struct> state;
Machine machine;
Media media;
float confidence = 0.0f;
float confidence = 0.5f;
};
typedef std::vector<std::unique_ptr<Target>> TargetList;
using TargetList = std::vector<std::unique_ptr<Target>>;
/*!
Attempts, through any available means, to return a list of potential targets for the file with the given name.
@@ -79,5 +82,3 @@ TargetList GetTargets(const std::string &file_name);
Media GetMedia(const std::string &file_name);
}
#endif /* StaticAnalyser_hpp */

View File

@@ -12,27 +12,32 @@
#include <vector>
#include "Target.hpp"
#include "../../../Storage/Tape/Parsers/ZX8081.hpp"
#include "Storage/Tape/Parsers/ZX8081.hpp"
static std::vector<Storage::Data::ZX8081::File> GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape) {
static std::vector<Storage::Data::ZX8081::File> GetFiles(Storage::Tape::TapeSerialiser &serialiser) {
std::vector<Storage::Data::ZX8081::File> files;
Storage::Tape::ZX8081::Parser parser;
while(!tape->is_at_end()) {
std::shared_ptr<Storage::Data::ZX8081::File> next_file = parser.get_next_file(tape);
if(next_file != nullptr) {
files.push_back(*next_file);
while(!serialiser.is_at_end()) {
const auto next_file = parser.get_next_file(serialiser);
if(next_file) {
files.push_back(std::move(*next_file));
}
}
return files;
}
Analyser::Static::TargetList Analyser::Static::ZX8081::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType potential_platforms) {
Analyser::Static::TargetList Analyser::Static::ZX8081::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType potential_platforms,
bool
) {
TargetList destination;
if(!media.tapes.empty()) {
std::vector<Storage::Data::ZX8081::File> files = GetFiles(media.tapes.front());
media.tapes.front()->reset();
const auto serialiser = media.tapes.front()->serialiser();
std::vector<Storage::Data::ZX8081::File> files = GetFiles(*serialiser);
if(!files.empty()) {
Target *const target = new Target;
destination.push_back(std::unique_ptr<::Analyser::Static::Target>(target));

View File

@@ -6,17 +6,14 @@
// 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"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Storage/TargetPlatforms.hpp"
#include <string>
namespace Analyser::Static::ZX8081 {
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
TargetList GetTargets(const Media &, const std::string &, TargetPlatform::IntType, bool);
}
#endif /* StaticAnalyser_hpp */

View File

@@ -6,12 +6,11 @@
// 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"
#include "../StaticAnalyser.hpp"
#include "Analyser/Static/StaticAnalyser.hpp"
#include "Reflection/Enum.hpp"
#include "Reflection/Struct.hpp"
#include <string>
namespace Analyser::Static::ZX8081 {
@@ -28,16 +27,16 @@ struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<
bool ZX80_uses_ZX81_ROM = false;
std::string loading_command;
Target(): Analyser::Static::Target(Machine::ZX8081) {
if(needs_declare()) {
DeclareField(memory_model);
DeclareField(is_ZX81);
DeclareField(ZX80_uses_ZX81_ROM);
AnnounceEnum(MemoryModel);
}
Target(): Analyser::Static::Target(Machine::ZX8081) {}
private:
friend Reflection::StructImpl<Target>;
void declare_fields() {
DeclareField(memory_model);
DeclareField(is_ZX81);
DeclareField(ZX80_uses_ZX81_ROM);
AnnounceEnum(MemoryModel);
}
};
}
#endif /* Analyser_Static_ZX8081_Target_h */

View File

@@ -8,14 +8,17 @@
#include "StaticAnalyser.hpp"
#include "../../../Storage/Disk/Encodings/MFM/Parser.hpp"
#include "../../../Storage/Tape/Parsers/Spectrum.hpp"
#include "Storage/Disk/Parsers/CPM.hpp"
#include "Storage/Disk/Encodings/MFM/Parser.hpp"
#include "Storage/Tape/Parsers/Spectrum.hpp"
#include "Target.hpp"
#include <algorithm>
namespace {
bool IsSpectrumTape(const std::shared_ptr<Storage::Tape::Tape> &tape) {
bool IsSpectrumTape(Storage::Tape::TapeSerialiser &tape) {
using Parser = Storage::Tape::ZXSpectrum::Parser;
Parser parser(Parser::MachineType::ZXSpectrum);
@@ -33,30 +36,79 @@ bool IsSpectrumTape(const std::shared_ptr<Storage::Tape::Tape> &tape) {
}
bool IsSpectrumDisk(const std::shared_ptr<Storage::Disk::Disk> &disk) {
Storage::Encodings::MFM::Parser parser(true, disk);
Storage::Encodings::MFM::Parser parser(Storage::Encodings::MFM::Density::Double, disk);
// Get logical sector 1; the Spectrum appears to support various physical
// sectors as sector 1.
Storage::Encodings::MFM::Sector *boot_sector = nullptr;
uint8_t sector_mask = 0;
while(!boot_sector) {
boot_sector = parser.get_sector(0, 0, sector_mask + 1);
sector_mask += 0x40;
if(!sector_mask) break;
}
// Grab absolutely any sector from the first track to determine general encoding.
const Storage::Encodings::MFM::Sector *any_sector = parser.any_sector(0, 0);
if(!any_sector) return false;
// Determine the sector base and get logical sector 1.
const uint8_t sector_base = any_sector->address.sector & 0xc0;
const Storage::Encodings::MFM::Sector *boot_sector = parser.sector(0, 0, sector_base + 1);
if(!boot_sector) return false;
// Test that the contents of the boot sector sum to 3, modulo 256.
uint8_t byte_sum = 0;
for(auto byte: boot_sector->samples[0]) {
byte_sum += byte;
Storage::Disk::CPM::ParameterBlock cpm_format{};
switch(sector_base) {
case 0x40: cpm_format = Storage::Disk::CPM::ParameterBlock::cpc_system_format(); break;
case 0xc0: cpm_format = Storage::Disk::CPM::ParameterBlock::cpc_data_format(); break;
default: {
// Check the first ten bytes of the first sector for the disk format; if these are all
// the same value then instead substitute a default format.
std::array<uint8_t, 10> format;
std::copy(boot_sector->samples[0].begin(), boot_sector->samples[0].begin() + 10, format.begin());
if(std::all_of(format.begin(), format.end(), [&](const uint8_t v) { return v == format[0]; })) {
format = {0x00, 0x00, 0x28, 0x09, 0x02, 0x01, 0x03, 0x02, 0x2a, 0x52};
}
// Parse those ten bytes as:
//
// Byte 0: disc type
// Byte 1: sidedness
// bits 0-6: arrangement
// 0 => single sided
// 1 => double sided, flip sides
// 2 => double sided, up and over
// bit 7: double-track
// Byte 2: number of tracks per side
// Byte 3: number of sectors per track
// Byte 4: Log2(sector size) - 7
// Byte 5: number of reserved tracks
// Byte 6: Log2(block size) - 7
// Byte 7: number of directory blocks
// Byte 8: gap length (read/write)
// Byte 9: gap length(format)
cpm_format.sectors_per_track = format[3];
cpm_format.tracks = format[2];
cpm_format.block_size = 128 << format[6];
cpm_format.first_sector = sector_base + 1;
cpm_format.reserved_tracks = format[5];
// i.e. bits set downward from 0x4000 for as many blocks as form the catalogue.
cpm_format.catalogue_allocation_bitmap = 0x8000 - (0x8000 >> format[7]);
} break;
}
return byte_sum == 3;
// If the boot sector sums to 3 modulo 256 then this is a Spectrum disk.
const auto byte_sum = static_cast<uint8_t>(
std::accumulate(boot_sector->samples[0].begin(), boot_sector->samples[0].end(), 0));
if(byte_sum == 3) {
return true;
}
// ... otherwise read a CPM directory and look for a BASIC program called "DISK".
const auto catalogue = Storage::Disk::CPM::GetCatalogue(disk, cpm_format, false);
return catalogue && catalogue->is_zx_spectrum_booter();
}
}
Analyser::Static::TargetList Analyser::Static::ZXSpectrum::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
Analyser::Static::TargetList Analyser::Static::ZXSpectrum::GetTargets(
const Media &media,
const std::string &,
TargetPlatform::IntType,
bool
) {
TargetList destination;
auto target = std::make_unique<Target>();
target->confidence = 0.5;
@@ -64,7 +116,8 @@ Analyser::Static::TargetList Analyser::Static::ZXSpectrum::GetTargets(const Medi
if(!media.tapes.empty()) {
bool has_spectrum_tape = false;
for(auto &tape: media.tapes) {
has_spectrum_tape |= IsSpectrumTape(tape);
auto serialiser = tape->serialiser();
has_spectrum_tape |= IsSpectrumTape(*serialiser);
}
if(has_spectrum_tape) {

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