mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	Compare commits
	
		
			16 Commits
		
	
	
		
			FluxEngine
			...
			FluxEngine
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 46f1b0aef4 | ||
|  | 9923d67a7c | ||
|  | 99335a84fd | ||
|  | c266779433 | ||
|  | bdcc12cd53 | ||
|  | 7988d0fe24 | ||
|  | 27f5c294b1 | ||
|  | b9a53e0d1c | ||
|  | f8b6d5e6fb | ||
|  | 04ff31c348 | ||
|  | 77b4aebd1b | ||
|  | 4056364300 | ||
|  | 60bfe050d3 | ||
|  | 28d0ce765e | ||
|  | 4954d33307 | ||
|  | 55f3354287 | 
| @@ -15,7 +15,7 @@ install: | |||||||
|  |  | ||||||
| build_script: | build_script: | ||||||
|   - make |   - make | ||||||
|   - zip -9 fluxengine.zip fluxengine.exe brother120tool.exe |   - zip -9 fluxengine.zip fluxengine.exe brother120tool.exe FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex | ||||||
|  |  | ||||||
| artifacts: | artifacts: | ||||||
|   - path: fluxengine.zip |   - path: fluxengine.zip | ||||||
|   | |||||||
							
								
								
									
										4626
									
								
								FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4626
									
								
								FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -530,31 +530,38 @@ | |||||||
