From bc2f58e9de8b527c16bc385416989ad1b6f160e8 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 4 Nov 2017 19:36:46 -0400 Subject: [PATCH 01/14] Starts the process of adding an SDL-based 'kiosk' (i.e. TV UI, or even UI-less for now) mode. Specifically, introduces to the Mac side of things an SDL target with, so far, enough logic to create a window and pump SDL's events, after having decided which machine and configuration it should use. --- .../Clock Signal.xcodeproj/project.pbxproj | 256 ++++++++++++++++++ OSBindings/SDL/main.cpp | 65 +++++ 2 files changed, 321 insertions(+) create mode 100644 OSBindings/SDL/main.cpp diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 84ab437c3..575d34c4e 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -9,6 +9,71 @@ /* Begin PBXBuildFile section */ 4B01A6881F22F0DB001FD6E3 /* Z80MemptrTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */; }; 4B049CDD1DA3C82F00322067 /* BCDTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B049CDC1DA3C82F00322067 /* BCDTest.swift */; }; + 4B055A7A1FAE78A00060FFFF /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B055A771FAE78210060FFFF /* SDL2.framework */; }; + 4B055A7E1FAE84AA0060FFFF /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B055A7C1FAE84A50060FFFF /* main.cpp */; }; + 4B055A7F1FAE852F0060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1354A1D6D2C300054B2EA /* StaticAnalyser.cpp */; }; + 4B055A801FAE85350060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BA799931D8B656E0045123D /* StaticAnalyser.cpp */; }; + 4B055A811FAE853A0060FFFF /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF829641D8F732B001BAE39 /* Disk.cpp */; }; + 4B055A821FAE853D0060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD14B0F1D74627C0088EAD6 /* StaticAnalyser.cpp */; }; + 4B055A831FAE85410060FFFF /* Tape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B96F7201D75119A0058BB2D /* Tape.cpp */; }; + 4B055A841FAE85450060FFFF /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BA22B051D8817CE0008C640 /* Disk.cpp */; }; + 4B055A851FAE85480060FFFF /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BE77A2C1D84ADFB00BC3827 /* File.cpp */; }; + 4B055A861FAE854C0060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC5E4901D7ED365008CF980 /* StaticAnalyser.cpp */; }; + 4B055A871FAE854F0060FFFF /* Tape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC830CF1D6E7C690000A26F /* Tape.cpp */; }; + 4B055A881FAE85530060FFFF /* Disassembler6502.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5A12551DD55862007A2231 /* Disassembler6502.cpp */; }; + 4B055A891FAE85580060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF1FA91DADD41B0039D2E7 /* StaticAnalyser.cpp */; }; + 4B055A8A1FAE855B0060FFFF /* Tape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805FC1DD02552003085B1 /* Tape.cpp */; }; + 4B055A8B1FAE85670060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1497891EE4AC5E00CE2596 /* StaticAnalyser.cpp */; }; + 4B055A8C1FAE85670060FFFF /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B38F3421F2EB3E900D9235D /* StaticAnalyser.cpp */; }; + 4B055A8D1FAE85920060FFFF /* AsyncTaskQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3940E51DA83C8300427841 /* AsyncTaskQueue.cpp */; }; + 4B055A8E1FAE85920060FFFF /* BestEffortUpdater.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80ACFE1F85CAC900176895 /* BestEffortUpdater.cpp */; }; + 4B055A8F1FAE85A90060FFFF /* FileHolder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5FADB81DE3151600AEC565 /* FileHolder.cpp */; }; + 4B055A901FAE85A90060FFFF /* TimedEventLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */; }; + 4B055A911FAE85B50060FFFF /* Cartridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A6A1D72496600532C7B /* Cartridge.cpp */; }; + 4B055A921FAE85B50060FFFF /* PRG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A6D1D72496600532C7B /* PRG.cpp */; }; + 4B055A931FAE85B50060FFFF /* BinaryDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B37EE801D7345A6006A09A4 /* BinaryDump.cpp */; }; + 4B055A941FAE85B50060FFFF /* CommodoreROM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCA6CC61D9DD9F000C2D7B2 /* CommodoreROM.cpp */; }; + 4B055A951FAE85BB0060FFFF /* BitReverse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1558BE1F844ECD006E9A97 /* BitReverse.cpp */; }; + 4B055A961FAE85BB0060FFFF /* Commodore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805F51DCFF6C9003085B1 /* Commodore.cpp */; }; + 4B055A971FAE85BB0060FFFF /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */; }; + 4B055A981FAE85C50060FFFF /* Drive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B30512B1D989E2200B4FED8 /* Drive.cpp */; }; + 4B055A991FAE85CB0060FFFF /* DiskController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45187A1F75E91900926311 /* DiskController.cpp */; }; + 4B055A9A1FAE85CB0060FFFF /* MFMDiskController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45187C1F75E91900926311 /* MFMDiskController.cpp */; }; + 4B055A9B1FAE85DA0060FFFF /* AcornADF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45188D1F75FD1B00926311 /* AcornADF.cpp */; }; + 4B055A9C1FAE85DA0060FFFF /* CPCDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45188F1F75FD1B00926311 /* CPCDSK.cpp */; }; + 4B055A9D1FAE85DA0060FFFF /* D64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518911F75FD1B00926311 /* D64.cpp */; }; + 4B055A9E1FAE85DA0060FFFF /* G64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518931F75FD1B00926311 /* G64.cpp */; }; + 4B055A9F1FAE85DA0060FFFF /* HFE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518951F75FD1B00926311 /* HFE.cpp */; }; + 4B055AA01FAE85DA0060FFFF /* MFMSectorDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B58601C1F806AB200AEE2E3 /* MFMSectorDump.cpp */; }; + 4B055AA11FAE85DA0060FFFF /* OricMFMDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518971F75FD1B00926311 /* OricMFMDSK.cpp */; }; + 4B055AA21FAE85DA0060FFFF /* SSD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518991F75FD1B00926311 /* SSD.cpp */; }; + 4B055AA31FAE85DF0060FFFF /* ImplicitSectors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFDD78B1F7F2DB4008579B9 /* ImplicitSectors.cpp */; }; + 4B055AA41FAE85E50060FFFF /* DigitalPhaseLockedLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B45187F1F75E91900926311 /* DigitalPhaseLockedLoop.cpp */; }; + 4B055AA51FAE85EF0060FFFF /* Encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136841F78724F008B8ED9 /* Encoder.cpp */; }; + 4B055AA61FAE85EF0060FFFF /* Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B71368C1F788112008B8ED9 /* Parser.cpp */; }; + 4B055AA71FAE85EF0060FFFF /* SegmentParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B71368F1F789C93008B8ED9 /* SegmentParser.cpp */; }; + 4B055AA81FAE85EF0060FFFF /* Shifter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136871F78725F008B8ED9 /* Shifter.cpp */; }; + 4B055AA91FAE85EF0060FFFF /* CommodoreGCR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */; }; + 4B055AAA1FAE85F50060FFFF /* CPM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3FE75C1F3CF68B00448EE4 /* CPM.cpp */; }; + 4B055AAB1FAE85FD0060FFFF /* PCMPatchedTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518711F75E91800926311 /* PCMPatchedTrack.cpp */; }; + 4B055AAC1FAE85FD0060FFFF /* PCMSegment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518731F75E91800926311 /* PCMSegment.cpp */; }; + 4B055AAD1FAE85FD0060FFFF /* PCMTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518751F75E91800926311 /* PCMTrack.cpp */; }; + 4B055AAE1FAE85FD0060FFFF /* TrackSerialiser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBFFEE51F7B27F1005F3FEB /* TrackSerialiser.cpp */; }; + 4B055AAF1FAE85FD0060FFFF /* UnformattedTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518771F75E91800926311 /* UnformattedTrack.cpp */; }; + 4B055AB01FAE86070060FFFF /* PulseQueuedTape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B448E821F1C4C480009ABD6 /* PulseQueuedTape.cpp */; }; + 4B055AB11FAE86070060FFFF /* Tape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B69FB3B1C4D908A00B5F0AA /* Tape.cpp */; }; + 4B055AB21FAE860F0060FFFF /* CommodoreTAP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC91B811D1F160E00884B76 /* CommodoreTAP.cpp */; }; + 4B055AB31FAE860F0060FFFF /* CSW.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BF5AE1F146264005B6C36 /* CSW.cpp */; }; + 4B055AB41FAE860F0060FFFF /* OricTAP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B59199A1DAC6C46005BB85C /* OricTAP.cpp */; }; + 4B055AB51FAE860F0060FFFF /* TapePRG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2BFC5D1D613E0200BA3AA9 /* TapePRG.cpp */; }; + 4B055AB61FAE860F0060FFFF /* TapeUEF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */; }; + 4B055AB71FAE860F0060FFFF /* TZX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B448E7F1F1C45A00009ABD6 /* TZX.cpp */; }; + 4B055AB81FAE860F0060FFFF /* ZX80O81P.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1497861EE4A1DA00CE2596 /* ZX80O81P.cpp */; }; + 4B055AB91FAE86170060FFFF /* Acorn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805EE1DCFC99C003085B1 /* Acorn.cpp */; }; + 4B055ABA1FAE86170060FFFF /* Commodore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805F21DCFD22A003085B1 /* Commodore.cpp */; }; + 4B055ABB1FAE86170060FFFF /* Oric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805F91DCFF807003085B1 /* Oric.cpp */; }; + 4B055ABC1FAE86170060FFFF /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBFBB6A1EE8401E00C01E7A /* ZX8081.cpp */; }; + 4B055ABD1FAE86530060FFFF /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B69FB451C4D950F00B5F0AA /* libz.tbd */; }; 4B08A2751EE35D56008B7065 /* Z80InterruptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */; }; 4B08A2781EE39306008B7065 /* TestMachine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B08A2771EE39306008B7065 /* TestMachine.mm */; }; 4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CCC421C62D0B3001CAC5F /* CRT.cpp */; }; @@ -481,10 +546,25 @@ }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + 4B055A681FAE763F0060FFFF /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MemptrTests.swift; sourceTree = ""; }; 4B046DC31CFE651500E9E45E /* CRTMachine.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRTMachine.hpp; sourceTree = ""; }; 4B049CDC1DA3C82F00322067 /* BCDTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BCDTest.swift; sourceTree = ""; }; + 4B055A6A1FAE763F0060FFFF /* Clock Signal Kiosk */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Clock Signal Kiosk"; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B055A771FAE78210060FFFF /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = ../../../../Library/Frameworks/SDL2.framework; sourceTree = ""; }; + 4B055A7C1FAE84A50060FFFF /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; 4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80InterruptTests.swift; sourceTree = ""; }; 4B08A2761EE39306008B7065 /* TestMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestMachine.h; sourceTree = ""; }; 4B08A2771EE39306008B7065 /* TestMachine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestMachine.mm; sourceTree = ""; }; @@ -1134,6 +1214,15 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 4B055A671FAE763F0060FFFF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B055ABD1FAE86530060FFFF /* libz.tbd in Frameworks */, + 4B055A7A1FAE78A00060FFFF /* SDL2.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4BB73E9B1B587A5100552FC2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1160,6 +1249,23 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 4B055A761FAE78210060FFFF /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4B055A771FAE78210060FFFF /* SDL2.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 4B055A7B1FAE84A50060FFFF /* SDL */ = { + isa = PBXGroup; + children = ( + 4B055A7C1FAE84A50060FFFF /* main.cpp */, + ); + name = SDL; + path = ../SDL; + sourceTree = ""; + }; 4B0CCC411C62D0B3001CAC5F /* CRT */ = { isa = PBXGroup; children = ( @@ -2095,12 +2201,14 @@ 4BF660691F281573002CB053 /* ClockReceiver */, 4BC9DF4A1D04691600F44158 /* Components */, 4B3940E81DA83C8700427841 /* Concurrency */, + 4B055A761FAE78210060FFFF /* Frameworks */, 4B86E2581F8C628F006FAA45 /* Inputs */, 4BB73EDC1B587CA500552FC2 /* Machines */, 4BB697C81D4B559300248BDF /* NumberTheory */, 4B366DFD1B5C165F0026627B /* Outputs */, 4BB73EDD1B587CA500552FC2 /* Processors */, 4BB73E9F1B587A5100552FC2 /* Products */, + 4B055A7B1FAE84A50060FFFF /* SDL */, 4B2409591C45DF85004DA684 /* SignalProcessing */, 4BF1354D1D6D2C360054B2EA /* StaticAnalyser */, 4B69FB391C4D908A00B5F0AA /* Storage */, @@ -2116,6 +2224,7 @@ 4BB73E9E1B587A5100552FC2 /* Clock Signal.app */, 4BB73EB21B587A5100552FC2 /* Clock SignalTests.xctest */, 4BB73EBD1B587A5100552FC2 /* Clock SignalUITests.xctest */, + 4B055A6A1FAE763F0060FFFF /* Clock Signal Kiosk */, ); name = Products; sourceTree = ""; @@ -2496,6 +2605,23 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 4B055A691FAE763F0060FFFF /* Clock Signal Kiosk */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4B055A701FAE763F0060FFFF /* Build configuration list for PBXNativeTarget "Clock Signal Kiosk" */; + buildPhases = ( + 4B055A661FAE763F0060FFFF /* Sources */, + 4B055A671FAE763F0060FFFF /* Frameworks */, + 4B055A681FAE763F0060FFFF /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Clock Signal Kiosk"; + productName = "Clock Signal Kiosk"; + productReference = 4B055A6A1FAE763F0060FFFF /* Clock Signal Kiosk */; + productType = "com.apple.product-type.tool"; + }; 4BB73E9D1B587A5100552FC2 /* Clock Signal */ = { isa = PBXNativeTarget; buildConfigurationList = 4BB73EC61B587A5100552FC2 /* Build configuration list for PBXNativeTarget "Clock Signal" */; @@ -2559,6 +2685,10 @@ LastUpgradeCheck = 0900; ORGANIZATIONNAME = "Thomas Harte"; TargetAttributes = { + 4B055A691FAE763F0060FFFF = { + CreatedOnToolsVersion = 9.1; + ProvisioningStyle = Automatic; + }; 4BB73E9D1B587A5100552FC2 = { CreatedOnToolsVersion = 7.0; LastSwiftMigration = 0900; @@ -2596,6 +2726,7 @@ 4BB73E9D1B587A5100552FC2 /* Clock Signal */, 4BB73EB11B587A5100552FC2 /* Clock SignalTests */, 4BB73EBC1B587A5100552FC2 /* Clock SignalUITests */, + 4B055A691FAE763F0060FFFF /* Clock Signal Kiosk */, ); }; /* End PBXProject section */ @@ -2913,6 +3044,76 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 4B055A661FAE763F0060FFFF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B055AAA1FAE85F50060FFFF /* CPM.cpp in Sources */, + 4B055A9A1FAE85CB0060FFFF /* MFMDiskController.cpp in Sources */, + 4B055AA41FAE85E50060FFFF /* DigitalPhaseLockedLoop.cpp in Sources */, + 4B055A9B1FAE85DA0060FFFF /* AcornADF.cpp in Sources */, + 4B055A811FAE853A0060FFFF /* Disk.cpp in Sources */, + 4B055AA51FAE85EF0060FFFF /* Encoder.cpp in Sources */, + 4B055A8A1FAE855B0060FFFF /* Tape.cpp in Sources */, + 4B055AA71FAE85EF0060FFFF /* SegmentParser.cpp in Sources */, + 4B055A851FAE85480060FFFF /* File.cpp in Sources */, + 4B055AB41FAE860F0060FFFF /* OricTAP.cpp in Sources */, + 4B055AB71FAE860F0060FFFF /* TZX.cpp in Sources */, + 4B055A8C1FAE85670060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055AB61FAE860F0060FFFF /* TapeUEF.cpp in Sources */, + 4B055A9D1FAE85DA0060FFFF /* D64.cpp in Sources */, + 4B055ABB1FAE86170060FFFF /* Oric.cpp in Sources */, + 4B055A901FAE85A90060FFFF /* TimedEventLoop.cpp in Sources */, + 4B055AAB1FAE85FD0060FFFF /* PCMPatchedTrack.cpp in Sources */, + 4B055AA31FAE85DF0060FFFF /* ImplicitSectors.cpp in Sources */, + 4B055AAE1FAE85FD0060FFFF /* TrackSerialiser.cpp in Sources */, + 4B055A981FAE85C50060FFFF /* Drive.cpp in Sources */, + 4B055A9E1FAE85DA0060FFFF /* G64.cpp in Sources */, + 4B055AB81FAE860F0060FFFF /* ZX80O81P.cpp in Sources */, + 4B055A8E1FAE85920060FFFF /* BestEffortUpdater.cpp in Sources */, + 4B055AB01FAE86070060FFFF /* PulseQueuedTape.cpp in Sources */, + 4B055A801FAE85350060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055AAC1FAE85FD0060FFFF /* PCMSegment.cpp in Sources */, + 4B055AB31FAE860F0060FFFF /* CSW.cpp in Sources */, + 4B055A881FAE85530060FFFF /* Disassembler6502.cpp in Sources */, + 4B055AA21FAE85DA0060FFFF /* SSD.cpp in Sources */, + 4B055A9C1FAE85DA0060FFFF /* CPCDSK.cpp in Sources */, + 4B055ABA1FAE86170060FFFF /* Commodore.cpp in Sources */, + 4B055AA61FAE85EF0060FFFF /* Parser.cpp in Sources */, + 4B055A861FAE854C0060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055ABC1FAE86170060FFFF /* ZX8081.cpp in Sources */, + 4B055A991FAE85CB0060FFFF /* DiskController.cpp in Sources */, + 4B055AB11FAE86070060FFFF /* Tape.cpp in Sources */, + 4B055AA91FAE85EF0060FFFF /* CommodoreGCR.cpp in Sources */, + 4B055A7F1FAE852F0060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055AA01FAE85DA0060FFFF /* MFMSectorDump.cpp in Sources */, + 4B055AA11FAE85DA0060FFFF /* OricMFMDSK.cpp in Sources */, + 4B055A951FAE85BB0060FFFF /* BitReverse.cpp in Sources */, + 4B055A891FAE85580060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055A8D1FAE85920060FFFF /* AsyncTaskQueue.cpp in Sources */, + 4B055A941FAE85B50060FFFF /* CommodoreROM.cpp in Sources */, + 4B055A971FAE85BB0060FFFF /* ZX8081.cpp in Sources */, + 4B055AAD1FAE85FD0060FFFF /* PCMTrack.cpp in Sources */, + 4B055A841FAE85450060FFFF /* Disk.cpp in Sources */, + 4B055A831FAE85410060FFFF /* Tape.cpp in Sources */, + 4B055AA81FAE85EF0060FFFF /* Shifter.cpp in Sources */, + 4B055A8F1FAE85A90060FFFF /* FileHolder.cpp in Sources */, + 4B055A911FAE85B50060FFFF /* Cartridge.cpp in Sources */, + 4B055A8B1FAE85670060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055AB21FAE860F0060FFFF /* CommodoreTAP.cpp in Sources */, + 4B055AB51FAE860F0060FFFF /* TapePRG.cpp in Sources */, + 4B055A961FAE85BB0060FFFF /* Commodore.cpp in Sources */, + 4B055A821FAE853D0060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055A921FAE85B50060FFFF /* PRG.cpp in Sources */, + 4B055AAF1FAE85FD0060FFFF /* UnformattedTrack.cpp in Sources */, + 4B055A7E1FAE84AA0060FFFF /* main.cpp in Sources */, + 4B055A9F1FAE85DA0060FFFF /* HFE.cpp in Sources */, + 4B055AB91FAE86170060FFFF /* Acorn.cpp in Sources */, + 4B055A931FAE85B50060FFFF /* BinaryDump.cpp in Sources */, + 4B055A871FAE854F0060FFFF /* Tape.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4BB73E9A1B587A5100552FC2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -3182,6 +3383,44 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 4B055A6E1FAE763F0060FFFF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(USER_LIBRARY_DIR)/Frameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu11; + MACOSX_DEPLOYMENT_TARGET = 10.12; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 4B055A6F1FAE763F0060FFFF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(USER_LIBRARY_DIR)/Frameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu11; + MACOSX_DEPLOYMENT_TARGET = 10.12; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; 4BB73EC41B587A5100552FC2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -3294,6 +3533,10 @@ CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES; CODE_SIGN_ENTITLEMENTS = "Clock Signal/Clock Signal.entitlements"; COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(USER_LIBRARY_DIR)/Frameworks", + ); GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; @@ -3324,6 +3567,10 @@ CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES; CODE_SIGN_ENTITLEMENTS = "Clock Signal/Clock Signal.entitlements"; COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(USER_LIBRARY_DIR)/Frameworks", + ); GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; @@ -3408,6 +3655,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 4B055A701FAE763F0060FFFF /* Build configuration list for PBXNativeTarget "Clock Signal Kiosk" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4B055A6E1FAE763F0060FFFF /* Debug */, + 4B055A6F1FAE763F0060FFFF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 4BB73E991B587A5100552FC2 /* Build configuration list for PBXProject "Clock Signal" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp new file mode 100644 index 000000000..e207105ca --- /dev/null +++ b/OSBindings/SDL/main.cpp @@ -0,0 +1,65 @@ +// +// main.cpp +// Clock Signal +// +// Created by Thomas Harte on 04/11/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#include +#include + +#include "../../StaticAnalyser/StaticAnalyser.hpp" + +int main(int argc, char *argv[]) { + SDL_Window *window = nullptr; + + if(argc < 2) { + std::cerr << "Usage: " << argv[0] << " [file]" << std::endl; + return -1; + } + + std::list targets = StaticAnalyser::GetTargets(argv[1]); + if(targets.empty()) { + std::cerr << "Cannot open " << argv[1] << std::endl; + return -1; + } + + if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { + std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl; + return -1; + } + + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + window = SDL_CreateWindow( "Clock Signal", + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + 400, 300, + SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); + + if(!window) + { + std::cerr << "Could not create window" << std::endl; + return -1; + } + + bool should_quit = false; + while(!should_quit) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_QUIT: should_quit = true; break; + + case SDL_KEYDOWN: + break; + case SDL_KEYUP: + break; + } + } + } + + SDL_DestroyWindow( window ); + SDL_Quit(); + + return 0; +} From 1e1efcdcb8c0749efd77031c53220955f86d2d41 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 5 Nov 2017 12:49:28 -0500 Subject: [PATCH 02/14] Pushes far enough along the path of having the SDL version do work that it becomes obvious I've never figured out the correct course of action if there is no sound output. --- Machines/Utility/MachineForTarget.cpp | 56 +++++++++ Machines/Utility/MachineForTarget.hpp | 41 +++++++ .../Clock Signal.xcodeproj/project.pbxproj | 106 +++++++++++++++++- OSBindings/SDL/main.cpp | 78 ++++++++++++- 4 files changed, 276 insertions(+), 5 deletions(-) create mode 100644 Machines/Utility/MachineForTarget.cpp create mode 100644 Machines/Utility/MachineForTarget.hpp diff --git a/Machines/Utility/MachineForTarget.cpp b/Machines/Utility/MachineForTarget.cpp new file mode 100644 index 000000000..9638f340b --- /dev/null +++ b/Machines/Utility/MachineForTarget.cpp @@ -0,0 +1,56 @@ +// +// MachineForTarget.cpp +// Clock Signal +// +// Created by Thomas Harte on 04/11/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#include "MachineForTarget.hpp" + +#include "../AmstradCPC/AmstradCPC.hpp" +#include "../Atari2600/Atari2600.hpp" +#include "../Commodore/Vic-20/Vic20.hpp" +#include "../Electron/Electron.hpp" +#include "../Oric/Oric.hpp" +#include "../ZX8081/ZX8081.hpp" + +namespace { + +template class TypedDynamicMachine: public ::Machine::DynamicMachine { + public: + TypedDynamicMachine(T *machine) : machine_(machine) {} + + ConfigurationTarget::Machine *configuration_target() { + return dynamic_cast(machine_.get()); + } + + CRTMachine::Machine *crt_machine() { + return dynamic_cast(machine_.get()); + } + + JoystickMachine::Machine *joystick_machine() { + return dynamic_cast(machine_.get()); + } + + KeyboardMachine::Machine *keyboard_machine() { + return dynamic_cast(machine_.get()); + } + + private: + std::unique_ptr machine_; +}; + +} + +::Machine::DynamicMachine *::Machine::MachineForTarget(const StaticAnalyser::Target &target) { + switch(target.machine) { + case StaticAnalyser::Target::AmstradCPC: return new TypedDynamicMachine(AmstradCPC::Machine::AmstradCPC()); +// case StaticAnalyser::Target::Atari2600: return new TypedDynamicMachine(Atari2600::Machine::Atari2600()); +// case StaticAnalyser::Target::Electron: return new TypedDynamicMachine(Electron::Machine::Electron()); +// case StaticAnalyser::Target::Oric: return new TypedDynamicMachine(Oric::Machine::Oric()); +// case StaticAnalyser::Target::Vic20: return new TypedDynamicMachine(Commodore::Vic20::Machine::Vic20()); +// case StaticAnalyser::Target::ZX8081: return new TypedDynamicMachine(ZX8081::Machine::ZX8081(target)); + default: return nullptr; + } +} diff --git a/Machines/Utility/MachineForTarget.hpp b/Machines/Utility/MachineForTarget.hpp new file mode 100644 index 000000000..488382c35 --- /dev/null +++ b/Machines/Utility/MachineForTarget.hpp @@ -0,0 +1,41 @@ +// +// MachineForTarget.hpp +// Clock Signal +// +// Created by Thomas Harte on 04/11/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#ifndef MachineForTarget_hpp +#define MachineForTarget_hpp + +#include "../../StaticAnalyser/StaticAnalyser.hpp" + +#include "../ConfigurationTarget.hpp" +#include "../CRTMachine.hpp" +#include "../JoystickMachine.hpp" +#include "../KeyboardMachine.hpp" + +namespace Machine { + +/*! + Provides the structure for owning a machine and dynamically casting it as desired without knowledge of + the machine's parent class or, therefore, the need to establish a common one. +*/ +struct DynamicMachine { + virtual ConfigurationTarget::Machine *configuration_target() = 0; + virtual CRTMachine::Machine *crt_machine() = 0; + virtual JoystickMachine::Machine *joystick_machine() = 0; + virtual KeyboardMachine::Machine *keyboard_machine() = 0; +}; + +/*! + Allocates an instance of DynamicMachine holding a machine that can + receive the supplied target. The machine has been allocated on the heap. + It is the caller's responsibility to delete the class when finished. +*/ +DynamicMachine *MachineForTarget(const StaticAnalyser::Target &target); + +} + +#endif /* MachineForTarget_hpp */ diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 575d34c4e..dbf307ba2 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -74,6 +74,55 @@ 4B055ABB1FAE86170060FFFF /* Oric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805F91DCFF807003085B1 /* Oric.cpp */; }; 4B055ABC1FAE86170060FFFF /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBFBB6A1EE8401E00C01E7A /* ZX8081.cpp */; }; 4B055ABD1FAE86530060FFFF /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B69FB451C4D950F00B5F0AA /* libz.tbd */; }; + 4B055AC11FAE98DC0060FFFF /* MachineForTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B055ABE1FAE98000060FFFF /* MachineForTarget.cpp */; }; + 4B055AC21FAE9AE30060FFFF /* KeyboardMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */; }; + 4B055AC31FAE9AE80060FFFF /* AmstradCPC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B38F3461F2EC11D00D9235D /* AmstradCPC.cpp */; }; + 4B055AC41FAE9AE80060FFFF /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0C11F8D91CD0050900F /* Keyboard.cpp */; }; + 4B055AC51FAE9AEE0060FFFF /* Atari2600.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E2D971C3A06EC00138695 /* Atari2600.cpp */; }; + 4B055AC61FAE9AEE0060FFFF /* Speaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEA52641DF3472B007E74F2 /* Speaker.cpp */; }; + 4B055AC71FAE9AEE0060FFFF /* TIA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BE7C9161E3D397100A5496D /* TIA.cpp */; }; + 4B055AC81FAE9AFB0060FFFF /* C1540.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334941F5E25B60097E338 /* C1540.cpp */; }; + 4B055AC91FAE9AFB0060FFFF /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0C41F8D91D90050900F /* Keyboard.cpp */; }; + 4B055ACA1FAE9AFB0060FFFF /* Vic20.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC81F1D2C2425003C5BF8 /* Vic20.cpp */; }; + 4B055ACB1FAE9AFB0060FFFF /* SerialBus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */; }; + 4B055ACC1FAE9B030060FFFF /* Electron.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E2D9B1C3A070400138695 /* Electron.cpp */; }; + 4B055ACD1FAE9B030060FFFF /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0C61F8D91E50050900F /* Keyboard.cpp */; }; + 4B055ACE1FAE9B030060FFFF /* Plus3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B30512E1D98ACC600B4FED8 /* Plus3.cpp */; }; + 4B055ACF1FAE9B030060FFFF /* Speaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEA52611DF339D7007E74F2 /* Speaker.cpp */; }; + 4B055AD01FAE9B030060FFFF /* Tape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEA525D1DF33323007E74F2 /* Tape.cpp */; }; + 4B055AD11FAE9B030060FFFF /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7913CA1DFCD80E00175A82 /* Video.cpp */; }; + 4B055AD21FAE9B0B0060FFFF /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BD1F8D8F450050900F /* Keyboard.cpp */; }; + 4B055AD31FAE9B0B0060FFFF /* Microdisc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5FADBE1DE3BF2B00AEC565 /* Microdisc.cpp */; }; + 4B055AD41FAE9B0B0060FFFF /* Oric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF1FA21DADC3DD0039D2E7 /* Oric.cpp */; }; + 4B055AD51FAE9B0B0060FFFF /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2BFDB01DAEF5FF001A68B8 /* Video.cpp */; }; + 4B055AD61FAE9B130060FFFF /* MemoryFuzzer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2B3A481F9B8FA70062DABF /* MemoryFuzzer.cpp */; }; + 4B055AD71FAE9B180060FFFF /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0CA1F8D92580050900F /* Keyboard.cpp */; }; + 4B055AD81FAE9B180060FFFF /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD3A3091EE755C800B5B501 /* Video.cpp */; }; + 4B055AD91FAE9B180060FFFF /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1497901EE4B5A800CE2596 /* ZX8081.cpp */; }; + 4B055ADA1FAE9B460060FFFF /* 1770.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD468F51D8DF41D0084958B /* 1770.cpp */; }; + 4B055ADB1FAE9B460060FFFF /* 6560.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC9DF4D1D04691600F44158 /* 6560.cpp */; }; + 4B055ADC1FAE9B460060FFFF /* AY38910.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4A762E1DB1A3FA007AAE2E /* AY38910.cpp */; }; + 4B055ADD1FAE9B460060FFFF /* i8272.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBC951C1F368D83008F4C34 /* i8272.cpp */; }; + 4B055ADE1FAE9B4C0060FFFF /* 6522Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B83348B1F5DB99C0097E338 /* 6522Base.cpp */; }; + 4B055ADF1FAE9B4C0060FFFF /* IRQDelegatePortHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334891F5DB94B0097E338 /* IRQDelegatePortHandler.cpp */; }; + 4B055AE01FAE9B660060FFFF /* CRT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CCC421C62D0B3001CAC5F /* CRT.cpp */; }; + 4B055AE11FAE9B6F0060FFFF /* ArrayBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5073051DDD3B9400C48FBD /* ArrayBuilder.cpp */; }; + 4B055AE21FAE9B6F0060FFFF /* CRTOpenGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF990A1C8FBA6F0075DAFB /* CRTOpenGL.cpp */; }; + 4B055AE31FAE9B6F0060FFFF /* TextureBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99081C8FBA6F0075DAFB /* TextureBuilder.cpp */; }; + 4B055AE41FAE9B6F0060FFFF /* TextureTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99121C8FBA6F0075DAFB /* TextureTarget.cpp */; }; + 4B055AE51FAE9B6F0060FFFF /* IntermediateShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB142F1CD2CECE00BDB55C /* IntermediateShader.cpp */; }; + 4B055AE61FAE9B6F0060FFFF /* OutputShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B7501CD1956900F86E85 /* OutputShader.cpp */; }; + 4B055AE71FAE9B6F0060FFFF /* Shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B74D1CD194CC00F86E85 /* Shader.cpp */; }; + 4B055AE81FAE9B7B0060FFFF /* FIRFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC76E671C98E31700E6EF73 /* FIRFilter.cpp */; }; + 4B055AE91FAE9B990060FFFF /* 6502Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */; }; + 4B055AEA1FAE9B990060FFFF /* 6502Storage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334851F5DA3780097E338 /* 6502Storage.cpp */; }; + 4B055AEB1FAE9BA20060FFFF /* PartialMachineCycle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334811F5D9FF70097E338 /* PartialMachineCycle.cpp */; }; + 4B055AEC1FAE9BA20060FFFF /* Z80Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B322E031F5A2E3C004EB04C /* Z80Base.cpp */; }; + 4B055AED1FAE9BA20060FFFF /* Z80Storage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334831F5DA0360097E338 /* Z80Storage.cpp */; }; + 4B055AEE1FAE9BBF0060FFFF /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B86E2591F8C628F006FAA45 /* Keyboard.cpp */; }; + 4B055AEF1FAE9BF00060FFFF /* Typer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2B3A471F9B8FA70062DABF /* Typer.cpp */; }; + 4B055AF11FAE9C160060FFFF /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BC76E6A1C98F43700E6EF73 /* Accelerate.framework */; }; + 4B055AF21FAE9C1C0060FFFF /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B055AF01FAE9C080060FFFF /* OpenGL.framework */; }; 4B08A2751EE35D56008B7065 /* Z80InterruptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */; }; 4B08A2781EE39306008B7065 /* TestMachine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B08A2771EE39306008B7065 /* TestMachine.mm */; }; 4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CCC421C62D0B3001CAC5F /* CRT.cpp */; }; @@ -563,8 +612,11 @@ 4B046DC31CFE651500E9E45E /* CRTMachine.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRTMachine.hpp; sourceTree = ""; }; 4B049CDC1DA3C82F00322067 /* BCDTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BCDTest.swift; sourceTree = ""; }; 4B055A6A1FAE763F0060FFFF /* Clock Signal Kiosk */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Clock Signal Kiosk"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4B055A771FAE78210060FFFF /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = ../../../../Library/Frameworks/SDL2.framework; sourceTree = ""; }; + 4B055A771FAE78210060FFFF /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = ../../../../Library/Frameworks/SDL2.framework; sourceTree = SOURCE_ROOT; }; 4B055A7C1FAE84A50060FFFF /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 4B055ABE1FAE98000060FFFF /* MachineForTarget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MachineForTarget.cpp; sourceTree = ""; }; + 4B055ABF1FAE98000060FFFF /* MachineForTarget.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MachineForTarget.hpp; sourceTree = ""; }; + 4B055AF01FAE9C080060FFFF /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; 4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80InterruptTests.swift; sourceTree = ""; }; 4B08A2761EE39306008B7065 /* TestMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestMachine.h; sourceTree = ""; }; 4B08A2771EE39306008B7065 /* TestMachine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestMachine.mm; sourceTree = ""; }; @@ -1218,6 +1270,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 4B055AF21FAE9C1C0060FFFF /* OpenGL.framework in Frameworks */, + 4B055AF11FAE9C160060FFFF /* Accelerate.framework in Frameworks */, 4B055ABD1FAE86530060FFFF /* libz.tbd in Frameworks */, 4B055A7A1FAE78A00060FFFF /* SDL2.framework in Frameworks */, ); @@ -1252,6 +1306,7 @@ 4B055A761FAE78210060FFFF /* Frameworks */ = { isa = PBXGroup; children = ( + 4B055AF01FAE9C080060FFFF /* OpenGL.framework */, 4B055A771FAE78210060FFFF /* SDL2.framework */, ); name = Frameworks; @@ -1406,6 +1461,8 @@ 4B2B3A461F9B8FA70062DABF /* Utility */ = { isa = PBXGroup; children = ( + 4B055ABE1FAE98000060FFFF /* MachineForTarget.cpp */, + 4B055ABF1FAE98000060FFFF /* MachineForTarget.hpp */, 4B2B3A471F9B8FA70062DABF /* Typer.cpp */, 4B2B3A481F9B8FA70062DABF /* MemoryFuzzer.cpp */, 4B2B3A491F9B8FA70062DABF /* MemoryFuzzer.hpp */, @@ -3050,24 +3107,41 @@ files = ( 4B055AAA1FAE85F50060FFFF /* CPM.cpp in Sources */, 4B055A9A1FAE85CB0060FFFF /* MFMDiskController.cpp in Sources */, + 4B055ACB1FAE9AFB0060FFFF /* SerialBus.cpp in Sources */, 4B055AA41FAE85E50060FFFF /* DigitalPhaseLockedLoop.cpp in Sources */, + 4B055AE61FAE9B6F0060FFFF /* OutputShader.cpp in Sources */, 4B055A9B1FAE85DA0060FFFF /* AcornADF.cpp in Sources */, + 4B055AD51FAE9B0B0060FFFF /* Video.cpp in Sources */, 4B055A811FAE853A0060FFFF /* Disk.cpp in Sources */, + 4B055AE11FAE9B6F0060FFFF /* ArrayBuilder.cpp in Sources */, 4B055AA51FAE85EF0060FFFF /* Encoder.cpp in Sources */, + 4B055AEA1FAE9B990060FFFF /* 6502Storage.cpp in Sources */, 4B055A8A1FAE855B0060FFFF /* Tape.cpp in Sources */, 4B055AA71FAE85EF0060FFFF /* SegmentParser.cpp in Sources */, + 4B055AC11FAE98DC0060FFFF /* MachineForTarget.cpp in Sources */, + 4B055AD81FAE9B180060FFFF /* Video.cpp in Sources */, + 4B055AE51FAE9B6F0060FFFF /* IntermediateShader.cpp in Sources */, 4B055A851FAE85480060FFFF /* File.cpp in Sources */, + 4B055AD31FAE9B0B0060FFFF /* Microdisc.cpp in Sources */, 4B055AB41FAE860F0060FFFF /* OricTAP.cpp in Sources */, 4B055AB71FAE860F0060FFFF /* TZX.cpp in Sources */, 4B055A8C1FAE85670060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055ADA1FAE9B460060FFFF /* 1770.cpp in Sources */, + 4B055ADC1FAE9B460060FFFF /* AY38910.cpp in Sources */, + 4B055AD71FAE9B180060FFFF /* Keyboard.cpp in Sources */, 4B055AB61FAE860F0060FFFF /* TapeUEF.cpp in Sources */, 4B055A9D1FAE85DA0060FFFF /* D64.cpp in Sources */, 4B055ABB1FAE86170060FFFF /* Oric.cpp in Sources */, + 4B055AE81FAE9B7B0060FFFF /* FIRFilter.cpp in Sources */, 4B055A901FAE85A90060FFFF /* TimedEventLoop.cpp in Sources */, 4B055AAB1FAE85FD0060FFFF /* PCMPatchedTrack.cpp in Sources */, + 4B055AC71FAE9AEE0060FFFF /* TIA.cpp in Sources */, + 4B055AD21FAE9B0B0060FFFF /* Keyboard.cpp in Sources */, 4B055AA31FAE85DF0060FFFF /* ImplicitSectors.cpp in Sources */, 4B055AAE1FAE85FD0060FFFF /* TrackSerialiser.cpp in Sources */, 4B055A981FAE85C50060FFFF /* Drive.cpp in Sources */, + 4B055AE21FAE9B6F0060FFFF /* CRTOpenGL.cpp in Sources */, + 4B055AC31FAE9AE80060FFFF /* AmstradCPC.cpp in Sources */, 4B055A9E1FAE85DA0060FFFF /* G64.cpp in Sources */, 4B055AB81FAE860F0060FFFF /* ZX80O81P.cpp in Sources */, 4B055A8E1FAE85920060FFFF /* BestEffortUpdater.cpp in Sources */, @@ -3075,41 +3149,71 @@ 4B055A801FAE85350060FFFF /* StaticAnalyser.cpp in Sources */, 4B055AAC1FAE85FD0060FFFF /* PCMSegment.cpp in Sources */, 4B055AB31FAE860F0060FFFF /* CSW.cpp in Sources */, + 4B055ACF1FAE9B030060FFFF /* Speaker.cpp in Sources */, + 4B055AEE1FAE9BBF0060FFFF /* Keyboard.cpp in Sources */, 4B055A881FAE85530060FFFF /* Disassembler6502.cpp in Sources */, + 4B055AED1FAE9BA20060FFFF /* Z80Storage.cpp in Sources */, + 4B055AD11FAE9B030060FFFF /* Video.cpp in Sources */, 4B055AA21FAE85DA0060FFFF /* SSD.cpp in Sources */, + 4B055ADD1FAE9B460060FFFF /* i8272.cpp in Sources */, + 4B055AC51FAE9AEE0060FFFF /* Atari2600.cpp in Sources */, 4B055A9C1FAE85DA0060FFFF /* CPCDSK.cpp in Sources */, + 4B055AE41FAE9B6F0060FFFF /* TextureTarget.cpp in Sources */, 4B055ABA1FAE86170060FFFF /* Commodore.cpp in Sources */, 4B055AA61FAE85EF0060FFFF /* Parser.cpp in Sources */, + 4B055AE91FAE9B990060FFFF /* 6502Base.cpp in Sources */, 4B055A861FAE854C0060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055AEF1FAE9BF00060FFFF /* Typer.cpp in Sources */, + 4B055ACA1FAE9AFB0060FFFF /* Vic20.cpp in Sources */, 4B055ABC1FAE86170060FFFF /* ZX8081.cpp in Sources */, + 4B055AC91FAE9AFB0060FFFF /* Keyboard.cpp in Sources */, 4B055A991FAE85CB0060FFFF /* DiskController.cpp in Sources */, + 4B055ACC1FAE9B030060FFFF /* Electron.cpp in Sources */, 4B055AB11FAE86070060FFFF /* Tape.cpp in Sources */, 4B055AA91FAE85EF0060FFFF /* CommodoreGCR.cpp in Sources */, 4B055A7F1FAE852F0060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055ADB1FAE9B460060FFFF /* 6560.cpp in Sources */, 4B055AA01FAE85DA0060FFFF /* MFMSectorDump.cpp in Sources */, 4B055AA11FAE85DA0060FFFF /* OricMFMDSK.cpp in Sources */, 4B055A951FAE85BB0060FFFF /* BitReverse.cpp in Sources */, 4B055A891FAE85580060FFFF /* StaticAnalyser.cpp in Sources */, + 4B055ACE1FAE9B030060FFFF /* Plus3.cpp in Sources */, 4B055A8D1FAE85920060FFFF /* AsyncTaskQueue.cpp in Sources */, + 4B055AC41FAE9AE80060FFFF /* Keyboard.cpp in Sources */, 4B055A941FAE85B50060FFFF /* CommodoreROM.cpp in Sources */, 4B055A971FAE85BB0060FFFF /* ZX8081.cpp in Sources */, 4B055AAD1FAE85FD0060FFFF /* PCMTrack.cpp in Sources */, 4B055A841FAE85450060FFFF /* Disk.cpp in Sources */, 4B055A831FAE85410060FFFF /* Tape.cpp in Sources */, + 4B055AC61FAE9AEE0060FFFF /* Speaker.cpp in Sources */, 4B055AA81FAE85EF0060FFFF /* Shifter.cpp in Sources */, + 4B055AC81FAE9AFB0060FFFF /* C1540.cpp in Sources */, 4B055A8F1FAE85A90060FFFF /* FileHolder.cpp in Sources */, 4B055A911FAE85B50060FFFF /* Cartridge.cpp in Sources */, + 4B055ACD1FAE9B030060FFFF /* Keyboard.cpp in Sources */, 4B055A8B1FAE85670060FFFF /* StaticAnalyser.cpp in Sources */, 4B055AB21FAE860F0060FFFF /* CommodoreTAP.cpp in Sources */, + 4B055ADF1FAE9B4C0060FFFF /* IRQDelegatePortHandler.cpp in Sources */, 4B055AB51FAE860F0060FFFF /* TapePRG.cpp in Sources */, + 4B055AE01FAE9B660060FFFF /* CRT.cpp in Sources */, + 4B055AD01FAE9B030060FFFF /* Tape.cpp in Sources */, 4B055A961FAE85BB0060FFFF /* Commodore.cpp in Sources */, + 4B055ADE1FAE9B4C0060FFFF /* 6522Base.cpp in Sources */, + 4B055AD41FAE9B0B0060FFFF /* Oric.cpp in Sources */, 4B055A821FAE853D0060FFFF /* StaticAnalyser.cpp in Sources */, 4B055A921FAE85B50060FFFF /* PRG.cpp in Sources */, 4B055AAF1FAE85FD0060FFFF /* UnformattedTrack.cpp in Sources */, 4B055A7E1FAE84AA0060FFFF /* main.cpp in Sources */, 4B055A9F1FAE85DA0060FFFF /* HFE.cpp in Sources */, + 4B055AE71FAE9B6F0060FFFF /* Shader.cpp in Sources */, + 4B055AEC1FAE9BA20060FFFF /* Z80Base.cpp in Sources */, + 4B055AE31FAE9B6F0060FFFF /* TextureBuilder.cpp in Sources */, 4B055AB91FAE86170060FFFF /* Acorn.cpp in Sources */, 4B055A931FAE85B50060FFFF /* BinaryDump.cpp in Sources */, + 4B055AD61FAE9B130060FFFF /* MemoryFuzzer.cpp in Sources */, + 4B055AC21FAE9AE30060FFFF /* KeyboardMachine.cpp in Sources */, + 4B055AD91FAE9B180060FFFF /* ZX8081.cpp in Sources */, + 4B055AEB1FAE9BA20060FFFF /* PartialMachineCycle.cpp in Sources */, 4B055A871FAE854F0060FFFF /* Tape.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index e207105ca..9e3dda043 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -7,31 +7,84 @@ // #include +#include #include #include "../../StaticAnalyser/StaticAnalyser.hpp" +#include "../../Machines/Utility/MachineForTarget.hpp" + +#include "../../Machines/ConfigurationTarget.hpp" +#include "../../Machines/CRTMachine.hpp" + +#include "../../Concurrency/BestEffortUpdater.hpp" + +namespace { + +struct CRTMachineDelegate: public CRTMachine::Machine::Delegate { + + void machine_did_change_clock_rate(CRTMachine::Machine *machine) { + best_effort_updater->set_clock_rate(machine->get_clock_rate()); + } + + void machine_did_change_clock_is_unlimited(CRTMachine::Machine *machine) { + } + + Concurrency::BestEffortUpdater *best_effort_updater; +}; + +struct BestEffortUpdaterDelegate: public Concurrency::BestEffortUpdater::Delegate { + + void update(Concurrency::BestEffortUpdater *updater, int cycles, bool did_skip_previous_update) { + machine->crt_machine()->run_for(Cycles(cycles)); + } + + Machine::DynamicMachine *machine; +}; + +} int main(int argc, char *argv[]) { SDL_Window *window = nullptr; + // Perform a sanity check on arguments. if(argc < 2) { std::cerr << "Usage: " << argv[0] << " [file]" << std::endl; return -1; } - + + // Determine the machine for the supplied file. std::list targets = StaticAnalyser::GetTargets(argv[1]); if(targets.empty()) { std::cerr << "Cannot open " << argv[1] << std::endl; return -1; } + Concurrency::BestEffortUpdater updater; + BestEffortUpdaterDelegate best_effort_updater_delegate; + CRTMachineDelegate crt_delegate; + + // Create and configure a machine. + std::unique_ptr<::Machine::DynamicMachine> machine(::Machine::MachineForTarget(targets.front())); + machine->configuration_target()->configure_as_target(targets.front()); + + crt_delegate.best_effort_updater = &updater; + best_effort_updater_delegate.machine = machine.get(); + + machine->crt_machine()->set_delegate(&crt_delegate); + updater.set_delegate(&best_effort_updater_delegate); + + // Attempt to set up video and audio. if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl; return -1; } + // Ask for no depth buffer, a core profile and vsync-aligned rendering. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetSwapInterval(1); + window = SDL_CreateWindow( "Clock Signal", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 400, 300, @@ -43,21 +96,38 @@ int main(int argc, char *argv[]) { return -1; } + SDL_GLContext gl_context = SDL_GL_CreateContext(window); + SDL_GL_MakeCurrent(window, gl_context); + + // Setup output, assuming a CRT machine for now, and prepare a best-effort updater. + machine->crt_machine()->setup_output(4.0 / 3.0); + + // Run the main event loop until the OS tells us to quit. bool should_quit = false; while(!should_quit) { + // Process all pending events. SDL_Event event; - while (SDL_PollEvent(&event)) { + while(SDL_PollEvent(&event)) { switch(event.type) { + default: std::cout << "Unhandled " << event.type << std::endl; break; case SDL_QUIT: should_quit = true; break; - + case SDL_KEYDOWN: break; case SDL_KEYUP: break; } } + + // Display a new frame and wait for vsync. + updater.update(); + int width, height; + SDL_GetWindowSize(window, &width, &height); + machine->crt_machine()->get_crt()->draw_frame(static_cast(width), static_cast(height), true); + SDL_GL_SwapWindow(window); } - + + // Clean up. SDL_DestroyWindow( window ); SDL_Quit(); From 512e877d066fb1431bb5f8d145953d88cbd012c7 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 5 Nov 2017 20:11:18 -0500 Subject: [PATCH 03/14] Ensures proper initialisation of the delegate pointer. --- Outputs/Speaker.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Outputs/Speaker.hpp b/Outputs/Speaker.hpp index 9eb18ce86..868fb5967 100644 --- a/Outputs/Speaker.hpp +++ b/Outputs/Speaker.hpp @@ -109,7 +109,7 @@ class Speaker { size_t buffer_in_progress_pointer_; size_t number_of_taps_, requested_number_of_taps_; bool coefficients_are_dirty_; - Delegate *delegate_; + Delegate *delegate_ = nullptr; float input_cycles_per_second_, output_cycles_per_second_; From 0116d7f071936b15abc31003c1f70635812f541d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 5 Nov 2017 20:12:01 -0500 Subject: [PATCH 04/14] Added a platform-neutral route for feeding ROMs to machines, in a platform-dependant fashion; implemented for the CPC. --- Machines/AmstradCPC/AmstradCPC.cpp | 18 ++++++++++ Machines/CRTMachine.hpp | 5 +++ Machines/Utility/MachineForTarget.cpp | 22 ++++++++---- Machines/Utility/MachineForTarget.hpp | 9 +++++ OSBindings/SDL/main.cpp | 51 ++++++++++++++++++++++++--- 5 files changed, 95 insertions(+), 10 deletions(-) diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index 01cc1c2d3..fbe4bf05f 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -923,6 +923,24 @@ class ConcreteMachine: roms_[static_cast(type)] = data; } + // Obtains the system ROMs. + bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) override { + const char *os_files[] = { + "os464.rom", "basic464.rom", + "os664.rom", "basic664.rom", + "os6128.rom", "basic6128.rom", + "amsdos.rom" + }; + + for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) { + auto data = rom_with_name("AmstradCPC", os_files[index]); + if(!data) return false; + set_rom(static_cast(index), *data); + } + + return true; + } + void set_component_is_sleeping(void *component, bool is_sleeping) override final { fdc_is_sleeping_ = fdc_.is_sleeping(); tape_player_is_sleeping_ = tape_player_.is_sleeping(); diff --git a/Machines/CRTMachine.hpp b/Machines/CRTMachine.hpp index 96f2ba7fd..6c5fb346c 100644 --- a/Machines/CRTMachine.hpp +++ b/Machines/CRTMachine.hpp @@ -35,6 +35,11 @@ class Machine { OpenGL context is bound. */ virtual void close_output() = 0; + + /*! + Provides the machine with a way to obtain such ROMs as it needs. + */ + virtual bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) { return true; } /// @returns The CRT this machine is drawing to. Should not be @c nullptr. virtual std::shared_ptr get_crt() = 0; diff --git a/Machines/Utility/MachineForTarget.cpp b/Machines/Utility/MachineForTarget.cpp index 9638f340b..3bd1ed25d 100644 --- a/Machines/Utility/MachineForTarget.cpp +++ b/Machines/Utility/MachineForTarget.cpp @@ -46,11 +46,21 @@ template class TypedDynamicMachine: public ::Machine::DynamicMachine ::Machine::DynamicMachine *::Machine::MachineForTarget(const StaticAnalyser::Target &target) { switch(target.machine) { case StaticAnalyser::Target::AmstradCPC: return new TypedDynamicMachine(AmstradCPC::Machine::AmstradCPC()); -// case StaticAnalyser::Target::Atari2600: return new TypedDynamicMachine(Atari2600::Machine::Atari2600()); -// case StaticAnalyser::Target::Electron: return new TypedDynamicMachine(Electron::Machine::Electron()); -// case StaticAnalyser::Target::Oric: return new TypedDynamicMachine(Oric::Machine::Oric()); -// case StaticAnalyser::Target::Vic20: return new TypedDynamicMachine(Commodore::Vic20::Machine::Vic20()); -// case StaticAnalyser::Target::ZX8081: return new TypedDynamicMachine(ZX8081::Machine::ZX8081(target)); - default: return nullptr; + case StaticAnalyser::Target::Atari2600: return new TypedDynamicMachine(Atari2600::Machine::Atari2600()); + case StaticAnalyser::Target::Electron: return new TypedDynamicMachine(Electron::Machine::Electron()); + case StaticAnalyser::Target::Oric: return new TypedDynamicMachine(Oric::Machine::Oric()); + case StaticAnalyser::Target::Vic20: return new TypedDynamicMachine(Commodore::Vic20::Machine::Vic20()); + case StaticAnalyser::Target::ZX8081: return new TypedDynamicMachine(ZX8081::Machine::ZX8081(target)); + } +} + +std::string Machine::NameForTarget(const StaticAnalyser::Target &target) { + switch(target.machine) { + case StaticAnalyser::Target::AmstradCPC: return "AmstradCPC"; + case StaticAnalyser::Target::Atari2600: return "Atari2600"; + case StaticAnalyser::Target::Electron: return "Electron"; + case StaticAnalyser::Target::Oric: return "Oric"; + case StaticAnalyser::Target::Vic20: return "Vic20"; + case StaticAnalyser::Target::ZX8081: return "ZX8081"; } } diff --git a/Machines/Utility/MachineForTarget.hpp b/Machines/Utility/MachineForTarget.hpp index 488382c35..14adcecf7 100644 --- a/Machines/Utility/MachineForTarget.hpp +++ b/Machines/Utility/MachineForTarget.hpp @@ -16,6 +16,8 @@ #include "../JoystickMachine.hpp" #include "../KeyboardMachine.hpp" +#include + namespace Machine { /*! @@ -36,6 +38,13 @@ struct DynamicMachine { */ DynamicMachine *MachineForTarget(const StaticAnalyser::Target &target); +/*! + Returns a short string name for the machine identified by the target, + which is guaranteed not to have any spaces or other potentially + filesystem-bothering contents. +*/ +std::string NameForTarget(const StaticAnalyser::Target &target); + } #endif /* MachineForTarget_hpp */ diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index 9e3dda043..af170e8ef 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -8,6 +8,8 @@ #include #include +#include + #include #include "../../StaticAnalyser/StaticAnalyser.hpp" @@ -65,8 +67,8 @@ int main(int argc, char *argv[]) { // Create and configure a machine. std::unique_ptr<::Machine::DynamicMachine> machine(::Machine::MachineForTarget(targets.front())); - machine->configuration_target()->configure_as_target(targets.front()); - + + updater.set_clock_rate(machine->crt_machine()->get_clock_rate()); crt_delegate.best_effort_updater = &updater; best_effort_updater_delegate.machine = machine.get(); @@ -98,9 +100,50 @@ int main(int argc, char *argv[]) { SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GL_MakeCurrent(window, gl_context); + + // Create an audio pipe. +// SDL_AudioSpec desired_audio_spec; +// SDL_AudioSpec obtained_audio_spec; +// desired_audio_spec.freq = 192000; // An arbitrary high number. +// desired_audio_spec.format = AUDIO_S16; +// desired_audio_spec.channels = 1; // Setup output, assuming a CRT machine for now, and prepare a best-effort updater. machine->crt_machine()->setup_output(4.0 / 3.0); + machine->crt_machine()->get_crt()->set_output_gamma(2.2f); + + // For vanilla SDL purposes, assume system ROMs can be found in one of: + // + // /usr/local/share/CLK/[system]; or + // /usr/share/CLK/[system] + machine->crt_machine()->install_roms( [] (const std::string &machine, const std::string &name) -> std::unique_ptr> { + std::string local_path = "/usr/local/share/CLK/" + machine + "/" + name; + FILE *file = fopen(local_path.c_str(), "r"); + if(!file) { + std::string path = "/usr/share/CLK/" + machine + "/" + name; + file = fopen(path.c_str(), "r"); + } + + if(!file) return nullptr; + + std::unique_ptr> data(new std::vector); + + fseek(file, 0, SEEK_END); + data->resize(ftell(file)); + fseek(file, 0, SEEK_SET); + fread(data->data(), 1, data->size(), file); + fclose(file); + + return data; + }); + + machine->configuration_target()->configure_as_target(targets.front()); + + // For now, lie about audio output intentions. + auto speaker = machine->crt_machine()->get_speaker(); + if(speaker) { + speaker->set_output_rate(44100, 1024); + } // Run the main event loop until the OS tells us to quit. bool should_quit = false; @@ -109,7 +152,7 @@ int main(int argc, char *argv[]) { SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { - default: std::cout << "Unhandled " << event.type << std::endl; break; +// default: std::cout << "Unhandled " << event.type << std::endl; break; case SDL_QUIT: should_quit = true; break; case SDL_KEYDOWN: @@ -123,7 +166,7 @@ int main(int argc, char *argv[]) { updater.update(); int width, height; SDL_GetWindowSize(window, &width, &height); - machine->crt_machine()->get_crt()->draw_frame(static_cast(width), static_cast(height), true); + machine->crt_machine()->get_crt()->draw_frame(static_cast(width), static_cast(height), false); SDL_GL_SwapWindow(window); } From a209ae76ca074e8a7a7310b9c598e6427ac12665 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 5 Nov 2017 21:16:14 -0500 Subject: [PATCH 05/14] Adds keyboard input from SDL. --- OSBindings/SDL/main.cpp | 69 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index af170e8ef..72e5179e8 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -43,6 +43,67 @@ struct BestEffortUpdaterDelegate: public Concurrency::BestEffortUpdater::Delegat Machine::DynamicMachine *machine; }; +bool KeyboardKeyForSDLScancode(SDL_Keycode scancode, Inputs::Keyboard::Key &key) { +#define BIND(x, y) case SDL_SCANCODE_##x: key = Inputs::Keyboard::Key::y; break; + switch(scancode) { + default: return false; + + BIND(F1, F1) BIND(F2, F2) BIND(F3, F3) BIND(F4, F4) BIND(F5, F5) BIND(F6, F6) + BIND(F7, F7) BIND(F8, F8) BIND(F9, F9) BIND(F10, F10) BIND(F11, F11) BIND(F12, F12) + + BIND(1, k1) BIND(2, k2) BIND(3, k3) BIND(4, k4) BIND(5, k5) + BIND(6, k6) BIND(7, k7) BIND(8, k8) BIND(9, k9) BIND(0, k0) + + BIND(Q, Q) BIND(W, W) BIND(E, E) BIND(R, R) BIND(T, T) + BIND(Y, Y) BIND(U, U) BIND(I, I) BIND(O, O) BIND(P, P) + BIND(A, A) BIND(S, S) BIND(D, D) BIND(F, F) BIND(G, G) + BIND(H, H) BIND(J, J) BIND(K, K) BIND(L, L) + BIND(Z, Z) BIND(X, X) BIND(C, C) BIND(V, V) + BIND(B, B) BIND(N, N) BIND(M, M) + + BIND(KP_7, KeyPad7) BIND(KP_8, KeyPad8) BIND(KP_9, KeyPad9) + BIND(KP_4, KeyPad4) BIND(KP_5, KeyPad5) BIND(KP_6, KeyPad6) + BIND(KP_1, KeyPad1) BIND(KP_2, KeyPad2) BIND(KP_3, KeyPad3) + BIND(KP_0, KeyPad0) + + BIND(ESCAPE, Escape) + + BIND(PRINTSCREEN, PrintScreen) BIND(SCROLLLOCK, ScrollLock) BIND(PAUSE, Pause) + + BIND(GRAVE, BackTick) BIND(MINUS, Hyphen) BIND(EQUALS, Equals) BIND(BACKSPACE, BackSpace) + + BIND(TAB, Tab) + BIND(LEFTBRACKET, OpenSquareBracket) BIND(RIGHTBRACKET, CloseSquareBracket) + BIND(BACKSLASH, BackSlash) + + BIND(CAPSLOCK, CapsLock) BIND(SEMICOLON, Semicolon) + BIND(APOSTROPHE, Quote) BIND(RETURN, Enter) + + BIND(LSHIFT, LeftShift) BIND(COMMA, Comma) BIND(PERIOD, FullStop) + BIND(SLASH, ForwardSlash) BIND(RSHIFT, RightShift) + + BIND(LCTRL, LeftControl) BIND(LALT, LeftOption) BIND(LGUI, LeftMeta) + BIND(SPACE, Space) + BIND(RCTRL, RightControl) BIND(RALT, RightOption) BIND(RGUI, RightMeta) + + BIND(LEFT, Left) BIND(RIGHT, Right) BIND(UP, Up) BIND(DOWN, Down) + + BIND(INSERT, Insert) BIND(HOME, Home) BIND(PAGEUP, PageUp) + BIND(DELETE, Delete) BIND(END, End) BIND(PAGEDOWN, PageDown) + + BIND(NUMLOCKCLEAR, NumLock) BIND(KP_DIVIDE, KeyPadSlash) BIND(KP_MULTIPLY, KeyPadAsterisk) + BIND(KP_PLUS, KeyPadPlus) BIND(KP_MINUS, KeyPadMinus) BIND(KP_ENTER, KeyPadEnter) + BIND(KP_DECIMAL, KeyPadDecimalPoint) + BIND(KP_EQUALS, KeyPadEquals) + BIND(HELP, Help) + +// BIND(HASH, Hash) +// BIND(KP_DELE, KeyPadAsterisk) + } +#undef BIND + return true; +} + } int main(int argc, char *argv[]) { @@ -152,12 +213,16 @@ int main(int argc, char *argv[]) { SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { -// default: std::cout << "Unhandled " << event.type << std::endl; break; case SDL_QUIT: should_quit = true; break; case SDL_KEYDOWN: - break; case SDL_KEYUP: + KeyboardMachine::Machine *keyboard_machine = machine->keyboard_machine(); + if(!keyboard_machine) break; + + Inputs::Keyboard::Key key = Inputs::Keyboard::Key::Space; + if(!KeyboardKeyForSDLScancode(event.key.keysym.scancode, key)) break; + keyboard_machine->get_keyboard().set_key_pressed(key, event.type == SDL_KEYDOWN); break; } } From 13406fedd8468988cff8eb42ee81c535b87419a1 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 5 Nov 2017 21:29:20 -0500 Subject: [PATCH 06/14] Explains commenting. --- OSBindings/SDL/main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index 72e5179e8..714a7bb72 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -97,8 +97,7 @@ bool KeyboardKeyForSDLScancode(SDL_Keycode scancode, Inputs::Keyboard::Key &key) BIND(KP_EQUALS, KeyPadEquals) BIND(HELP, Help) -// BIND(HASH, Hash) -// BIND(KP_DELE, KeyPadAsterisk) + // SDL doesn't seem to have scancodes for hash or keypad delete? } #undef BIND return true; From 4b68c372c6bd069825fe4fb21dd24ec87de948bd Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 5 Nov 2017 22:29:25 -0500 Subject: [PATCH 07/14] Adds a first attempt at audio via SDL. --- OSBindings/SDL/main.cpp | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index 714a7bb72..35be65aba 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -23,7 +23,6 @@ namespace { struct CRTMachineDelegate: public CRTMachine::Machine::Delegate { - void machine_did_change_clock_rate(CRTMachine::Machine *machine) { best_effort_updater->set_clock_rate(machine->get_clock_rate()); } @@ -35,7 +34,6 @@ struct CRTMachineDelegate: public CRTMachine::Machine::Delegate { }; struct BestEffortUpdaterDelegate: public Concurrency::BestEffortUpdater::Delegate { - void update(Concurrency::BestEffortUpdater *updater, int cycles, bool did_skip_previous_update) { machine->crt_machine()->run_for(Cycles(cycles)); } @@ -43,6 +41,20 @@ struct BestEffortUpdaterDelegate: public Concurrency::BestEffortUpdater::Delegat Machine::DynamicMachine *machine; }; +// This is set to a relatively large number for now. +const int AudioBufferSize = 1024; + +struct SpeakerDelegate: public Outputs::Speaker::Delegate { + void speaker_did_complete_samples(Outputs::Speaker *speaker, const std::vector &buffer) { + if(SDL_GetQueuedAudioSize(audio_device) < AudioBufferSize*3) + SDL_QueueAudio(audio_device, reinterpret_cast(buffer.data()), static_cast(buffer.size() * sizeof(uint16_t))); + updater->update(); + } + + SDL_AudioDeviceID audio_device; + Concurrency::BestEffortUpdater *updater; +}; + bool KeyboardKeyForSDLScancode(SDL_Keycode scancode, Inputs::Keyboard::Key &key) { #define BIND(x, y) case SDL_SCANCODE_##x: key = Inputs::Keyboard::Key::y; break; switch(scancode) { @@ -124,6 +136,7 @@ int main(int argc, char *argv[]) { Concurrency::BestEffortUpdater updater; BestEffortUpdaterDelegate best_effort_updater_delegate; CRTMachineDelegate crt_delegate; + SpeakerDelegate speaker_delegate; // Create and configure a machine. std::unique_ptr<::Machine::DynamicMachine> machine(::Machine::MachineForTarget(targets.front())); @@ -131,6 +144,7 @@ int main(int argc, char *argv[]) { updater.set_clock_rate(machine->crt_machine()->get_clock_rate()); crt_delegate.best_effort_updater = &updater; best_effort_updater_delegate.machine = machine.get(); + speaker_delegate.updater = &updater; machine->crt_machine()->set_delegate(&crt_delegate); updater.set_delegate(&best_effort_updater_delegate); @@ -161,13 +175,6 @@ int main(int argc, char *argv[]) { SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GL_MakeCurrent(window, gl_context); - // Create an audio pipe. -// SDL_AudioSpec desired_audio_spec; -// SDL_AudioSpec obtained_audio_spec; -// desired_audio_spec.freq = 192000; // An arbitrary high number. -// desired_audio_spec.format = AUDIO_S16; -// desired_audio_spec.channels = 1; - // Setup output, assuming a CRT machine for now, and prepare a best-effort updater. machine->crt_machine()->setup_output(4.0 / 3.0); machine->crt_machine()->get_crt()->set_output_gamma(2.2f); @@ -202,7 +209,21 @@ int main(int argc, char *argv[]) { // For now, lie about audio output intentions. auto speaker = machine->crt_machine()->get_speaker(); if(speaker) { - speaker->set_output_rate(44100, 1024); + // Create an audio pipe. + SDL_AudioSpec desired_audio_spec; + SDL_AudioSpec obtained_audio_spec; + + SDL_zero(desired_audio_spec); + desired_audio_spec.freq = 48000; // TODO: how can I get SDL to reveal the output rate of this machine? + desired_audio_spec.format = AUDIO_S16; + desired_audio_spec.channels = 1; + desired_audio_spec.samples = AudioBufferSize; + + speaker_delegate.audio_device = SDL_OpenAudioDevice(nullptr, 0, &desired_audio_spec, &obtained_audio_spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); + + speaker->set_output_rate(obtained_audio_spec.freq, obtained_audio_spec.samples); + speaker->set_delegate(&speaker_delegate); + SDL_PauseAudioDevice(speaker_delegate.audio_device, 0); } // Run the main event loop until the OS tells us to quit. From 0da78065cecd114679b551f13d2879d17485dcdf Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 6 Nov 2017 22:12:39 -0500 Subject: [PATCH 08/14] Eliminates some dangling cases of undefined initial state in the TIA. --- Machines/Atari2600/TIA.hpp | 73 +++++++++++++------------------------- 1 file changed, 25 insertions(+), 48 deletions(-) diff --git a/Machines/Atari2600/TIA.hpp b/Machines/Atari2600/TIA.hpp index a3d114d6a..5426ea989 100644 --- a/Machines/Atari2600/TIA.hpp +++ b/Machines/Atari2600/TIA.hpp @@ -135,42 +135,27 @@ class TIA { // objects template struct Object { // the two programmer-set values - int position; - int motion; + int position = 0; + int motion = 0; // motion_step_ is the current motion counter value; motion_time_ is the next time it will fire - int motion_step; - int motion_time; + int motion_step = 0; + int motion_time = 0; // indicates whether this object is currently undergoing motion - bool is_moving; - - Object() : position(0), motion(0), motion_step(0), motion_time(0), is_moving(false) {}; + bool is_moving = false; }; // player state struct Player: public Object { - Player() : - adder(4), - copy_flags(0), - graphic{0, 0}, - reverse_mask(false), - graphic_index(0), - pixel_position(32), - pixel_counter(0), - latched_pixel4_time(-1), - copy_index_(0), - queue_read_pointer_(0), - queue_write_pointer_(0) {} + int adder = 4; + int copy_flags = 0; // a bit field, corresponding to the first few values of NUSIZ + uint8_t graphic[2] = {0, 0}; // the player graphic; 1 = new, 0 = current + int reverse_mask = false; // 7 for a reflected player, 0 for normal + int graphic_index = 0; - int adder; - int copy_flags; // a bit field, corresponding to the first few values of NUSIZ - uint8_t graphic[2]; // the player graphic; 1 = new, 0 = current - int reverse_mask; // 7 for a reflected player, 0 for normal - int graphic_index; - - int pixel_position, pixel_counter; - int latched_pixel4_time; + int pixel_position = 32, pixel_counter = 0; + int latched_pixel4_time = -1; const bool enqueues = true; inline void skip_pixels(const int count, int from_horizontal_counter) { @@ -219,15 +204,14 @@ class TIA { } private: - int copy_index_; + int copy_index_ = 0; struct QueuedPixels { - int start, end; - int pixel_position; - int adder; - int reverse_mask; - QueuedPixels() : start(0), end(0), pixel_position(0), adder(0), reverse_mask(false) {} + int start = 0, end = 0; + int pixel_position = 0; + int adder = 0; + int reverse_mask = false; } queue_[4]; - int queue_read_pointer_, queue_write_pointer_; + int queue_read_pointer_ = 0, queue_write_pointer_ = 0; inline void output_pixels(uint8_t *const target, const int count, const uint8_t collision_identity, int output_pixel_position, int output_adder, int output_reverse_mask) { if(output_pixel_position == 32 || !graphic[graphic_index]) return; @@ -244,8 +228,8 @@ class TIA { // common actor for things that appear as a horizontal run of pixels struct HorizontalRun: public Object { - int pixel_position; - int size; + int pixel_position = 0; + int size = 1; const bool enqueues = false; inline void skip_pixels(const int count, int from_horizontal_counter) { @@ -268,16 +252,13 @@ class TIA { void dequeue_pixels(uint8_t *const target, const uint8_t collision_identity, const int time_now) {} void enqueue_pixels(const int start, const int end, int from_horizontal_counter) {} - - HorizontalRun() : pixel_position(0), size(1) {} }; - // missile state struct Missile: public HorizontalRun { - bool enabled; - bool locked_to_player; - int copy_flags; + bool enabled = false; + bool locked_to_player = false; + int copy_flags = 0; inline void output_pixels(uint8_t *const target, const int count, const uint8_t collision_identity, int from_horizontal_counter) { if(!pixel_position) return; @@ -287,14 +268,12 @@ class TIA { skip_pixels(count, from_horizontal_counter); } } - - Missile() : enabled(false), copy_flags(0) {} } missile_[2]; // ball state struct Ball: public HorizontalRun { - bool enabled[2]; - int enabled_index; + bool enabled[2] = {false, false}; + int enabled_index = 0; const int copy_flags = 0; inline void output_pixels(uint8_t *const target, const int count, const uint8_t collision_identity, int from_horizontal_counter) { @@ -305,8 +284,6 @@ class TIA { skip_pixels(count, from_horizontal_counter); } } - - Ball() : enabled{false, false}, enabled_index(0) {} } ball_; // motion From d605022ea3ddbbdacf97e9ce1952958cdf828676 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 6 Nov 2017 22:13:38 -0500 Subject: [PATCH 09/14] Moves output setup to after the machine has been configured as its target. --- OSBindings/SDL/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index 35be65aba..c414a2234 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -174,10 +174,6 @@ int main(int argc, char *argv[]) { SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GL_MakeCurrent(window, gl_context); - - // Setup output, assuming a CRT machine for now, and prepare a best-effort updater. - machine->crt_machine()->setup_output(4.0 / 3.0); - machine->crt_machine()->get_crt()->set_output_gamma(2.2f); // For vanilla SDL purposes, assume system ROMs can be found in one of: // @@ -206,6 +202,10 @@ int main(int argc, char *argv[]) { machine->configuration_target()->configure_as_target(targets.front()); + // Setup output, assuming a CRT machine for now, and prepare a best-effort updater. + machine->crt_machine()->setup_output(4.0 / 3.0); + machine->crt_machine()->get_crt()->set_output_gamma(2.2f); + // For now, lie about audio output intentions. auto speaker = machine->crt_machine()->get_speaker(); if(speaker) { From 35da3edf60d5008168f1bb3d4e8cd3649288bd04 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 6 Nov 2017 22:14:15 -0500 Subject: [PATCH 10/14] Implements install_roms on the Electron, Oric and ZX80/81. --- Machines/Electron/Electron.cpp | 31 +++++++++++++++++++++++++++---- Machines/Electron/Electron.hpp | 3 ++- Machines/Oric/Oric.cpp | 16 ++++++++++++++++ Machines/Oric/Oric.hpp | 2 +- Machines/ZX8081/ZX8081.cpp | 15 +++++++++++++++ Machines/ZX8081/ZX8081.hpp | 2 +- 6 files changed, 62 insertions(+), 7 deletions(-) diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index edde9f14e..647ed2ed6 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -43,7 +43,8 @@ class ConcreteMachine: uint8_t *target = nullptr; switch(slot) { case ROMSlotDFS: dfs_ = data; return; - case ROMSlotADFS: adfs_ = data; return; + case ROMSlotADFS1: adfs1_ = data; return; + case ROMSlotADFS2: adfs2_ = data; return; case ROMSlotOS: target = os_; break; default: @@ -55,6 +56,28 @@ class ConcreteMachine: memcpy(target, &data[0], std::min(static_cast(16384), data.size())); } + // Obtains the system ROMs. + bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) override { + ROMSlot slots[] = { + ROMSlotDFS, + ROMSlotADFS1, ROMSlotADFS2, + ROMSlotBASIC, ROMSlotOS + }; + const char *os_files[] = { + "DFS-1770-2.20.rom", + "ADFS-E00_1.rom", "ADFS-E00_2.rom", + "basic.rom", "os.rom" + }; + + for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) { + auto data = rom_with_name("Electron", os_files[index]); + if(!data) return false; + set_rom(slots[index], *data, false); + } + + return true; + } + void set_key_state(uint16_t key, bool isPressed) override final { if(key == KeyBreak) { m6502_.set_reset_line(isPressed); @@ -91,8 +114,8 @@ class ConcreteMachine: set_rom(ROMSlot0, dfs_, true); } if(target.acorn.has_adfs) { - set_rom(ROMSlot4, adfs_, true); - set_rom(ROMSlot5, std::vector(adfs_.begin() + 16384, adfs_.end()), true); + set_rom(ROMSlot4, adfs1_, true); + set_rom(ROMSlot5, adfs2_, true); } } @@ -435,7 +458,7 @@ class ConcreteMachine: uint8_t roms_[16][16384]; bool rom_write_masks_[16] = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}; uint8_t os_[16384], ram_[32768]; - std::vector dfs_, adfs_; + std::vector dfs_, adfs1_, adfs2_; // Paging ROMSlot active_rom_ = ROMSlot::ROMSlot0; diff --git a/Machines/Electron/Electron.hpp b/Machines/Electron/Electron.hpp index 724956157..cc76e219e 100644 --- a/Machines/Electron/Electron.hpp +++ b/Machines/Electron/Electron.hpp @@ -28,7 +28,8 @@ enum ROMSlot: uint8_t { ROMSlot12, ROMSlot13, ROMSlot14, ROMSlot15, - ROMSlotOS, ROMSlotDFS, ROMSlotADFS + ROMSlotOS, ROMSlotDFS, + ROMSlotADFS1, ROMSlotADFS2 }; /*! diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index 0e1ad22c7..f5cacc1ad 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -203,6 +203,22 @@ class ConcreteMachine: } } + // Obtains the system ROMs. + bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) override { + const char *os_files[] = { + "basic10.rom", "basic11.rom", + "microdisc.rom", "colour.rom" + }; + + for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) { + auto data = rom_with_name("Oric", os_files[index]); + if(!data) return false; + set_rom(static_cast(index), *data); + } + + return true; + } + void set_key_state(uint16_t key, bool is_pressed) override final { if(key == KeyNMI) { m6502_.set_nmi_line(is_pressed); diff --git a/Machines/Oric/Oric.hpp b/Machines/Oric/Oric.hpp index 9a69965a7..4e4a8c418 100644 --- a/Machines/Oric/Oric.hpp +++ b/Machines/Oric/Oric.hpp @@ -19,7 +19,7 @@ namespace Oric { enum ROM { - BASIC10, BASIC11, Microdisc, Colour + BASIC10 = 0, BASIC11, Microdisc, Colour }; /*! diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index dcedbdeeb..d9186cc73 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -297,6 +297,21 @@ template class ConcreteMachine: } } + // Obtains the system ROMs. + bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) override { + const char *os_files[] = { + "zx80.rom", "zx81.rom", + }; + + for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) { + auto data = rom_with_name("ZX8081", os_files[index]); + if(!data) return false; + set_rom(static_cast(index), *data); + } + + return true; + } + #pragma mark - Keyboard void set_key_state(uint16_t key, bool isPressed) override final { diff --git a/Machines/ZX8081/ZX8081.hpp b/Machines/ZX8081/ZX8081.hpp index 9750183e6..8e119823d 100644 --- a/Machines/ZX8081/ZX8081.hpp +++ b/Machines/ZX8081/ZX8081.hpp @@ -19,7 +19,7 @@ namespace ZX8081 { enum ROMType: uint8_t { - ZX80, ZX81 + ZX80 = 0, ZX81 }; class Machine: From ddcdd07dd08ed2ddb2041c6d7edc8796fe2efb7c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 7 Nov 2017 21:19:51 -0500 Subject: [PATCH 11/14] Modifies the Vic-20 and C1540 to bring them into the realm of self-ROM fetching. Hence enables Vic-20 support within kiosk mode as currently drafted. --- Machines/AmstradCPC/AmstradCPC.cpp | 22 +- Machines/AmstradCPC/AmstradCPC.hpp | 2 +- Machines/CRTMachine.hpp | 8 +- Machines/Commodore/1540/C1540.hpp | 16 +- .../Commodore/1540/Implementation/C1540.cpp | 16 +- Machines/Commodore/Vic-20/Vic20.cpp | 188 +++++++++++------- Machines/Commodore/Vic-20/Vic20.hpp | 12 +- Machines/Electron/Electron.cpp | 20 +- Machines/Electron/Electron.hpp | 2 +- Machines/Oric/Oric.cpp | 16 +- Machines/ROMMachine.hpp | 27 +++ Machines/ZX8081/ZX8081.cpp | 16 +- Machines/ZX8081/ZX8081.hpp | 2 +- .../Clock Signal.xcodeproj/project.pbxproj | 2 + OSBindings/SDL/main.cpp | 42 ++-- 15 files changed, 252 insertions(+), 139 deletions(-) create mode 100644 Machines/ROMMachine.hpp diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index fbe4bf05f..38e1b1b06 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -919,21 +919,23 @@ class ConcreteMachine: } // See header; provides the system ROMs. - void set_rom(ROMType type, std::vector data) override final { + void set_rom(ROMType type, const std::vector &data) override final { roms_[static_cast(type)] = data; } // Obtains the system ROMs. - bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) override { - const char *os_files[] = { - "os464.rom", "basic464.rom", - "os664.rom", "basic664.rom", - "os6128.rom", "basic6128.rom", - "amsdos.rom" - }; + bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names) override { + auto roms = roms_with_names( + "AmstradCPC", + { + "os464.rom", "basic464.rom", + "os664.rom", "basic664.rom", + "os6128.rom", "basic6128.rom", + "amsdos.rom" + }); - for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) { - auto data = rom_with_name("AmstradCPC", os_files[index]); + for(size_t index = 0; index < roms.size(); ++index) { + auto &data = roms[index]; if(!data) return false; set_rom(static_cast(index), *data); } diff --git a/Machines/AmstradCPC/AmstradCPC.hpp b/Machines/AmstradCPC/AmstradCPC.hpp index c070b3bb9..27c48c6df 100644 --- a/Machines/AmstradCPC/AmstradCPC.hpp +++ b/Machines/AmstradCPC/AmstradCPC.hpp @@ -39,7 +39,7 @@ class Machine: static Machine *AmstradCPC(); /// Sets the contents of rom @c type to @c data. Assumed to be a setup step; has no effect once a machine is running. - virtual void set_rom(ROMType type, std::vector data) = 0; + virtual void set_rom(ROMType type, const std::vector &data) = 0; }; } diff --git a/Machines/CRTMachine.hpp b/Machines/CRTMachine.hpp index 6c5fb346c..f6fbd9c30 100644 --- a/Machines/CRTMachine.hpp +++ b/Machines/CRTMachine.hpp @@ -12,6 +12,7 @@ #include "../Outputs/CRT/CRT.hpp" #include "../Outputs/Speaker.hpp" #include "../ClockReceiver/ClockReceiver.hpp" +#include "ROMMachine.hpp" namespace CRTMachine { @@ -20,7 +21,7 @@ namespace CRTMachine { that optionally provide a speaker, and that nominate a clock rate and can announce to a delegate should that clock rate change. */ -class Machine { +class Machine: public ROMMachine::Machine { public: Machine() : clock_is_unlimited_(false), delegate_(nullptr) {} @@ -36,11 +37,6 @@ class Machine { */ virtual void close_output() = 0; - /*! - Provides the machine with a way to obtain such ROMs as it needs. - */ - virtual bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) { return true; } - /// @returns The CRT this machine is drawing to. Should not be @c nullptr. virtual std::shared_ptr get_crt() = 0; diff --git a/Machines/Commodore/1540/C1540.hpp b/Machines/Commodore/1540/C1540.hpp index 4c3954672..5d3c5564c 100644 --- a/Machines/Commodore/1540/C1540.hpp +++ b/Machines/Commodore/1540/C1540.hpp @@ -10,6 +10,7 @@ #define Commodore1540_hpp #include "../SerialBus.hpp" +#include "../../ROMMachine.hpp" #include "../../../Storage/Disk/Disk.hpp" #include "Implementation/C1540Base.hpp" @@ -19,12 +20,18 @@ namespace C1540 { /*! Provides an emulation of the C1540. */ -class Machine: public MachineBase { +class Machine: public MachineBase, public ROMMachine::Machine { public: + enum Personality { + C1540, + C1541 + }; + Machine(Personality p); + /*! - Sets the ROM image to use for this drive; it is asserted that the buffer provided is 16 kb in size. + Sets the source for this drive's ROM image. */ - void set_rom(const std::vector &rom); + bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names); /*! Sets the serial bus to which this drive should attach itself. @@ -36,6 +43,9 @@ class Machine: public MachineBase { /// Inserts @c disk into the drive. void set_disk(std::shared_ptr disk); + + private: + Personality personality_; }; } diff --git a/Machines/Commodore/1540/Implementation/C1540.cpp b/Machines/Commodore/1540/Implementation/C1540.cpp index ac2a98e76..316c0ab0d 100644 --- a/Machines/Commodore/1540/Implementation/C1540.cpp +++ b/Machines/Commodore/1540/Implementation/C1540.cpp @@ -40,6 +40,8 @@ MachineBase::MachineBase() : set_drive(drive_); } +Machine::Machine(Commodore::C1540::Machine::Personality personality) : personality_(personality) {} + void Machine::set_serial_bus(std::shared_ptr<::Commodore::Serial::Bus> serial_bus) { Commodore::Serial::AttachPortAndBus(serial_port_, serial_bus); } @@ -80,9 +82,17 @@ Cycles MachineBase::perform_bus_operation(CPU::MOS6502::BusOperation operation, return Cycles(1); } -void Machine::set_rom(const std::vector &rom) { - assert(rom.size() == sizeof(rom_)); - memcpy(rom_, rom.data(), std::min(sizeof(rom_), rom.size())); +bool Machine::set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names) { + std::string rom_name; + switch(personality_) { + case Personality::C1540: rom_name = "1540.bin"; break; + case Personality::C1541: rom_name = "1541.bin"; break; + } + + auto roms = roms_with_names("Commodore1540", {rom_name}); + if(!roms[0]) return false; + memcpy(rom_, roms[0]->data(), std::min(sizeof(rom_), roms[0]->size())); + return true; } void Machine::set_disk(std::shared_ptr disk) { diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index 7b10b4eb1..98de4c8b5 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -37,6 +37,18 @@ enum JoystickInput { Fire = 0x20 }; +enum ROM { + CharactersDanish = 0, + CharactersEnglish, + CharactersJapanese, + CharactersSwedish, + KernelDanish, + KernelJapanese, + KernelNTSC, + KernelPAL, + KernelSwedish +}; + /*! Models the user-port VIA, which is the Vic's connection point for controlling its tape recorder — sensing the presence or absence of a tape and controlling the tape motor — and reading the current @@ -280,12 +292,6 @@ class ConcreteMachine: keyboard_via_port_handler_->set_interrupt_delegate(this); tape_->set_delegate(this); - // establish the memory maps - set_memory_size(MemorySize::Default); - - // set the NTSC clock rate - set_region(NTSC); - // install a joystick joysticks_.emplace_back(new Joystick(*user_port_via_port_handler_, *keyboard_via_port_handler_)); } @@ -294,24 +300,32 @@ class ConcreteMachine: delete[] rom_; } - void set_rom(ROMSlot slot, size_t length, const uint8_t *data) override final { - uint8_t *target = nullptr; - size_t max_length = 0x2000; - switch(slot) { - case Kernel: target = kernel_rom_; break; - case Characters: target = character_rom_; max_length = 0x1000; break; - case BASIC: target = basic_rom_; break; - case Drive: - drive_rom_.resize(length); - memcpy(drive_rom_.data(), data, length); - install_disk_rom(); - return; - } + void set_rom(ROMSlot slot, const std::vector &data) override final { + } - if(target) { - size_t length_to_copy = std::min(max_length, length); - memcpy(target, data, length_to_copy); + // Obtains the system ROMs. + bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names) override { + auto roms = roms_with_names( + "Vic20", + { + "characters-danish.bin", + "characters-english.bin", + "characters-japanese.bin", + "characters-swedish.bin", + "kernel-danish.bin", + "kernel-japanese.bin", + "kernel-ntsc.bin", + "kernel-pal.bin", + "kernel-swedish.bin", + "basic.bin" + }); + + for(size_t index = 0; index < roms.size(); ++index) { + auto &data = roms[index]; + if(!data) return false; + if(index < 9) roms_[index] = *data; else basic_rom_ = *data; } + return true; } void configure_as_target(const StaticAnalyser::Target &target) override final { @@ -333,13 +347,13 @@ class ConcreteMachine: if(target.media.disks.size()) { // construct the 1540 - c1540_.reset(new ::Commodore::C1540::Machine); + c1540_.reset(new ::Commodore::C1540::Machine(Commodore::C1540::Machine::C1540)); // attach it to the serial bus c1540_->set_serial_bus(serial_bus_); - // install the ROM if it was previously set - install_disk_rom(); + // give it a means to obtain its ROM + c1540_->set_rom_fetcher(rom_fetcher_); } insert_media(target.media); @@ -383,10 +397,38 @@ class ConcreteMachine: } void set_memory_size(MemorySize size) override final { + memory_size_ = size; + needs_configuration_ = true; + } + + void set_region(Region region) override final { + region_ = region; + needs_configuration_ = true; + } + + void configure_memory() { + // Determine PAL/NTSC + if(region_ == American || region_ == Japanese) { + // NTSC + set_clock_rate(1022727); + if(mos6560_) { + mos6560_->set_output_mode(MOS::MOS6560::OutputMode::NTSC); + mos6560_->set_clock_rate(1022727); + } + } else { + // PAL + set_clock_rate(1108404); + if(mos6560_) { + mos6560_->set_output_mode(MOS::MOS6560::OutputMode::PAL); + mos6560_->set_clock_rate(1108404); + } + } + memset(processor_read_memory_map_, 0, sizeof(processor_read_memory_map_)); memset(processor_write_memory_map_, 0, sizeof(processor_write_memory_map_)); + memset(mos6560_->video_memory_map, 0, sizeof(mos6560_->video_memory_map)); - switch(size) { + switch(memory_size_) { default: break; case ThreeKB: write_to_map(processor_read_memory_map_, expansion_ram_, 0x0000, 0x1000); @@ -402,40 +444,52 @@ class ConcreteMachine: write_to_map(processor_read_memory_map_, user_basic_memory_, 0x0000, sizeof(user_basic_memory_)); write_to_map(processor_read_memory_map_, screen_memory_, 0x1000, sizeof(screen_memory_)); write_to_map(processor_read_memory_map_, colour_memory_, 0x9400, sizeof(colour_memory_)); - write_to_map(processor_read_memory_map_, character_rom_, 0x8000, sizeof(character_rom_)); - write_to_map(processor_read_memory_map_, basic_rom_, 0xc000, sizeof(basic_rom_)); - write_to_map(processor_read_memory_map_, kernel_rom_, 0xe000, sizeof(kernel_rom_)); - + write_to_map(processor_write_memory_map_, user_basic_memory_, 0x0000, sizeof(user_basic_memory_)); write_to_map(processor_write_memory_map_, screen_memory_, 0x1000, sizeof(screen_memory_)); write_to_map(processor_write_memory_map_, colour_memory_, 0x9400, sizeof(colour_memory_)); + write_to_map(mos6560_->video_memory_map, user_basic_memory_, 0x2000, sizeof(user_basic_memory_)); + write_to_map(mos6560_->video_memory_map, screen_memory_, 0x3000, sizeof(screen_memory_)); + mos6560_->colour_memory = colour_memory_; + + write_to_map(processor_read_memory_map_, basic_rom_.data(), 0xc000, basic_rom_.size()); + + ROM character_rom; + ROM kernel_rom; + switch(region_) { + case American: + character_rom = CharactersEnglish; + kernel_rom = KernelNTSC; + break; + case Danish: + character_rom = CharactersDanish; + kernel_rom = KernelDanish; + break; + case Japanese: + character_rom = CharactersJapanese; + kernel_rom = KernelJapanese; + break; + case European: + character_rom = CharactersEnglish; + kernel_rom = KernelPAL; + break; + case Swedish: + character_rom = CharactersSwedish; + kernel_rom = KernelSwedish; + break; + } + + write_to_map(processor_read_memory_map_, roms_[character_rom].data(), 0x8000, roms_[character_rom].size()); + write_to_map(mos6560_->video_memory_map, roms_[character_rom].data(), 0x0000, roms_[character_rom].size()); + write_to_map(processor_read_memory_map_, roms_[kernel_rom].data(), 0xe000, roms_[kernel_rom].size()); + // install the inserted ROM if there is one if(rom_) { write_to_map(processor_read_memory_map_, rom_, rom_address_, rom_length_); } } - void set_region(Region region) override final { - region_ = region; - switch(region) { - case PAL: - set_clock_rate(1108404); - if(mos6560_) { - mos6560_->set_output_mode(MOS::MOS6560::OutputMode::PAL); - mos6560_->set_clock_rate(1108404); - } - break; - case NTSC: - set_clock_rate(1022727); - if(mos6560_) { - mos6560_->set_output_mode(MOS::MOS6560::OutputMode::NTSC); - mos6560_->set_clock_rate(1022727); - } - break; - } - } - void set_use_fast_tape_hack(bool activate) override final { use_fast_tape_hack_ = activate; } @@ -542,19 +596,16 @@ class ConcreteMachine: } void run_for(const Cycles cycles) override final { + if(needs_configuration_) { + needs_configuration_ = false; + configure_memory(); + } m6502_.run_for(cycles); } void setup_output(float aspect_ratio) override final { mos6560_.reset(new Vic6560()); mos6560_->get_speaker()->set_high_frequency_cut_off(1600); // There is a 1.6Khz low-pass filter in the Vic-20. - set_region(region_); - - memset(mos6560_->video_memory_map, 0, sizeof(mos6560_->video_memory_map)); - write_to_map(mos6560_->video_memory_map, character_rom_, 0x0000, sizeof(character_rom_)); - write_to_map(mos6560_->video_memory_map, user_basic_memory_, 0x2000, sizeof(user_basic_memory_)); - write_to_map(mos6560_->video_memory_map, screen_memory_, 0x3000, sizeof(screen_memory_)); - mos6560_->colour_memory = colour_memory_; } void close_output() override final { @@ -590,9 +641,11 @@ class ConcreteMachine: private: CPU::MOS6502::Processor m6502_; - uint8_t character_rom_[0x1000]; - uint8_t basic_rom_[0x2000]; - uint8_t kernel_rom_[0x2000]; + std::vector roms_[9]; + + std::vector character_rom_; + std::vector basic_rom_; + std::vector kernel_rom_; uint8_t expansion_ram_[0x8000]; uint8_t *rom_; @@ -601,7 +654,8 @@ class ConcreteMachine: uint8_t user_basic_memory_[0x0400]; uint8_t screen_memory_[0x1000]; uint8_t colour_memory_[0x0400]; - std::vector drive_rom_; + + std::function>>(const std::string &machine, const std::vector &names)> rom_fetcher_; uint8_t *processor_read_memory_map_[64]; uint8_t *processor_write_memory_map_[64]; @@ -615,7 +669,10 @@ class ConcreteMachine: } } - Region region_; + Region region_ = European; + MemorySize memory_size_ = MemorySize::Default; + bool needs_configuration_ = true; + Commodore::Vic20::KeyboardMapper keyboard_mapper_; std::vector> joysticks_; @@ -635,13 +692,6 @@ class ConcreteMachine: // Disk std::shared_ptr<::Commodore::C1540::Machine> c1540_; - void install_disk_rom() { - if(!drive_rom_.empty() && c1540_) { - c1540_->set_rom(drive_rom_); - c1540_->run_for(Cycles(2000000)); - drive_rom_.clear(); - } - } }; } diff --git a/Machines/Commodore/Vic-20/Vic20.hpp b/Machines/Commodore/Vic-20/Vic20.hpp index aac1025d5..e99c34c73 100644 --- a/Machines/Commodore/Vic-20/Vic20.hpp +++ b/Machines/Commodore/Vic-20/Vic20.hpp @@ -20,7 +20,7 @@ namespace Commodore { namespace Vic20 { enum ROMSlot { - Kernel, + Kernel = 0, BASIC, Characters, Drive @@ -33,8 +33,11 @@ enum MemorySize { }; enum Region { - NTSC, - PAL + American, + Danish, + Japanese, + European, + Swedish }; class Machine: @@ -49,8 +52,7 @@ class Machine: static Machine *Vic20(); /// Sets the contents of the rom in @c slot to the buffer @c data of length @c length. - virtual void set_rom(ROMSlot slot, size_t length, const uint8_t *data) = 0; - // TODO: take a std::vector to collapse length and data. + virtual void set_rom(ROMSlot slot, const std::vector &data) = 0; /// Sets the memory size of this Vic-20. virtual void set_memory_size(MemorySize size) = 0; diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index 647ed2ed6..da2624f51 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -39,7 +39,7 @@ class ConcreteMachine: set_clock_rate(2000000); } - void set_rom(ROMSlot slot, std::vector data, bool is_writeable) override final { + void set_rom(ROMSlot slot, const std::vector &data, bool is_writeable) override final { uint8_t *target = nullptr; switch(slot) { case ROMSlotDFS: dfs_ = data; return; @@ -57,20 +57,22 @@ class ConcreteMachine: } // Obtains the system ROMs. - bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) override { + bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names) override { + auto roms = roms_with_names( + "Electron", + { + "DFS-1770-2.20.rom", + "ADFS-E00_1.rom", "ADFS-E00_2.rom", + "basic.rom", "os.rom" + }); ROMSlot slots[] = { ROMSlotDFS, ROMSlotADFS1, ROMSlotADFS2, ROMSlotBASIC, ROMSlotOS }; - const char *os_files[] = { - "DFS-1770-2.20.rom", - "ADFS-E00_1.rom", "ADFS-E00_2.rom", - "basic.rom", "os.rom" - }; - for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) { - auto data = rom_with_name("Electron", os_files[index]); + for(size_t index = 0; index < roms.size(); ++index) { + auto &data = roms[index]; if(!data) return false; set_rom(slots[index], *data, false); } diff --git a/Machines/Electron/Electron.hpp b/Machines/Electron/Electron.hpp index cc76e219e..80fd0fa4c 100644 --- a/Machines/Electron/Electron.hpp +++ b/Machines/Electron/Electron.hpp @@ -52,7 +52,7 @@ class Machine: Sets the contents of @c slot to @c data. If @c is_writeable is @c true then writing to the slot is enabled — it acts as if it were sideways RAM. Otherwise the slot is modelled as containing ROM. */ - virtual void set_rom(ROMSlot slot, std::vector data, bool is_writeable) = 0; + virtual void set_rom(ROMSlot slot, const std::vector &data, bool is_writeable) = 0; /// Enables or disables turbo-speed tape loading. virtual void set_use_fast_tape_hack(bool activate) = 0; diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index f5cacc1ad..c2b53c71f 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -204,14 +204,16 @@ class ConcreteMachine: } // Obtains the system ROMs. - bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) override { - const char *os_files[] = { - "basic10.rom", "basic11.rom", - "microdisc.rom", "colour.rom" - }; + bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names) override { + auto roms = roms_with_names( + "Oric", + { + "basic10.rom", "basic11.rom", + "microdisc.rom", "colour.rom" + }); - for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) { - auto data = rom_with_name("Oric", os_files[index]); + for(size_t index = 0; index < roms.size(); ++index) { + auto &data = roms[index]; if(!data) return false; set_rom(static_cast(index), *data); } diff --git a/Machines/ROMMachine.hpp b/Machines/ROMMachine.hpp new file mode 100644 index 000000000..d95ae7042 --- /dev/null +++ b/Machines/ROMMachine.hpp @@ -0,0 +1,27 @@ +// +// ROMMachine.hpp +// Clock Signal +// +// Created by Thomas Harte on 07/11/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#ifndef ROMMachine_hpp +#define ROMMachine_hpp + +#include +#include +#include + +namespace ROMMachine { + +struct Machine { + /*! + Provides the machine with a way to obtain such ROMs as it needs. + */ + virtual bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &rom_with_name) { return true; } +}; + +} + +#endif /* ROMMachine_h */ diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index d9186cc73..e587f4561 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -290,7 +290,7 @@ template class ConcreteMachine: Utility::TypeRecipient::set_typer_for_string(string, std::move(mapper)); } - void set_rom(ROMType type, std::vector data) override final { + void set_rom(ROMType type, const std::vector &data) override final { switch(type) { case ZX80: zx80_rom_ = data; break; case ZX81: zx81_rom_ = data; break; @@ -298,13 +298,15 @@ template class ConcreteMachine: } // Obtains the system ROMs. - bool install_roms(const std::function>(const std::string &machine, const std::string &name)> &rom_with_name) override { - const char *os_files[] = { - "zx80.rom", "zx81.rom", - }; + bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names) override { + auto roms = roms_with_names( + "ZX8081", + { + "zx80.rom", "zx81.rom", + }); - for(size_t index = 0; index < sizeof(os_files) / sizeof(*os_files); ++index) { - auto data = rom_with_name("ZX8081", os_files[index]); + for(size_t index = 0; index < roms.size(); ++index) { + auto &data = roms[index]; if(!data) return false; set_rom(static_cast(index), *data); } diff --git a/Machines/ZX8081/ZX8081.hpp b/Machines/ZX8081/ZX8081.hpp index 8e119823d..ce797fbf8 100644 --- a/Machines/ZX8081/ZX8081.hpp +++ b/Machines/ZX8081/ZX8081.hpp @@ -30,7 +30,7 @@ class Machine: static Machine *ZX8081(const StaticAnalyser::Target &target_hint); virtual ~Machine(); - virtual void set_rom(ROMType type, std::vector data) = 0; + virtual void set_rom(ROMType type, const std::vector &data) = 0; virtual void set_use_fast_tape_hack(bool activate) = 0; virtual void set_tape_is_playing(bool is_playing) = 0; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index dbf307ba2..e8c6029ad 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -1210,6 +1210,7 @@ 4BD5F1931D13528900631CD1 /* CSBestEffortUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSBestEffortUpdater.h; path = Updater/CSBestEffortUpdater.h; sourceTree = ""; }; 4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CSBestEffortUpdater.mm; path = Updater/CSBestEffortUpdater.mm; sourceTree = ""; }; 4BD9137D1F311BC5009BCF85 /* i8255.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = i8255.hpp; path = 8255/i8255.hpp; sourceTree = ""; }; + 4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ROMMachine.hpp; sourceTree = ""; }; 4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MachineCycleTests.swift; sourceTree = ""; }; 4BE77A2C1D84ADFB00BC3827 /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = File.cpp; path = ../../StaticAnalyser/Commodore/File.cpp; sourceTree = ""; }; 4BE77A2D1D84ADFB00BC3827 /* File.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = File.hpp; path = ../../StaticAnalyser/Commodore/File.hpp; sourceTree = ""; }; @@ -2352,6 +2353,7 @@ isa = PBXGroup; children = ( 4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */, + 4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */, 4BA9C3CF1D8164A9002DDB61 /* ConfigurationTarget.hpp */, 4B046DC31CFE651500E9E45E /* CRTMachine.hpp */, 4B7041271F92C26900735E45 /* JoystickMachine.hpp */, diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index c414a2234..9a1fb34fb 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -179,25 +179,33 @@ int main(int argc, char *argv[]) { // // /usr/local/share/CLK/[system]; or // /usr/share/CLK/[system] - machine->crt_machine()->install_roms( [] (const std::string &machine, const std::string &name) -> std::unique_ptr> { - std::string local_path = "/usr/local/share/CLK/" + machine + "/" + name; - FILE *file = fopen(local_path.c_str(), "r"); - if(!file) { - std::string path = "/usr/share/CLK/" + machine + "/" + name; - file = fopen(path.c_str(), "r"); + machine->crt_machine()->set_rom_fetcher( [] (const std::string &machine, const std::vector &names) -> std::vector>> { + std::vector>> results; + for(auto &name: names) { + std::string local_path = "/usr/local/share/CLK/" + machine + "/" + name; + FILE *file = fopen(local_path.c_str(), "r"); + if(!file) { + std::string path = "/usr/share/CLK/" + machine + "/" + name; + file = fopen(path.c_str(), "r"); + } + + if(!file) { + results.emplace_back(nullptr); + continue; + } + + std::unique_ptr> data(new std::vector); + + fseek(file, 0, SEEK_END); + data->resize(ftell(file)); + fseek(file, 0, SEEK_SET); + fread(data->data(), 1, data->size(), file); + fclose(file); + + results.emplace_back(std::move(data)); } - if(!file) return nullptr; - - std::unique_ptr> data(new std::vector); - - fseek(file, 0, SEEK_END); - data->resize(ftell(file)); - fseek(file, 0, SEEK_SET); - fread(data->data(), 1, data->size(), file); - fclose(file); - - return data; + return results; }); machine->configuration_target()->configure_as_target(targets.front()); From 0d1b63a8c5447ccd52208e914dc64b698845e187 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 7 Nov 2017 22:29:57 -0500 Subject: [PATCH 12/14] Switches the Objective-C machine bindings to use the set_rom_fetcher path for supplying ROMs, simplifying and unifying. --- .../Mac/Clock Signal/Machine/CSMachine.mm | 20 ++++++ .../Machine/Wrappers/CSAmstradCPC.mm | 29 -------- .../Machine/Wrappers/CSElectron.mm | 30 -------- .../Clock Signal/Machine/Wrappers/CSOric.mm | 19 ----- .../Clock Signal/Machine/Wrappers/CSVic20.h | 4 +- .../Clock Signal/Machine/Wrappers/CSVic20.mm | 69 ++----------------- .../Clock Signal/Machine/Wrappers/CSZX8081.mm | 10 --- 7 files changed, 27 insertions(+), 154 deletions(-) diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm index 6c7746ac0..c1a3049f2 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm @@ -16,6 +16,9 @@ #include "JoystickMachine.hpp" #include "KeyboardMachine.hpp" +#import "NSBundle+DataResource.h" +#import "NSData+StdVector.h" + @interface CSMachine() - (void)speaker:(Outputs::Speaker *)speaker didCompleteSamples:(const int16_t *)samples length:(int)length; - (void)machineDidChangeClockRate; @@ -69,6 +72,23 @@ struct MachineDelegate: CRTMachine::Machine::Delegate, public LockProtectedDeleg _speakerDelegate.machineAccessLock = _delegateMachineAccessLock; _machine->set_delegate(&_machineDelegate); + _machine->set_rom_fetcher( [] (const std::string &machine, const std::vector &names) -> std::vector>> { + NSString *subDirectory = [@"ROMImages/" stringByAppendingString:[NSString stringWithUTF8String:machine.c_str()]]; + std::vector>> results; + for(auto &name: names) { + NSData *fileData = [[NSBundle mainBundle] dataForResource:[NSString stringWithUTF8String:name.c_str()] withExtension:nil subdirectory:subDirectory]; + + if(!fileData) + results.emplace_back(nullptr); + else { + std::unique_ptr> data(new std::vector); + *data = fileData.stdVector8; + results.emplace_back(std::move(data)); + } + } + + return results; + }); } return self; } diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAmstradCPC.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAmstradCPC.mm index f129bdecb..c3442c2c8 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAmstradCPC.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAmstradCPC.mm @@ -10,10 +10,6 @@ #include "AmstradCPC.hpp" -#import "CSMachine+Subclassing.h" -#import "NSData+StdVector.h" -#import "NSBundle+DataResource.h" - @implementation CSAmstradCPC { std::unique_ptr _amstradCPC; } @@ -24,35 +20,10 @@ self = [super initWithMachine:machine]; if(self) { _amstradCPC.reset(machine); - - NSDictionary *roms = @{ - @(AmstradCPC::ROMType::OS464) : @"os464", - @(AmstradCPC::ROMType::OS664) : @"os664", - @(AmstradCPC::ROMType::OS6128) : @"os6128", - @(AmstradCPC::ROMType::BASIC464) : @"basic464", - @(AmstradCPC::ROMType::BASIC664) : @"basic664", - @(AmstradCPC::ROMType::BASIC6128) : @"basic6128", - @(AmstradCPC::ROMType::AMSDOS) : @"amsdos", - }; - - for(NSNumber *key in roms.allKeys) { - AmstradCPC::ROMType type = (AmstradCPC::ROMType)key.integerValue; - NSString *name = roms[key]; - NSData *data = [self rom:name]; - if(data) { - _amstradCPC->set_rom(type, data.stdVector8); - } else { - NSLog(@"Amstrad CPC ROM missing: %@", name); - } - } } return self; } -- (NSData *)rom:(NSString *)name { - return [[NSBundle mainBundle] dataForResource:name withExtension:@"rom" subdirectory:@"ROMImages/AmstradCPC"]; -} - - (NSString *)userDefaultsPrefix { return @"amstradCPC"; } @end diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSElectron.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSElectron.mm index 8a9611ed3..1f0aa2ba0 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSElectron.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSElectron.mm @@ -9,11 +9,7 @@ #import "CSElectron.h" #include "Electron.hpp" -#include "StaticAnalyser.hpp" -#import "CSMachine+Subclassing.h" -#import "NSData+StdVector.h" -#import "NSBundle+DataResource.h" @implementation CSElectron { std::unique_ptr _electron; @@ -25,38 +21,12 @@ self = [super initWithMachine:machine]; if(self) { _electron.reset(machine); - - [self setOSROM:[self rom:@"os"]]; - [self setBASICROM:[self rom:@"basic"]]; - [self setDFSROM:[self rom:@"DFS-1770-2.20"]]; - - NSMutableData *adfs = [[self rom:@"ADFS-E00_1"] mutableCopy]; - [adfs appendData:[self rom:@"ADFS-E00_2"]]; - [self setADFSROM:adfs]; } return self; } -- (NSData *)rom:(NSString *)name { - return [[NSBundle mainBundle] dataForResource:name withExtension:@"rom" subdirectory:@"ROMImages/Electron"]; -} - #pragma mark - ROM setting -- (void)setOSROM:(nonnull NSData *)rom { [self setROM:rom slot:Electron::ROMSlotOS]; } -- (void)setBASICROM:(nonnull NSData *)rom { [self setROM:rom slot:Electron::ROMSlotBASIC]; } -- (void)setADFSROM:(nonnull NSData *)rom { [self setROM:rom slot:Electron::ROMSlotADFS]; } -- (void)setDFSROM:(nonnull NSData *)rom { [self setROM:rom slot:Electron::ROMSlotDFS]; } - -- (void)setROM:(nonnull NSData *)rom slot:(int)slot { - if(rom) - { - @synchronized(self) { - _electron->set_rom((Electron::ROMSlot)slot, rom.stdVector8, false); - } - } -} - - (NSString *)userDefaultsPrefix { return @"electron"; } #pragma mark - Options diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm index 2e9a5daf0..5c5a396f0 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm @@ -9,11 +9,6 @@ #import "CSOric.h" #include "Oric.hpp" -#include "StaticAnalyser.hpp" - -#import "CSMachine+Subclassing.h" -#import "NSData+StdVector.h" -#import "NSBundle+DataResource.h" @implementation CSOric { std::unique_ptr _oric; @@ -25,24 +20,10 @@ self = [super initWithMachine:machine]; if(self) { _oric.reset(machine); - - NSData *basic10 = [self rom:@"basic10"]; - NSData *basic11 = [self rom:@"basic11"]; - NSData *colour = [self rom:@"colour"]; - NSData *microdisc = [self rom:@"microdisc"]; - - if(basic10) _oric->set_rom(Oric::BASIC10, basic10.stdVector8); - if(basic11) _oric->set_rom(Oric::BASIC11, basic11.stdVector8); - if(colour) _oric->set_rom(Oric::Colour, colour.stdVector8); - if(microdisc) _oric->set_rom(Oric::Microdisc, microdisc.stdVector8); } return self; } -- (NSData *)rom:(NSString *)name { - return [[NSBundle mainBundle] dataForResource:name withExtension:@"rom" subdirectory:@"ROMImages/Oric"]; -} - #pragma mark - Options - (void)setUseFastLoadingHack:(BOOL)useFastLoadingHack { diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.h b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.h index 8a4af6136..0a71e6e3f 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.h +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.h @@ -11,11 +11,11 @@ typedef NS_ENUM(NSInteger, CSVic20Country) { + CSVic20CountryAmerican, CSVic20CountryDanish, CSVic20CountryEuropean, CSVic20CountryJapanese, - CSVic20CountrySwedish, - CSVic20CountryAmerican + CSVic20CountrySwedish }; typedef NS_ENUM(NSInteger, CSVic20MemorySize) diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm index fbfbbe20c..0e4977b9b 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm @@ -9,12 +9,6 @@ #import "CSVic20.h" #include "Vic20.hpp" -#include "CommodoreTAP.hpp" -#include "G64.hpp" -#include "D64.hpp" - -#import "CSmachine+Subclassing.h" -#import "NSBundle+DataResource.h" using namespace Commodore::Vic20; @@ -31,41 +25,11 @@ using namespace Commodore::Vic20; self = [super initWithMachine:machine]; if(self) { _vic20.reset(machine); - [self setDriveROM:[[NSBundle mainBundle] dataForResource:@"1540" withExtension:@"bin" subdirectory:@"ROMImages/Commodore1540"]]; - [self setBASICROM:[self rom:@"basic"]]; [self setCountry:CSVic20CountryEuropean]; } return self; } -- (NSData *)rom:(NSString *)name { - return [[NSBundle mainBundle] dataForResource:name withExtension:@"bin" subdirectory:@"ROMImages/Vic20"]; -} - -#pragma mark - ROM setting - -- (void)setROM:(nonnull NSData *)rom slot:(ROMSlot)slot { - @synchronized(self) { - _vic20->set_rom(slot, rom.length, (const uint8_t *)rom.bytes); - } -} - -- (void)setKernelROM:(nonnull NSData *)rom { - [self setROM:rom slot:Kernel]; -} - -- (void)setBASICROM:(nonnull NSData *)rom { - [self setROM:rom slot:BASIC]; -} - -- (void)setCharactersROM:(nonnull NSData *)rom { - [self setROM:rom slot:Characters]; -} - -- (void)setDriveROM:(nonnull NSData *)rom { - [self setROM:rom slot:Drive]; -} - #pragma mark - Keyboard map /*- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed { @@ -89,40 +53,17 @@ using namespace Commodore::Vic20; - (void)setCountry:(CSVic20Country)country { _country = country; - NSString *charactersROM, *kernelROM; Commodore::Vic20::Region region; switch(country) { - case CSVic20CountryDanish: - region = Commodore::Vic20::Region::PAL; - charactersROM = @"characters-danish"; - kernelROM = @"kernel-danish"; - break; - case CSVic20CountryEuropean: - region = Commodore::Vic20::Region::PAL; - charactersROM = @"characters-english"; - kernelROM = @"kernel-pal"; - break; - case CSVic20CountryJapanese: - region = Commodore::Vic20::Region::NTSC; - charactersROM = @"characters-japanese"; - kernelROM = @"kernel-japanese"; - break; - case CSVic20CountrySwedish: - region = Commodore::Vic20::Region::PAL; - charactersROM = @"characters-swedish"; - kernelROM = @"kernel-swedish"; - break; - case CSVic20CountryAmerican: - region = Commodore::Vic20::Region::NTSC; - charactersROM = @"characters-english"; - kernelROM = @"kernel-ntsc"; - break; + case CSVic20CountryDanish: region = Commodore::Vic20::Danish; break; + case CSVic20CountryEuropean: region = Commodore::Vic20::European; break; + case CSVic20CountryJapanese: region = Commodore::Vic20::Japanese; break; + case CSVic20CountrySwedish: region = Commodore::Vic20::Swedish; break; + case CSVic20CountryAmerican: region = Commodore::Vic20::American; break; } @synchronized(self) { _vic20->set_region(region); - [self setCharactersROM:[self rom:charactersROM]]; - [self setKernelROM:[self rom:kernelROM]]; } } diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm index fb5d07578..800c1b6f7 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm @@ -10,10 +10,6 @@ #include "ZX8081.hpp" -#import "CSMachine+Subclassing.h" -#import "NSData+StdVector.h" -#import "NSBundle+DataResource.h" - @implementation CSZX8081 { std::unique_ptr _zx8081; } @@ -24,16 +20,10 @@ self = [super initWithMachine:machine]; if(self) { _zx8081.reset(machine); - _zx8081->set_rom(ZX8081::ROMType::ZX80, [self rom:@"zx80"].stdVector8); - _zx8081->set_rom(ZX8081::ROMType::ZX81, [self rom:@"zx81"].stdVector8); } return self; } -- (NSData *)rom:(NSString *)name { - return [[NSBundle mainBundle] dataForResource:name withExtension:@"rom" subdirectory:@"ROMImages/ZX8081"]; -} - - (NSString *)userDefaultsPrefix { return @"zx8081"; } #pragma mark - Options From e10d369e53c56eb74039eac65f224b518d51746e Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 7 Nov 2017 22:32:59 -0500 Subject: [PATCH 13/14] Ensures that execution doesn't proceed if ROMs are missing. --- OSBindings/SDL/main.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index 9a1fb34fb..2363da84b 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -179,7 +179,7 @@ int main(int argc, char *argv[]) { // // /usr/local/share/CLK/[system]; or // /usr/share/CLK/[system] - machine->crt_machine()->set_rom_fetcher( [] (const std::string &machine, const std::vector &names) -> std::vector>> { + bool roms_loaded = machine->crt_machine()->set_rom_fetcher( [] (const std::string &machine, const std::vector &names) -> std::vector>> { std::vector>> results; for(auto &name: names) { std::string local_path = "/usr/local/share/CLK/" + machine + "/" + name; @@ -207,6 +207,11 @@ int main(int argc, char *argv[]) { return results; }); + + if(!roms_loaded) { + std::cerr << "Could not find system ROMs; please install to /usr/local/share/CLK/ or /usr/share/CLK/" << std::endl; + return -1; + } machine->configuration_target()->configure_as_target(targets.front()); From 16c96b605a1abba623e1c1bc899a99a7b141a984 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 7 Nov 2017 22:43:25 -0500 Subject: [PATCH 14/14] Xcode 9.1 auto-change. --- .../xcshareddata/xcschemes/Clock Signal.xcscheme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme index 952d0cbdc..b254c3119 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme +++ b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme @@ -72,7 +72,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - enableUBSanitizer = "YES" + disableMainThreadChecker = "YES" language = "" launchStyle = "0" useCustomWorkingDirectory = "NO"