| <CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFolderSerialize" version="3"> | <CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFolderSerialize" version="3"> | ||||||
| <CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtBaseContainerSerialize" version="1"> | <CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtBaseContainerSerialize" version="1"> | ||||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="LED" persistent=""> | <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="LED" persistent=""> | ||||||
| <Hidden v="False" /> | <Hidden v="True" /> | ||||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||||
| <CyGuid_0820c2e7-528d-4137-9a08-97257b946089 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemListSerialize" version="2"> | <CyGuid_0820c2e7-528d-4137-9a08-97257b946089 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemListSerialize" version="2"> | ||||||
| <dependencies> | <dependencies> | ||||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="LED_aliases.h" persistent="Generated_Source\PSoC5\LED_aliases.h"> | <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="LED_aliases.h" persistent="Generated_Source\PSoC5\LED_aliases.h"> | ||||||
| <Hidden v="False" /> | <Hidden v="True" /> | ||||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||||
| <build_action v="HEADER;;;;" /> | <build_action v="HEADER;;;;" /> | ||||||
| <PropertyDeltas /> | <PropertyDeltas /> | ||||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="LED.c" persistent="Generated_Source\PSoC5\LED.c"> | <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="LED.c" persistent="Generated_Source\PSoC5\LED.c"> | ||||||
| <Hidden v="False" /> | <Hidden v="True" /> | ||||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||||
| <build_action v="SOURCE_C;CortexM3;;;" /> | <build_action v="SOURCE_C;CortexM3;;;" /> | ||||||
| <PropertyDeltas /> | <PropertyDeltas /> | ||||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="LED.h" persistent="Generated_Source\PSoC5\LED.h"> | <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="LED.h" persistent="Generated_Source\PSoC5\LED.h"> | ||||||
| <Hidden v="False" /> | <Hidden v="True" /> | ||||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||||
| <build_action v="HEADER;;;;" /> | <build_action v="HEADER;;;;" /> | ||||||
| <PropertyDeltas /> | <PropertyDeltas /> | ||||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||||
|  | <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||||
|  | <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="LED_PM.c" persistent="Generated_Source\PSoC5\LED_PM.c"> | ||||||
|  | <Hidden v="True" /> | ||||||
|  | </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||||
|  | <build_action v="SOURCE_C;CortexM3;;;" /> | ||||||
|  | <PropertyDeltas /> | ||||||
|  | </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||||
| </dependencies> | </dependencies> | ||||||
| </CyGuid_0820c2e7-528d-4137-9a08-97257b946089> | </CyGuid_0820c2e7-528d-4137-9a08-97257b946089> | ||||||
| </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | ||||||
| @@ -3282,6 +3289,39 @@ | |||||||
| </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | ||||||
| <filters /> | <filters /> | ||||||
| </CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0> | </CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0> | ||||||
|  | <CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFolderSerialize" version="3"> | ||||||
|  | <CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtBaseContainerSerialize" version="1"> | ||||||
|  | <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="LED_PIN" persistent=""> | ||||||
|  | <Hidden v="False" /> | ||||||
|  | </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||||
|  | <CyGuid_0820c2e7-528d-4137-9a08-97257b946089 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemListSerialize" version="2"> | ||||||
|  | <dependencies> | ||||||
|  | <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||||
|  | <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="LED_PIN_aliases.h" persistent="Generated_Source\PSoC5\LED_PIN_aliases.h"> | ||||||
|  | <Hidden v="False" /> | ||||||
|  | </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||||
|  | <build_action v="HEADER;;;;" /> | ||||||
|  | <PropertyDeltas /> | ||||||
|  | </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||||
|  | <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||||
|  | <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="LED_PIN.c" persistent="Generated_Source\PSoC5\LED_PIN.c"> | ||||||
|  | <Hidden v="False" /> | ||||||
|  | </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||||
|  | <build_action v="SOURCE_C;CortexM3;;;" /> | ||||||
|  | <PropertyDeltas /> | ||||||
|  | </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||||
|  | <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||||
|  | <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="LED_PIN.h" persistent="Generated_Source\PSoC5\LED_PIN.h"> | ||||||
|  | <Hidden v="False" /> | ||||||
|  | </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||||
|  | <build_action v="HEADER;;;;" /> | ||||||
|  | <PropertyDeltas /> | ||||||
|  | </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||||
|  | </dependencies> | ||||||
|  | </CyGuid_0820c2e7-528d-4137-9a08-97257b946089> | ||||||
|  | </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | ||||||
|  | <filters /> | ||||||
|  | </CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0> | ||||||
| </dependencies> | </dependencies> | ||||||
| </CyGuid_0820c2e7-528d-4137-9a08-97257b946089> | </CyGuid_0820c2e7-528d-4137-9a08-97257b946089> | ||||||
| </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | ||||||
| @@ -3700,6 +3740,6 @@ | |||||||
| </ignored_deps> | </ignored_deps> | ||||||
| </CyGuid_495451fe-d201-4d01-b22d-5d3f5609ac37> | </CyGuid_495451fe-d201-4d01-b22d-5d3f5609ac37> | ||||||
| <boot_component v="" /> | <boot_component v="" /> | ||||||
| <current_generation v="60" /> | <current_generation v="68" /> | ||||||
| </CyGuid_fec8f9e8-2365-4bdb-96d3-a4380222e01b> | </CyGuid_fec8f9e8-2365-4bdb-96d3-a4380222e01b> | ||||||
| </CyXmlSerializer> | </CyXmlSerializer> | ||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -134,6 +134,9 @@ void IbmDecoder::decodeSectorRecord() | |||||||
|     uint16_t gotCrc = crc16(CCITT_POLY, bytes.slice(0, _currentHeaderLength + 5)); |     uint16_t gotCrc = crc16(CCITT_POLY, bytes.slice(0, _currentHeaderLength + 5)); | ||||||
|     if (wantCrc == gotCrc) |     if (wantCrc == gotCrc) | ||||||
|         _sector->status = Sector::DATA_MISSING; /* correct but unintuitive */ |         _sector->status = Sector::DATA_MISSING; /* correct but unintuitive */ | ||||||
|  |  | ||||||
|  |     if (_ignoreSideByte) | ||||||
|  |         _sector->logicalSide = _sector->physicalSide; | ||||||
| } | } | ||||||
|  |  | ||||||
| void IbmDecoder::decodeDataRecord() | void IbmDecoder::decodeDataRecord() | ||||||
|   | |||||||
| @@ -31,8 +31,9 @@ struct IbmIdam | |||||||
| class IbmDecoder : public AbstractDecoder | class IbmDecoder : public AbstractDecoder | ||||||
| { | { | ||||||
| public: | public: | ||||||
|     IbmDecoder(unsigned sectorBase): |     IbmDecoder(unsigned sectorBase, bool ignoreSideByte=false): | ||||||
|         _sectorBase(sectorBase) |         _sectorBase(sectorBase), | ||||||
|  |         _ignoreSideByte(ignoreSideByte) | ||||||
|     {} |     {} | ||||||
|  |  | ||||||
|     RecordType advanceToNextRecord(); |     RecordType advanceToNextRecord(); | ||||||
| @@ -41,6 +42,7 @@ public: | |||||||
|  |  | ||||||
| private: | private: | ||||||
|     unsigned _sectorBase; |     unsigned _sectorBase; | ||||||
|  |     bool _ignoreSideByte; | ||||||
|     unsigned _currentSectorSize; |     unsigned _currentSectorSize; | ||||||
|     unsigned _currentHeaderLength; |     unsigned _currentHeaderLength; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -103,7 +103,43 @@ the unconnected pins and solder a short piece of wire to a GND pin on the | |||||||
| board. Alternatively you'll need to splice it into your drive's power supply | board. Alternatively you'll need to splice it into your drive's power supply | ||||||
| cable somehow. (The black one.) | cable somehow. (The black one.) | ||||||
|  |  | ||||||
| ## Building the firmware | ## Programming the board | ||||||
|  |  | ||||||
|  | You've got two options here. You can either use the precompiled firmware | ||||||
|  | supplied with the source, or else install the Cypress SDK and build it | ||||||
|  | yourself. If you want to hack the firmware source you need the latter, but | ||||||
|  | if you trust me to do it for you use the precompiled firmware. In either | ||||||
|  | case you'll need Windows and have to install some Cypress stuff. | ||||||
|  |  | ||||||
|  | **Before you read this:** If you're on Windows, good news! You can download a | ||||||
|  | precompiled version of the FluxEngine client and precompiled firmware [from | ||||||
|  | the GitHub releases | ||||||
|  | page](https://github.com/davidgiven/fluxengine/releases/latest). Simply unzip | ||||||
|  | it somewhere and run the `.exe` files from a `cmd` window (or other shell). | ||||||
|  | Follow the instructions below to program the board with the firmware. | ||||||
|  |  | ||||||
|  | ### Using the precompiled firmware | ||||||
|  |  | ||||||
|  | On your Windows machine, [install the PSoC | ||||||
|  | Programmer](https://www.cypress.com/products/psoc-programming-solutions). | ||||||
|  | **Note:** _not_ the Cypress Programmer, which is for a different board! | ||||||
|  | Cypress will make you register. | ||||||
|  |  | ||||||
|  | Once done, run it. Plug the blunt end of the FluxEngine board into a USB | ||||||
|  | port (the end which is a USB connector). The programmer should detect it | ||||||
|  | and report it as a KitProg. You may be prompted to upgrade the programmer | ||||||
|  | hardware; if so, follow the instructions and do it. | ||||||
|  |  | ||||||
|  | Now go to File -> File Load and open | ||||||
|  | `FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex` in the | ||||||
|  | project. If you're on Windows, the precompiled zipfile also contains a copy | ||||||
|  | of this file. Press the Program button (the one in the toolbar marked with a | ||||||
|  | down arrow). Stuff will happen and you should be left with three green boxes | ||||||
|  | in the status bar and 'Programming Succeeded' at the top of the log window. | ||||||
|  |  | ||||||
|  | You're done. You can unplug the board and close the programmer. | ||||||
|  |  | ||||||
|  | ### Building the firmware yourself | ||||||
|  |  | ||||||
| On your Windows machine, [install the Cypress SDK and CY8CKIT-059 | On your Windows machine, [install the Cypress SDK and CY8CKIT-059 | ||||||
| BSP](http://www.cypress.com/documentation/development-kitsboards/cy8ckit-059-psoc-5lp-prototyping-kit-onboard-programmer-and). | BSP](http://www.cypress.com/documentation/development-kitsboards/cy8ckit-059-psoc-5lp-prototyping-kit-onboard-programmer-and). | ||||||
| @@ -118,7 +154,7 @@ tutorial and making the LED on your board flash. It'll tell you where all the | |||||||
| controls are and how to program the board. Remember that the big end of the | controls are and how to program the board. Remember that the big end of the | ||||||
| board plugs into your computer for programming. | board plugs into your computer for programming. | ||||||
|  |  | ||||||
| When you're ready, open the `FluxEngine.cydsn/FluxEngine.cywrk` workspace, | When you're ready, open the `FluxEngine.cydsn/FluxEngine.cyprj` project, | ||||||
| pick 'Program' from the menu, and the firmware should compile and be | pick 'Program' from the menu, and the firmware should compile and be | ||||||
| programmed onto your board. | programmed onto your board. | ||||||
|  |  | ||||||
| @@ -139,11 +175,6 @@ the port and proceed normally. | |||||||
|  |  | ||||||
| ## Building the client | ## Building the client | ||||||
|  |  | ||||||
| **Before you read this:** If you're on Windows, good news! You can download a |  | ||||||
| *precompiled version of the FluxEngine client [from the GitHub releases |  | ||||||
| *page](https://github.com/davidgiven/fluxengine/releases/latest). Simply unzip |  | ||||||
| *it somewhere and run it from a `cmd` window (or other shell). |  | ||||||
|  |  | ||||||
| The client software is where the intelligence, such as it is, is. It's pretty | The client software is where the intelligence, such as it is, is. It's pretty | ||||||
| generic libusb stuff and should build and run on Windows, Linux and OSX as | generic libusb stuff and should build and run on Windows, Linux and OSX as | ||||||
| well, although on Windows it'll need MSYS2 and mingw32. You'll need to | well, although on Windows it'll need MSYS2 and mingw32. You'll need to | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								doc/using.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								doc/using.md
									
									
									
									
									
								
							| @@ -225,6 +225,21 @@ Commands which normally take `--source` or `--dest` get a sensible default if | |||||||
| left unspecified. `fluxengine read ibm` on its own will read drive 0 and | left unspecified. `fluxengine read ibm` on its own will read drive 0 and | ||||||
| write an `ibm.img` file. | write an `ibm.img` file. | ||||||
|  |  | ||||||
|  | ## Visualisation | ||||||
|  |  | ||||||
|  | When doing a read (either from a real disk or from a flux file) you can use | ||||||
|  | `--write-svg=output.svg` to write out a graphical visualisation of where the | ||||||
|  | sectors are on the disk. Here's a IBM PC 1232kB disk: | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Blue represents data, light blue a header, and red is a bad sector. Side zero | ||||||
|  | is on the left and side one is on the right. | ||||||
|  |  | ||||||
|  | The visualiser is extremely primitive and you have to explicitly tell it how | ||||||
|  | big your disk is, in milliseconds. The default is 200ms (for a normal 3.5" | ||||||
|  | disk). For a 5.25" disk, use `--visualiser-period=166`. | ||||||
|  |  | ||||||
| ## Extra programs | ## Extra programs | ||||||
|  |  | ||||||
| Supplied with FluxEngine, but not part of FluxEngine, are some little tools I | Supplied with FluxEngine, but not part of FluxEngine, are some little tools I | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								doc/visualiser.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								doc/visualiser.svg
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| After Width: | Height: | Size: 394 KiB | 
| @@ -43,19 +43,25 @@ void AbstractDecoder::decodeToSectors(Track& track) | |||||||
|  |  | ||||||
|         recordStart = fmr.tell(); |         recordStart = fmr.tell(); | ||||||
|         decodeSectorRecord(); |         decodeSectorRecord(); | ||||||
|         pushRecord(recordStart, fmr.tell()); |         Fluxmap::Position recordEnd = fmr.tell(); | ||||||
|  |         pushRecord(recordStart, recordEnd); | ||||||
|         if (sector.status == Sector::DATA_MISSING) |         if (sector.status == Sector::DATA_MISSING) | ||||||
|         { |         { | ||||||
|             /* The data is in a separate record. */ |             /* The data is in a separate record. */ | ||||||
|  |  | ||||||
|  |             sector.headerStartTime = recordStart.ns(); | ||||||
|  |             sector.headerEndTime = recordEnd.ns(); | ||||||
|             r = advanceToNextRecord(); |             r = advanceToNextRecord(); | ||||||
|             if (r == DATA_RECORD) |             if (r == DATA_RECORD) | ||||||
|             { |             { | ||||||
|                 recordStart = fmr.tell(); |                 recordStart = fmr.tell(); | ||||||
|                 decodeDataRecord(); |                 decodeDataRecord(); | ||||||
|                 pushRecord(recordStart, fmr.tell()); |                 recordEnd = fmr.tell(); | ||||||
|  |                 pushRecord(recordStart, recordEnd); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         sector.dataStartTime = recordStart.ns(); | ||||||
|  |         sector.dataEndTime = recordEnd.ns(); | ||||||
|  |  | ||||||
|         if (sector.status != Sector::MISSING) |         if (sector.status != Sector::MISSING) | ||||||
|             track.sectors.push_back(sector); |             track.sectors.push_back(sector); | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ public: | |||||||
|     void recalibrate() {} |     void recalibrate() {} | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     const std::string& _path; |     const std::string _path; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| std::unique_ptr<FluxSource> FluxSource::createStreamFluxSource(const std::string& path) | std::unique_ptr<FluxSource> FluxSource::createStreamFluxSource(const std::string& path) | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ extern void hexdumpForSrp16(std::ostream& stream, const Bytes& bytes); | |||||||
| class Error | class Error | ||||||
| { | { | ||||||
| public: | public: | ||||||
|     ~Error() |     [[ noreturn ]] ~Error() | ||||||
|     { |     { | ||||||
|         std::cerr << "Error: " << _stream.str() << std::endl; |         std::cerr << "Error: " << _stream.str() << std::endl; | ||||||
|         exit(1); |         exit(1); | ||||||
|   | |||||||
| @@ -7,6 +7,13 @@ | |||||||
| #include "imagereader/imagereader.h" | #include "imagereader/imagereader.h" | ||||||
| #include "fmt/format.h" | #include "fmt/format.h" | ||||||
|  |  | ||||||
|  | std::map<std::string, ImageReader::Constructor> ImageReader::formats = | ||||||
|  | { | ||||||
|  | 	{".adf", ImageReader::createImgImageReader}, | ||||||
|  | 	{".d81", ImageReader::createImgImageReader}, | ||||||
|  | 	{".img", ImageReader::createImgImageReader}, | ||||||
|  | }; | ||||||
|  |  | ||||||
| static bool ends_with(const std::string& value, const std::string& ending) | static bool ends_with(const std::string& value, const std::string& ending) | ||||||
| { | { | ||||||
|     if (ending.size() > value.size()) |     if (ending.size() > value.size()) | ||||||
| @@ -14,15 +21,29 @@ static bool ends_with(const std::string& value, const std::string& ending) | |||||||
|     return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); |     return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); | ||||||
| } | } | ||||||
|  |  | ||||||
| std::unique_ptr<ImageReader> ImageReader::create(const ImageSpec& spec) | ImageReader::Constructor ImageReader::findConstructor(const ImageSpec& spec) | ||||||
| { | { | ||||||
|     const auto& filename = spec.filename; |     const auto& filename = spec.filename; | ||||||
|  |  | ||||||
|     if (ends_with(filename, ".img") || ends_with(filename, ".adf")) | 	for (const auto& e : formats) | ||||||
|         return createImgImageReader(spec); | 	{ | ||||||
|  | 		if (ends_with(filename, e.first)) | ||||||
|  | 			return e.second; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|     Error() << "unrecognised image filename extension"; | 	return NULL; | ||||||
|     return std::unique_ptr<ImageReader>(); | } | ||||||
|  |  | ||||||
|  | std::unique_ptr<ImageReader> ImageReader::create(const ImageSpec& spec) | ||||||
|  | { | ||||||
|  |     verifyImageSpec(spec); | ||||||
|  |     return findConstructor(spec)(spec); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ImageReader::verifyImageSpec(const ImageSpec& spec) | ||||||
|  | { | ||||||
|  |     if (!findConstructor(spec)) | ||||||
|  |         Error() << "unrecognised image filename extension"; | ||||||
| } | } | ||||||
|  |  | ||||||
| ImageReader::ImageReader(const ImageSpec& spec): | ImageReader::ImageReader(const ImageSpec& spec): | ||||||
|   | |||||||
| @@ -12,10 +12,21 @@ public: | |||||||
|  |  | ||||||
| public: | public: | ||||||
|     static std::unique_ptr<ImageReader> create(const ImageSpec& spec); |     static std::unique_ptr<ImageReader> create(const ImageSpec& spec); | ||||||
|  | 	static void verifyImageSpec(const ImageSpec& spec); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|  | 	typedef  | ||||||
|  | 		std::function< | ||||||
|  | 			std::unique_ptr<ImageReader>(const ImageSpec& spec) | ||||||
|  | 		> | ||||||
|  | 		Constructor; | ||||||
|  |  | ||||||
|  | 	static std::map<std::string, Constructor> formats; | ||||||
|  |  | ||||||
|     static std::unique_ptr<ImageReader> createImgImageReader(const ImageSpec& spec); |     static std::unique_ptr<ImageReader> createImgImageReader(const ImageSpec& spec); | ||||||
|  |  | ||||||
|  | 	static Constructor findConstructor(const ImageSpec& spec); | ||||||
|  |  | ||||||
| public: | public: | ||||||
| 	virtual SectorSet readImage() = 0; | 	virtual SectorSet readImage() = 0; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,6 +7,15 @@ | |||||||
| #include "imagewriter/imagewriter.h" | #include "imagewriter/imagewriter.h" | ||||||
| #include "fmt/format.h" | #include "fmt/format.h" | ||||||
|  |  | ||||||
|  | std::map<std::string, ImageWriter::Constructor> ImageWriter::formats = | ||||||
|  | { | ||||||
|  | 	{".adf", ImageWriter::createImgImageWriter}, | ||||||
|  | 	{".d64", ImageWriter::createD64ImageWriter}, | ||||||
|  | 	{".d81", ImageWriter::createImgImageWriter}, | ||||||
|  | 	{".img", ImageWriter::createImgImageWriter}, | ||||||
|  | 	{".ldbs", ImageWriter::createLDBSImageWriter}, | ||||||
|  | }; | ||||||
|  |  | ||||||
| static bool ends_with(const std::string& value, const std::string& ending) | static bool ends_with(const std::string& value, const std::string& ending) | ||||||
| { | { | ||||||
|     if (ending.size() > value.size()) |     if (ending.size() > value.size()) | ||||||
| @@ -14,19 +23,29 @@ static bool ends_with(const std::string& value, const std::string& ending) | |||||||
|     return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); |     return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); | ||||||
| } | } | ||||||
|  |  | ||||||
| std::unique_ptr<ImageWriter> ImageWriter::create(const SectorSet& sectors, const ImageSpec& spec) | ImageWriter::Constructor ImageWriter::findConstructor(const ImageSpec& spec) | ||||||
| { | { | ||||||
|     const auto& filename = spec.filename; |     const auto& filename = spec.filename; | ||||||
|  |  | ||||||
|     if (ends_with(filename, ".img") || ends_with(filename, ".adf")) | 	for (const auto& e : formats) | ||||||
|         return createImgImageWriter(sectors, spec); | 	{ | ||||||
| 	else if (ends_with(filename, ".ldbs")) | 		if (ends_with(filename, e.first)) | ||||||
| 		return createLDBSImageWriter(sectors, spec); | 			return e.second; | ||||||
| 	else if (ends_with(filename, ".d64")) | 	} | ||||||
| 		return createD64ImageWriter(sectors, spec); |  | ||||||
|  |  | ||||||
|     Error() << "unrecognised image filename extension"; | 	return NULL; | ||||||
|     return std::unique_ptr<ImageWriter>(); | } | ||||||
|  |  | ||||||
|  | std::unique_ptr<ImageWriter> ImageWriter::create(const SectorSet& sectors, const ImageSpec& spec) | ||||||
|  | { | ||||||
|  | 	verifyImageSpec(spec); | ||||||
|  | 	return findConstructor(spec)(sectors, spec); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ImageWriter::verifyImageSpec(const ImageSpec& spec) | ||||||
|  | { | ||||||
|  | 	if (!findConstructor(spec)) | ||||||
|  | 		Error() << "unrecognised image filename extension"; | ||||||
| } | } | ||||||
|  |  | ||||||
| ImageWriter::ImageWriter(const SectorSet& sectors, const ImageSpec& spec): | ImageWriter::ImageWriter(const SectorSet& sectors, const ImageSpec& spec): | ||||||
|   | |||||||
| @@ -12,8 +12,17 @@ public: | |||||||
|  |  | ||||||
| public: | public: | ||||||
|     static std::unique_ptr<ImageWriter> create(const SectorSet& sectors, const ImageSpec& spec); |     static std::unique_ptr<ImageWriter> create(const SectorSet& sectors, const ImageSpec& spec); | ||||||
|  | 	static void verifyImageSpec(const ImageSpec& filename); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|  | 	typedef  | ||||||
|  | 		std::function< | ||||||
|  | 			std::unique_ptr<ImageWriter>(const SectorSet& sectors, const ImageSpec& spec) | ||||||
|  | 		> | ||||||
|  | 		Constructor; | ||||||
|  |  | ||||||
|  | 	static std::map<std::string, Constructor> formats; | ||||||
|  |  | ||||||
|     static std::unique_ptr<ImageWriter> createImgImageWriter( |     static std::unique_ptr<ImageWriter> createImgImageWriter( | ||||||
| 		const SectorSet& sectors, const ImageSpec& spec); | 		const SectorSet& sectors, const ImageSpec& spec); | ||||||
|     static std::unique_ptr<ImageWriter> createLDBSImageWriter( |     static std::unique_ptr<ImageWriter> createLDBSImageWriter( | ||||||
| @@ -21,6 +30,8 @@ private: | |||||||
|     static std::unique_ptr<ImageWriter> createD64ImageWriter( |     static std::unique_ptr<ImageWriter> createD64ImageWriter( | ||||||
| 		const SectorSet& sectors, const ImageSpec& spec); | 		const SectorSet& sectors, const ImageSpec& spec); | ||||||
|  |  | ||||||
|  | 	static Constructor findConstructor(const ImageSpec& spec); | ||||||
|  |  | ||||||
| public: | public: | ||||||
| 	virtual void adjustGeometry(); | 	virtual void adjustGeometry(); | ||||||
| 	void printMap(); | 	void printMap(); | ||||||
|   | |||||||
| @@ -9,14 +9,16 @@ | |||||||
| #include "decoders/decoders.h" | #include "decoders/decoders.h" | ||||||
| #include "sector.h" | #include "sector.h" | ||||||
| #include "sectorset.h" | #include "sectorset.h" | ||||||
|  | #include "visualiser.h" | ||||||
| #include "record.h" | #include "record.h" | ||||||
| #include "image.h" | #include "image.h" | ||||||
| #include "bytes.h" | #include "bytes.h" | ||||||
| #include "decoders/rawbits.h" | #include "decoders/rawbits.h" | ||||||
| #include "track.h" | #include "track.h" | ||||||
|  | #include "imagewriter/imagewriter.h" | ||||||
| #include "fmt/format.h" | #include "fmt/format.h" | ||||||
|  |  | ||||||
| FlagGroup readerFlags { &hardwareFluxSourceFlags, &fluxmapReaderFlags }; | FlagGroup readerFlags { &hardwareFluxSourceFlags, &fluxmapReaderFlags, &visualiserFlags }; | ||||||
|  |  | ||||||
| static DataSpecFlag source( | static DataSpecFlag source( | ||||||
|     { "--source", "-s" }, |     { "--source", "-s" }, | ||||||
| @@ -33,6 +35,11 @@ static StringFlag destination( | |||||||
|     "write the raw magnetic flux to this file", |     "write the raw magnetic flux to this file", | ||||||
|     ""); |     ""); | ||||||
|  |  | ||||||
|  | static StringFlag visualise( | ||||||
|  | 	{ "--write-svg" }, | ||||||
|  | 	"write a visualisation of the disk to this file", | ||||||
|  | 	""); | ||||||
|  |  | ||||||
| static SettableFlag justRead( | static SettableFlag justRead( | ||||||
| 	{ "--just-read" }, | 	{ "--just-read" }, | ||||||
| 	"just read the disk and do no further processing"); | 	"just read the disk and do no further processing"); | ||||||
| @@ -142,7 +149,7 @@ static void replace_sector(std::unique_ptr<Sector>& replacing, Sector& replaceme | |||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if (!replacing || (replacing->status != Sector::OK)) | 	if (!replacing || ((replacing->status != Sector::OK) && (replacement.status == Sector::OK))) | ||||||
| 	{ | 	{ | ||||||
| 		if (!replacing) | 		if (!replacing) | ||||||
| 			replacing.reset(new Sector); | 			replacing.reset(new Sector); | ||||||
| @@ -153,7 +160,8 @@ static void replace_sector(std::unique_ptr<Sector>& replacing, Sector& replaceme | |||||||
| void readDiskCommand(AbstractDecoder& decoder) | void readDiskCommand(AbstractDecoder& decoder) | ||||||
| { | { | ||||||
| 	const ImageSpec outputSpec(output); | 	const ImageSpec outputSpec(output); | ||||||
|  | 	ImageWriter::verifyImageSpec(outputSpec); | ||||||
|  |          | ||||||
| 	bool failures = false; | 	bool failures = false; | ||||||
| 	SectorSet allSectors; | 	SectorSet allSectors; | ||||||
| 	auto tracks = readTracks(); | 	auto tracks = readTracks(); | ||||||
| @@ -251,6 +259,9 @@ void readDiskCommand(AbstractDecoder& decoder) | |||||||
|         std::cout << size << " bytes decoded." << std::endl; |         std::cout << size << " bytes decoded." << std::endl; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | 	if (!visualise.get().empty()) | ||||||
|  | 		visualiseSectorsToFile(allSectors, visualise.get()); | ||||||
|  |  | ||||||
|     writeSectorsToFile(allSectors, outputSpec); |     writeSectorsToFile(allSectors, outputSpec); | ||||||
| 	if (failures) | 	if (failures) | ||||||
| 		std::cerr << "Warning: some sectors could not be decoded." << std::endl; | 		std::cerr << "Warning: some sectors could not be decoded." << std::endl; | ||||||
|   | |||||||
| @@ -27,6 +27,10 @@ public: | |||||||
| 	Status status = Status::INTERNAL_ERROR; | 	Status status = Status::INTERNAL_ERROR; | ||||||
|     Fluxmap::Position position; |     Fluxmap::Position position; | ||||||
|     nanoseconds_t clock = 0; |     nanoseconds_t clock = 0; | ||||||
|  |     nanoseconds_t headerStartTime = 0; | ||||||
|  |     nanoseconds_t headerEndTime = 0; | ||||||
|  |     nanoseconds_t dataStartTime = 0; | ||||||
|  |     nanoseconds_t dataEndTime = 0; | ||||||
|     int physicalTrack = 0; |     int physicalTrack = 0; | ||||||
|     int physicalSide = 0; |     int physicalSide = 0; | ||||||
|     int logicalTrack = 0; |     int logicalTrack = 0; | ||||||
|   | |||||||
| @@ -17,6 +17,9 @@ public: | |||||||
| 	std::unique_ptr<Sector>& get(int track, int head, int sector); | 	std::unique_ptr<Sector>& get(int track, int head, int sector); | ||||||
| 	Sector* get(int track, int head, int sector) const; | 	Sector* get(int track, int head, int sector) const; | ||||||
|  |  | ||||||
|  | 	const std::map<const key_t, std::unique_ptr<Sector>>& get() const | ||||||
|  | 	{ return _data; } | ||||||
|  |  | ||||||
| 	void calculateSize( | 	void calculateSize( | ||||||
| 		unsigned& numTracks, unsigned& numHeads, unsigned& numSectors, | 		unsigned& numTracks, unsigned& numHeads, unsigned& numSectors, | ||||||
| 		unsigned& sectorSize) const; | 		unsigned& sectorSize) const; | ||||||
|   | |||||||
							
								
								
									
										95
									
								
								lib/visualiser.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								lib/visualiser.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | |||||||
|  | #define _USE_MATH_DEFINES | ||||||
|  | #include "globals.h" | ||||||
|  | #include "image.h" | ||||||
|  | #include "sector.h" | ||||||
|  | #include "sectorset.h" | ||||||
|  | #include "visualiser.h" | ||||||
|  | #include "fmt/format.h" | ||||||
|  | #include "flags.h" | ||||||
|  | #include <iostream> | ||||||
|  | #include <fstream> | ||||||
|  | #include <math.h> | ||||||
|  |  | ||||||
|  | FlagGroup visualiserFlags; | ||||||
|  |  | ||||||
|  | static IntFlag period( | ||||||
|  |     { "--visualiser-period" }, | ||||||
|  |     "rotational period for use by the visualiser (milliseconds)", | ||||||
|  |     200); | ||||||
|  |  | ||||||
|  | static const int SIZE = 480; | ||||||
|  | static const int BORDER = 10; | ||||||
|  | static const int RADIUS = (SIZE/2) - (BORDER/2); | ||||||
|  | static const int CORE = 50; | ||||||
|  | static const int TRACKS = 83; | ||||||
|  | static const double TRACK_SPACING = double(RADIUS-CORE) / TRACKS; | ||||||
|  |  | ||||||
|  | void visualiseSectorsToFile(const SectorSet& sectors, const std::string& filename) | ||||||
|  | { | ||||||
|  |     std::cout << "writing visualisation\n"; | ||||||
|  |     std::ofstream f(filename, std::ios::out); | ||||||
|  |     if (!f.is_open()) | ||||||
|  |         Error() << "cannot open visualisation file"; | ||||||
|  |  | ||||||
|  |     f << fmt::format("<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"{0} {1} {2} {3}\">", | ||||||
|  |         0, 0, SIZE*2, SIZE); | ||||||
|  |  | ||||||
|  |     const double radians_per_ns = 2.0*M_PI / (period*1e6); | ||||||
|  |  | ||||||
|  |     auto drawSide = [&](int side) | ||||||
|  |     { | ||||||
|  |         f << fmt::format("<g transform='matrix(1 0 0 -1 {} {})'>", SIZE/2 + (side*SIZE), SIZE/2); | ||||||
|  |         f << fmt::format("<circle cx='0' cy='0' r='{}' stroke='none' fill='#ccc'/>", RADIUS); | ||||||
|  |  | ||||||
|  |         for (int physicalTrack = 0; physicalTrack < TRACKS; physicalTrack++) | ||||||
|  |         { | ||||||
|  |             double radius = CORE + physicalTrack*TRACK_SPACING; | ||||||
|  |             f << fmt::format("<circle cx='0' cy='0' r='{}' stroke='#888' stroke-width='0.5' fill='none'/>", radius); | ||||||
|  |  | ||||||
|  |             auto drawArc = [&](const std::unique_ptr<Sector>& sector, nanoseconds_t start, nanoseconds_t end, const std::string& colour) | ||||||
|  |             { | ||||||
|  |                 start %= period*1000000; | ||||||
|  |                 end %= period*1000000; | ||||||
|  |                 if (end < start) | ||||||
|  |                     end += period*1000000; | ||||||
|  |                  | ||||||
|  |                 double theta1 = start * radians_per_ns; | ||||||
|  |                 double theta2 = end * radians_per_ns; | ||||||
|  |                 int large = (theta2 - theta1) >= M_PI; | ||||||
|  |  | ||||||
|  |                 f << fmt::format("\n<!-- {} {} = {} {} -->", start, end, theta1, theta2); | ||||||
|  |                 f << fmt::format("<path fill='none' stroke='{}' stroke-width='1.5' d='", colour); | ||||||
|  |                 f << fmt::format("M {} {} ", cos(theta1)*radius, sin(theta1)*radius); | ||||||
|  |                 f << fmt::format("A {0} {0} 0 {3} 1 {1} {2}", radius, cos(theta2)*radius, sin(theta2)*radius, large); | ||||||
|  |                 f << fmt::format("'><title>Track {} Head {} Sector {}; {}ms to {}ms</title></path>", | ||||||
|  |                     sector->logicalTrack, sector->logicalSide, sector->logicalSector, | ||||||
|  |                     start/1e6, end/1e6); | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             /* Sadly, SectorSets aren't indexable by physical track. */ | ||||||
|  |             for (const auto& e : sectors.get()) | ||||||
|  |             { | ||||||
|  |                 const auto& sector = e.second; | ||||||
|  |                 if ((sector->physicalSide == side) && (sector->physicalTrack == physicalTrack)) | ||||||
|  |                 { | ||||||
|  |                     const char* colour = "#f00"; | ||||||
|  |                     if (sector->status == Sector::OK) | ||||||
|  |                         colour = "#00f"; | ||||||
|  |                     if (sector->headerStartTime && sector->headerEndTime) | ||||||
|  |                         drawArc(sector, sector->headerStartTime, sector->headerEndTime, "#0ff"); | ||||||
|  |                     if (sector->dataStartTime && sector->dataEndTime) | ||||||
|  |                         drawArc(sector, sector->dataStartTime, sector->dataEndTime, colour); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         f << "</g>"; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     f << fmt::format("<rect x='0' y='0' width='{}' height='{}' stroke='none' fill='#fff'/>", SIZE*2, SIZE); | ||||||
|  |  | ||||||
|  |     drawSide(0); | ||||||
|  |     drawSide(1); | ||||||
|  |  | ||||||
|  |     f << "</svg>"; | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								lib/visualiser.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								lib/visualiser.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | #ifndef VISUALISER_H | ||||||
|  | #define VISUALISER_H | ||||||
|  |  | ||||||
|  | #include "flags.h" | ||||||
|  |  | ||||||
|  | class SectorSet; | ||||||
|  |  | ||||||
|  | extern FlagGroup visualiserFlags; | ||||||
|  |  | ||||||
|  | extern void visualiseSectorsToFile(const SectorSet& sectors, const std::string& filename); | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -183,6 +183,7 @@ buildlibrary libbackend.a \ | |||||||
|     lib/sectorset.cc \ |     lib/sectorset.cc \ | ||||||
|     lib/sql.cc \ |     lib/sql.cc \ | ||||||
|     lib/usb.cc \ |     lib/usb.cc \ | ||||||
|  |     lib/visualiser.cc \ | ||||||
|     lib/writer.cc \ |     lib/writer.cc \ | ||||||
|  |  | ||||||
| buildlibrary libfrontend.a \ | buildlibrary libfrontend.a \ | ||||||
|   | |||||||
| @@ -17,13 +17,18 @@ static IntFlag sectorIdBase( | |||||||
| 	"Sector ID of the first sector.", | 	"Sector ID of the first sector.", | ||||||
| 	1); | 	1); | ||||||
|  |  | ||||||
|  | static BoolFlag ignoreSideByte( | ||||||
|  | 	{ "--ignore-side-byte" }, | ||||||
|  | 	"Ignore the side byte in the sector ID, and use the physical side instead.", | ||||||
|  | 	false); | ||||||
|  |  | ||||||
| int mainReadIBM(int argc, const char* argv[]) | int mainReadIBM(int argc, const char* argv[]) | ||||||
| { | { | ||||||
| 	setReaderDefaultSource(":t=0-79:s=0-1"); | 	setReaderDefaultSource(":t=0-79:s=0-1"); | ||||||
| 	setReaderDefaultOutput("ibm.img"); | 	setReaderDefaultOutput("ibm.img"); | ||||||
|     flags.parseFlags(argc, argv); |     flags.parseFlags(argc, argv); | ||||||
|  |  | ||||||
| 	IbmDecoder decoder(sectorIdBase); | 	IbmDecoder decoder(sectorIdBase, ignoreSideByte); | ||||||
| 	readDiskCommand(decoder); | 	readDiskCommand(decoder); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user