mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-31 11:17:01 -07:00 
			
		
		
		
	Compare commits
	
		
			576 Commits
		
	
	
		
			FluxEngine
			...
			375/merge
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					0457282d47 | ||
| 
						 | 
					06d8609200 | ||
| 
						 | 
					fa975b5511 | ||
| 
						 | 
					194b9b1193 | ||
| 
						 | 
					27fceb3f41 | ||
| 
						 | 
					930e0bcd67 | ||
| 
						 | 
					d81e0a3ed4 | ||
| 
						 | 
					5f5f22c82b | ||
| 
						 | 
					709e300960 | ||
| 
						 | 
					d2f677d84e | ||
| 
						 | 
					18d90c44dd | ||
| 
						 | 
					298f77f52e | ||
| 
						 | 
					70b2f7efb4 | ||
| 
						 | 
					78a070bd99 | ||
| 
						 | 
					c88ff973b1 | ||
| 
						 | 
					d36a18c17a | ||
| 
						 | 
					8efd95346a | ||
| 
						 | 
					04b91377c9 | ||
| 
						 | 
					f5d04d989c | ||
| 
						 | 
					06a497f346 | ||
| 
						 | 
					b1cf706a8f | ||
| 
						 | 
					91f04e36e9 | ||
| 
						 | 
					5d76eec0f6 | ||
| 
						 | 
					7822325866 | ||
| 
						 | 
					521123f139 | ||
| 
						 | 
					b3f511b025 | ||
| 
						 | 
					ff63840beb | ||
| 
						 | 
					1fbcf4aa5f | ||
| 
						 | 
					8d6a811204 | ||
| 
						 | 
					08fe2a9e27 | ||
| 
						 | 
					d8465f4374 | ||
| 
						 | 
					8a3cd14723 | ||
| 
						 | 
					91e794add1 | ||
| 
						 | 
					9c98caf21d | ||
| 
						 | 
					f97c42017f | ||
| 
						 | 
					3033a2cb95 | ||
| 
						 | 
					bcf6f48d46 | ||
| 
						 | 
					4c97f15a65 | ||
| 
						 | 
					5dc6349818 | ||
| 
						 | 
					6ab5c4012a | ||
| 
						 | 
					1d50e45777 | ||
| 
						 | 
					3cbf420acd | ||
| 
						 | 
					ea407b2182 | ||
| 
						 | 
					5228885760 | ||
| 
						 | 
					676845aaf3 | ||
| 
						 | 
					61af9b3810 | ||
| 
						 | 
					406a433c3f | ||
| 
						 | 
					2abd413c08 | ||
| 
						 | 
					ad96c9bb9f | ||
| 
						 | 
					b412d54998 | ||
| 
						 | 
					6247d3c5e6 | ||
| 
						 | 
					b7ee513dfd | ||
| 
						 | 
					3795abc19e | ||
| 
						 | 
					1d32a4d984 | ||
| 
						 | 
					a20a78cd64 | ||
| 
						 | 
					a2f51b36ec | ||
| 
						 | 
					910ccb273a | ||
| 
						 | 
					2cbe39e553 | ||
| 
						 | 
					994c8fc02d | ||
| 
						 | 
					57dcd6d520 | ||
| 
						 | 
					20ade1de7b | ||
| 
						 | 
					28aff78469 | ||
| 
						 | 
					056055bf0b | ||
| 
						 | 
					368d329459 | ||
| 
						 | 
					2fe1ffeaf1 | ||
| 
						 | 
					e252e8eb1d | ||
| 
						 | 
					e160bcc7d5 | ||
| 
						 | 
					41bd035690 | ||
| 
						 | 
					b0003fc7e5 | ||
| 
						 | 
					8e1be97589 | ||
| 
						 | 
					181f2f38d8 | ||
| 
						 | 
					661940114e | ||
| 
						 | 
					9874d4bec5 | ||
| 
						 | 
					7d5fedf35f | ||
| 
						 | 
					69ad36a9ae | ||
| 
						 | 
					a00137d742 | ||
| 
						 | 
					e002842640 | ||
| 
						 | 
					41e9c46cba | ||
| 
						 | 
					bc2d58bee3 | ||
| 
						 | 
					c54de27503 | ||
| 
						 | 
					d9bfd77fba | ||
| 
						 | 
					336cc0077c | ||
| 
						 | 
					0be673b210 | ||
| 
						 | 
					028e2498fb | ||
| 
						 | 
					249f1dea9d | ||
| 
						 | 
					07c7b22669 | ||
| 
						 | 
					6623058a18 | ||
| 
						 | 
					68e4d569d0 | ||
| 
						 | 
					7186b25a69 | ||
| 
						 | 
					42cacb18bd | ||
| 
						 | 
					d09c03f4d2 | ||
| 
						 | 
					ad240b150e | ||
| 
						 | 
					1177ef6f8d | ||
| 
						 | 
					2ff50c0c56 | ||
| 
						 | 
					4f4ed1307f | ||
| 
						 | 
					6d5b7cb64e | ||
| 
						 | 
					00fc4e3890 | ||
| 
						 | 
					7344ee4402 | ||
| 
						 | 
					740eacc7ac | ||
| 
						 | 
					8b1bcf21ee | ||
| 
						 | 
					b0a5174c0a | ||
| 
						 | 
					b7cca1b95b | ||
| 
						 | 
					44c51f1246 | ||
| 
						 | 
					516d43d7a8 | ||
| 
						 | 
					86d49d563e | ||
| 
						 | 
					a2911a9585 | ||
| 
						 | 
					9a12b651f9 | ||
| 
						 | 
					9fa631acca | ||
| 
						 | 
					8df7998a83 | ||
| 
						 | 
					c81c1926c0 | ||
| 
						 | 
					7ab1288424 | ||
| 
						 | 
					3ee88adfa9 | ||
| 
						 | 
					29e8c99b4f | ||
| 
						 | 
					8b115f8156 | ||
| 
						 | 
					11c546f113 | ||
| 
						 | 
					c087539eb7 | ||
| 
						 | 
					27f7cbb892 | ||
| 
						 | 
					11ffb09b66 | ||
| 
						 | 
					114f9f522d | ||
| 
						 | 
					91dc51d59a | ||
| 
						 | 
					11b3922b02 | ||
| 
						 | 
					05552cc3e5 | ||
| 
						 | 
					3db7964509 | ||
| 
						 | 
					2a06adcabb | ||
| 
						 | 
					8cec3354ea | ||
| 
						 | 
					f9df728f45 | ||
| 
						 | 
					46eead34c4 | ||
| 
						 | 
					786b35fee2 | ||
| 
						 | 
					5c6c609991 | ||
| 
						 | 
					0be8fedf26 | ||
| 
						 | 
					1f9aaf1ac0 | ||
| 
						 | 
					3926de3fa1 | ||
| 
						 | 
					9086f18413 | ||
| 
						 | 
					ad2576bc76 | ||
| 
						 | 
					4523407d9d | ||
| 
						 | 
					53162ac934 | ||
| 
						 | 
					1dac51d4ba | ||
| 
						 | 
					13deef3416 | ||
| 
						 | 
					b887bebb26 | ||
| 
						 | 
					d51160babb | ||
| 
						 | 
					44b9e7a398 | ||
| 
						 | 
					065cd113c1 | ||
| 
						 | 
					a5f618b7e4 | ||
| 
						 | 
					a06e4e862d | ||
| 
						 | 
					084c858446 | ||
| 
						 | 
					5d889d4d95 | ||
| 
						 | 
					f589e094b2 | ||
| 
						 | 
					2eff798d74 | ||
| 
						 | 
					239cecff9e | ||
| 
						 | 
					fa36af454e | ||
| 
						 | 
					458d0f7a1b | ||
| 
						 | 
					f1f27ffd33 | ||
| 
						 | 
					4a2e09e8eb | ||
| 
						 | 
					4b3fada646 | ||
| 
						 | 
					690befc98b | ||
| 
						 | 
					c6b3c0f9eb | ||
| 
						 | 
					b423a71b38 | ||
| 
						 | 
					e226773066 | ||
| 
						 | 
					98918d160a | ||
| 
						 | 
					969298fb58 | ||
| 
						 | 
					bc60f3b45a | ||
| 
						 | 
					f7a4785d22 | ||
| 
						 | 
					1bf41cbfd7 | ||
| 
						 | 
					e9d80423ae | ||
| 
						 | 
					928ffbd7af | ||
| 
						 | 
					25ebad2448 | ||
| 
						 | 
					dd951dc0ed | ||
| 
						 | 
					aed9e44b6b | ||
| 
						 | 
					1fa2547aff | ||
| 
						 | 
					164ceb845e | ||
| 
						 | 
					ce463686dc | ||
| 
						 | 
					92aa28cac2 | ||
| 
						 | 
					f8674230ed | ||
| 
						 | 
					326969e488 | ||
| 
						 | 
					155e8c2a4b | ||
| 
						 | 
					7f95f6b43f | ||
| 
						 | 
					b2d7ba1a65 | ||
| 
						 | 
					b550bbbd08 | ||
| 
						 | 
					cc79977ac0 | ||
| 
						 | 
					4cbb75df60 | ||
| 
						 | 
					7d8926659e | ||
| 
						 | 
					37ca3f74c7 | ||
| 
						 | 
					56cbf39d59 | ||
| 
						 | 
					a783e7f500 | ||
| 
						 | 
					2f4ac42684 | ||
| 
						 | 
					ec689e100e | ||
| 
						 | 
					6f0909d992 | ||
| 
						 | 
					0092dec49e | ||
| 
						 | 
					3447689c19 | ||
| 
						 | 
					d4563fd842 | ||
| 
						 | 
					d2ecec6009 | ||
| 
						 | 
					26f26aec50 | ||
| 
						 | 
					34dfc2767f | ||
| 
						 | 
					bc3d3cabce | ||
| 
						 | 
					23d80b93ae | ||
| 
						 | 
					0d59d3d195 | ||
| 
						 | 
					192427cf80 | ||
| 
						 | 
					98e4094d70 | ||
| 
						 | 
					e88b939866 | ||
| 
						 | 
					aed5a02ee1 | ||
| 
						 | 
					9f1e1bb2b6 | ||
| 
						 | 
					15e9383d0b | ||
| 
						 | 
					4ec056900c | ||
| 
						 | 
					983feb59b0 | ||
| 
						 | 
					8b2ce33f83 | ||
| 
						 | 
					44b452b30b | ||
| 
						 | 
					f60c9981b8 | ||
| 
						 | 
					7c3df93580 | ||
| 
						 | 
					601d7dfcf8 | ||
| 
						 | 
					41cb53a550 | ||
| 
						 | 
					87c13ae20c | ||
| 
						 | 
					c30482af66 | ||
| 
						 | 
					5f4f2f10d7 | ||
| 
						 | 
					ae630a0e18 | ||
| 
						 | 
					c66931cb12 | ||
| 
						 | 
					fb2dbe25cd | ||
| 
						 | 
					bf4831be9f | ||
| 
						 | 
					0f83082cf0 | ||
| 
						 | 
					fbfde604e7 | ||
| 
						 | 
					5e2dfbed73 | ||
| 
						 | 
					571602d3de | ||
| 
						 | 
					85693f2577 | ||
| 
						 | 
					60bc8ad888 | ||
| 
						 | 
					9bf309eb5c | ||
| 
						 | 
					eeddfa87b6 | ||
| 
						 | 
					861fe2466c | ||
| 
						 | 
					3a2cce78ca | ||
| 
						 | 
					4e01f1de0d | ||
| 
						 | 
					4f0a5e854c | ||
| 
						 | 
					c669a9c808 | ||
| 
						 | 
					e4d827256f | ||
| 
						 | 
					1c1ad2725e | ||
| 
						 | 
					d18e54c5a3 | ||
| 
						 | 
					7a885e23d3 | ||
| 
						 | 
					33dde3a465 | ||
| 
						 | 
					8d4ac59f03 | ||
| 
						 | 
					4fbfc492ce | ||
| 
						 | 
					ac1fb71bc5 | ||
| 
						 | 
					01d6b37b83 | ||
| 
						 | 
					2284b4dce1 | ||
| 
						 | 
					b92f80e6be | ||
| 
						 | 
					bd5596fa30 | ||
| 
						 | 
					4614b63c30 | ||
| 
						 | 
					cf41b6cbb2 | ||
| 
						 | 
					87f3e0e291 | ||
| 
						 | 
					1997abcde6 | ||
| 
						 | 
					8b761298ee | ||
| 
						 | 
					df0356b841 | ||
| 
						 | 
					dc158ebff4 | ||
| 
						 | 
					f8192b90f4 | ||
| 
						 | 
					5237049e2c | ||
| 
						 | 
					9d70fb261e | ||
| 
						 | 
					8370b8a743 | ||
| 
						 | 
					25656d81a1 | ||
| 
						 | 
					be97791428 | ||
| 
						 | 
					18b683d22e | ||
| 
						 | 
					34e9742f71 | ||
| 
						 | 
					087eb7777e | ||
| 
						 | 
					c469c5e3a1 | ||
| 
						 | 
					485c29bb49 | ||
| 
						 | 
					aa0cf150bd | ||
| 
						 | 
					91c52e91cd | ||
| 
						 | 
					a1f4014738 | ||
| 
						 | 
					8a136ac4f6 | ||
| 
						 | 
					ea43b3dc6a | ||
| 
						 | 
					57fc787819 | ||
| 
						 | 
					a0164b8de3 | ||
| 
						 | 
					9df35c1814 | ||
| 
						 | 
					9d2a5fee86 | ||
| 
						 | 
					a6b2e932fa | ||
| 
						 | 
					05aaa2634b | ||
| 
						 | 
					2c98f5c542 | ||
| 
						 | 
					d246fca9df | ||
| 
						 | 
					c79feb405c | ||
| 
						 | 
					b1145f8da3 | ||
| 
						 | 
					3588d681a2 | ||
| 
						 | 
					55d894ae1f | ||
| 
						 | 
					0509caf432 | ||
| 
						 | 
					5d1d807e78 | ||
| 
						 | 
					22ba38b2e0 | ||
| 
						 | 
					42f858267c | ||
| 
						 | 
					5b1a3173f8 | ||
| 
						 | 
					97822bd9a8 | ||
| 
						 | 
					b926f5a692 | ||
| 
						 | 
					191dfdf13f | ||
| 
						 | 
					a100f1fe1e | ||
| 
						 | 
					471ccf281c | ||
| 
						 | 
					6c959be188 | ||
| 
						 | 
					010887f18f | ||
| 
						 | 
					e4b5e4c502 | ||
| 
						 | 
					2de3b4f92e | ||
| 
						 | 
					225a93330d | ||
| 
						 | 
					41b36649a9 | ||
| 
						 | 
					55c26ab1c4 | ||
| 
						 | 
					8b1e60a1fd | ||
| 
						 | 
					ed0f38748b | ||
| 
						 | 
					7d75a720ca | ||
| 
						 | 
					5a38db166f | ||
| 
						 | 
					3c9fb79263 | ||
| 
						 | 
					98d5a2dad9 | ||
| 
						 | 
					4ab8b4984d | ||
| 
						 | 
					f741ad058e | ||
| 
						 | 
					2512a4fc32 | ||
| 
						 | 
					5554d5e608 | ||
| 
						 | 
					48d5ed2ff9 | ||
| 
						 | 
					2632668d0e | ||
| 
						 | 
					f46e444aa2 | ||
| 
						 | 
					1149ad86a2 | ||
| 
						 | 
					e1398d98b0 | ||
| 
						 | 
					8133e2b7aa | ||
| 
						 | 
					ebe678b18b | ||
| 
						 | 
					509217606c | ||
| 
						 | 
					6fb694669c | ||
| 
						 | 
					5a63172a86 | ||
| 
						 | 
					93dcc7e242 | ||
| 
						 | 
					243eea33e9 | ||
| 
						 | 
					38a8367f62 | ||
| 
						 | 
					a02953cccc | ||
| 
						 | 
					f13f96967e | ||
| 
						 | 
					f7c31281e0 | ||
| 
						 | 
					ac34a43d9b | ||
| 
						 | 
					c8d0950979 | ||
| 
						 | 
					a4ff59eccb | ||
| 
						 | 
					c3a50f9442 | ||
| 
						 | 
					57e81ee72e | ||
| 
						 | 
					05df0a37b1 | ||
| 
						 | 
					25f2c3a8c1 | ||
| 
						 | 
					c3aa12db78 | ||
| 
						 | 
					a3bd7cc644 | ||
| 
						 | 
					5a186b6960 | ||
| 
						 | 
					639588fa68 | ||
| 
						 | 
					f9510c54b2 | ||
| 
						 | 
					3a8ddf8025 | ||
| a2801ea88c | |||
| 
						 | 
					c2aae7ee18 | ||
| 
						 | 
					9d0804eff4 | ||
| 
						 | 
					6ff84b3693 | ||
| 
						 | 
					b641e0282b | ||
| 
						 | 
					37a467cabc | ||
| 
						 | 
					e01a7110ac | ||
| 
						 | 
					5dad5de548 | ||
| 
						 | 
					295325a20b | ||
| 
						 | 
					df0a9bac96 | ||
| 
						 | 
					cf9cef6f87 | ||
| 
						 | 
					f92814b24b | ||
| 
						 | 
					331b59cd1e | ||
| 
						 | 
					ed6d211aff | ||
| 
						 | 
					a8f1469d36 | ||
| 
						 | 
					74cb332706 | ||
| 
						 | 
					89165369b1 | ||
| 
						 | 
					a54e3d33a6 | ||
| 
						 | 
					0f17984f41 | ||
| 
						 | 
					6527ceb913 | ||
| 
						 | 
					64a57ba837 | ||
| 
						 | 
					74da9330f8 | ||
| 
						 | 
					4fa1dd6860 | ||
| 
						 | 
					e55effc9ca | ||
| 
						 | 
					924b862f7c | ||
| 
						 | 
					5f077762d5 | ||
| 
						 | 
					1b0ec50711 | ||
| 
						 | 
					22f320f1c4 | ||
| 
						 | 
					9949476584 | ||
| 
						 | 
					1b5b170557 | ||
| 
						 | 
					925a3a4bdb | ||
| 
						 | 
					720fe9f95f | ||
| 
						 | 
					7c4f8e1443 | ||
| 
						 | 
					79d24dff46 | ||
| 
						 | 
					928435a31d | ||
| 
						 | 
					26ac92eaa3 | ||
| 
						 | 
					2974c08b08 | ||
| 
						 | 
					5a7b0b3050 | ||
| 
						 | 
					cc2d9bbdd1 | ||
| 
						 | 
					e912152784 | ||
| 
						 | 
					d00681f623 | ||
| 
						 | 
					52942c3d2a | ||
| 
						 | 
					dedabdd8d8 | ||
| 
						 | 
					3061499860 | ||
| 
						 | 
					20f18755ed | ||
| 
						 | 
					333f2aba54 | ||
| 
						 | 
					1cb673ed80 | ||
| 
						 | 
					57e0bc784a | ||
| 
						 | 
					425afa93da | ||
| 
						 | 
					259b2cebc7 | ||
| 
						 | 
					06589826c8 | ||
| 
						 | 
					2245cd982a | ||
| 
						 | 
					065b50769f | ||
| 
						 | 
					d1e99852bc | ||
| 
						 | 
					bf8f6ae687 | ||
| 
						 | 
					4ad6805ea1 | ||
| 
						 | 
					4f4e3f0b89 | ||
| 
						 | 
					b51f2c1ec8 | ||
| 
						 | 
					1bec06fd75 | ||
| 
						 | 
					451d2e2d1d | ||
| 
						 | 
					9cee12f9f4 | ||
| 
						 | 
					f5d6011a77 | ||
| 
						 | 
					64b2ff19ea | ||
| 
						 | 
					9c17a64773 | ||
| 
						 | 
					69c877ff66 | ||
| 
						 | 
					ac557ffedc | ||
| 
						 | 
					b1e41bc583 | ||
| 
						 | 
					a144395ec9 | ||
| 
						 | 
					0cf9d05489 | ||
| 
						 | 
					0e6c0a41d0 | ||
| 
						 | 
					8a83652d08 | ||
| 
						 | 
					91ee72a8d6 | ||
| 
						 | 
					91b1c8c13c | ||
| 
						 | 
					26effeabe6 | ||
| 
						 | 
					611c9740ed | ||
| 
						 | 
					2a048c3228 | ||
| 
						 | 
					f4fd83d999 | ||
| 
						 | 
					cf68585808 | ||
| 
						 | 
					9f9e926cff | ||
| 
						 | 
					9dc0dd75fd | ||
| 
						 | 
					9f285710f8 | ||
| 
						 | 
					ee1c448327 | ||
| 
						 | 
					e85bf1713e | ||
| 
						 | 
					7341c71277 | ||
| 
						 | 
					d579863311 | ||
| 
						 | 
					c79cfc19aa | ||
| 
						 | 
					997a6be267 | ||
| 
						 | 
					762bb3006d | ||
| 
						 | 
					07f2bd8cab | ||
| 
						 | 
					daf83db9b3 | ||
| 
						 | 
					55c6e19af4 | ||
| 
						 | 
					9cadc94c5a | ||
| 
						 | 
					cacdf9ef56 | ||
| 
						 | 
					a3042fc6c0 | ||
| 
						 | 
					3efd492525 | ||
| 
						 | 
					55a5cbc356 | ||
| 
						 | 
					2887b024ab | ||
| 
						 | 
					917303edb9 | ||
| 
						 | 
					c712c15a30 | ||
| 
						 | 
					0c541db8e0 | ||
| 
						 | 
					603b1520d7 | ||
| 
						 | 
					c7eb8ad5c8 | ||
| 
						 | 
					0b285aa7f4 | ||
| 
						 | 
					e8665bd00c | ||
| 
						 | 
					fb4eaa4332 | ||
| 
						 | 
					874a9eae76 | ||
| 
						 | 
					8230520956 | ||
| 
						 | 
					66da9675f1 | ||
| 
						 | 
					61ff48c005 | ||
| 
						 | 
					5fc8a1e52a | ||
| 
						 | 
					df1ac74069 | ||
| 
						 | 
					91f718bf38 | ||
| 
						 | 
					46e987e393 | ||
| 
						 | 
					a59b4f7be7 | ||
| 
						 | 
					ca66e3c35c | ||
| 
						 | 
					31e2ad8cba | ||
| 
						 | 
					320f32895a | ||
| 
						 | 
					d4db131d3c | ||
| 
						 | 
					27c2c9045e | ||
| 
						 | 
					f97b7c7d62 | ||
| 
						 | 
					9eb33d31ac | ||
| 
						 | 
					6dd84d6fc2 | ||
| 
						 | 
					daddd60581 | ||
| 
						 | 
					e832723ee4 | ||
| 
						 | 
					35f4a63c0e | ||
| 
						 | 
					28478ea4ac | ||
| 
						 | 
					0f93a68694 | ||
| 
						 | 
					1a2d5d13b3 | ||
| 
						 | 
					5f2894fc5b | ||
| 
						 | 
					66cb39dce2 | ||
| 
						 | 
					d44c871c54 | ||
| 
						 | 
					dff0378ba8 | ||
| 
						 | 
					4f7b1b7140 | ||
| 
						 | 
					662514304b | ||
| 
						 | 
					0913e9e0c0 | ||
| 
						 | 
					d403733627 | ||
| 
						 | 
					fae5b439d0 | ||
| 
						 | 
					bc66de6d85 | ||
| 
						 | 
					57e598156c | ||
| 
						 | 
					b570e44ee4 | ||
| 
						 | 
					b115d0b55b | ||
| 
						 | 
					03fc1419de | ||
| 
						 | 
					8b71c0d737 | ||
| 
						 | 
					a833aa0a00 | ||
| 
						 | 
					52332b04ac | ||
| 
						 | 
					529488cab0 | ||
| 
						 | 
					b2429a7ca3 | ||
| 
						 | 
					0bce12d3b4 | ||
| 
						 | 
					75f557cb18 | ||
| 
						 | 
					035dd1fad1 | ||
| 
						 | 
					d2df79a665 | ||
| 
						 | 
					103e0a13bb | ||
| 
						 | 
					d1b5eec84a | ||
| 
						 | 
					6b1e6b31ed | ||
| 
						 | 
					f6f6db913e | ||
| 
						 | 
					ec0a6416fd | ||
| 
						 | 
					1787402be9 | ||
| 
						 | 
					5f6d99f138 | ||
| 
						 | 
					d1e2b0d1f8 | ||
| 
						 | 
					c2c51bbe33 | ||
| 
						 | 
					bb806e3853 | ||
| 
						 | 
					a11d0e75c8 | ||
| 
						 | 
					5406ff0ea3 | ||
| 
						 | 
					c88317b44a | ||
| 
						 | 
					6898062d66 | ||
| 
						 | 
					6e1f264e6a | ||
| 
						 | 
					082be14232 | ||
| 
						 | 
					231aa44d03 | ||
| 
						 | 
					cdb12f35d4 | ||
| 
						 | 
					e831ee8b44 | ||
| 
						 | 
					40e9a6082f | ||
| 
						 | 
					53cec292d0 | ||
| 
						 | 
					3f85309ee5 | ||
| 
						 | 
					70944f8521 | ||
| 
						 | 
					2ab00c42ff | ||
| 
						 | 
					a572742caa | ||
| 
						 | 
					400e5f8580 | ||
| 
						 | 
					74f0fd89b6 | ||
| 
						 | 
					09f9bea7a2 | ||
| 
						 | 
					8bffb38117 | ||
| 
						 | 
					eb5d545c35 | ||
| 
						 | 
					a79a545730 | ||
| 
						 | 
					3863dab944 | ||
| 
						 | 
					e53b7ecd8b | ||
| 
						 | 
					7d88673ed5 | ||
| 
						 | 
					41f2da71e4 | ||
| 
						 | 
					cb4ee0fd74 | ||
| 
						 | 
					088381a5a6 | ||
| 
						 | 
					629af2a697 | ||
| 
						 | 
					884edfd497 | ||
| 
						 | 
					83dd9e462e | ||
| 
						 | 
					70a6dfd98a | ||
| 
						 | 
					7f5d96382b | ||
| 
						 | 
					fd4d1c4bb7 | ||
| 
						 | 
					7eaf3de572 | ||
| 
						 | 
					4b608de3fb | ||
| 
						 | 
					b47e6e852b | ||
| 
						 | 
					a8a8ce4a36 | ||
| 
						 | 
					c61376d5a1 | ||
| 
						 | 
					d3a5bb08d3 | ||
| 
						 | 
					f1506d0dbd | ||
| 
						 | 
					15e6d4959e | ||
| 
						 | 
					41216fd1cd | ||
| 
						 | 
					b8786866db | ||
| 
						 | 
					82bd1bead4 | ||
| 
						 | 
					6e2bdcad79 | ||
| 
						 | 
					ef3c9f3d03 | ||
| 
						 | 
					5427f24df2 | ||
| 
						 | 
					b374340303 | ||
| 
						 | 
					c78ed2c6ad | ||
| 
						 | 
					3b02bc8cf1 | ||
| 
						 | 
					c7e48a7e76 | ||
| 
						 | 
					77d125c03d | ||
| 
						 | 
					8aa52aeefd | ||
| 
						 | 
					0bab038454 | ||
| 
						 | 
					6c3b49f4d0 | ||
| 
						 | 
					03dd689f17 | ||
| 
						 | 
					c375c948c0 | ||
| 
						 | 
					cbcf457ce3 | ||
| 
						 | 
					4855f825e2 | ||
| 
						 | 
					85bc1637f2 | ||
| 
						 | 
					73398b83a9 | ||
| 
						 | 
					2727e66d40 | ||
| 
						 | 
					8b6be5a501 | ||
| 
						 | 
					4fee29307c | ||
| 
						 | 
					35f8249c67 | ||
| 
						 | 
					d1467a14b8 | ||
| 
						 | 
					3e6b9eb74d | ||
| 
						 | 
					ce2e8fb4b5 | ||
| 
						 | 
					7eaa75c05d | ||
| 
						 | 
					e86de4483a | ||
| 
						 | 
					203a74713f | ||
| 
						 | 
					59ed2a6793 | ||
| 
						 | 
					a03283ce64 | ||
| 
						 | 
					984cdaeb03 | ||
| 
						 | 
					a1ed4a9171 | ||
| 
						 | 
					93caf8e549 | ||
| 
						 | 
					3841942153 | ||
| 
						 | 
					5706877b67 | ||
| 
						 | 
					d60900262b | ||
| 
						 | 
					54ea34400b | ||
| 
						 | 
					db2ab8841a | ||
| 
						 | 
					adb9809692 | 
@@ -1,41 +0,0 @@
 | 
			
		||||
version: '{branch}.{build}'
 | 
			
		||||
clone_depth: 1
 | 
			
		||||
skip_tags: true
 | 
			
		||||
 | 
			
		||||
environment:
 | 
			
		||||
  MSYSTEM: MINGW32
 | 
			
		||||
 | 
			
		||||
init:
 | 
			
		||||
  - git config --global core.autocrlf input
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
  - set PATH=c:\msys64\mingw32\bin;c:\msys64\usr\bin;c:\msys64\bin;%PATH%
 | 
			
		||||
  - echo %PATH%
 | 
			
		||||
  - pacman -S --noconfirm --needed make ninja mingw-w64-i686-libusb mingw-w64-i686-sqlite3 mingw-w64-i686-zlib mingw-w64-i686-gcc zip
 | 
			
		||||
 | 
			
		||||
build_script:
 | 
			
		||||
  - make
 | 
			
		||||
  - zip -9 fluxengine.zip fluxengine.exe brother120tool.exe brother240tool.exe FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
 | 
			
		||||
 | 
			
		||||
artifacts:
 | 
			
		||||
  - path: fluxengine.zip
 | 
			
		||||
    name: fluxengine.zip
 | 
			
		||||
 | 
			
		||||
deploy:
 | 
			
		||||
  release: FluxEngine Windows client version $(APPVEYOR_BUILD_NUMBER)
 | 
			
		||||
  description: >
 | 
			
		||||
    This is an automatically built version of the FluxEngine Windows client
 | 
			
		||||
    which is generated whenever a significant checkin has happened. It's had
 | 
			
		||||
    no testing whatsoever.
 | 
			
		||||
 | 
			
		||||
    To use, download it, put it somewhere, and then run it from a cmd window
 | 
			
		||||
    or other command line shell.
 | 
			
		||||
  provider: GitHub
 | 
			
		||||
  auth_token:
 | 
			
		||||
    secure: dfJjj7fWCoDUz+Ni11OcNPB/U3TNJFwNA2AsL++ChFjniUsZLlC6SDWHiL/t4FZo
 | 
			
		||||
  artifact: fluxengine.zip
 | 
			
		||||
  draft: false
 | 
			
		||||
  prerelease: false
 | 
			
		||||
  on:
 | 
			
		||||
    branch: master
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										45
									
								
								.github/workflows/ccpp.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								.github/workflows/ccpp.yml
									
									
									
									
										vendored
									
									
								
							@@ -10,32 +10,45 @@ jobs:
 | 
			
		||||
      with:
 | 
			
		||||
        fetch-depth: 1
 | 
			
		||||
    - name: apt
 | 
			
		||||
      run: sudo apt update && sudo apt install libusb-1.0-0-dev libsqlite3-dev ninja-build
 | 
			
		||||
      run: sudo apt update && sudo apt install libusb-1.0-0-dev libsqlite3-dev ninja-build protobuf-compiler
 | 
			
		||||
    - name: make
 | 
			
		||||
      run: make
 | 
			
		||||
 | 
			
		||||
  build-macos:
 | 
			
		||||
    runs-on: macos-latest
 | 
			
		||||
    steps:
 | 
			
		||||
    - uses: actions/checkout@v1
 | 
			
		||||
    - uses: actions/checkout@v2
 | 
			
		||||
      with:
 | 
			
		||||
        fetch-depth: 1
 | 
			
		||||
    - name: brew
 | 
			
		||||
      run: brew install sqlite pkg-config libusb ninja
 | 
			
		||||
      run: brew install sqlite pkg-config libusb ninja protobuf truncate
 | 
			
		||||
    - name: make
 | 
			
		||||
      run: make
 | 
			
		||||
 | 
			
		||||
#  build-windows:
 | 
			
		||||
#    runs-on: windows-latest
 | 
			
		||||
#    steps:
 | 
			
		||||
#    - uses: numworks/setup-msys2@v1
 | 
			
		||||
#      with:
 | 
			
		||||
#        path-type: inherit
 | 
			
		||||
#    - uses: actions/checkout@v1
 | 
			
		||||
#    - name: pacman
 | 
			
		||||
#      run: |
 | 
			
		||||
#        msys2do pacman -S --noconfirm --needed make ninja mingw-w64-i686-libusb mingw-w64-i686-sqlite3 mingw-w64-i686-zlib mingw-w64-i686-gcc zip
 | 
			
		||||
#    - name: build
 | 
			
		||||
#      run: |
 | 
			
		||||
#        msys2do make
 | 
			
		||||
  build-windows:
 | 
			
		||||
    runs-on: windows-latest
 | 
			
		||||
    defaults:
 | 
			
		||||
      run:
 | 
			
		||||
        shell: msys2 {0}
 | 
			
		||||
    steps:
 | 
			
		||||
    - uses: msys2/setup-msys2@v2
 | 
			
		||||
      with:
 | 
			
		||||
        update: true
 | 
			
		||||
        msystem: MINGW32
 | 
			
		||||
        install: >-
 | 
			
		||||
          make
 | 
			
		||||
          ninja
 | 
			
		||||
          mingw-w64-i686-libusb
 | 
			
		||||
          mingw-w64-i686-sqlite3
 | 
			
		||||
          mingw-w64-i686-zlib
 | 
			
		||||
          mingw-w64-i686-gcc
 | 
			
		||||
          zip
 | 
			
		||||
          mingw-w64-i686-protobuf
 | 
			
		||||
          vim
 | 
			
		||||
    - uses: actions/checkout@v1
 | 
			
		||||
      with:
 | 
			
		||||
        fetch-depth: 1
 | 
			
		||||
    - name: build
 | 
			
		||||
      run: |
 | 
			
		||||
        make
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										63
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
name: Autorelease
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches:
 | 
			
		||||
      - "master"
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  dev-release:
 | 
			
		||||
    runs-on: windows-latest
 | 
			
		||||
    defaults:
 | 
			
		||||
      run:
 | 
			
		||||
        shell: msys2 {0}
 | 
			
		||||
    steps:
 | 
			
		||||
    - uses: msys2/setup-msys2@v2
 | 
			
		||||
      with:
 | 
			
		||||
        update: true
 | 
			
		||||
        msystem: MINGW32
 | 
			
		||||
        install: >-
 | 
			
		||||
          make
 | 
			
		||||
          ninja
 | 
			
		||||
          mingw-w64-i686-libusb
 | 
			
		||||
          mingw-w64-i686-sqlite3
 | 
			
		||||
          mingw-w64-i686-zlib
 | 
			
		||||
          mingw-w64-i686-gcc
 | 
			
		||||
          zip
 | 
			
		||||
          mingw-w64-i686-protobuf
 | 
			
		||||
          vim
 | 
			
		||||
    - uses: actions/checkout@v2
 | 
			
		||||
      with:
 | 
			
		||||
        fetch-depth: 1
 | 
			
		||||
    - name: build
 | 
			
		||||
      run: |
 | 
			
		||||
        make
 | 
			
		||||
    - name: zip
 | 
			
		||||
      run: |
 | 
			
		||||
        zip -9 fluxengine.zip fluxengine.exe brother120tool.exe brother240tool.exe FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
 | 
			
		||||
    - name: date
 | 
			
		||||
      run: |
 | 
			
		||||
        echo "RELEASE_DATE=$(date --rfc-3339=date)" >> ${GITHUB_ENV}
 | 
			
		||||
    - name: tag
 | 
			
		||||
      uses: EndBug/latest-tag@latest
 | 
			
		||||
      with:
 | 
			
		||||
        tag-name: dev
 | 
			
		||||
      env:
 | 
			
		||||
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
    - name: delete-old-assets
 | 
			
		||||
      uses: mknejp/delete-release-assets@v1
 | 
			
		||||
      with:
 | 
			
		||||
        token: ${{ github.token }}
 | 
			
		||||
        tag: dev
 | 
			
		||||
        assets: | 
 | 
			
		||||
          fluxengine.zip
 | 
			
		||||
        fail-if-no-assets: false
 | 
			
		||||
    - name: release
 | 
			
		||||
      uses: softprops/action-gh-release@v1
 | 
			
		||||
      with:
 | 
			
		||||
        name: Development build ${{ env.RELEASE_DATE }}
 | 
			
		||||
        files: |
 | 
			
		||||
          fluxengine.zip
 | 
			
		||||
        tag_name: dev
 | 
			
		||||
      env:
 | 
			
		||||
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
@@ -1,246 +1,246 @@
 | 
			
		||||
:400000000080002011000000A10F0000A10F0000064A08B5136843F020031360044B1A6803F53F5302331A6000F0D8FFE8460040FA46004010B5054C237833B9044B13B1EF
 | 
			
		||||
:400040000448AFF300800123237010BD6881FF1F0000000020380000084B10B51BB108490848AFF300800848036803B910BD074B002BFBD0BDE81040184700BF00000000E9
 | 
			
		||||
:400080006C81FF1F20380000C880FF1F000000000A4A0B4B116801310B40002BBEBF03F1FF3363F03F030133136011685368994202BF024B01221A72704700BF8881FF1F64
 | 
			
		||||
:4000C0003F0000800A4A0B4B516801310B40002BBEBF03F1FF3363F03F030133536051681368994202BF024B01221A72704700BF8881FF1F3F000080024B012200205A7293
 | 
			
		||||
:4001000002F012B98881FF1F10B5C4B2204601F027F90128FAD110BD08B572B60F4B0F49DA680132DA601A690132C82A08BF00221A615A6918690132A72A08BF00224A613A
 | 
			
		||||
:400140005B69002B0CBF02230023002814BF184643F0010002F050FE62B608BD8881FF1F38B50446C5B2284602F080F8062002F09DFA44F00200C0B202F078F8062002F055
 | 
			
		||||
:4001800095FA284602F072F8BDE83840062002F077BA10B5642402F063F830B90120FFF7DFFF013CF7D1204610BD012010BD70B5C4B2054620460E4601F0D2F8012805D089
 | 
			
		||||
:4001C000204601F0EBF92846FFF79EFF204601F0CFF8314605460246204601F08BF9204601F0BEF80028FAD1284670BD38B5044D0024285D013402F009FA402CF9D138BDE9
 | 
			
		||||
:40020000A081FF1F08B502F023FC002002F02CFC02F03EFC02F048FC80B208BD10B50446012002F03BF8642002F02AFAFFF7EAFF2080002002F032F8642002F021FAFFF7ED
 | 
			
		||||
:40024000E1FF608010BD08B502F02EFD002002F037FD02F049FD02F053FD80B208BD10B50446FFF796FF322002F00AFAFFF7EBFF20800020FFF774FF322002F001FAFFF740
 | 
			
		||||
:40028000E2FF608010BD0FB400B593B014AB53F8042B402102A8019302F0AAFE02A802F04AF802F054F813B05DF804EB04B0704710B5044601780648FFF7E5FF0420FFF72B
 | 
			
		||||
:4002C00023FF62782146BDE81040042001F0A0B83438000007B50023ADF804308DF80600032301A88DF80530FFF7E2FF03B05DF804FB000010B5074C94F8583043B10020E3
 | 
			
		||||
:4003000001F0A8FF002002F03BFD002384F8583010BD00BF8881FF1F38B5104D837895F85B2004469A4204D0FFF7E4FF002385F85E302368C5F859302279094B1A71A3784D
 | 
			
		||||
:40034000002B14BF0220012002F01AFDE07802F011FD2079BDE8384002F048BD8881FF1FE181FF1F38B50D4C94F8585065B904F15900FFF7D1FF012001F06CFF4FF47A7031
 | 
			
		||||
:4003800002F07EF984F85E50E3682366012384F85830BDE8384002F0B1B900BF8881FF1FF8B51E4C0646FFF7DDFF94F85E3003B15EB91B48FFF767FFFFF7EBFE0120002353
 | 
			
		||||
:4003C00084F85E00636602F071F93246616E1548FFF759FF114D0027636E9E4216D001F03FFF00B16F66636E9E4205DD0020FFF7B7FE6B6E013305E005DA0120FFF7B0FE47
 | 
			
		||||
:400400006B6E013B6B6602F079F9E5E7322002F037F9BDE8F8400448FFF735BF8881FF1F4138000048380000653800002DE9F04F99B062B602F0CCF99949042002F0F0F914
 | 
			
		||||
:40044000984801F019FF984802F0BCFC974801F04DFF02F09DFB02F06FFA002002F090FC01F068FF0221002000F030FF904C012001F0A8F8002384F85B30FFF773FFFFF79A
 | 
			
		||||
:4004800088FE84F86800FFF735FF012384F85B30FFF768FFFFF77DFE84F86900FFF72AFF844B94F86800844994F869202546002A14BF0A461A46002808BF19467F48FFF7E3
 | 
			
		||||
:4004C000E2FE0321084602F0F9F8264602F016F994F8583043B12A6EEB689B1A41F28832934201D9FFF706FF00F028FF18B97448FFF7C9FE04E000F027FF0028F7D10BE0E5
 | 
			
		||||
:4005000000F01CFF10B902F0F9F8F9E76D48FFF7BAFE032001F042F8032000F021FF0128D4D16948FFF7F8FE68490320FFF73FFE94F86A106648FFF7A6FE94F86A30023B1D
 | 
			
		||||
:40054000142B00F2AB83DFE813F01500A9031E00A9032400A9034600A9036C00A903CF00A903AA01A903E202A9030103A9030803A903220303238DF820308DF821300E23FD
 | 
			
		||||
:400580008DF82230FFE294F86C00FFF709FF514BF6E2FFF7E7FE00236372E068627A02F0FF0132B9EB681B1AB3F57A7FF6DD0B4608E03BB100227272F168627A12B9EB68CB
 | 
			
		||||
:4005C0005B1AFAE707228DF8202004228DF82120ADF82230D7E20220FFF796FD4FF000080DF1200A02F08AF84FF480790027C9EB0803DA1907F80A200137402FF9D10220BC
 | 
			
		||||
:40060000FFF782FD3A465146022000F001FFB9F10109EBD108F10108B8F1400FE2D12E4B38E04FF0010A4FF000080DF1200B02F065F84FF0000959460120FFF7B8FD08EBBF
 | 
			
		||||
:40064000090300270493049B1BF807203B44DBB2934209D08DE80C0041463B464A461F48FFF711FE4FF0000A0137402FEBD109F10109B9F5807FDED108F10108B8F1400F92
 | 
			
		||||
:40068000D5D151461648FFF7FEFDBAF1000F00F00E81144B1B8807A8ADF81C3074E200BF19010000F900000091000000C50000008881FF1F77380000733800007A38000022
 | 
			
		||||
:4006C00092380000A5380000E181FF1FF281FF1FAF3800002438000026380000BE380000DA3800002838000094F86C0001F0D6FD606EFFF755FE02F0E7FBB24BDFF8E0825C
 | 
			
		||||
:400700001A78002702F0FB021A701A7842F001021A701A7802F0FE021A701A7802F0FE021A7002F0D5FB0220FFF7EEFC012141F6FF734FF48042084602F028FB84F8AA00FD
 | 
			
		||||
:4007400001F04AFF08F807000137402FF8D1DFF894A200270AF199091FFA89F80137402F14BF3A4600221AF8010F22440623127E402101F065FF424646F244519AF8000063
 | 
			
		||||
:4007800001F070FF08F14008402F1FFA88F8E5D196F86D3033B100237372637A002BFCD00023737200234FF0FF32236062602372236894F8AA002344197E01F0C5FE94F87B
 | 
			
		||||
:4007C000AA0001F083FE012194F8AA0001F056FE2368002BFCD0002398467360D6F80CA0012701F08BFFE368B4F86E20CAEB030393420DD367B1042195F8AA0001F0B0FEC5
 | 
			
		||||
:4008000094F8AA0001F0BCFE0028F9D107463072237AFBB96A682B689A4202D1002FE0D118E00220FFF770FC6968402209EB8111022000F0EDFD6A68634B01321340002B4F
 | 
			
		||||
:40084000BEBF03F1FF3363F03F03013308F101086360C6E70220277AFFF756FC00221146022000F0D5FDFFB20220FFF74DFCFFF7BDFC37B15548FFF706FD0220FFF72AFDB4
 | 
			
		||||
:4008800006E0534B08A81B88ADF82030FFF710FD627A4146237A4F48FFF7F5FC01E24E48FFF7F1FCD4F86E7017F03F0701D00320F5E1012001F0F8FC95F86C0001F0EEFCF4
 | 
			
		||||
:4008C00002F002FB454BDFF818811A7842F004021A701A7842F001021A701A7802F0FE021A701A7802F0FE021A7002F0F1FA686EFFF756FD01214FF4804341F6FF7208462E
 | 
			
		||||
:4009000001F0D8FC85F8AA0001F066FE08F807000137402FF8D1DFF8CC90002709F199031FFA83F804930137402F14BF3A46002219F8010F22440523127E402101F080FEB9
 | 
			
		||||
:40094000414646F24B4299F8000001F08BFE08F14008402F1FFA88F8E5D100274FF0FF33376098467360BB463B46D6F86E9037725FEA99190CBF4FF0010A4FF0000A216868
 | 
			
		||||
:40098000114A01310A40002ABCBF02F1FF3262F03F026068B8BF013282426BD02BB1227A002A76D16A7A002A73D12068049A059302EB8010BAF1000F16D040223F2102F0C9
 | 
			
		||||
:4009C000E3FA1CE0946500403F000080E43800002A380000FE380000113900009B640040A081FF1F9F81FF1F014601370120FFF7DEFBC7EB0903D3F1000A4AEB030A2168A6
 | 
			
		||||
:400A0000AB4A01310A40002ABEBF02F1FF3262F03F02013222606268059B01322AD12A683F2A27D14FF00008C5F8048001F070FC85F808806B6895F8AA002B44197E01F0BC
 | 
			
		||||
:400A400083FD95F8AA0001F041FD012195F8AA0001F014FD85F80980637A002BFCD04FF00008012086F8098001F05EFC404601F01BFC00E023B1237A5BB96B7A4BB90123A1
 | 
			
		||||
:400A8000626842453FF47BAF0BF1010BD5F8048075E701F043FC012001F006FC002001F043FC042194F8AA0001F05AFD94F8AA0001F066FD0028F9D196F8AA0001F0F4FC07
 | 
			
		||||
:400AC000737A327A0293012303920193CDF800A05B463A4649467748FFF7D5FBBAF1000F08D0FFF783FB237A63B17348FFF7CBFB0220D4E0B945F4D070490120FFF757FBF9
 | 
			
		||||
:400B00000137F7E76E48FFF7BEFB6E4B38E094F86C0001F0C3FB606EFFF742FC6A48FFF7B2FB00236372637A002BFCD0012001F0FBFB00237372637A002BFCD0002001F0AA
 | 
			
		||||
:400B4000F3FB6248FFF79FFB614B19E0002084F85E00FFF725FC5F4B12E094F8683023B195F869200AB985F86C2094F869201AB113B9012385F86C305748FFF7CDFB574B39
 | 
			
		||||
:400B80001B88ADF8203008A8FFF792FB89E0FFF7B1FB02F07BF8002002F01EF82A2701F049FF002001F0ECFE3A46002108A802F0EBF917238DF820308DF8217001F09EFD75
 | 
			
		||||
:400BC000002001F047FB002002F0DAF8C82001F057FD0DF12200FFF721FB0DF13600FFF73EFB01F08BFD012002F0CAF8322001F047FD0DF12600FFF711FB0DF13A00FFF7D3
 | 
			
		||||
:400C00002EFB012001F026FB4FF4967001F038FD01F074FD0DF12E00FFF700FB0DF14200FFF71DFB002001F015FB4FF4967001F027FD01F063FD022002F0A2F8322001F05B
 | 
			
		||||
:400C40001FFD0DEB0700FFF7E9FA0DF13E00FFF706FB012001F0FEFA4FF4967001F010FD01F04CFD0DF13200FFF7D8FA0DF14600FFF7F5FA002001F0EDFA4FF4967001F06F
 | 
			
		||||
:400C8000FFFC01F03BFD002002F07AF8002384F85E3001F07DFF01F04FFE74E70120FFF719FB032000F07AFC0D48FFF7ECFA0DE43F0000801B3900004B3900003892FF1F04
 | 
			
		||||
:400CC000553900002C3800005D3900006B3900002E38000030380000F281FF1F32380000783900002DE9F04172B6884B61221A70A3F5F06301221A801924854A9C7092E8C5
 | 
			
		||||
:400D000003008033062283F8002283E80300522203F580731A707F4B7F4A1B787F4EDBB2137040F618027E4B00251A8041F2512223F8022C33784FF4F07003F0010343EAA5
 | 
			
		||||
:400D4000450502F0B9F8013C05F003052ED0032DF0D1744B4FF480721A8007221A70724A002548211570917002221D705D7103F8032C0422DA716D4A6D4C13786D4E43F049
 | 
			
		||||
:400D80000103137012F8013C062743F0030302F8013C2378012243F0800323705B4B1A70654A137843F02003137000E0FEE707FB056300219A881868013502F0E5F8072D53
 | 
			
		||||
:400DC000F5D15E485E4E002550F8041F05F1105303F14A0221F0FF074B33C9B20B4452005B0002329A4206D012F802EC12F801CC0EF807C0F5E7B0420D44E5D1514A002391
 | 
			
		||||
:400E000013609360136193614F4B504F1A68504BDFF888811A604F4B1A684F4B1A604F4A137843F002031370137C43F0020313742378A2F5863243F040032370413A1378DE
 | 
			
		||||
:400E400043F010031370464A464B07CA03C31A80454A2833106843F8250C127903F8212C424A07CA03C31A80414AE83B07CA03C31A80404A083307CA03C31A803E4A3F4B12
 | 
			
		||||
:400E8000A2F5616203CBC2F8100EC2F8141E1378042043F008031370394B02F5AA521B783D78DBB298F80060EDB203F007010C321B091170F6B2537045F003033B7046F096
 | 
			
		||||
:400EC000030388F800302F4B48221A702E4A402313702E49937013729372082382F81F3220220A7048710A72294A0A20137001F0DDFB284B88F8006044223D70264D1A7039
 | 
			
		||||
:400F000094E80F0007C52B80BDE8F08100480040140C00480F010049A146004025420040224200400440004006400040A2430040A04300407D390000E8460040FCFFFF4727
 | 
			
		||||
:400F400090000048007600401C0C0048F846004020760040200C00482876004003500140D40B0048C0510040E00B0048E80B0048F40B0048000C0048325100400C0C004895
 | 
			
		||||
:400F8000CF0100491D51004001590040235B0040585B004076580040B0430040F946004008B501F0C5FF03680C2B00D1FEE7FEE7084908B50B68084A1844821A802A01DC5E
 | 
			
		||||
:400FC000086005E001F0B4FF0C2303604FF0FF33184608BDCC80FF1F8893FF1F80B51148114B0025C0B1A3F1100192C922460439161BB74204D051F8046F42F8046BF7E7D1
 | 
			
		||||
:40100000114653F8046C8C1AA64202D041F8045BF9E701381033E5E701F090FFFFF706FAFEE700BF010000004C3B0000124A134B10B51A60124A134C1368134843F40073A8
 | 
			
		||||
:4010400013600023032B98BF54F823204FEA830188BF0E4A0133302B4250F3D10C4B1A780C4B1A700C4B084A1A60FFF73BFEBDE8104001F0EDB900BF0004FA050CED00E042
 | 
			
		||||
:4010800014ED00E0000000000080FF1FA10F0000BC760040C080FF1F08ED00E0F8B501F013FF4B4A01271378022643F001031370137C484C43F001031374474B02F5E352E3
 | 
			
		||||
:4010C0001F700B3203F8946C1378054603F07F031370002001F0EAFA2378404A03F0F90323701378384603F0DF03137023783B43237001F0DBFA282001F0D8FA384B3046E8
 | 
			
		||||
:401100001A7802F07F021A701A7802F0BF021A7023783343237001F0C9FA2378314A43F0040323700023137053702F4AFF2199540133092BFBD1284601F0CAFE072117206D
 | 
			
		||||
:4011400001F0FCFA2949172001F0EAFA0721182001F0F4FA2649182001F0E2FA0721152001F0ECFA2349152001F0DAFA0721052001F0E4FA2049052001F0D2FA0721062008
 | 
			
		||||
:4011800001F0DCFA1D49062001F0CAFA0721084601F0D4FA1A49072001F0C2FA0721082001F0CCFA1749082001F0BAFA0021162001F0C4FA1449162001F0B2FA07210C20FD
 | 
			
		||||
:4011C00001F0BCFABDE8F84010490C2001F0A8BAA5430040944300409D60004012600040F851004084600040AD92FF1F6B1A0000A5180000691A00009D190000C9190000FE
 | 
			
		||||
:40120000F9190000311A0000711A0000E51A0000214B224A10B5187000231370204A40201370204A0F2413701F4A13701F4A13701F4A13701F4A13701F4B4FF400021A60B6
 | 
			
		||||
:401240004FF080721A604FF400121A6020221A601860802018604FF480701860174804704FF480001860164B1A70933B19B91A7802F0FE0202E01A7842F001021A70114B51
 | 
			
		||||
:4012800003221A70802203F8202C012001F014FE0D4B04221A7010BDC892FF1FCE92FF1FCC92FF1FCD92FF1FC992FF1FB892FF1FCB92FF1F4093FF1F00E100E09E60004062
 | 
			
		||||
:4012C0009C600040286000401260004070B5074C054623780E461BB9FFF7E0FE0123237031462846BDE87040FFF792BF7892FF1F0A4A002313700A4A13700A4A13700A4A82
 | 
			
		||||
:4013000013700A4A13700A4A13700A4A13700A4B03221A70802203F8202C7047CE92FF1FCC92FF1FCD92FF1FC992FF1FB892FF1FCB92FF1F4093FF1F28600040014B187899
 | 
			
		||||
:40134000704700BFCD92FF1F044B1A7802F0FF001AB118780022C0B21A707047CC92FF1F024A0C2303FB002040787047D492FF1F431E072B0CD8074A064B00010344805C33
 | 
			
		||||
:401380005B7800F00F0043EA0020023880B2704700207047FC5F00401A4A38B50C2303FB00231B79090C13F0800F00F1FF35044619BF8AB24FF480438BB24FF48042032DA2
 | 
			
		||||
:4013C00018D8DFE805F002070C110021084601F01BF80DE00021084600F0FAFF08E00021084600F0D9FF03E00021084600F0B8FF054B1855EDB2072D03D801F0EDF8034BBC
 | 
			
		||||
:40140000185538BDD492FF1FA492FF1FAD92FF1F431E072B2DE9F0470446894615465CD82F4F0C2202FB0072D388DFF8B8A09BB2C3F500739D424FF00C0303FB007388BF8B
 | 
			
		||||
:40144000D588DB7884BFC5F50075ADB2254A43EA15230601B354B244EBB28AF80130224B1A5C9846FF2A01D1FFF796FF0C2303FB047200215170B9F1000F28D03DB31B4FEC
 | 
			
		||||
:40148000385D01F011F811232946FE2218F8040001F0D6F806F5C04278321FFA89F118F8040001F0DFF8124D18F80410385D01F04BF80121385D00F0E1FF735D43F0020316
 | 
			
		||||
:4014C0007355735D03F0FD037355BDE8F08703FB04746379DBB28AF80230BDE8F08700BFD492FF1FFC5F0040AD92FF1FA492FF1F706000402DE9F047044615468846002946
 | 
			
		||||
:4015000040D0431E072B3FD8FFF732FFA84203D22046FFF72DFF05461D4E335DFF2B03D141462046FFF738FFDFF868A027011AF8040000F0B9FF1223FE222946305D01F01E
 | 
			
		||||
:401540007FF807F5C0411FFA88F27831305D01F089F8DFF84490315D1AF8040000F0F4FF01211AF8040000F089FF17F8093043F0020307F8093017F8093003F0FD0307F8E8
 | 
			
		||||
:40158000093002E00D4600E000252846BDE8F087AD92FF1FA492FF1F70600040431E072B0AD8064A0C2303FB002300225A705A79034BD2B200011A54704700BFD492FF1F5E
 | 
			
		||||
:4015C000FE5F0040431E072B9FBF024B000108221A547047FE5F004030B51A4A1A491B4D0878138803449BB21380194A00231488D8B2A4B27CB1082B0CD050680078C0B2ED
 | 
			
		||||
:40160000E85450680133013050601088013880B21080ECE718460B780E4C082B0E4A00D040B10E4D2B7883F080032B700F232370022301E0022323701370094B18700870CB
 | 
			
		||||
:4016400030BD00BF4493FF1F4093FF1F00600040BC92FF1FB992FF1FCE92FF1FCA92FF1F4193FF1F074B02221A70074B80221A70064B0F221A70064A00231370054A012089
 | 
			
		||||
:4016800013707047CE92FF1FCA92FF1FB992FF1F4093FF1F4193FF1F30B5164B16491B780A8803F00F03023BDBB21A4492B20A80124C134A0020118889B279B173B155682D
 | 
			
		||||
:4016C000215C013BC9B229705168DBB20131516011880130013989B21180ECE7094A1370094A137883F080031370084B0B221A7030BD00BF296000404493FF1F0060004010
 | 
			
		||||
:40170000BC92FF1F4193FF1FCA92FF1FB992FF1F064A06231370064A01201370054B80221A70054B00221A70704700BFCE92FF1FB992FF1FCA92FF1F4193FF1F054B9A68E5
 | 
			
		||||
:401740003AB19A68044910709A680988518000229A607047BC92FF1F4493FF1F08B5124B1A78D2B21A701B78DBB21A0602D50F4A137008BD0220FFF7E1FF0D4B1B7803F0CF
 | 
			
		||||
:401780006003202B05D0402B06D043B900F012FC04E001F0A1FB01E000F046FD10B9034B03221A7008BD00BF28600040B992FF1F0060004008B5084A084B0120197813881C
 | 
			
		||||
:4017C0000B449BB21380064B00221A70FFF7B6FF044B03221A7008BD4493FF1F4093FF1FCE92FF1FB992FF1F08B50C4B1B78DBB2042B07D0062B09D0022B0DD1BDE8084046
 | 
			
		||||
:40180000FFF7D8BFBDE80840FFF746BF0320FFF795FF034B03221A7008BD00BFCE92FF1FB992FF1F08B5054B002201201A70FFF785FF034B03221A7008BD00BFCE92FF1FCB
 | 
			
		||||
:40184000B992FF1F08B50A4B1A7832B11A78094942F080020A7000221A70074B002201201A70FFF76BFF054B03221A7008BD00BFB892FF1F08600040CE92FF1FB992FF1FC1
 | 
			
		||||
:40188000074B1B78DBB2042B05D0062B05D0022B05D1FFF7A1BEFFF7C5BFFFF7D3BF7047CE92FF1F38B51D4C2378DBB2DD0634D518060AD503F00F03012B2ED1FFF74EFF43
 | 
			
		||||
:4018C000174B1B78190609D538BD5A0602D5FFF7D7FF03E09D0620D5FFF786FF23781B061BD4104B1A78104B1B7813430F4A13701278934211D10A4A0849154613782078EC
 | 
			
		||||
:40190000DBB2000605D41378DBB20B700B7803F00F0328788342F1D138BD38BD28600040B992FF1FCA92FF1F4193FF1F29600040054A00231380054A916819B191680B701E
 | 
			
		||||
:4019400092685380704700BF4493FF1FBC92FF1F0E4808B503889BB213B9FFF783FE13E00B4B02221A700B4B00221A70FFF7E0FF094AD1799379028843EA012392B293422A
 | 
			
		||||
:4019800038BF0380FFF728FE012008BDBC92FF1FCE92FF1FCA92FF1F00600040084B01221A700F3B9B7C074B1A7B02F00302012A1EBFDA7B82F08002DA7301225A73704723
 | 
			
		||||
:4019C0000B600040D492FF1F094B02221A700F3B93F82230074B1A7E02F00302012A1EBFDA7E82F08002DA7601225A76704700BF0B600040D492FF1F0B4B04221A700F3B22
 | 
			
		||||
:401A000093F83230094B93F8242002F00302012A1EBF93F8272082F0800283F82720012283F82520704700BF0B600040D492FF1F0B4B08221A700F3B93F84230094B93F857
 | 
			
		||||
:401A4000302002F00302012A1EBF93F8332082F0800283F83320012283F83120704700BF0B600040D492FF1F7047FFF741BC0000F0B5184B184E19780C27C9B201234FF029
 | 
			
		||||
:401A8000000C31B3CA0720D5144A4FEA031E7244947850782040C5070DD507FB03652C79240608D5147804F0FE0414706D790C4CEDB204F80E50840706D507FB0364257960
 | 
			
		||||
:401AC0002D0658BF84F801C090700133DBB24908D7E7F0BD9F600040D492FF1F70600040FE5F004000F0ACBC70B50446184B88B003AA03F11006154618685968083303C5BA
 | 
			
		||||
:401B0000B3422A46F7D11B782B70FCB12223237001AD03232846637000F08AFE002220461146AB5C08AC04EB131414F8144C03F00F03847008AC234413F8143C0132082A48
 | 
			
		||||
:401B4000C1700371417100F10400EAD108B070BDA73900002DE9F0431C4D01222E460C201F274FF0800E4FF0080C194B00FB02581401234418705F70164998F80590214449
 | 
			
		||||
:401B8000B9F1000F07D098F8044024064CBF887081F802C001E081F802E000FB0261CC880132E4B29C71CC88092AC4F30724DC71CC88E4B21C71C988C1F307215971D4D1CC
 | 
			
		||||
:401BC000054BFF221A70BDE8F08300BFD492FF1F70600040FC5F00400A600040064B074A1B7802EBC30253681A7C824286BF03EBC003586900207047C892FF1F083A0000F6
 | 
			
		||||
:401C00002DE9F84F424B1A78002A7ED01878414D0138C0B2FFF7E2FFA8463F4AC3681478007ADFF800C1E4B203EBC0000C2600274FF0010E834268D01A78A24263D11CF82A
 | 
			
		||||
:401C40000420597891425ED19A7893F8039002F07F0206FB02FA05EB0A01CF7093F802B009F0030981F804B093F803B005F80AB0B3F804A0A1F808A093F902A0BAF1000FB7
 | 
			
		||||
:401C80000BDAB9F1010F0CBF4FF007094FF00D0981F8059081F801E009E0B9F1010F0CBF4FF005094FF0090981F805904F704FEA02191A4906FB0282494481F802E0B2F807
 | 
			
		||||
:401CC00008A0CAF3072A81F800A0B2F808A05FFA8AFA81F801A0B2F806A011495FFA8AFA494481F806A0B2F80690C9F3072981F80790B2F806905FFA89F981F80490D288FB
 | 
			
		||||
:401D0000C2F307224A71083394E7BDE8F88F00BFCD92FF1FD492FF1FC992FF1FFC5F004070600040BA92FF1F08B5064B18780138C0B2FFF753FF20B143681B7900EBC3008B
 | 
			
		||||
:401D4000406908BDCD92FF1F00212DE9F84F0B464E4E0C2707FB01F401313219092933554FF000059370494CD3701381937253705371EFD118B1464B1D70464B1D70464B17
 | 
			
		||||
:401D80001A78002A7FD0187801250138C0B2FFF725FFA8464368DFF8F8E0DB790C2713F0400F3E4B4FF0000C1A7814BF42F0010202F0FE021A70027AD20007FB0541C368D1
 | 
			
		||||
:401DC00003EB02094B4531D093F802A00AF07F06AE4229D10E89B3F804B0B6B25E4538BFA1F808B01E7893F801B01EF80660B3451AD181F804A0DE780E7093F902A0DE78D4
 | 
			
		||||
:401E0000BAF1000F06F0030607DA012E0CBF07260D264E7181F8018006E0012E0CBF052609264E7181F801C00833CBE70135092DC3D1C1680A328B1C0A440C20083393423F
 | 
			
		||||
:401E400009D013F8081C13F80A5C01F07F0100FB01418D72F2E7FFF767FF114B0121186000230C2000FB0142D3801289013113449BB203F00102134409299BB2F2D1BDE88C
 | 
			
		||||
:401E8000F84FFFF767BEBDE8F88F00BFD492FF1FBA92FF1F4293FF1FCD92FF1FCB92FF1FD092FF1F114B1B7903F07F035A1E072A19D80F490C2202FB031291781B0141F08F
 | 
			
		||||
:401EC000010191700021D170517841F002015170127912F0800F074A1A4414BF8D2389239370FFF715BC0020704700BF00600040D492FF1FFC5F004030B4194B1A7902F0D9
 | 
			
		||||
:401F00007F02531E072B27D8164B0C2404FB02339978154D01F0FE0199700021D97029461201505D114400F07F0050555A7802F0FD025A701A795B78120605D5012B01D168
 | 
			
		||||
:401F40008C7006E00D2303E0012B0CBF082309238B7030BCFFF7DCBB002030BC704700BF00600040D492FF1FFC5F004010B50D4B0D4C21791878C9B20138C0B2FFF72EFE81
 | 
			
		||||
:401F800043681B798B4201D2012909D8074A0848535CDBB24354A3780120DBB2535410BD002010BDCD92FF1F00600040BA92FF1F4293FF1F38B58A4A8A4C13780021DBB24F
 | 
			
		||||
:401FC00021801806517840F18D800A2900F20581DFE811F05D00030103010301030103010B0003017E0003018200D3787C49012B09D17D4B1A787D4B03EBC2035B685B68B3
 | 
			
		||||
:402000006360122310E0CB78022B12D18878FFF7E5FD002800F0E180436863606368DA7863689B7843EA02232380BDE83840FFF78FBCCB78032B26D16D4B00228878D5B28F
 | 
			
		||||
:40204000854209D3664A91786A4AEE2908BF1346634A917881B106E0187801320028F1D018780344EAE764499278097C914203D16248FFF739FD614B1A78002A00F0AD80B9
 | 
			
		||||
:402080001A78228018E0BDE8384000F025BF13F0030313D0022B40F0A0802380504B0C211B7903F07F02564B01FB02339A78554BD2B21A7000225A706360B6E70222228083
 | 
			
		||||
:4020C000514A11784F4AC9B2117053706260ACE7012323804D4BEFE70123238013794C4A1344E9E701390A2977D8DFE801F037764F76067676760A7620009378454ADBB2B5
 | 
			
		||||
:402100005AE0937803F0FF0153B9404B1A7891425FD01970404B01201870FFF715FE58E0481EC0B2FFF75AFD0028EED155E0FFF71DFF002851D02A4A384913791279DBB209
 | 
			
		||||
:40214000D2B20A70364A3249D25CCB5C9A4240D0314B01221A70FFF753FD3AE003F00303012B2BD009D3022B37D11D4B9B78002B33D1BDE83840FFF7BFBE194B9B78012B8E
 | 
			
		||||
:402180002BD1214A137803F0FD0315E003F00303012B13D008D3022B1FD1114B9B78E3B9BDE83840FFF77EBE0D4B9B78012B14D1154A137843F0020313700AE0084B1A79FA
 | 
			
		||||
:4021C0005AB998781B791749DBB2CA5C22EA0002CA54BDE83840FFF79BBA002038BD00BF00600040BC92FF1FC892FF1F083A00006C3A0000F4390000DF3A00006093FF1FEA
 | 
			
		||||
:40220000D492FF1F7992FF1FCB92FF1FCD92FF1FBA92FF1FB892FF1FCC92FF1FC992FF1F4293FF1FCF92FF1F074B1A78120609D55B78012B06D1054B054A5A6012781A8093
 | 
			
		||||
:40224000FFF786BB0020704700600040BC92FF1FCC390000014B1870704700BF78650040014B1878704700BF68650040014B1870704700BF76640040064A0123136002F636
 | 
			
		||||
:4022800088321268E0211064034A1170A2F540721360704780E100E000E400E0014B1870704700BF77640040014B1870704700BF7A64004073B515461E460B4C05230022DA
 | 
			
		||||
:4022C000019200920A4601461846237000F064F932462946207800F01FF90221207800F009F9207802B070BDD080FF1F064A0423136002F688321268E0219064034A1170F2
 | 
			
		||||
:40230000A2F202321360704780E100E002E400E0014B04221A60704700E100E0014B04221A60704780E100E0014B1870704700BF74650040704738B505460078012428B194
 | 
			
		||||
:4023400000F062FD285D0134E4B2F8E738BD08B50D2000F059FDBDE808400A2000F054BDF7B516461F460B4C00230325019300930A4601462846257000F00EF93A463146E4
 | 
			
		||||
:40238000207800F0C9F80221207800F0B3F8207803B0F0BDE080FF1FF7B516461F460B4C00230225019300930A4601462846257000F0F2F83A463146207800F0ADF82946CC
 | 
			
		||||
:4023C000207800F097F8207803B0F0BDE180FF1FF7B516461F460B4C00230125019300930A4601462846257000F0D6F83A463146207800F091F80221207800F07BF8207805
 | 
			
		||||
:4024000003B0F0BDE280FF1F73B515461E460B4C0023019300930A4601461846237000F0BBF832462946207800F076F80221207800F060F8207802B070BD00BFE380FF1F72
 | 
			
		||||
:40244000024B1878C0F38010704700BF8F450040074A7F23802113705170064A013BDBB202F80839002BF9D1034A1370704700BFE480FF1FF87B00400078004017280FD838
 | 
			
		||||
:40248000084B0001C25C11B142F0200201E002F0DF02C254C25C42F00102C25400207047012070471070004017280BD8064B0001C25C02F0FE02C254C25C02F0DF02C25451
 | 
			
		||||
:4024C00000207047012070471070004017280DD8074900010B4603441A7942F004021A71435C43F00103435400207047012070471070004017280BD8064A0001835C490093
 | 
			
		||||
:4025000003F0F10301F00E011943815400207047012070471070004041F6FF73994208BF4FF400519A4208BF4FF4005217289FBFC00000F1804000F5EC4081809ABFC28032
 | 
			
		||||
:40254000002001207047000017289FBF034B00011954002088BF0120704700BF1970004017289FBF054B00011A5C01F007019DBF1143195400200120704700BF147000404E
 | 
			
		||||
:4025800017289FBF034B0001185C00F0070088BFFF20704714700040172810B51AD8C00001F07F0100F1804441EAC21204F5EC44D2B222709DF8082003F00F0343EA0213C5
 | 
			
		||||
:4025C000DBB263709DF80C30002003F00F03A370E07010BD012010BD10B500F075FC0A4A5378182B0AD91478013B5370E30003F1804303F5F0431B78137000E0FF2400F0A3
 | 
			
		||||
:4026000067FC204610BD00BFE480FF1F030610B5044611D400F058FC084AE300117803F1804303F5F04319705378147001335370BDE8104000F04CBC10BD00BFE480FF1F18
 | 
			
		||||
:4026400030B504060CD411F4704509D1C40004F1804404F5F0442180A270E370284630BD012030BD03065FBFC00000F1804000F5F04081805ABFC2800020012070470000CD
 | 
			
		||||
:4026800038B50446084DB4F5004F05D9286800F013FCA4F50044F6E7034B58686043BDE8384000F009BC00BFEC80FF1F024B1B7A584300F001BC00BFEC80FF1F0E4B00F0E7
 | 
			
		||||
:4026C00003001A78490102F0FC02104318701A7801F0600142F080021A701A7802F07F021A701A7802F09F020A431A701A7842F010021A70704700BF83430040014B012238
 | 
			
		||||
:402700001A70704784430040044B00F00F021B6853F8220043F82210704700BF08ED00E0054A00F01F00126800F1100352F8230042F82310704700BF08ED00E000F01F0049
 | 
			
		||||
:4027400000F16040490100F56440C9B2017070470F4B10B50F4900240F205C609C60DC601C615C61FFF7D0FF0B4A136843F0040313600A4B4FF47A72DB68B3FBF2F3084A5C
 | 
			
		||||
:402780001360084B4FF400421C60C3F8E82010BD7C92FF1FFD27000010E000E0EC80FF1F14E000E018E000E0024A136843F002031360704710E000E008B5FFF7F5FF034A7F
 | 
			
		||||
:4027C000136843F00103136008BD00BF10E000E010B5054CA3691BB9FFF7BAFF0123A361BDE81040FFF7E8BF7C92FF1F024B1868C0F30040704700BF10E000E038B5FFF7EC
 | 
			
		||||
:40280000F5FF012808D1054D002455F8243003B198470134052CF8D138BD00BF8092FF1F024B03EB80035868596070477C92FF1F134B144A1B78DBB20360127843EA0223B0
 | 
			
		||||
:40284000114A0360127843EA0243104A0360127843EA026303600E4B0E4A1B78DBB24360127843EA02230C4A4360127843EA02430A4A4360127843EA02634360704700BFF1
 | 
			
		||||
:402880000301004904010049EC460040020100490101004900010049050100490601004910B500F011FB204A044613780A2043F002031370137C43F00203137412F80A3C08
 | 
			
		||||
:4028C00043F0010302F80A3C937943F00103937102F5AB52137843F003031370134B18221A7013F8012C42F0400203F8012C13F8012C02F0FC0203F8012CCE2203F8062C7C
 | 
			
		||||
:40290000A3F597530222183B1A70094A137843F008031370FFF7CAFE064B10222046BDE810401A6000F0D4BAAB4300400E5900402F5B004080E200E008B500F0C5FA0F4A3B
 | 
			
		||||
:40294000137803F0FE031370A2F5AA521D3A137803F0FD031370137C03F0FD03137412F80A3C03F0FE0302F80A3C937903F0FE039371BDE8084000F0ABBA00BF0859004037
 | 
			
		||||
:40298000044A137803F03F0343EA8010C0B21070704700BF08590040082804D00A280CBF8223C22300E0422308380E4AC0B20428137098BF0C4B4FF0000298BF33F9101028
 | 
			
		||||
:4029C0000A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B1A8070470A590040B83900004A93FF1F4C93FF1F5093FF1F08B5102000F0A6F974
 | 
			
		||||
:402A000007210420FFF79AFE07490420FFF788FE064A0C20137843F006031370FFF7BCFF034B00221A8008BDF12A0000095900404893FF1F10B5054C23781BB9FFF7DCFF7A
 | 
			
		||||
:402A400001232370BDE81040FFF72ABF9892FF1F044B1A7802F0FB021A701A7842F001021A7070470859004010B5084B1C7814F0010403D10028F9D0002404E02046FFF7A2
 | 
			
		||||
:402A800015FE024B1B78204610BD00BF09590040034A044B1B881088181A00B2704700BF5093FF1FA25B00400E4A13881BB223B111880A2309B2594301E00B4B19680B4B61
 | 
			
		||||
:402AC0001B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270474A93FF1F4C93FF1F4893FF1F7047000010B500F0E7F9214A0446137861
 | 
			
		||||
:402B00000A2043F001031370137C43F00103137412F80A3C43F0020302F80A3C937943F00203937102F5AA521832137843F003031370144B18221A7013F8012C42F0400201
 | 
			
		||||
:402B400003F8012C13F8012C02F0FC0203F8012CCE2203F8062CA3F597530222123B1A70094A137843F008031370FFF79FFD074B08222046BDE810401A6000F0A9B900BFB0
 | 
			
		||||
:402B8000AB43004006590040275B004080E200E008B500F099F90F4A137803F0FE031370A2F5AA52153A137803F0FE031370137C03F0FE03137412F80A3C03F0FD0302F87F
 | 
			
		||||
:402BC0000A3C937903F0FD039371BDE8084000F07FB900BF00590040044A137803F03F0343EA8010C0B21070704700BF00590040082804D00A280CBF8223C22300E0422383
 | 
			
		||||
:402C000008380E4AC0B20428137098BF0C4B4FF0000298BF33F910100A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B1A8070470259004054
 | 
			
		||||
:402C4000C23900005693FF1F5C93FF1F5493FF1F08B5102000F084F807210320FFF76EFD07490320FFF75CFD064A0C20137843F006031370FFF7BCFF034B00221A8008BD33
 | 
			
		||||
:402C8000492D0000015900405893FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040FFF728BF9992FF1F044B1A7802F0FB021A701A7842F001021A70704700590040D8
 | 
			
		||||
:402CC00010B5084B1C7814F0010403D10028F9D0002404E02046FFF7E9FC024B1B78204610BD00BF01590040034A044B1B881088181A00B2704700BF5493FF1FA05B004034
 | 
			
		||||
:402D00000E4A13881BB223B111880A2309B2594301E00B4B19680B4B1B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270475693FF1FD5
 | 
			
		||||
:402D40005C93FF1F5893FF1F70470000034A00F0F800137803431370704700BF02410040034A00F0F800137803431370704700BF06410040014B1870704700BF7F64004011
 | 
			
		||||
:402D8000014B1870704700BF7B65004073B515461E460B4C04230022019200920A46014618462370FFF7F8FB324629462078FFF7B3FB02212078FFF79DFB207802B070BDA9
 | 
			
		||||
:402DC000FC80FF1F074A0223136002F688321268E0215064044A11706FF440710A441360704700BF80E100E001E400E0014B1870704700BF7A650040014B1870704700BF9C
 | 
			
		||||
:402E00007965004000000000FEB5494652465B460EB40746244909688A46244A12682448022100F071F8030020480068C018204900F06AF8143883460121C9430C4601254B
 | 
			
		||||
:402E4000002600F041F8814651460B7823400B705846013000F030F83800F04028400B78234003430B70584600F026F80136072EF2D9002001300138013001200B78234041
 | 
			
		||||
:402E800003430B705846043000F016F8484600F01FF800BF00BF00BF0EBC894692469B46FEBD00BFAFF30080D480FF1FF880FF1F00C20100000000000230800803D000BFAA
 | 
			
		||||
:402EC00001380046FCD17047EFF3108072B6704780F31088704700BF094A137803F00303012B0AD0022B09D113790C2103F07F02044B01FB02339B7A00E013790020704714
 | 
			
		||||
:402F000000600040D492FF1F002902D0B0FBF1F0704708B14FF0FF3000F008B80029F8D00246B0FBF1F000FB11217047704700BF014B1868704700BF6081FF1F0E4B70B57A
 | 
			
		||||
:402F40001E460E4C0025E41AA410A54204D056F8253098470135F8E700F0DEFD084B094C1E46E41AA4100025A54204D056F8253098470135F8E770BD243B0000243B00007F
 | 
			
		||||
:402F8000243B00002C3B000003460244934202D003F8011BFAE7704730B5141E05469BB0184604DA8B232B604FF0FF301DE04FF40273ADF80C300CBF234604F1FF33029350
 | 
			
		||||
:402FC00005934FF6FF7300910491ADF80E3002461E9B6946284600F073F8431CBCBF8B232B6014B1009B00221A701BB030BD000007B5009313460A46014603480068FFF741
 | 
			
		||||
:40300000CBFF03B05DF804FB6081FF1F2DE9F0478E6882469E420C46914698463ED88A8912F4906F3AD02568096902236F1A656905EB450595FBF3F57B1C43449D4238BF75
 | 
			
		||||
:403040001D4653050FD5294600F04AFB064698B13A46216900F0D2FAA38923F4906343F08003A38113E02A4600F098FB064670B92169504600F0E8FA0C23CAF80030A38908
 | 
			
		||||
:403080004FF0FF3043F04003A381BDE8F08726613E44266046466561ED1BA560464528BF464649463246206800F0B3FAA36800209B1BA36023681E442660BDE8F087000061
 | 
			
		||||
:4030C0002DE9F04F9DB003938B8980461C060D4616460DD50B695BB9402100F001FB2860286118B90C23C8F80030CDE040236B610023099320238DF82930DFF89CB1302302
 | 
			
		||||
:403100008DF82A3037463C4614F8013B1BB9B7EB060910D003E0252BF9D02746F3E74B46324629464046FFF771FF013000F0A780099B4B4409933B78002B00F0A080002335
 | 
			
		||||
:403140004FF0FF3204930793059206938DF853301A930126052221784E4800F041FA671C049B38B14B4A3C46801A06FA00F018430490EFE7D90644BF20228DF853201A0773
 | 
			
		||||
:4031800044BF2B228DF8532022782A2A03D0079A00210A200BE0039A111D12680391002A10DA524243F00200079204900BE027463B780134303B092B03D800FB0232012141
 | 
			
		||||
:4031C000F5E701B107923B782E2B1ED17B782A2B0AD1039B02371A1D1B680392002BB8BF4FF0FF33059310E0002319460593781C0A2407463A780130303A092A03D804FB46
 | 
			
		||||
:4032000001210123F5E703B1059103223978224800F0E6F940B14023CBEB000003FA00F0049B013718430490397806221B487E1C8DF8281000F0D4F988B1194B33B9039BDF
 | 
			
		||||
:40324000073323F007030833039314E003AB00932A46144B04A94046AFF3008007E003AB00932A460F4B04A9404600F093F8B0F1FF3F824603D0099B5344099342E7AB897F
 | 
			
		||||
:403280005B0601D4099801E04FF0FF301DB0BDE8F08F00BFF33A0000F93A0000FD3A0000000000000D3000002DE9F04791461F460A698B6806469342B8BF1346C9F8003093
 | 
			
		||||
:4032C00091F843200C46DDF8208012B10133C9F800302368990642BFD9F800300233C9F80030256815F0060510D104F1190A07E00123524639463046C04701301AD001355B
 | 
			
		||||
:40330000E368D9F800209B1A9D42F1DB94F843302268003318BF012392060FD5E118302081F843005A1C94F845102244023382F8431003E04FF0FF30BDE8F08704F1430253
 | 
			
		||||
:4033400039463046C0470130F4D02268D9F80050E36802F00602042A08BF5D1B2269A3680CBF25EAE57500259342C4BF9B1AED184FF000091A344D4509D0012322463946F2
 | 
			
		||||
:403380003046C0470130D5D009F10109F3E70020BDE8F0872DE9F04317460A7E85B06E2A984606460C460C9B01F1430E00F0AE8011D8632A22D009D8002A00F0BB80582A01
 | 
			
		||||
:4033C00040F0CA8081F84520834955E0642A1ED0692A1CD0C0E0732A00F0B08009D86F2A2ED0702A40F0B8800A6842F020020A603EE0752A24D0782A3AD0ADE01A6801F114
 | 
			
		||||
:403400004205111D1960136884F84230A8E021681A6811F0800F02D0111D196008E011F0400F02F10401196002D0B2F9003000E01368002B3CDA2D225B4284F8432037E0C5
 | 
			
		||||
:4034400021681A6811F0800F02D0111D196007E011F0400F02F10401196001D0138800E01368227E5C496F2A14BF0A2208221BE078225A4984F845202268186812F0800F0E
 | 
			
		||||
:4034800000F104051D6003D1550601D5038800E00368D00744BF42F0200222601BB9226822F0200222601022002084F8430001E049490A226568002DA56008DB206820F0CC
 | 
			
		||||
:4034C000040020602BB9002D7DD175460CE0002B79D07546B3FBF2F002FB1033CB5C05F8013D03460028F5D1082A0BD12368DA0708D5236962689A42DEBF302305F8013CF7
 | 
			
		||||
:4035000005F1FF35C5EB0E0323612EE008681A6810F0800F496903D0101D1860136808E010F0400F02F104001860136801D0198000E0196000232361754616E01A68111DFC
 | 
			
		||||
:403540001960156800216268284600F049F808B1401B6060636804E004F1420584F8422001232361002384F84330CDF800803B4603AA21463046FFF797FE013002D14FF056
 | 
			
		||||
:40358000FF3026E023692A4639463046C0470130F5D023689B0710D5002504F1190907E001234A4639463046C0470130E7D00135E368039A9B1A9D42F2DBE068039B9842DC
 | 
			
		||||
:4035C000B8BF184605E00B7804F1420584F842308AE705B0BDE8F083A7390000043B000010B5C9B202449042034605D01C7801308C42F8D1184610BD002010BD10B5431EF7
 | 
			
		||||
:403600000A44914204D011F8014B03F8014FF8E710BD884210B501EB020301D8421E0BE09842FBD28118D21AD34204D013F8014D01F8014DF8E710BD994204D011F8014B40
 | 
			
		||||
:4036400002F8014FF8E710BD38B50546002944D051F8043C0C1F002BB8BFE41800F0D4F81E4A1368114613B96360146030E0A3420DD92268A018834201BF18685B68121885
 | 
			
		||||
:40368000226063600C6023E0A24203D813465A68002AF9D118681918A1420BD12168014458188242196013D110685268014419605A600DE002D90C232B6009E021686018A3
 | 
			
		||||
:4036C000824201BF106852680918216062605C602846BDE8384000F098B838BDA092FF1F70B5CD1C25F0030508350C2D38BF0C25002D064601DBA94202D90C23336046E018
 | 
			
		||||
:4037000000F082F8234B1C681A462146A1B10B685B1B0ED40B2B03D90B60CC18CD501EE08C420BBF63684B681360636018BF0C4615E00C464968E9E7174C23681BB9304658
 | 
			
		||||
:4037400000F052F820602946304600F04DF8431C18D0C41C24F00304A0420DD12560304600F053F804F10B00231D20F00700C31A0ED05A42E25070BD211A304600F034F863
 | 
			
		||||
:403780000130EBD10C233360304600F03EF8002070BD00BFA092FF1F9C92FF1FF8B5074615460E4621B91146BDE8F840FFF798BF1AB9FFF749FF2846F8BD00F027F8854208
 | 
			
		||||
:4037C0000ED929463846FFF78BFF044650B131462A46FFF713FF31463846FFF735FF01E03046F8BD2046F8BD38B5064C0023054608462360FDF7DCFB431C02D1236803B13B
 | 
			
		||||
:403800002B6038BD8493FF1F7047704751F8040C0028BEBF091851F8043CC0180438704700000000050209020B020D020F021102130215027265706C792030782530327881
 | 
			
		||||
:4038400000686F6D696E6700626567696E6E696E67207365656B2066726F6D20256420746F2025640066696E6973686564207365656B00796573006E6F00647269766520AA
 | 
			
		||||
:40388000303A20257320647269766520313A2025730057616974696E6720666F72205553422E2E2E0055534220726561647900636F6D6D616E64203078253032780066610F
 | 
			
		||||
:4038C000696C2025642B25642B2564203D3D2025642C206E6F74202564007061737365643D256400756E64657272756E206166746572202564207061636B65747300636FE8
 | 
			
		||||
:40390000756E743D256420693D256420643D256400636D645F777269746500703D25642063723D25642063773D256420663D256420773D256420696E6465783D2564207526
 | 
			
		||||
:403940006E64657272756E3D256400756E64657272756E2100737563636573730073746172742065726173696E670073746F702065726173696E670069646C650000510001
 | 
			
		||||
:4039800040100040510040300000000140001000140140000800400140000A004C014000020050014020003031323334353637383941424344454600000100000004000096
 | 
			
		||||
:4039C00000100001000000040000001028000000000104000100000000000000000157494E5553420000303030303100000000000000000012034D0053004600540031002A
 | 
			
		||||
:403A0000300030000100000001000000103A000001000000DF3A0000000000000000000001000000283A000001000000B13A0000040000004A3A00000000000000000000E9
 | 
			
		||||
:403A400000000000483A0000FF00000001024000FF00000082024000FF00000003034000FF00000084034000FF00020304030904160346006C007500780045006E006700CA
 | 
			
		||||
:403A800069006E0065002A0343006F0077006C00610072006B00200054006500630068006E006F006C006F0067006900650073000009022E0001010080320904000004FFC9
 | 
			
		||||
:403AC00000000107050102400000070582024000000705030340000A0705840340000A12010002FF0001080912006E0100020180014300232D302B2000686C4C00656667E2
 | 
			
		||||
:403B0000454647003031323334353637383961626364656600000000F8B500BFF8BC08BC9E467047590000002D100000F8B500BFF8BC08BC9E46704735000000503B0000FD
 | 
			
		||||
:403B4000C880FF1FA00000002012000000000000000000008893FF1FFF000000675000400C00000007000000FFFFFFFF7F8000003F0000000000007D00FA000040000000DA
 | 
			
		||||
:403B80000090D003FF0000000000000000000000000000000000000000000000000000000000000000000000F13A0000000000000000000000000000000000000000000078
 | 
			
		||||
:403BC000000000000000000000000000000000000000000000000000000000000000000000000000000000000081FF1F000000000000000000000000000000000000000026
 | 
			
		||||
:403C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084
 | 
			
		||||
:403C40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044
 | 
			
		||||
:403C80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004
 | 
			
		||||
:4000000000800020110000004110000041100000064A08B5136843F020031360044B1A6803F53F5302331A6001F028F8E8460040FA46004010B5054C237833B9044B13B163
 | 
			
		||||
:400040000448AFF300800123237010BD6881FF1F00000000C8380000084B10B51BB108490848AFF300800848036803B910BD074B002BFBD0BDE81040184700BF0000000041
 | 
			
		||||
:400080006C81FF1FC8380000C880FF1F000000000A4A0B4B116801310B40002BBEBF03F1FF3363F03F030133136011685368994202BF024B01221A72704700BF8881FF1FBC
 | 
			
		||||
:4000C0003F0000800A4A0B4B516801310B40002BBEBF03F1FF3363F03F030133536051681368994202BF024B01221A72704700BF8881FF1F3F000080114BDA68196919B9FD
 | 
			
		||||
:4001000001221A75597514E09969521A19698A4294BF587D00201875187D094908B1002204E0086982428CBF002201224A75DA689A611B7D13B1002002F046B9704700BF70
 | 
			
		||||
:400140008881FF1F10B5C4B2204601F059F90128FAD110BD08B572B60F4B0F49DA680132DA60DA690132C82A08BF0022DA611A6AD8690132A72A08BF00220A621B6A002B13
 | 
			
		||||
:400180000CBF02230023002814BF184643F0010002F082FE62B608BD8881FF1F38B50446C5B2284602F0B2F8062002F0CFFA44F00200C0B202F0AAF8062002F0C7FA28460D
 | 
			
		||||
:4001C00002F0A4F8BDE83840062002F0A9BA10B5642402F095F828B9FFF7E0FF013CF8D1204610BD012010BD70B5C4B2054620460E4601F005F9012805D0204601F01EFA34
 | 
			
		||||
:400200002846FFF79FFF204601F002F9314605460246204601F0BEF9204601F0F1F80028FAD1284670BD000038B5044D0024285D013402F03BFA402CF9D138BDAC81FF1FCB
 | 
			
		||||
:4002400008B502F055FC002002F05EFC02F070FC02F07AFC80B208BD10B50446012002F06DF8642002F05CFAFFF7EAFF2080002002F064F8642002F053FAFFF7E1FF60809C
 | 
			
		||||
:4002800010BD08B502F060FD002002F069FD02F07BFD02F085FD80B208BD10B50446FFF796FF322002F03CFAFFF7EBFF20800120FFF774FF322002F033FAFFF7E2FF6080D2
 | 
			
		||||
:4002C00010BD0FB400B593B014AB53F8042B402102A8019302F0E0FE02A802F07CF802F086F813B05DF804EB04B0704710B5044601780648FFF7E5FF0420FFF723FF627816
 | 
			
		||||
:400300002146BDE81040042001F0D2B8DC38000007B50023ADF804308DF80600032301A88DF80530FFF7E2FF03B05DF804FB000010B5074C94F8643043B1002001F0DAFFEE
 | 
			
		||||
:40034000002002F06DFD002384F8643010BD00BF8881FF1F38B5104D837895F8672004469A4204D0FFF7E4FF002385F86A302368C5F865302279094B1A71A378002B14BF45
 | 
			
		||||
:400380000220012002F04CFDE07802F043FD2079BDE8384002F07ABD8881FF1FED81FF1F38B50D4C94F8645065B904F16500FFF7D1FF012001F09EFF4FF47A7002F0B0F968
 | 
			
		||||
:4003C00084F86A50E368E366012384F86430BDE8384002F0E3B900BF8881FF1FF8B5214C0546FFF7DDFF94F86A3003B15DB91E48FFF767FFFFF7EBFE0120002384F86A007C
 | 
			
		||||
:40040000236702F0A3F92A46216F1848FFF759FF144E0027236F9D4216D001F071FF00B13767236F9D4205DD0120FFF7B7FE336F013305E005DA0020FFF7B0FE336F013B0B
 | 
			
		||||
:40044000336702F0ABF9E5E7322002F069F92A2DCCBF0020012002F025FDBDE8F8400448FFF72FBF8881FF1FE9380000F03800000D3900002DE9F04F99B062B602F0F8F947
 | 
			
		||||
:400480009E49042002F01CFA9D4801F045FF9D4802F0E8FC9C4801F079FF02F0C9FB02F09BFA002002F0BCFC01F094FF0221002000F05CFF954C012001F0D4F8002384F890
 | 
			
		||||
:4004C0006730FFF76DFFFFF782FE84F87400FFF72FFF012384F86730FFF762FFFFF777FE84F87500FFF724FF894B94F87400894994F875202546002A14BF0A461A4600286F
 | 
			
		||||
:4005000008BF19468448FFF7DCFE0321084602F025F9264602F042F994F8643043B1EA6EEB689B1A41F28832934201D9FFF700FF00F054FF18B97948FFF7C3FE04E000F079
 | 
			
		||||
:4005400053FF0028F7D10BE000F048FF10B902F025F9F9E77248FFF7B4FE032001F06EF8032000F04DFF0128D4D16E48FFF7F2FE6D490320FFF738FE94F876106B48FFF7F9
 | 
			
		||||
:40058000A0FE94F87630023B142B00F2D683DFE813F01500D4031E00D4032400D4035000D4037600D403D900D403C101D4030803D4032C03D4033303D4034D0303238DF851
 | 
			
		||||
:4005C00020308DF821300F238DF822302AE394F87800FFF703FF564B21E340F2DC57FFF7DFFE00232375E068227D02F0FF012AB9EB681B1ABB42F7DD0B4611E083B100227E
 | 
			
		||||
:40060000174696F87810F068277594F814E0BEF1000F02D1EB681B1AF7E701329142F3DA07228DF8202004228DF82120ADF82230F8E20220FFF786FD4FF000080DF1200A54
 | 
			
		||||
:4006400002F0ACF84FF480790027C9EB0803DA1907F80A200137402FF9D10220FFF772FD3A465146022000F023FFB9F10109EBD108F10108B8F1400FE2D12E4B38E04FF076
 | 
			
		||||
:40068000010A4FF000080DF1200B02F087F84FF0000959460120FFF7A7FD08EB090300270493049B1BF807203B44DBB29A4209D08DE80C0041463B464A461F48FFF701FEE0
 | 
			
		||||
:4006C0004FF0000A0137402FEBD109F10109B9F5807FDED108F10108B8F1400FD5D151461648FFF7EEFDBAF1000F00F01B81144B1B8807A8ADF81C3095E200BF5501000004
 | 
			
		||||
:40070000F900000091000000C50000008881FF1F1F3900001B390000223900003A3900004D390000ED81FF1FFE81FF1F57390000CC380000CE380000663900008239000026
 | 
			
		||||
:40074000D0380000206FFFF749FE94F8780001F0F5FD94F8780001F0D9FD02F009FCB94BDFF8FC821A78002702F0FB021A701A7842F001021A701A7802F0FE021A701A7880
 | 
			
		||||
:4007800002F0FE021A7002F0F7FB0220FFF7DAFC012141F6FF734FF48042084602F046FB84F8B60001F068FF08F807000137402FF8D1DFF8B0A200270AF195091FFA89F816
 | 
			
		||||
:4007C0000137402F14BF3A4600221AF8010F2244062392F82420402101F082FF424646F240419AF8000001F08DFF08F14008402F1FFA88F8E4D196F8793053B196F87C30C8
 | 
			
		||||
:40080000336100233375237D002BFCD000233375336100234FF0FF32236062602372236894F8B600234493F8241001F0DDFE94F8B60001F09BFE012194F8B60001F06EFEAA
 | 
			
		||||
:400840002368002BFCD0002398467360D6F80CA0012701F0A3FFE368B4F87A20CAEB030393420DD367B1042195F8B60001F0C8FE94F8B60001F0D4FE0028F9D107463072CF
 | 
			
		||||
:40088000237AFBB96A682B689A4202D1002FE0D118E00220FFF756FC6968402209EB8111022000F005FE6A68674B01321340002BBEBF03F1FF3363F03F03013308F1010820
 | 
			
		||||
:4008C0006360C6E70220277AFFF73CFC00221146022000F0EDFD0220FFF734FCFFB2FFF7A3FC002001F012FD37B15848FFF7E9FC0220FFF70DFD06E0554B08A81B88ADF871
 | 
			
		||||
:400900002030FFF7F3FC227D4146237A5148FFF7D8FC15E25048FFF7D4FCD4F87A7017F03F0701D0032009E2286FFFF757FD95F8780001F003FD95F8780001F0E7FC012054
 | 
			
		||||
:4009400001F002FD02F014FB444BDFF814811A7842F004021A701A7842F001021A701A7802F0FE021A701A7802F0FE021A7002F003FB01214FF4804341F6FF72084601F0CB
 | 
			
		||||
:40098000E9FC85F8B60001F077FE08F807000137402FF8D1DFF8CC90002709F195031FFA83F804930137402F14BF3A46002219F8010F2244052392F82420402101F090FEB2
 | 
			
		||||
:4009C000414646F2475299F8000001F09BFE08F14008402F1FFA88F8E4D100274FF0FF33376098467360BB463B46D6F87A9037725FEA99190CBF4FF0010A4FF0000A2168C1
 | 
			
		||||
:400A0000114A01310A40002ABCBF02F1FF3262F03F026068B8BF013282426FD02BB1227A002A7AD12A7D002A77D12068049A059302EB8010BAF1000F16D040223F2102F079
 | 
			
		||||
:400A4000F7FA1CE0906400403F0000808C390000D2380000A6390000B939000097650040AC81FF1FAB81FF1F014601370120FFF7BBFBC7EB0903D3F1000A4AEB030A216882
 | 
			
		||||
:400A8000B34A01310A40002ABEBF02F1FF3262F03F02013222606268059B01322ED12A683F2A2BD14FF00008C5F8048001F080FC85F808806B6895F8B6002B4493F82410D9
 | 
			
		||||
:400AC00001F092FD95F8B60001F050FD012195F8B60001F023FD95F87E302B6185F81480237D002BFCD04FF00008012086F8148001F06AFC404601F027FC00E023B1237A54
 | 
			
		||||
:400B00005BB92B7D4BB90123626842453FF477AF0BF1010BD5F8048071E701F04FFC012001F012FC002001F04FFC042194F8B60001F066FD94F8B60001F072FD8046002873
 | 
			
		||||
:400B4000F8D196F8B60001F0FFFC337D327A0293012303920193CDF800A05B463A4649467C48FFF7AEFBC6F81080BAF1000F0BD0FFF75AFB002001F0C9FB237A63B1764854
 | 
			
		||||
:400B8000FFF79FFB0220D9E0B945F1D073490120FFF72AFB0137F7E77148FFF792FB714B3DE094F8780001F0C9FB206FFFF716FC6D48FFF786FB94F87930236100232375F8
 | 
			
		||||
:400BC000237D002BFCD0012001F0FEFB00233375237D002BFCD0002001F0F6FB002363483361FFF76EFB624B19E0002084F86A00FFF7F4FB5F4B12E094F8743023B195F870
 | 
			
		||||
:400C000075200AB985F8782094F875201AB113B9012385F878305848FFF79CFB574B1B88ADF8203008A8FFF761FB89E0FFF780FB02F07CF8002002F01FF82A2701F04AFFE9
 | 
			
		||||
:400C4000002001F0EDFE3A46002108A802F0F0F917238DF820308DF8217001F09FFD002001F048FB002002F0DBF8C82001F058FD0DF12200FFF7F0FA0DF13600FFF70DFB01
 | 
			
		||||
:400C800001F08CFD012002F0CBF8322001F048FD0DF12600FFF7E0FA0DF13A00FFF7FDFA012001F027FB4FF4967001F039FD01F075FD0DF12E00FFF7CFFA0DF14200FFF71B
 | 
			
		||||
:400CC000ECFA002001F016FB4FF4967001F028FD01F064FD022002F0A3F8322001F020FD0DEB0700FFF7B8FA0DF13E00FFF7D5FA012001F0FFFA4FF4967001F011FD01F040
 | 
			
		||||
:400D00004DFD0DF13200FFF7A7FA0DF14600FFF7C4FA002001F0EEFA4FF4967001F000FD01F03CFD002002F07BF8002384F86A3001F07EFF01F050FE74E70120FFF7E8FA91
 | 
			
		||||
:400D4000032000F07BFC0E48FFF7BBFAFFF7E2BB3F000080C3390000F33900004092FF1FFD390000D4380000053A0000133A0000D6380000D8380000FE81FF1FDA380000E3
 | 
			
		||||
:400D8000203A00002DE9F04172B6884B61221A70A3F5F06301221A801924854A9C7092E803008033062283F8002283E80300522203F580731A707F4B7F4A1B787F4EDBB2FE
 | 
			
		||||
:400DC000137040F618027E4B00251A8041F2512223F8022C33784FF4F07003F0010343EA450502F0BDF8013C05F003052ED0032DF0D1744B4FF480721A8007221A70724A20
 | 
			
		||||
:400E0000002548211570917002221D705D7103F8032C0422DA716D4A6D4C13786D4E43F00103137012F8013C062743F0030302F8013C2378012243F0800323705B4B1A70F9
 | 
			
		||||
:400E4000654A137843F02003137000E0FEE707FB056300219A881868013502F0E9F8072DF5D15E485E4E002550F8041F05F1105303F1480221F0FF074933C9B20B44520042
 | 
			
		||||
:400E80005B0002329A4206D012F802EC12F801CC0EF807C0F5E7B0420D44E5D1514A002313609360136193614F4B504F1A68504BDFF888811A604F4B1A684F4B1A604F4A7B
 | 
			
		||||
:400EC000137843F002031370137C43F0020313742378A2F5863243F040032370413A137843F010031370464A464B07CA03C31A80454A2833106843F8250C127903F8212CA9
 | 
			
		||||
:400F0000424A07CA03C31A80414AE83B07CA03C31A80404A083307CA03C31A803E4A3F4BA2F5616203CBC2F8100EC2F8141E1378042043F008031370394B02F5AA521B78A7
 | 
			
		||||
:400F40003D78DBB298F80060EDB203F007010C321B091170F6B2537045F003033B7046F0030388F800302F4B48221A702E4A402313702E49937013729372082382F81F32BF
 | 
			
		||||
:400F800020220A7048710A72294A0A20137001F0DDFB284B88F8006044223D70264D1A7094E80F0007C52B80BDE8F081004800404C0A00480F010049A1460040254200408F
 | 
			
		||||
:400FC000224200400440004006400040A2430040A0430040253A0000E8460040FCFFFF478C00004800760040540A0048F846004020760040580A004828760040035001404D
 | 
			
		||||
:401000000C0A0048C0510040180A0048200A00482C0A0048380A004832510040440A0048CF0100491D51004001590040235B0040585B004076580040B0430040F9460040F2
 | 
			
		||||
:4010400008B501F0C9FF03680C2B00D1FEE7FEE7084908B50B68084A1844821A802A01DC086005E001F0B8FF0C2303604FF0FF33184608BDCC80FF1F9093FF1F80B5114817
 | 
			
		||||
:40108000114B0025C0B1A3F1100192C922460439161BB74204D051F8046F42F8046BF7E7114653F8046C8C1AA64202D041F8045BF9E701381033E5E701F094FFFFF7DAF9D9
 | 
			
		||||
:4010C000FEE700BF01000000F43B0000124A134B10B51A60124A134C1368134843F4007313600023032B98BF54F823204FEA830188BF0E4A0133302B4250F3D10C4B1A7814
 | 
			
		||||
:401100000C4B1A700C4B084A1A60FFF73BFEBDE8104001F0EDB900BF0004FA050CED00E014ED00E0000000000080FF1F41100000BC760040C080FF1F08ED00E0F8B501F042
 | 
			
		||||
:4011400017FF4B4A01271378022643F001031370137C484C43F001031374474B02F5E3521F700B3203F8946C1378054603F07F031370002001F0EAFA2378404A03F0F903F2
 | 
			
		||||
:4011800023701378384603F0DF03137023783B43237001F0DBFA282001F0D8FA384B30461A7802F07F021A701A7802F0BF021A7023783343237001F0C9FA2378314A43F0C6
 | 
			
		||||
:4011C000040323700023137053702F4AFF2199540133092BFBD1284601F0CEFE0721172001F0FCFA2949172001F0EAFA0721182001F0F4FA2649182001F0E2FA0721152033
 | 
			
		||||
:4012000001F0ECFA2349152001F0DAFA0721052001F0E4FA2049052001F0D2FA0721062001F0DCFA1D49062001F0CAFA0721084601F0D4FA1A49072001F0C2FA07210820F8
 | 
			
		||||
:4012400001F0CCFA1749082001F0BAFA0021162001F0C4FA1449162001F0B2FA07210C2001F0BCFABDE8F84010490C2001F0A8BAA5430040944300409D6000401260004076
 | 
			
		||||
:40128000F851004084600040B592FF1F0B1B000045190000091B00003D1A0000691A0000991A0000D11A0000111B0000851B0000214B224A10B5187000231370204A40209B
 | 
			
		||||
:4012C0001370204A0F2413701F4A13701F4A13701F4A13701F4A13701F4B4FF400021A604FF080721A604FF400121A6020221A601860802018604FF480701860174804702E
 | 
			
		||||
:401300004FF480001860164B1A70933B19B91A7802F0FE0202E01A7842F001021A70114B03221A70802203F8202C012001F018FE0D4B04221A7010BDD092FF1FD692FF1F39
 | 
			
		||||
:40134000D492FF1FD592FF1FD192FF1FC092FF1FD392FF1F4893FF1F00E100E09E6000409C600040286000401260004070B5074C054623780E461BB9FFF7E0FE0123237031
 | 
			
		||||
:4013800031462846BDE87040FFF792BF8092FF1F0A4A002313700A4A13700A4A13700A4A13700A4A13700A4A13700A4A13700A4B03221A70802203F8202C7047D692FF1F4E
 | 
			
		||||
:4013C000D492FF1FD592FF1FD192FF1FC092FF1FD392FF1F4893FF1F28600040014B1878704700BFD592FF1F044B1A7802F0FF001AB118780022C0B21A707047D492FF1F52
 | 
			
		||||
:40140000024A0C2303FB002040787047DC92FF1F431E072B0CD8074A064B00010344805C5B7800F00F0043EA0020023880B2704700207047FC5F00401A4A38B50C2303FBA9
 | 
			
		||||
:4014400000231B79090C13F0800F00F1FF35044619BF8AB24FF480438BB24FF48042032D18D8DFE805F002070C110021084601F01BF80DE00021084600F0FAFF08E0002180
 | 
			
		||||
:40148000084600F0D9FF03E00021084600F0B8FF054B1855EDB2072D03D801F0EDF8034B185538BDDC92FF1FAC92FF1FB592FF1F431E072B2DE9F0470446894615465CD857
 | 
			
		||||
:4014C0002F4F0C2202FB0072D388DFF8B8A09BB2C3F500739D424FF00C0303FB007388BFD588DB7884BFC5F50075ADB2254A43EA15230601B354B244EBB28AF80130224BD4
 | 
			
		||||
:401500001A5C9846FF2A01D1FFF796FF0C2303FB047200215170B9F1000F28D03DB31B4F385D01F011F811232946FE2218F8040001F0D6F806F5C04278321FFA89F118F8D2
 | 
			
		||||
:40154000040001F0DFF8124D18F80410385D01F04BF80121385D00F0E1FF735D43F002037355735D03F0FD037355BDE8F08703FB04746379DBB28AF80230BDE8F08700BFE7
 | 
			
		||||
:40158000DC92FF1FFC5F0040B592FF1FAC92FF1F706000402DE9F047044615468846002940D0431E072B3FD8FFF732FFA84203D22046FFF72DFF05461D4E335DFF2B03D1DE
 | 
			
		||||
:4015C00041462046FFF738FFDFF868A027011AF8040000F0B9FF1223FE222946305D01F07FF807F5C0411FFA88F27831305D01F089F8DFF84490315D1AF8040000F0F4FFE9
 | 
			
		||||
:4016000001211AF8040000F089FF17F8093043F0020307F8093017F8093003F0FD0307F8093002E00D4600E000252846BDE8F087B592FF1FAC92FF1F70600040431E072BA7
 | 
			
		||||
:401640000AD8064A0C2303FB002300225A705A79034BD2B200011A54704700BFDC92FF1FFE5F0040431E072B9FBF024B000108221A547047FE5F004030B51A4A1A491B4D0A
 | 
			
		||||
:401680000878138803449BB21380194A00231488D8B2A4B27CB1082B0CD050680078C0B2E85450680133013050601088013880B21080ECE718460B780E4C082B0E4A00D003
 | 
			
		||||
:4016C00040B10E4D2B7883F080032B700F232370022301E0022323701370094B1870087030BD00BF4C93FF1F4893FF1F00600040C492FF1FC192FF1FD692FF1FD292FF1FE1
 | 
			
		||||
:401700004993FF1F074B02221A70074B80221A70064B0F221A70064A00231370054A012013707047D692FF1FD292FF1FC192FF1F4893FF1F4993FF1F30B5164B16491B78E1
 | 
			
		||||
:401740000A8803F00F03023BDBB21A4492B20A80124C134A0020118889B279B173B15568215C013BC9B229705168DBB20131516011880130013989B21180ECE7094A1370B3
 | 
			
		||||
:40178000094A137883F080031370084B0B221A7030BD00BF296000404C93FF1F00600040C492FF1F4993FF1FD292FF1FC192FF1F064A06231370064A01201370054B802273
 | 
			
		||||
:4017C0001A70054B00221A70704700BFD692FF1FC192FF1FD292FF1F4993FF1F054B9A683AB19A68044910709A680988518000229A607047C492FF1F4C93FF1F08B5124BAC
 | 
			
		||||
:401800001A78D2B21A701B78DBB21A0602D50F4A137008BD0220FFF7E1FF0D4B1B7803F06003202B05D0402B06D043B900F012FC04E001F0A5FB01E000F046FD10B9034B1C
 | 
			
		||||
:4018400003221A7008BD00BF28600040C192FF1F0060004008B5084A084B0120197813880B449BB21380064B00221A70FFF7B6FF044B03221A7008BD4C93FF1F4893FF1F1D
 | 
			
		||||
:40188000D692FF1FC192FF1F08B50C4B1B78DBB2042B07D0062B09D0022B0DD1BDE80840FFF7D8BFBDE80840FFF746BF0320FFF795FF034B03221A7008BD00BFD692FF1FCC
 | 
			
		||||
:4018C000C192FF1F08B5054B002201201A70FFF785FF034B03221A7008BD00BFD692FF1FC192FF1F08B50A4B1A7832B11A78094942F080020A7000221A70074B00220120D1
 | 
			
		||||
:401900001A70FFF76BFF054B03221A7008BD00BFC092FF1F08600040D692FF1FC192FF1F074B1B78DBB2042B05D0062B05D0022B05D1FFF7A1BEFFF7C5BFFFF7D3BF70479E
 | 
			
		||||
:40194000D692FF1F38B51D4C2378DBB2DD0634D518060AD503F00F03012B2ED1FFF74EFF174B1B78190609D538BD5A0602D5FFF7D7FF03E09D0620D5FFF786FF23781B066B
 | 
			
		||||
:401980001BD4104B1A78104B1B7813430F4A13701278934211D10A4A0849154613782078DBB2000605D41378DBB20B700B7803F00F0328788342F1D138BD38BD2860004067
 | 
			
		||||
:4019C000C192FF1FD292FF1F4993FF1F29600040054A00231380054A916819B191680B7092685380704700BF4C93FF1FC492FF1F0E4808B503889BB213B9FFF783FE13E0D1
 | 
			
		||||
:401A00000B4B02221A700B4B00221A70FFF7E0FF094AD1799379028843EA012392B2934238BF0380FFF728FE012008BDC492FF1FD692FF1FD292FF1F00600040084B012220
 | 
			
		||||
:401A40001A700F3B9B7C074B1A7B02F00302012A1EBFDA7B82F08002DA7301225A7370470B600040DC92FF1F094B02221A700F3B93F82230074B1A7E02F00302012A1EBF0F
 | 
			
		||||
:401A8000DA7E82F08002DA7601225A76704700BF0B600040DC92FF1F0B4B04221A700F3B93F83230094B93F8242002F00302012A1EBF93F8272082F0800283F827200122E0
 | 
			
		||||
:401AC00083F82520704700BF0B600040DC92FF1F0B4B08221A700F3B93F84230094B93F8302002F00302012A1EBF93F8332082F0800283F83320012283F83120704700BFF5
 | 
			
		||||
:401B00000B600040DC92FF1F7047FFF741BC0000F0B5184B184E19780C27C9B201234FF0000C31B3CA0720D5144A4FEA031E7244947850782040C5070DD507FB03652C799F
 | 
			
		||||
:401B4000240608D5147804F0FE0414706D790C4CEDB204F80E50840706D507FB036425792D0658BF84F801C090700133DBB24908D7E7F0BD9F600040DC92FF1F70600040D5
 | 
			
		||||
:401B8000FE5F004000F0ACBC70B50446184B88B003AA03F11006154618685968083303C5B3422A46F7D11B782B70FCB12223237001AD03232846637000F08AFE00222046DB
 | 
			
		||||
:401BC0001146AB5C08AC04EB131414F8144C03F00F03847008AC234413F8143C0132082AC1700371417100F10400EAD108B070BD4F3A00002DE9F0431C4D01222E460C2093
 | 
			
		||||
:401C00001F274FF0800E4FF0080C194B00FB02581401234418705F70164998F805902144B9F1000F07D098F8044024064CBF887081F802C001E081F802E000FB0261CC880F
 | 
			
		||||
:401C40000132E4B29C71CC88092AC4F30724DC71CC88E4B21C71C988C1F307215971D4D1054BFF221A70BDE8F08300BFDC92FF1F70600040FC5F00400A600040064B074A70
 | 
			
		||||
:401C80001B7802EBC30253681A7C824286BF03EBC003586900207047D092FF1FB03A00002DE9F84F424B1A78002A7ED01878414D0138C0B2FFF7E2FFA8463F4AC368147810
 | 
			
		||||
:401CC000007ADFF800C1E4B203EBC0000C2600274FF0010E834268D01A78A24263D11CF80420597891425ED19A7893F8039002F07F0206FB02FA05EB0A01CF7093F802B01E
 | 
			
		||||
:401D000009F0030981F804B093F803B005F80AB0B3F804A0A1F808A093F902A0BAF1000F0BDAB9F1010F0CBF4FF007094FF00D0981F8059081F801E009E0B9F1010F0CBF20
 | 
			
		||||
:401D40004FF005094FF0090981F805904F704FEA02191A4906FB0282494481F802E0B2F808A0CAF3072A81F800A0B2F808A05FFA8AFA81F801A0B2F806A011495FFA8AFAAB
 | 
			
		||||
:401D8000494481F806A0B2F80690C9F3072981F80790B2F806905FFA89F981F80490D288C2F307224A71083394E7BDE8F88F00BFD592FF1FDC92FF1FD192FF1FFC5F004052
 | 
			
		||||
:401DC00070600040C292FF1F08B5064B18780138C0B2FFF753FF20B143681B7900EBC300406908BDD592FF1F00212DE9F84F0B464E4E0C2707FB01F4013132190929335553
 | 
			
		||||
:401E00004FF000059370494CD3701381937253705371EFD118B1464B1D70464B1D70464B1A78002A7FD0187801250138C0B2FFF725FFA8464368DFF8F8E0DB790C2713F0B5
 | 
			
		||||
:401E4000400F3E4B4FF0000C1A7814BF42F0010202F0FE021A70027AD20007FB0541C36803EB02094B4531D093F802A00AF07F06AE4229D10E89B3F804B0B6B25E4538BF50
 | 
			
		||||
:401E8000A1F808B01E7893F801B01EF80660B3451AD181F804A0DE780E7093F902A0DE78BAF1000F06F0030607DA012E0CBF07260D264E7181F8018006E0012E0CBF052673
 | 
			
		||||
:401EC00009264E7181F801C00833CBE70135092DC3D1C1680A328B1C0A440C200833934209D013F8081C13F80A5C01F07F0100FB01418D72F2E7FFF767FF114B01211860E6
 | 
			
		||||
:401F000000230C2000FB0142D3801289013113449BB203F00102134409299BB2F2D1BDE8F84FFFF767BEBDE8F88F00BFDC92FF1FC292FF1F4A93FF1FD592FF1FD392FF1FCE
 | 
			
		||||
:401F4000D892FF1F114B1B7903F07F035A1E072A19D80F490C2202FB031291781B0141F0010191700021D170517841F002015170127912F0800F074A1A4414BF8D238923CF
 | 
			
		||||
:401F80009370FFF715BC0020704700BF00600040DC92FF1FFC5F004030B4194B1A7902F07F02531E072B27D8164B0C2404FB02339978154D01F0FE0199700021D970294600
 | 
			
		||||
:401FC0001201505D114400F07F0050555A7802F0FD025A701A795B78120605D5012B01D18C7006E00D2303E0012B0CBF082309238B7030BCFFF7DCBB002030BC704700BF9C
 | 
			
		||||
:4020000000600040DC92FF1FFC5F004010B50D4B0D4C21791878C9B20138C0B2FFF72EFE43681B798B4201D2012909D8074A0848535CDBB24354A3780120DBB2535410BD56
 | 
			
		||||
:40204000002010BDD592FF1F00600040C292FF1F4A93FF1F38B58A4A8A4C13780021DBB221801806517840F18D800A2900F20581DFE811F05D000301030103010301030167
 | 
			
		||||
:402080000B0003017E0003018200D3787C49012B09D17D4B1A787D4B03EBC2035B685B686360122310E0CB78022B12D18878FFF7E5FD002800F0E180436863606368DA7885
 | 
			
		||||
:4020C00063689B7843EA02232380BDE83840FFF78FBCCB78032B26D16D4B00228878D5B2854209D3664A91786A4AEE2908BF1346634A917881B106E0187801320028F1D025
 | 
			
		||||
:4021000018780344EAE764499278097C914203D16248FFF739FD614B1A78002A00F0AD801A78228018E0BDE8384000F029BF13F0030313D0022B40F0A0802380504B0C21C4
 | 
			
		||||
:402140001B7903F07F02564B01FB02339A78554BD2B21A7000225A706360B6E702222280514A11784F4AC9B2117053706260ACE7012323804D4BEFE70123238013794C4AC4
 | 
			
		||||
:402180001344E9E701390A2977D8DFE801F037764F76067676760A7620009378454ADBB25AE0937803F0FF0153B9404B1A7891425FD01970404B01201870FFF715FE58E082
 | 
			
		||||
:4021C000481EC0B2FFF75AFD0028EED155E0FFF71DFF002851D02A4A384913791279DBB2D2B20A70364A3249D25CCB5C9A4240D0314B01221A70FFF753FD3AE003F00303EE
 | 
			
		||||
:40220000012B2BD009D3022B37D11D4B9B78002B33D1BDE83840FFF7BFBE194B9B78012B2BD1214A137803F0FD0315E003F00303012B13D008D3022B1FD1114B9B78E3B9A4
 | 
			
		||||
:40224000BDE83840FFF77EBE0D4B9B78012B14D1154A137843F0020313700AE0084B1A795AB998781B791749DBB2CA5C22EA0002CA54BDE83840FFF79BBA002038BD00BFEC
 | 
			
		||||
:4022800000600040C492FF1FD092FF1FB03A0000143B00009C3A0000873B00006893FF1FDC92FF1F8192FF1FD392FF1FD592FF1FC292FF1FC092FF1FD492FF1FD192FF1FF4
 | 
			
		||||
:4022C0004A93FF1FD792FF1F074B1A78120609D55B78012B06D1054B054A5A6012781A80FFF786BB0020704700600040C492FF1F743A0000014B1870704700BF76650040FA
 | 
			
		||||
:40230000014B1878704700BF67640040014B1870704700BF77640040064A0123136002F688321268E0211064034A1170A2F540721360704780E100E000E400E0014B187039
 | 
			
		||||
:40234000704700BF74640040014B1870704700BF7565004073B515461E460B4C05230022019200920A4601461846237000F064F932462946207800F01FF90221207800F0B7
 | 
			
		||||
:4023800009F9207802B070BDD080FF1F064A0423136002F688321268E0219064034A1170A2F202321360704780E100E002E400E0014B04221A60704700E100E0014B04228E
 | 
			
		||||
:4023C0001A60704780E100E0014B1870704700BF74650040704738B505460078012428B100F066FD285D0134E4B2F8E738BD08B50D2000F05DFDBDE808400A2000F058BDDC
 | 
			
		||||
:40240000F7B516461F460B4C00230325019300930A4601462846257000F00EF93A463146207800F0C9F80221207800F0B3F8207803B0F0BDE080FF1FF7B516461F460B4C05
 | 
			
		||||
:4024400000230225019300930A4601462846257000F0F2F83A463146207800F0ADF82946207800F097F8207803B0F0BDE180FF1FF7B516461F460B4C002301250193009322
 | 
			
		||||
:402480000A4601462846257000F0D6F83A463146207800F091F80221207800F07BF8207803B0F0BDE280FF1F73B515461E460B4C0023019300930A4601461846237000F026
 | 
			
		||||
:4024C000BBF832462946207800F076F80221207800F060F8207802B070BD00BFE380FF1F024B1878C0F38010704700BF8F450040074A7F23802113705170064A013BDBB2F7
 | 
			
		||||
:4025000002F80839002BF9D1034A1370704700BFE480FF1FF87B00400078004017280FD8084B0001C25C11B142F0200201E002F0DF02C254C25C42F00102C2540020704780
 | 
			
		||||
:40254000012070471070004017280BD8064B0001C25C02F0FE02C254C25C02F0DF02C25400207047012070471070004017280DD8074900010B4603441A7942F004021A7150
 | 
			
		||||
:40258000435C43F00103435400207047012070471070004017280BD8064A0001835C490003F0F10301F00E011943815400207047012070471070004041F6FF73994208BFD2
 | 
			
		||||
:4025C0004FF400519A4208BF4FF4005217289FBFC00000F1804000F5EC4081809ABFC280002001207047000017289FBF034B00011954002088BF0120704700BF197000402C
 | 
			
		||||
:4026000017289FBF054B00011A5C01F007019DBF1143195400200120704700BF1470004017289FBF034B0001185C00F0070088BFFF20704714700040172810B51AD8C000B7
 | 
			
		||||
:4026400001F07F0100F1804441EAC21204F5EC44D2B222709DF8082003F00F0343EA0213DBB263709DF80C30002003F00F03A370E07010BD012010BD10B500F079FC0A4A00
 | 
			
		||||
:402680005378182B0AD91478013B5370E30003F1804303F5F0431B78137000E0FF2400F06BFC204610BD00BFE480FF1F030610B5044611D400F05CFC084AE300117803F1FE
 | 
			
		||||
:4026C000804303F5F04319705378147001335370BDE8104000F050BC10BD00BFE480FF1F30B504060CD411F4704509D1C40004F1804404F5F0442180A270E370284630BDB0
 | 
			
		||||
:40270000012030BD03065FBFC00000F1804000F5F04081805ABFC280002001207047000038B50446084DB4F5004F05D9286800F017FCA4F50044F6E7034B58686043BDE875
 | 
			
		||||
:40274000384000F00DBC00BFEC80FF1F024B1B7A584300F005BC00BFEC80FF1F0E4B00F003001A78490102F0FC02104318701A7801F0600142F080021A701A7802F07F024E
 | 
			
		||||
:402780001A701A7802F09F020A431A701A7842F010021A70704700BF83430040014B01221A70704784430040044B00F00F021B6853F8220043F82210704700BF08ED00E008
 | 
			
		||||
:4027C000054A00F01F00126800F1100352F8230042F82310704700BF08ED00E000F01F0000F16040490100F56440C9B2017070470F4B10B50F4900240F205C609C60DC60F4
 | 
			
		||||
:402800001C615C61FFF7D0FF0B4A136843F0040313600A4B4FF47A72DB68B3FBF2F3084A1360084B4FF400421C60C3F8E82010BD8492FF1F9D28000010E000E0EC80FF1FC6
 | 
			
		||||
:4028400014E000E018E000E0024A136843F002031360704710E000E008B5FFF7F5FF034A136843F00103136008BD00BF10E000E010B5054CA3691BB9FFF7BAFF0123A36179
 | 
			
		||||
:40288000BDE81040FFF7E8BF8492FF1F024B1868C0F30040704700BF10E000E038B5FFF7F5FF012808D1054D002455F8243003B198470134052CF8D138BD00BF8892FF1FAE
 | 
			
		||||
:4028C000024B03EB80035868596070478492FF1F134B144A1B78DBB20360127843EA0223114A0360127843EA0243104A0360127843EA026303600E4B0E4A1B78DBB2436031
 | 
			
		||||
:40290000127843EA02230C4A4360127843EA02430A4A4360127843EA02634360704700BF0301004904010049EC46004002010049010100490001004905010049060100490D
 | 
			
		||||
:4029400010B500F015FB204A044613780A2043F002031370137C43F00203137412F80A3C43F0010302F80A3C937943F00103937102F5AB52137843F003031370134B18223F
 | 
			
		||||
:402980001A7013F8012C42F0400203F8012C13F8012C02F0FC0203F8012CCE2203F8062CA3F597530222183B1A70094A137843F008031370FFF7CAFE064B10222046BDE8DE
 | 
			
		||||
:4029C00010401A6000F0D8BAAB4300400E5900402F5B004080E200E008B500F0C9FA0F4A137803F0FE031370A2F5AA521D3A137803F0FD031370137C03F0FD03137412F8E1
 | 
			
		||||
:402A00000A3C03F0FE0302F80A3C937903F0FE039371BDE8084000F0AFBA00BF08590040044A137803F03F0343EA8010C0B21070704700BF08590040082804D00A280CBF9D
 | 
			
		||||
:402A40008223C22300E0422308380E4AC0B20428137098BF0C4B4FF0000298BF33F910100A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B33
 | 
			
		||||
:402A80001A8070470A590040603A00005293FF1F5493FF1F5893FF1F08B5102000F0A6F907210420FFF79AFE07490420FFF788FE064A0C20137843F006031370FFF7BCFFBA
 | 
			
		||||
:402AC000034B00221A8008BD912B0000095900405093FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040FFF72ABFA092FF1F044B1A7802F0FB021A701A7842F0010256
 | 
			
		||||
:402B00001A7070470859004010B5084B1C7814F0010403D10028F9D0002404E02046FFF715FE024B1B78204610BD00BF09590040034A044B1B881088181A00B2704700BF1D
 | 
			
		||||
:402B40005893FF1FA25B00400E4A13881BB223B111880A2309B2594301E00B4B19680B4B1B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F0C1
 | 
			
		||||
:402B800000B270475293FF1F5493FF1F5093FF1F7047000010B500F0EBF9214A044613780A2043F001031370137C43F00103137412F80A3C43F0020302F80A3C937943F0DB
 | 
			
		||||
:402BC0000203937102F5AA521832137843F003031370144B18221A7013F8012C42F0400203F8012C13F8012C02F0FC0203F8012CCE2203F8062CA3F597530222123B1A7067
 | 
			
		||||
:402C0000094A137843F008031370FFF79FFD074B08222046BDE810401A6000F0ADB900BFAB43004006590040275B004080E200E008B500F09DF90F4A137803F0FE0313708E
 | 
			
		||||
:402C4000A2F5AA52153A137803F0FE031370137C03F0FE03137412F80A3C03F0FD0302F80A3C937903F0FD039371BDE8084000F083B900BF00590040044A137803F03F0361
 | 
			
		||||
:402C800043EA8010C0B21070704700BF00590040082804D00A280CBF8223C22300E0422308380E4AC0B20428137098BF0C4B4FF0000298BF33F910100A4B88BF11461A80AE
 | 
			
		||||
:402CC00042F210734B4341F2883103F6C41393FBF1F305490B60054B1A807047025900406A3A00005E93FF1F6493FF1F5C93FF1F08B5102000F084F807210320FFF76EFD92
 | 
			
		||||
:402D000007490320FFF75CFD064A0C20137843F006031370FFF7BCFF034B00221A8008BDE92D0000015900406093FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040C8
 | 
			
		||||
:402D4000FFF728BFA192FF1F044B1A7802F0FB021A701A7842F001021A7070470059004010B5084B1C7814F0010403D10028F9D0002404E02046FFF7E9FC024B1B78204621
 | 
			
		||||
:402D800010BD00BF01590040034A044B1B881088181A00B2704700BF5C93FF1FA05B00400E4A13881BB223B111880A2309B2594301E00B4B19680B4B1B88C01A42F2107381
 | 
			
		||||
:402DC00000B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270475E93FF1F6493FF1F6093FF1F70470000034A00F0F800137803431370704700BF02410040A1
 | 
			
		||||
:402E0000034A00F0F800137803431370704700BF06410040014B1870704700BF72640040014B1870704700BF7864004073B515461E460B4C04230022019200920A46014603
 | 
			
		||||
:402E400018462370FFF7F8FB324629462078FFF7B3FB02212078FFF79DFB207802B070BDFC80FF1F074A0223136002F688321268E0215064044A11706FF440710A4413608D
 | 
			
		||||
:402E8000704700BF80E100E001E400E0014B1870704700BF75640040014B1870704700BF76640040014B1870704700BF79640040FEB5494652465B460EB407462449096800
 | 
			
		||||
:402EC0008A46244A12682448022100F071F8030020480068C018204900F06AF8143883460121C9430C460125002600F041F8814651460B7823400B705846013000F030F81C
 | 
			
		||||
:402F00003800F04028400B78234003430B70584600F026F80136072EF2D9002001300138013001200B78234003430B705846043000F016F8484600F01FF800BF00BF00BF12
 | 
			
		||||
:402F40000EBC894692469B46FEBD00BFAFF30080D480FF1FF880FF1F00C20100000000000230800803D000BF01380046FCD17047EFF3108072B6704780F31088704700BF77
 | 
			
		||||
:402F8000094A137803F00303012B0AD0022B09D113790C2103F07F02044B01FB02339B7A00E013790020704700600040DC92FF1F002902D0B0FBF1F0704708B14FF0FF3097
 | 
			
		||||
:402FC00000F008B80029F8D00246B0FBF1F000FB11217047704700BF014B1868704700BF6081FF1F0E4B70B51E460E4C0025E41AA410A54204D056F8253098470135F8E75C
 | 
			
		||||
:4030000000F0DEFD084B094C1E46E41AA4100025A54204D056F8253098470135F8E770BDCC3B0000CC3B0000CC3B0000D43B000003460244934202D003F8011BFAE770475A
 | 
			
		||||
:4030400030B5141E05469BB0184604DA8B232B604FF0FF301DE04FF40273ADF80C300CBF234604F1FF33029305934FF6FF7300910491ADF80E3002461E9B6946284600F0D4
 | 
			
		||||
:4030800073F8431CBCBF8B232B6014B1009B00221A701BB030BD000007B5009313460A46014603480068FFF7CBFF03B05DF804FB6081FF1F2DE9F0478E6882469E420C46D9
 | 
			
		||||
:4030C000914698463ED88A8912F4906F3AD02568096902236F1A656905EB450595FBF3F57B1C43449D4238BF1D4653050FD5294600F04AFB064698B13A46216900F0D2FA24
 | 
			
		||||
:40310000A38923F4906343F08003A38113E02A4600F098FB064670B92169504600F0E8FA0C23CAF80030A3894FF0FF3043F04003A381BDE8F08726613E44266046466561E0
 | 
			
		||||
:40314000ED1BA560464528BF464649463246206800F0B3FAA36800209B1BA36023681E442660BDE8F08700002DE9F04F9DB003938B8980461C060D4616460DD50B695BB958
 | 
			
		||||
:40318000402100F001FB2860286118B90C23C8F80030CDE040236B610023099320238DF82930DFF89CB130238DF82A3037463C4614F8013B1BB9B7EB060910D003E0252BD0
 | 
			
		||||
:4031C000F9D02746F3E74B46324629464046FFF771FF013000F0A780099B4B4409933B78002B00F0A08000234FF0FF3204930793059206938DF853301A93012605222178C6
 | 
			
		||||
:403200004E4800F041FA671C049B38B14B4A3C46801A06FA00F018430490EFE7D90644BF20228DF853201A0744BF2B228DF8532022782A2A03D0079A00210A200BE0039AA2
 | 
			
		||||
:40324000111D12680391002A10DA524243F00200079204900BE027463B780134303B092B03D800FB02320121F5E701B107923B782E2B1ED17B782A2B0AD1039B02371A1DAA
 | 
			
		||||
:403280001B680392002BB8BF4FF0FF33059310E0002319460593781C0A2407463A780130303A092A03D804FB01210123F5E703B1059103223978224800F0E6F940B1402309
 | 
			
		||||
:4032C000CBEB000003FA00F0049B013718430490397806221B487E1C8DF8281000F0D4F988B1194B33B9039B073323F007030833039314E003AB00932A46144B04A940468F
 | 
			
		||||
:40330000AFF3008007E003AB00932A460F4B04A9404600F093F8B0F1FF3F824603D0099B5344099342E7AB895B0601D4099801E04FF0FF301DB0BDE8F08F00BF9B3B000071
 | 
			
		||||
:40334000A13B0000A53B000000000000B53000002DE9F04791461F460A698B6806469342B8BF1346C9F8003091F843200C46DDF8208012B10133C9F800302368990642BF15
 | 
			
		||||
:40338000D9F800300233C9F80030256815F0060510D104F1190A07E00123524639463046C04701301AD00135E368D9F800209B1A9D42F1DB94F843302268003318BF01230D
 | 
			
		||||
:4033C00092060FD5E118302081F843005A1C94F845102244023382F8431003E04FF0FF30BDE8F08704F1430239463046C0470130F4D02268D9F80050E36802F00602042AD7
 | 
			
		||||
:4034000008BF5D1B2269A3680CBF25EAE57500259342C4BF9B1AED184FF000091A344D4509D00123224639463046C0470130D5D009F10109F3E70020BDE8F0872DE9F0438A
 | 
			
		||||
:4034400017460A7E85B06E2A984606460C460C9B01F1430E00F0AE8011D8632A22D009D8002A00F0BB80582A40F0CA8081F84520834955E0642A1ED0692A1CD0C0E0732A65
 | 
			
		||||
:4034800000F0B08009D86F2A2ED0702A40F0B8800A6842F020020A603EE0752A24D0782A3AD0ADE01A6801F14205111D1960136884F84230A8E021681A6811F0800F02D098
 | 
			
		||||
:4034C000111D196008E011F0400F02F10401196002D0B2F9003000E01368002B3CDA2D225B4284F8432037E021681A6811F0800F02D0111D196007E011F0400F02F104010E
 | 
			
		||||
:40350000196001D0138800E01368227E5C496F2A14BF0A2208221BE078225A4984F845202268186812F0800F00F104051D6003D1550601D5038800E00368D00744BF42F032
 | 
			
		||||
:40354000200222601BB9226822F0200222601022002084F8430001E049490A226568002DA56008DB206820F0040020602BB9002D7DD175460CE0002B79D07546B3FBF2F020
 | 
			
		||||
:4035800002FB1033CB5C05F8013D03460028F5D1082A0BD12368DA0708D5236962689A42DEBF302305F8013C05F1FF35C5EB0E0323612EE008681A6810F0800F496903D0FC
 | 
			
		||||
:4035C000101D1860136808E010F0400F02F104001860136801D0198000E0196000232361754616E01A68111D1960156800216268284600F049F808B1401B6060636804E0BC
 | 
			
		||||
:4036000004F1420584F8422001232361002384F84330CDF800803B4603AA21463046FFF797FE013002D14FF0FF3026E023692A4639463046C0470130F5D023689B0710D563
 | 
			
		||||
:40364000002504F1190907E001234A4639463046C0470130E7D00135E368039A9B1A9D42F2DBE068039B9842B8BF184605E00B7804F1420584F842308AE705B0BDE8F083AB
 | 
			
		||||
:403680004F3A0000AC3B000010B5C9B202449042034605D01C7801308C42F8D1184610BD002010BD10B5431E0A44914204D011F8014B03F8014FF8E710BD884210B501EBCE
 | 
			
		||||
:4036C000020301D8421E0BE09842FBD28118D21AD34204D013F8014D01F8014DF8E710BD994204D011F8014B02F8014FF8E710BD38B50546002944D051F8043C0C1F002BF2
 | 
			
		||||
:40370000B8BFE41800F0D4F81E4A1368114613B96360146030E0A3420DD92268A018834201BF18685B681218226063600C6023E0A24203D813465A68002AF9D118681918DB
 | 
			
		||||
:40374000A1420BD12168014458188242196013D110685268014419605A600DE002D90C232B6009E021686018824201BF106852680918216062605C602846BDE8384000F0C4
 | 
			
		||||
:4037800098B838BDA892FF1F70B5CD1C25F0030508350C2D38BF0C25002D064601DBA94202D90C23336046E000F082F8234B1C681A462146A1B10B685B1B0ED40B2B03D94E
 | 
			
		||||
:4037C0000B60CC18CD501EE08C420BBF63684B681360636018BF0C4615E00C464968E9E7174C23681BB9304600F052F820602946304600F04DF8431C18D0C41C24F00304D4
 | 
			
		||||
:40380000A0420DD12560304600F053F804F10B00231D20F00700C31A0ED05A42E25070BD211A304600F034F80130EBD10C233360304600F03EF8002070BD00BFA892FF1F09
 | 
			
		||||
:40384000A492FF1FF8B5074615460E4621B91146BDE8F840FFF798BF1AB9FFF749FF2846F8BD00F027F885420ED929463846FFF78BFF044650B131462A46FFF713FF3146E1
 | 
			
		||||
:403880003846FFF735FF01E03046F8BD2046F8BD38B5064C0023054608462360FDF7D8FB431C02D1236803B12B6038BD8C93FF1F7047704751F8040C0028BEBF091851F8F0
 | 
			
		||||
:4038C000043CC0180438704700000000050209020B020D020F021102130215027265706C792030782530327800686F6D696E6700626567696E6E696E67207365656B2066CB
 | 
			
		||||
:40390000726F6D20256420746F2025640066696E6973686564207365656B00796573006E6F00647269766520303A20257320647269766520313A2025730057616974696E5F
 | 
			
		||||
:403940006720666F72205553422E2E2E0055534220726561647900636F6D6D616E6420307825303278006661696C2025642B25642B2564203D3D2025642C206E6F7420254E
 | 
			
		||||
:4039800064007061737365643D256400756E64657272756E206166746572202564207061636B65747300636F756E743D256420693D256420643D256400636D645F77726997
 | 
			
		||||
:4039C000746500703D25642063723D25642063773D256420663D256420773D256420696E6465783D256420756E64657272756E3D256400756E64657272756E21007375635E
 | 
			
		||||
:403A0000636573730073746172742065726173696E670073746F702065726173696E670069646C6500005100401000405100403000000001400010001401400008004001A3
 | 
			
		||||
:403A400040000A004C0140000200500140200030313233343536373839414243444546000001000000040000001000010000000400000010280000000001040001000000C2
 | 
			
		||||
:403A800000000000000157494E5553420000303030303100000000000000000012034D005300460054003100300030000100000001000000B83A000001000000873B0000A5
 | 
			
		||||
:403AC000000000000000000001000000D03A000001000000593B000004000000F23A0000000000000000000000000000F03A0000FF00000001024000FF00000082024000C7
 | 
			
		||||
:403B0000FF00000003034000FF00000084034000FF00020304030904160346006C007500780045006E00670069006E0065002A0343006F0077006C00610072006B00200034
 | 
			
		||||
:403B400054006500630068006E006F006C006F0067006900650073000009022E0001010080320904000004FF00000107050102400000070582024000000705030340000AE8
 | 
			
		||||
:403B80000705840340000A12010002FF0001080912006E0100020180014300232D302B2000686C4C0065666745464700303132333435363738396162636465660000000069
 | 
			
		||||
:403BC000F8B500BFF8BC08BC9E46704759000000CD100000F8B500BFF8BC08BC9E46704735000000F83B0000C880FF1FA00000002812000000000000000000009093FF1FA8
 | 
			
		||||
:403C0000FF000000675000400C00000007000000FFFFFFFF7F8000003F0000000000007D00FA0000400000000090D003FF0000000000000000000000000000000000000028
 | 
			
		||||
:403C400000000000000000000000000000000000993B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070
 | 
			
		||||
:403C8000000000000000000000000000000000000081FF1F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065
 | 
			
		||||
:403CC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C4
 | 
			
		||||
:403D00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083
 | 
			
		||||
:403D40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043
 | 
			
		||||
@@ -4098,55 +4098,55 @@
 | 
			
		||||
:40FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041
 | 
			
		||||
:40FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
 | 
			
		||||
:0200000480007A
 | 
			
		||||
:400000000145004008520040015B0040016400400103014008050140440601404807014051080140520901404B0A01404E0B0140650C0140450D0140580E0140350F0140DA
 | 
			
		||||
:40004000471401405B150140221701403F18014056190140481A0140561B01400A4001400E4101400E420140084301400244014009450140064601400B4701400F48014016
 | 
			
		||||
:4000800011490140174C0140094D014007500140045101407E0208020901100211821902601661157C4027212D0AE21029022B4088408CA88E808F05E628EA08003F032039
 | 
			
		||||
:4000C0000538062007010A380B200E070F3811041220131016201707183819021A011B381C041D041E101F082220232024042608272028022A382B202D3F2E20353F363F03
 | 
			
		||||
:40010000580459045B045C995F01822086208A078C3F910292209438950196019A209C049E10A220A404A608A802AA38AE38B102B301B43FBF05D608D804D904DB04DC0965
 | 
			
		||||
:40014000DD90DF01012A030205490604082009080A010B800C100D040E010F801210136114021690172019301D402040220427042C042D082F4232083301358036023724A4
 | 
			
		||||
:400180003D043E203F815A605B08600862486A806C046D8085108728880689018B408C0891089301960898A099029AA0A008A344A440A540AB40AD04AE20B140B204C0FFAF
 | 
			
		||||
:4001C000C2FFC4FFCAF0CCF3CEF0D60ED80EE20BEA0CEE20020206040760080C09070A200B100C800D770E0C10FF112013101403152016FC1A081B071C0C1E101F08200CD3
 | 
			
		||||
:40020000210122402306240125012602270229012A022B042C0C2D012EF1310F334036FF37303B803E40580459045B045C905F0181108204860489148A078B218C078D7F65
 | 
			
		||||
:40024000920495099604981899019A029B0E9D089E109F01A008A604A750A909AA01AD01AE04AF22B21FB330B50FB740BE04D804D904DC90DF01009001010310040A052049
 | 
			
		||||
:400280000701081009100A820B200E420F141190120A13091404150A174019041D402019211822102308250126842741280829082A802C882E042F02325033043540360469
 | 
			
		||||
:4002C0003721381139403E403F186C026D40850888048B088D088E048F04908A910A9244933494309531980499309A049B309C109E80A088A203A302A446A509A680A70142
 | 
			
		||||
:40030000AB10AD20B020C0FFC2FFC4FFCAFECCFECE7DE040E229E680E88000010104033909051120160119341B0A1D0528022904311033203401350C360237033E503F047C
 | 
			
		||||
:40034000580459045B045C905F018077831186E4871188168A218B778D778E1490119288930E96779A149BE19E14A214A410A511A642A744A911AA14AB22AC01AD11AE0EF7
 | 
			
		||||
:40038000AF88B10FB20FB3F0B4F0BA28BB0AC006C60EC70CC814C9FFCAFFCBFFD004D601D804D904DA04DB04DC99DD09DF01E2C0000104A406800A200C020D180F02120442
 | 
			
		||||
:4003C00014121501171019401B101C041D341F1020012104221923202480260227102B042C122D1032513602371038013B103C983F024F2057845C205D806AC06B016C893C
 | 
			
		||||
:400400006D806E046F027649878088848C028D148E0290089102931494029508964499A09A049D409E499F21A201A488A541A688A702AE40C0F8C2F4C4F2CA74CCADCEF509
 | 
			
		||||
:40044000D220D630E250E610EA08EE02004001120220047E0512083E09080A400B130D121112120114401610184019111A081C401E041F02230424802710288029122A7E0E
 | 
			
		||||
:400480002C402D182E0231083310350736FF39203E403F05580459045C905F01808081248204852486048804891A8A208BE48E0290FF916C93809404950A9610971098035A
 | 
			
		||||
:4004C00099249AFC9D409E029F84A004A208A301A404A524A6F9A801A924AA02AC04AE40AF10B1F9B2FFB307B90ABE04C035C702C810C9FFCAFFCBFFCD20CEF0D110D80495
 | 
			
		||||
:40050000D904DA04DC90DD09DF01E108E240E340E480E640E74000040120028103400402062809480A680C880E440F801102120813441603173819081F802101220623502F
 | 
			
		||||
:40054000249C26102708281029202B422D202E402FA0329A3410369139013B143D033E203F5440104940520483018C4093069408950A9644975099A09D089E429F59A108DA
 | 
			
		||||
:40058000A201A320A488A501A6CAA702C07FC2FFC4EFCAFFCCBFCEF7D002D208E210E404004001010280030E04020501060C07040872090F0A800C080E041080122014047E
 | 
			
		||||
:4005C0001608170F18101C101D011F022010210F24102710280E29012AF02B082D012E0134FF351F3820580459045C995F018201831086108708881089078BF88C1F8DFF45
 | 
			
		||||
:4006000090409118934094099612970799189A069B209C109D809E089F18A010A118A3E0A40CA501A601A706A901AA20AB02AD01AE10AF04B040B238B3FFB407B638BE018F
 | 
			
		||||
:40064000BF04D608D804D904DB04DC09DD90DF010120028003120408052006410701080409800B440C020E0A0F10110212011318150A176019201D881E0A1FA12304272093
 | 
			
		||||
:40068000280429082A012B022C0C2D042E042F82308032083520368A39043A023B103D023E403F145E8065806C02C0FFC2FFC4FFCAFFCCFACEF7D610D810000A080D0F01A1
 | 
			
		||||
:4006C00012051C011D04201029012D02301031033403360C37043E013F40420345E0480249FF4AFF4BFF4F83580A59045A045B045C995D095F01801182888320840185381E
 | 
			
		||||
:40070000860E870188108A228B208E148F20913F921495049614970899029A049B389EE49F07A214A338A477A720AA77AB20AC16AD04AE41AF10B13FB20FB4F0B6F0BAA8F4
 | 
			
		||||
:40074000D804D904DC99DF010120024005050602070809020A020C080E010F8811021525160119201A021B021D041E011F60204021022280274029202A442B202C0A2E028D
 | 
			
		||||
:400780002F2032403501376838403D053E203F804108484059125B44608061646B017808810186018810892C8B208D0291219280950496029780988899519A639B2C9C104A
 | 
			
		||||
:4007C0009E049F01A00AA344A440A508A680A702A802AA01AD88AE02AF08B201B440B640C0FAC2F9C4F8CAFCCCF8CEF8D002D60FD80FDE02E008E212E609EA0CEE0A8202FC
 | 
			
		||||
:40080000869087028A01904091219280950496419780988899519A609B249C109D889E149F01A008A344A440A508A602A901AB02B404B610E008E243E408E614E840EA0CDF
 | 
			
		||||
:40084000EE08021006040A040E041007150216071A021E041F0120082104260428182A012D072E0433043502361F37013E40580459045B045C905F018101822085F1862038
 | 
			
		||||
:4008800088048A018B448C018E028F22900191CC923E932295AA962097449A109E20A240A311A620AA08AC7FAD88B03FB50FB640B7F0D608D804D909DB04DC99DD90DF01DE
 | 
			
		||||
:4008C00000900101031004820510071009500A800B200D290F221002120813091488160217281A821B011F802305242225302608272429012A402C022F80300833013480CD
 | 
			
		||||
:40090000350439503B0558405D80624069506A106E807B04815085808720884089208B408E108F20909091209320942095019682970199149B189C089E809F04A002A1482A
 | 
			
		||||
:40094000A30CA440A510A608A701A802B708C0FFC2FFC4FFCA99CC53CE0FD618D808DE04E240E408E690E810EA08EE0802010320070708100B200E020F20100C11FF1202C4
 | 
			
		||||
:400980001504160417901B201D041F48200821F823012401250227F8280A2A042B382F20300F31E03210333F340E3E14580459045B045C995F0182078404860889068A20DB
 | 
			
		||||
:4009C0008B098D098E388F06903F940296389A209E209F0CA220A404A610AA20AC38AE01B104B308B501B63FB702B9AABF55D608D804D904DB04DC09DD90DF01014203085E
 | 
			
		||||
:400A00000481051007200A900C020D100F2210081240130415011794190B1B201C011F8020A021052380240825042682288029102B11308233143640388039293D904080E9
 | 
			
		||||
:400A4000410142805F40640268086A806B016D90800285018682885089018A028C048D048F809080916092109344950399109A409B349D099E829F01A082A240A319A44806
 | 
			
		||||
:400A8000A720A920AC80AE08AF01B080B108C0FBC2FCC4FECA0FCC1FCE3FD610D810E080E270E6A0E860EE421B011F0831103308368037023B40C630CCF0CE103002338003
 | 
			
		||||
:400AC000358037043B083D808F0297409D109F02AE80AF01CCF0CE60500857108704894097489D109F04A402A540A780AD80D460E610EA10830497409D109F04A402A790B8
 | 
			
		||||
:400B0000B008E2801420C4045F80630883048F889820D604D802E208E4081B0898209C06A708AC06C608080809200C040F01830186018D0898209C06C20FE4082680838010
 | 
			
		||||
:400B40008D108E0297409D10A680A710AC02AF80B680C820E620EA10EE105202538078407D80844085408F10A202A380A710AF40D4A0DC80DE20E240E610EE40052008023A
 | 
			
		||||
:400B80000E411F105280550858406302870188208920960198209C02A108AC08AD20C001C20DC601D407D602E20577108F10AF10B040B6C0DE04E402E803EE0201010B01AE
 | 
			
		||||
:400BC0000D010F0111011B011D0100FF01AB020211050000BF0000A09F001F000000000000000000100000004000000000000000C0000000FF0000B8470047000001000053
 | 
			
		||||
:400C0000800000028200820000000000000303000300000027001801270018010004000000050000000000000000000000000000000000000000000000000000000000009C
 | 
			
		||||
:400000000145004009520040015B00400165004047000140380101404E0201404703014046040140440501404C060140490701402C08014031090140040B0140030D014075
 | 
			
		||||
:400040006C14014057150140591601404B17014011190140071B01400B400140104101400C4201400F43014002440140054501400A4601400B4701400C480140104901404C
 | 
			
		||||
:40008000174C01400C4D014006500140045101407E02080409021082110218021904601561137C402721240A02E40303040E0520064107C00A840B900E840F901001120693
 | 
			
		||||
:4000C00013901684179019011A841B481C081DFC1E221F0221C122182324268427902B9C2CE72E10300733E0351F36F83A023B084204460E480449FF4AFF4BFF4F83580B46
 | 
			
		||||
:40010000590B5A045B045C995D095F01868088028A8190E7921094019686980F9A409C0F9E20A2E0A618A804AA81AE80B207B4F8D80BDC09DF010022022003010524084089
 | 
			
		||||
:4001400009080A080B400C420D200E2010021108130215801610172119011A011C241E201F0C210422082308284029042B88312032643301382039883A013B804240528017
 | 
			
		||||
:400180005A215B4A600461016218634278027C028280C06FC2FFC4FDCA07CC0FCE0FD001D60FD80FDE8103140404050806110710081F0A800C010E1E0FE4101F124015102D
 | 
			
		||||
:4001C00016E0178218021A111B141C1F1E20211023212408261127142B142D1F2F4032F0330F360F37F03A083B80580B590B5B045C995F018203830884618608873088204C
 | 
			
		||||
:4002000089108A508B828DC78E108F2892109304961C97C49A109B04A061A110A204A341A440A630A704AB04AC7CAE02AF04B01FB30FB460B5F4BB08D80BD90BDB04DC99FF
 | 
			
		||||
:40024000DF01012A02200301040805400708081009080B8C0C420E200F04104211081504180819221A0C1B011C221D4C1E211F4820042218242025442731285029402B8839
 | 
			
		||||
:400280002C022E042F883204331134103508380439813A103D8C3E016230680269806A806D4078027C029308942096E897809C029D249F61A403A50CA620A781AA01AB0889
 | 
			
		||||
:4002C000C0EFC2FEC42DCAFFCC67CEDFDE81E208021004400620080C0C010E0210081101140818051A081C04200828202AC02CE02F0130603280341E3501360138203E40ED
 | 
			
		||||
:400300005608580459045B045C995D905F0181608209842487108A128B108F10903F93039407950197089B1C9D40A036A209A310A710A82DA901AA12AB04AC40AD7CAF0220
 | 
			
		||||
:40034000B11FB238B440B540B607B720BE10D608D80BD90BDB04DC99DD90DF01000201280302040A070409980B800C020E20104212081550170119281A401B401E201FA0A5
 | 
			
		||||
:4003800022102662274828022C022E052F043302364237283C203D803F0558805D80600267016B026D106F017C0287208B848F4091409205930496409B209C029F48A0124A
 | 
			
		||||
:4003C000A140A208A620A780AD01AE08C07FC23FC4DBCAF8CCF1CEF0D618D818DE80E208E408EA040104020F0440068008700A800C800E200F0110011106130114081602E9
 | 
			
		||||
:40040000170218011C0F1EF0200124072608288029052A102B022C082E04310736FF3E403F01580459045B045F018001811C820283E18402852087C0880489828B218C0248
 | 
			
		||||
:400440008D088F10900491FF940495089710980599029C049D04A002A1FCA402A520A740A802AC03AE04AF02B007B3FCB503BB20BE01D804D904DB04DC90DF010081012440
 | 
			
		||||
:4004800004450520084009080A080B810C080D010E020F041008120113861544172219011C0220042114222C23282740280229012B202D1030083180321033023705396892
 | 
			
		||||
:4004C0003A013D82588068066C016D806F048004810184048F0191109220940A9780980299209B019C409F04A401A598A702A880A980AF02C0FFC2FFC4FFCA2BCCCFCE9F8E
 | 
			
		||||
:40050000D608E24CE402E605EA04EC02EE0C06010B0410041304160119021C022101240829042C013001310232043304340236083701380239083E553F45560858045904A9
 | 
			
		||||
:400540005B045D905F0183018A029501A401AC02B401B501B602B880B920BE50BF10D804D904DB04DF01030804080D800F50100212101410154019101A021E2A1F022210BD
 | 
			
		||||
:40058000250226882C802F083308372138023F10584059105DA45E01645266106A406C076D406F09800282C085808608890293409980AF40C022C2B0C4A5CAA0CCA2CE2157
 | 
			
		||||
:4005C000D6FCD8F0EA04EE0C9980E208E448EA049980B180E208018002200608070108280B100C020D210E2C1028110F1434152117081828192F1C101E021F2F202821210D
 | 
			
		||||
:40060000230224022740282829212B042C202D212E012F0E321F336035803620371F39083E443F1040524720482049FF4AFF4BFF4D204EF05110580459045A045B045C9038
 | 
			
		||||
:400640005D095F01610862406340648066406740800F810183028503861087FC88208A018B048C208DFF8E0290039302942395809608970499049A409B209D049E2F9FF9AF
 | 
			
		||||
:40068000A023A104A20CA308A423A504A604A740A82FA904AB10AF02B060B3FFB460B61FB822BF04D804D904DB04DC09DF01012202200301040205040608070209880A04D5
 | 
			
		||||
:4006C0000B800C080D800E48118012081305144015051610171019881C401D401E041F602118228023112410284129082A102D202E402F6030083240331234013680372A63
 | 
			
		||||
:40070000381039423A083C063D803F1041104980510159025A0269806C016D806F0285018D409004914592C2930494429604979199249A089B3B9D40A009A180A22CA548B8
 | 
			
		||||
:40074000A722AC02B704C0FFC2FFC47FCAFFCCFFCEFFD004D208E402E808EE1200FF01880403054606FC07B8080C09880A100C0C0EF10F0112081510160417A0180C198849
 | 
			
		||||
:400780001A401C011D421E021F04218822022480259A260C2720280C29882A202E022F0431C132FF333F35C137C139A23E043F04580459045B045C905F01800282058521EF
 | 
			
		||||
:4007C000870288028C0291279403950896049B389D049F01A118A340A706AC02AF01B006B107B310B401B560B708BE10BF40C006C5ECC803C9FFCAFFCBFFD004D601D8046C
 | 
			
		||||
:40080000D904DA04DB04DC99DD09DF01E2C00020010203020406056007100A200C010D800E040F1013801542172819131D042003218022D5240425102605278128102901DB
 | 
			
		||||
:400840002A802D202E402F603180321433023680372838043C043D803F11481049104B0264016701684869476A406C02728873068410860194419546978799209B2C9F827A
 | 
			
		||||
:40088000A228A448A598A601A722AB40B002B481C0FBC2F4C4F1CAFBCC7FCEF2D204E220E604EA4082108A018E048F029222960197109D209F20A214A302B080B104B6017C
 | 
			
		||||
:4008C000E220EA10EC808F209F20AF10B211B520E412EE021B011F083240330836843B408140C630CCF0CE10E62030803204358037083A023D408480914096809740A6046A
 | 
			
		||||
:40090000AE80AF01CCF0CE60E210508057208580968897409D809E02A604AB08D460E210EA20832284808E02968097409E02A480A620A720AA24AE04E230E620EC80EE30D9
 | 
			
		||||
:400940001501C4045D828740B101D605EE011B04850287108D8097809D82A480A880C608E4020B880C800F108A109798A480A740AB44AF04C20FE404262080018A01974061
 | 
			
		||||
:40098000A280A302A620AA40B680C820E620EE8052805302551070017E0190029202A110A280A302AF40B510D4E0DC80DE20EE40052008040E020F801F1053805610588014
 | 
			
		||||
:4009C00063028E208F809A109D20A740B120C001C20DC601D407D602E002E402EA04762084809A209C80AF10B004B301B601DE04E801EA08EE01010109010B010D011101C4
 | 
			
		||||
:400A00001B0100FF01AB020211050000BF0000A09F001F000000000000000000100000004000000000000000C0000000FF0000B847004700000100008000000282008200DC
 | 
			
		||||
:400A400000000000000707000700000027001801270018010004000000050000000000000000000000000000000000000000000000000000000000000000000000000000D8
 | 
			
		||||
:400A80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036
 | 
			
		||||
:400AC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F6
 | 
			
		||||
:400B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B5
 | 
			
		||||
:400B40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000075
 | 
			
		||||
:400B80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035
 | 
			
		||||
:400BC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F5
 | 
			
		||||
:400C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B4
 | 
			
		||||
:400C40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000074
 | 
			
		||||
:400C80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034
 | 
			
		||||
:400CC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F4
 | 
			
		||||
@@ -4615,12 +4615,12 @@
 | 
			
		||||
:0200000490105A
 | 
			
		||||
:04000000BC90ACAF55
 | 
			
		||||
:0200000490303A
 | 
			
		||||
:020000004415A5
 | 
			
		||||
:02000000FEBF41
 | 
			
		||||
:0200000490402A
 | 
			
		||||
:4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C0
 | 
			
		||||
:400040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080
 | 
			
		||||
:400080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040
 | 
			
		||||
:4000C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
 | 
			
		||||
:0200000490501A
 | 
			
		||||
:0C00000000012E16106900002E30547E06
 | 
			
		||||
:0C00000000012E16106900002E300F28A1
 | 
			
		||||
:00000001FF
 | 
			
		||||
@@ -814,7 +814,7 @@
 | 
			
		||||
  </Group>
 | 
			
		||||
  <Group key="Component">
 | 
			
		||||
    <Group key="v1">
 | 
			
		||||
      <Data key="cy_boot" value="cy_boot_v5_80" />
 | 
			
		||||
      <Data key="cy_boot" value="cy_boot_v6_10" />
 | 
			
		||||
      <Data key="Em_EEPROM_Dynamic" value="Em_EEPROM_Dynamic_v2_20" />
 | 
			
		||||
      <Data key="LIN_Dynamic" value="LIN_Dynamic_v5_0" />
 | 
			
		||||
    </Group>
 | 
			
		||||
@@ -871,6 +871,7 @@
 | 
			
		||||
      <Data key="c5367cde-21d5-4866-9a32-d16abfea0c61" value="WPT" />
 | 
			
		||||
      <Data key="d19368c5-6855-41bb-a9ff-808938abef00" value="INDEX" />
 | 
			
		||||
      <Data key="e9f14b5a-b2bf-49b8-98f3-d7b5a43ace8d" value="DRVSB" />
 | 
			
		||||
      <Data key="e16b5ef8-00d3-40a4-bc1c-194983c8eb3d" value="LOW_CURRENT" />
 | 
			
		||||
      <Data key="e851a3b9-efb8-48be-bbb8-b303b216c393" value="INDEX300" />
 | 
			
		||||
      <Data key="e51063a9-4fad-40c7-a06b-7cc4b137dc18" value="DSKCHG" />
 | 
			
		||||
      <Data key="ea7ee228-8b3f-426c-8bb8-cd7a81937769" value="DIR" />
 | 
			
		||||
@@ -4161,6 +4162,11 @@
 | 
			
		||||
        <Data key="Port Format" value="12,3" />
 | 
			
		||||
      </Group>
 | 
			
		||||
    </Group>
 | 
			
		||||
    <Group key="e16b5ef8-00d3-40a4-bc1c-194983c8eb3d">
 | 
			
		||||
      <Group key="0">
 | 
			
		||||
        <Data key="Port Format" value="3,2" />
 | 
			
		||||
      </Group>
 | 
			
		||||
    </Group>
 | 
			
		||||
    <Group key="e851a3b9-efb8-48be-bbb8-b303b216c393">
 | 
			
		||||
      <Group key="0">
 | 
			
		||||
        <Data key="Port Format" value="3,0" />
 | 
			
		||||
 
 | 
			
		||||
@@ -2847,6 +2847,72 @@
 | 
			
		||||
</CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>
 | 
			
		||||
<filters />
 | 
			
		||||
</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="TK43_REG" 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="TK43_REG.h" persistent="Generated_Source\PSoC5\TK43_REG.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="TK43_REG.c" persistent="Generated_Source\PSoC5\TK43_REG.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="TK43_REG_PM.c" persistent="Generated_Source\PSoC5\TK43_REG_PM.c">
 | 
			
		||||
<Hidden v="False" />
 | 
			
		||||
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
 | 
			
		||||
<build_action v="SOURCE_C;CortexM3;;;" />
 | 
			
		||||
<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>
 | 
			
		||||
<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="TK43" 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="TK43_aliases.h" persistent="Generated_Source\PSoC5\TK43_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="TK43.c" persistent="Generated_Source\PSoC5\TK43.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="TK43.h" persistent="Generated_Source\PSoC5\TK43.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>
 | 
			
		||||
</CyGuid_0820c2e7-528d-4137-9a08-97257b946089>
 | 
			
		||||
</CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>
 | 
			
		||||
@@ -3414,8 +3480,8 @@
 | 
			
		||||
</platforms>
 | 
			
		||||
<project_current_platform v="c9323d49-d323-40b8-9b59-cc008d68a989" />
 | 
			
		||||
<last_selected_tab v="Cypress" />
 | 
			
		||||
<WriteAppVersionLastSavedWith v="4.2.0.641" />
 | 
			
		||||
<WriteAppMarketingVersionLastSavedWith v=" 4.2" />
 | 
			
		||||
<WriteAppVersionLastSavedWith v="4.4.0.80" />
 | 
			
		||||
<WriteAppMarketingVersionLastSavedWith v=" 4.4" />
 | 
			
		||||
<project_id v="ff3eb327-f593-4eb3-a00f-72497469e963" />
 | 
			
		||||
<GenerateDescriptionFiles v="False" />
 | 
			
		||||
</CyGuid_49cfd574-032a-4a64-b7be-d4eeeaf25e43>
 | 
			
		||||
@@ -3427,9 +3493,7 @@
 | 
			
		||||
<library_dep persistent="${CyRoot}\psoc\content\default\CyAnnotationLibrary\CyAnnotationLibrary.cylib\CyAnnotationLibrary.cyprj" />
 | 
			
		||||
</library_deps>
 | 
			
		||||
<CyGuid_b0d670ad-d48f-47cb-9d0b-b1642bab195c type_name="CyDesigner.Common.Base.CyExprTypeMgr" version="1" />
 | 
			
		||||
<ignored_deps>
 | 
			
		||||
<library_dep persistent="C:\Users\dg\Documents\PSoC Creator\4.1\Downloads ( 4.1).cylib\Downloads ( 4.1).cyprj" />
 | 
			
		||||
</ignored_deps>
 | 
			
		||||
<ignored_deps />
 | 
			
		||||
</CyGuid_495451fe-d201-4d01-b22d-5d3f5609ac37>
 | 
			
		||||
<boot_component v="" />
 | 
			
		||||
<current_generation v="150" />
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
 | 
			
		||||
//`#start header` -- edit after this line, do not edit this line
 | 
			
		||||
`include "cypress.v"
 | 
			
		||||
`include "../SuperCounter/SuperCounter.v"
 | 
			
		||||
 | 
			
		||||
//`#end` -- edit above this line, do not edit this line
 | 
			
		||||
// Generated on 12/11/2019 at 21:18
 | 
			
		||||
@@ -9,7 +8,7 @@
 | 
			
		||||
module Sampler (
 | 
			
		||||
	output [2:0] debug_state,
 | 
			
		||||
	output reg [7:0] opcode,
 | 
			
		||||
	output  req,
 | 
			
		||||
	output  reg       req,
 | 
			
		||||
	input   clock,
 | 
			
		||||
	input   index,
 | 
			
		||||
	input   rdata,
 | 
			
		||||
@@ -19,77 +18,62 @@ module Sampler (
 | 
			
		||||
 | 
			
		||||
//`#start body` -- edit after this line, do not edit this line
 | 
			
		||||
 | 
			
		||||
localparam STATE_WAITING = 0;
 | 
			
		||||
localparam STATE_OPCODE = 1;
 | 
			
		||||
// NOTE: Reset pulse is used in both clock domains, and must be long enough
 | 
			
		||||
// to be detected in both.
 | 
			
		||||
 | 
			
		||||
reg [0:0] state;
 | 
			
		||||
reg [5:0] counter;
 | 
			
		||||
 | 
			
		||||
reg oldsampleclock;
 | 
			
		||||
reg oldindex;
 | 
			
		||||
reg oldrdata;
 | 
			
		||||
reg index_q;
 | 
			
		||||
reg rdata_q;
 | 
			
		||||
 | 
			
		||||
reg sampleclocked;
 | 
			
		||||
reg indexed;
 | 
			
		||||
reg rdataed;
 | 
			
		||||
reg index_edge;
 | 
			
		||||
reg rdata_edge;
 | 
			
		||||
 | 
			
		||||
assign req = (state == STATE_OPCODE);
 | 
			
		||||
reg req_toggle;
 | 
			
		||||
 | 
			
		||||
always @(posedge clock)
 | 
			
		||||
always @(posedge sampleclock)
 | 
			
		||||
begin
 | 
			
		||||
    if (reset)
 | 
			
		||||
    begin
 | 
			
		||||
        state <= STATE_WAITING;
 | 
			
		||||
        opcode <= 0;
 | 
			
		||||
        sampleclocked <= 0;
 | 
			
		||||
        indexed <= 0;
 | 
			
		||||
        rdataed <= 0;
 | 
			
		||||
        oldsampleclock <= 0;
 | 
			
		||||
        oldindex <= 0;
 | 
			
		||||
        oldrdata <= 0;
 | 
			
		||||
        index_edge <= 0;
 | 
			
		||||
        rdata_edge <= 0;
 | 
			
		||||
        index_q <= 0;
 | 
			
		||||
        rdata_q <= 0;
 | 
			
		||||
        counter <= 0;
 | 
			
		||||
        req_toggle <= 0;
 | 
			
		||||
    end
 | 
			
		||||
    else
 | 
			
		||||
    begin
 | 
			
		||||
        /* Remember positive egdes for sampleclock, index and rdata. */
 | 
			
		||||
        /* Both index and rdata are active high -- positive-going edges
 | 
			
		||||
         * indicate the start of an index pulse and read pulse, respectively.
 | 
			
		||||
         */
 | 
			
		||||
         
 | 
			
		||||
        index_edge <= index && !index_q;
 | 
			
		||||
        index_q <= index;
 | 
			
		||||
        
 | 
			
		||||
        if (sampleclock && !oldsampleclock)
 | 
			
		||||
            sampleclocked <= 1;
 | 
			
		||||
        oldsampleclock <= sampleclock;
 | 
			
		||||
        rdata_edge <= rdata && !rdata_q;
 | 
			
		||||
        rdata_q <= rdata;
 | 
			
		||||
        
 | 
			
		||||
        if (index && !oldindex)
 | 
			
		||||
            indexed <= 1;
 | 
			
		||||
        oldindex <= index;
 | 
			
		||||
        
 | 
			
		||||
        if (rdata && !oldrdata)
 | 
			
		||||
            rdataed <= 1;
 | 
			
		||||
        oldrdata <= rdata;
 | 
			
		||||
        
 | 
			
		||||
        case (state)
 | 
			
		||||
            STATE_WAITING:
 | 
			
		||||
            begin
 | 
			
		||||
                if (sampleclocked)
 | 
			
		||||
                begin
 | 
			
		||||
                    if (rdataed || indexed || (counter == 6'h3f))
 | 
			
		||||
                    begin
 | 
			
		||||
                        opcode <= {rdataed, indexed, counter};
 | 
			
		||||
                        rdataed <= 0;
 | 
			
		||||
                        indexed <= 0;
 | 
			
		||||
                        counter <= 1; /* remember to count this tick */
 | 
			
		||||
                        state <= STATE_OPCODE;
 | 
			
		||||
                    end
 | 
			
		||||
                    else
 | 
			
		||||
                        counter <= counter + 1;
 | 
			
		||||
                        
 | 
			
		||||
                    sampleclocked <= 0;
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
            
 | 
			
		||||
            STATE_OPCODE: /* opcode sent here */
 | 
			
		||||
            begin
 | 
			
		||||
                state <= STATE_WAITING;
 | 
			
		||||
            end
 | 
			
		||||
        endcase
 | 
			
		||||
        if (rdata_edge || index_edge || (counter == 6'h3f)) begin
 | 
			
		||||
            opcode <= { rdata_edge, index_edge, counter };
 | 
			
		||||
            req_toggle <= ~req_toggle;
 | 
			
		||||
            counter <= 1;   /* remember to count this tick */
 | 
			
		||||
        end else begin
 | 
			
		||||
            counter <= counter + 1;
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
reg req_toggle_q;
 | 
			
		||||
 | 
			
		||||
always @(posedge clock)
 | 
			
		||||
begin
 | 
			
		||||
    if (reset) begin
 | 
			
		||||
        req_toggle_q <= 0;
 | 
			
		||||
        req <= 0;
 | 
			
		||||
    end else begin
 | 
			
		||||
        req_toggle_q <= req_toggle;
 | 
			
		||||
        req <= (req_toggle != req_toggle_q);
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,11 @@ begin
 | 
			
		||||
                if (dataclocked)
 | 
			
		||||
                begin
 | 
			
		||||
                    pulsepending <= opcode[7];
 | 
			
		||||
                    countdown <= opcode[5:0] - 1; /* compensate for delay in last tick */
 | 
			
		||||
                    if (opcode[5:0] == 0)
 | 
			
		||||
                        countdown <= 0;
 | 
			
		||||
                    else
 | 
			
		||||
                        countdown <= opcode[5:0] - 1; /* compensate for extra tick in state machine */
 | 
			
		||||
                    
 | 
			
		||||
                    state <= STATE_WRITING;
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -13,14 +13,18 @@
 | 
			
		||||
#define DISKSTATUS_WPT    1
 | 
			
		||||
#define DISKSTATUS_DSKCHG 2
 | 
			
		||||
 | 
			
		||||
#define STEP_TOWARDS0 1
 | 
			
		||||
#define STEP_AWAYFROM0 0
 | 
			
		||||
#define STEP_TOWARDS0 0
 | 
			
		||||
#define STEP_AWAYFROM0 1
 | 
			
		||||
 | 
			
		||||
static bool drive0_present;
 | 
			
		||||
static bool drive1_present;
 | 
			
		||||
 | 
			
		||||
static volatile uint32_t clock = 0; /* ms */
 | 
			
		||||
static volatile bool index_irq = false;
 | 
			
		||||
/* Duration in ms. 0 causes every pulse to be an index pulse. Durations since
 | 
			
		||||
 * last pulse greater than this value imply sector pulse. Otherwise is an index
 | 
			
		||||
 * pulse. */
 | 
			
		||||
static volatile uint32_t hardsec_index_threshold = 0;
 | 
			
		||||
 | 
			
		||||
static bool motor_on = false;
 | 
			
		||||
static uint32_t motor_on_time = 0;
 | 
			
		||||
@@ -69,12 +73,41 @@ static void system_timer_cb(void)
 | 
			
		||||
 | 
			
		||||
CY_ISR(index_irq_cb)
 | 
			
		||||
{
 | 
			
		||||
    index_irq = true;
 | 
			
		||||
    /* Hard sectored media has sector pulses at the beginning of every sector
 | 
			
		||||
     * and the index pulse is an extra pulse in the middle of the last sector.
 | 
			
		||||
     * When the extra pulse is seen, the next sector pulse is also the start of
 | 
			
		||||
     * the track. */
 | 
			
		||||
    static bool hardsec_index_irq_primed = false;
 | 
			
		||||
    static uint32_t hardsec_last_pulse_time = 0;
 | 
			
		||||
    uint32_t index_pulse_duration = clock - hardsec_last_pulse_time;
 | 
			
		||||
 | 
			
		||||
    if (!hardsec_index_threshold)
 | 
			
		||||
    {
 | 
			
		||||
        index_irq = true;
 | 
			
		||||
        hardsec_index_irq_primed = false;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        /* It's only an index pulse if the previous pulse is less than
 | 
			
		||||
         * the threshold.
 | 
			
		||||
         */
 | 
			
		||||
        index_irq = (index_pulse_duration <= hardsec_index_threshold) ?
 | 
			
		||||
            hardsec_index_irq_primed : false;
 | 
			
		||||
 | 
			
		||||
        if (index_irq)
 | 
			
		||||
            hardsec_index_irq_primed = false;
 | 
			
		||||
        else
 | 
			
		||||
            hardsec_index_irq_primed =
 | 
			
		||||
                index_pulse_duration <= hardsec_index_threshold;
 | 
			
		||||
 | 
			
		||||
        hardsec_last_pulse_time = clock;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /* Stop writing the instant the index pulse comes along; it may take a few
 | 
			
		||||
     * moments for the main code to notice the pulse, and we don't want to overwrite
 | 
			
		||||
     * the beginning of the track. */
 | 
			
		||||
    ERASE_REG_Write(0);
 | 
			
		||||
    if (index_irq)
 | 
			
		||||
        ERASE_REG_Write(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CY_ISR(capture_dma_finished_irq_cb)
 | 
			
		||||
@@ -249,6 +282,7 @@ static void seek_to(int track)
 | 
			
		||||
        CyWdtClear();
 | 
			
		||||
    }
 | 
			
		||||
    CyDelay(STEP_SETTLING_TIME);
 | 
			
		||||
    TK43_REG_Write(track < 43); /* high if 0..42, low if 43 or up */
 | 
			
		||||
    print("finished seek");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -267,7 +301,7 @@ static void cmd_recalibrate(void)
 | 
			
		||||
    send_reply(&r);    
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
static void cmd_measure_speed(struct any_frame* f)
 | 
			
		||||
static void cmd_measure_speed(struct measurespeed_frame* f)
 | 
			
		||||
{
 | 
			
		||||
    start_motor();
 | 
			
		||||
    
 | 
			
		||||
@@ -277,7 +311,7 @@ static void cmd_measure_speed(struct any_frame* f)
 | 
			
		||||
    while (!index_irq)
 | 
			
		||||
    {
 | 
			
		||||
        elapsed = clock - start_clock;
 | 
			
		||||
        if (elapsed > 1000)
 | 
			
		||||
        if (elapsed > 1500)
 | 
			
		||||
        {
 | 
			
		||||
            elapsed = 0;
 | 
			
		||||
            break;
 | 
			
		||||
@@ -286,10 +320,14 @@ static void cmd_measure_speed(struct any_frame* f)
 | 
			
		||||
 | 
			
		||||
    if (elapsed != 0)
 | 
			
		||||
    {
 | 
			
		||||
        index_irq = false;
 | 
			
		||||
        int target_pulse_count = f->hard_sector_count + 1;
 | 
			
		||||
        start_clock = clock;
 | 
			
		||||
        while (!index_irq)
 | 
			
		||||
            elapsed = clock - start_clock;
 | 
			
		||||
        for (int x=0; x<target_pulse_count; x++)
 | 
			
		||||
        {
 | 
			
		||||
            index_irq = false;
 | 
			
		||||
            while (!index_irq)
 | 
			
		||||
                elapsed = clock - start_clock;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    DECLARE_REPLY_FRAME(struct speed_frame, F_FRAME_MEASURE_SPEED_REPLY);
 | 
			
		||||
@@ -381,9 +419,9 @@ static void init_capture_dma(void)
 | 
			
		||||
 | 
			
		||||
static void cmd_read(struct read_frame* f)
 | 
			
		||||
{
 | 
			
		||||
    SIDE_REG_Write(f->side);
 | 
			
		||||
    seek_to(current_track);
 | 
			
		||||
    
 | 
			
		||||
    SIDE_REG_Write(f->side);
 | 
			
		||||
    STEP_REG_Write(f->side); /* for drives which multiplex SIDE and DIR */
 | 
			
		||||
    /* Do slow setup *before* we go into the real-time bit. */
 | 
			
		||||
    
 | 
			
		||||
    {
 | 
			
		||||
@@ -401,10 +439,12 @@ static void cmd_read(struct read_frame* f)
 | 
			
		||||
        
 | 
			
		||||
    if (f->synced)
 | 
			
		||||
    {
 | 
			
		||||
        hardsec_index_threshold = f->hardsec_threshold_ms;
 | 
			
		||||
        index_irq = false;
 | 
			
		||||
        while (!index_irq)
 | 
			
		||||
            ;
 | 
			
		||||
        index_irq = false;
 | 
			
		||||
        hardsec_index_threshold = 0;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    dma_writing_to_td = 0;
 | 
			
		||||
@@ -478,6 +518,7 @@ abort:;
 | 
			
		||||
    wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
 | 
			
		||||
    deinit_dma();
 | 
			
		||||
 | 
			
		||||
    STEP_REG_Write(0);
 | 
			
		||||
    if (saved_dma_underrun)
 | 
			
		||||
    {
 | 
			
		||||
        print("underrun after %d packets");
 | 
			
		||||
@@ -523,9 +564,10 @@ static void cmd_write(struct write_frame* f)
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    SEQUENCER_CONTROL_Write(1); /* put the sequencer into reset */
 | 
			
		||||
 | 
			
		||||
    seek_to(current_track);    
 | 
			
		||||
    SIDE_REG_Write(f->side);
 | 
			
		||||
    STEP_REG_Write(f->side); /* for drives which multiplex SIDE and DIR */
 | 
			
		||||
    SEQUENCER_CONTROL_Write(1); /* put the sequencer into reset */
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t i = CyEnterCriticalSection();        
 | 
			
		||||
        REPLAY_FIFO_SET_LEVEL_MID;
 | 
			
		||||
@@ -533,7 +575,6 @@ static void cmd_write(struct write_frame* f)
 | 
			
		||||
        REPLAY_FIFO_SINGLE_BUFFER_UNSET;
 | 
			
		||||
        CyExitCriticalSection(i);
 | 
			
		||||
    }
 | 
			
		||||
    seek_to(current_track);    
 | 
			
		||||
 | 
			
		||||
    init_replay_dma();
 | 
			
		||||
    bool writing = false; /* to the disk */
 | 
			
		||||
@@ -590,7 +631,7 @@ static void cmd_write(struct write_frame* f)
 | 
			
		||||
 | 
			
		||||
                /* Wait for the index marker. While this happens, the DMA engine
 | 
			
		||||
                 * will prime the FIFO. */
 | 
			
		||||
 | 
			
		||||
                hardsec_index_threshold = f->hardsec_threshold_ms;
 | 
			
		||||
                index_irq = false;
 | 
			
		||||
                while (!index_irq)
 | 
			
		||||
                    ;
 | 
			
		||||
@@ -625,6 +666,7 @@ abort:
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    print("p=%d cr=%d cw=%d f=%d w=%d index=%d underrun=%d", packets, count_read, count_written, finished, writing, index_irq, dma_underrun);
 | 
			
		||||
    hardsec_index_threshold = 0;
 | 
			
		||||
    if (!finished)
 | 
			
		||||
    {
 | 
			
		||||
        /* There's still some data to read, so just read and blackhole it ---
 | 
			
		||||
@@ -638,6 +680,7 @@ abort:
 | 
			
		||||
    
 | 
			
		||||
    deinit_dma();
 | 
			
		||||
    
 | 
			
		||||
    STEP_REG_Write(0);
 | 
			
		||||
    if (dma_underrun)
 | 
			
		||||
    {
 | 
			
		||||
        print("underrun!");
 | 
			
		||||
@@ -653,10 +696,11 @@ abort:
 | 
			
		||||
static void cmd_erase(struct erase_frame* f)
 | 
			
		||||
{
 | 
			
		||||
    SIDE_REG_Write(f->side);
 | 
			
		||||
    seek_to(current_track);    
 | 
			
		||||
    seek_to(current_track);
 | 
			
		||||
    /* Disk is now spinning. */
 | 
			
		||||
    
 | 
			
		||||
    print("start erasing");
 | 
			
		||||
    hardsec_index_threshold = f->hardsec_threshold_ms;
 | 
			
		||||
    index_irq = false;
 | 
			
		||||
    while (!index_irq)
 | 
			
		||||
        ;
 | 
			
		||||
@@ -665,6 +709,7 @@ static void cmd_erase(struct erase_frame* f)
 | 
			
		||||
    while (!index_irq)
 | 
			
		||||
        ;
 | 
			
		||||
    ERASE_REG_Write(0);
 | 
			
		||||
    hardsec_index_threshold = 0;
 | 
			
		||||
    print("stop erasing");
 | 
			
		||||
 | 
			
		||||
    DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_ERASE_REPLY);
 | 
			
		||||
@@ -790,7 +835,7 @@ static void handle_command(void)
 | 
			
		||||
            break;
 | 
			
		||||
        
 | 
			
		||||
        case F_FRAME_MEASURE_SPEED_CMD:
 | 
			
		||||
            cmd_measure_speed(f);
 | 
			
		||||
            cmd_measure_speed((struct measurespeed_frame*) f);
 | 
			
		||||
            break;
 | 
			
		||||
            
 | 
			
		||||
        case F_FRAME_BULK_WRITE_TEST_CMD:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,21 +1,28 @@
 | 
			
		||||
PACKAGES = zlib sqlite3 libusb-1.0
 | 
			
		||||
PACKAGES = zlib sqlite3 libusb-1.0 protobuf gtk+-3.0
 | 
			
		||||
 | 
			
		||||
export CFLAGS = --std=c++14 -ffunction-sections -fdata-sections
 | 
			
		||||
export LDFLAGS =
 | 
			
		||||
export CFLAGS = -ffunction-sections -fdata-sections
 | 
			
		||||
export CXXFLAGS = $(CFLAGS) \
 | 
			
		||||
	--std=gnu++2a \
 | 
			
		||||
	-Wno-deprecated-enum-enum-conversion \
 | 
			
		||||
	-Wno-deprecated-enum-float-conversion
 | 
			
		||||
export LDFLAGS = -pthread
 | 
			
		||||
 | 
			
		||||
export COPTFLAGS = -Os
 | 
			
		||||
export LDOPTFLAGS = -Os -s
 | 
			
		||||
export LDOPTFLAGS = -Os -ldl
 | 
			
		||||
 | 
			
		||||
export CDBGFLAGS = -O0 -g
 | 
			
		||||
export LDDBGFLAGS = -O0 -g
 | 
			
		||||
export LDDBGFLAGS = -O0 -g -ldl
 | 
			
		||||
 | 
			
		||||
ifeq ($(OS), Windows_NT)
 | 
			
		||||
export PROTOC = /mingw32/bin/protoc
 | 
			
		||||
export CC = /mingw32/bin/gcc
 | 
			
		||||
export CXX = /mingw32/bin/g++
 | 
			
		||||
export AR = /mingw32/bin/ar rcs
 | 
			
		||||
export AR = /mingw32/bin/ar rc
 | 
			
		||||
export RANLIB = /mingw32/bin/ranlib
 | 
			
		||||
export STRIP = /mingw32/bin/strip
 | 
			
		||||
export CFLAGS += -I/mingw32/include/libusb-1.0
 | 
			
		||||
export CFLAGS += -I/mingw32/include/libusb-1.0 -I/mingw32/include
 | 
			
		||||
export LDFLAGS +=
 | 
			
		||||
export LIBS = -static -lz -lsqlite3 -lusb-1.0
 | 
			
		||||
export LIBS += -L/mingw32/lib -static -lz -lsqlite3 -lusb-1.0 -lprotobuf
 | 
			
		||||
export EXTENSION = .exe
 | 
			
		||||
else
 | 
			
		||||
 | 
			
		||||
@@ -25,21 +32,32 @@ $(warning These pkg-config packages are installed: $(shell pkg-config --list-all
 | 
			
		||||
$(error You must have these pkg-config packages installed: $(PACKAGES))
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
export PROTOC = protoc
 | 
			
		||||
export CC = gcc
 | 
			
		||||
export CXX = g++
 | 
			
		||||
export AR = ar rcs
 | 
			
		||||
export AR = ar rc
 | 
			
		||||
export RANLIB = ranlib
 | 
			
		||||
export STRIP = strip
 | 
			
		||||
export CFLAGS += $(shell pkg-config --cflags $(PACKAGES))
 | 
			
		||||
export LDFLAGS +=
 | 
			
		||||
export LIBS = $(shell pkg-config --libs $(PACKAGES))
 | 
			
		||||
export LIBS += $(shell pkg-config --libs $(PACKAGES))
 | 
			
		||||
export EXTENSION =
 | 
			
		||||
 | 
			
		||||
ifeq ($(shell uname),Darwin)
 | 
			
		||||
AR = ar rcS
 | 
			
		||||
RANLIB += -c -no_warning_for_no_symbols
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
export XXD = xxd
 | 
			
		||||
 | 
			
		||||
CFLAGS += -Ilib -Idep/fmt -Iarch
 | 
			
		||||
 | 
			
		||||
export OBJDIR = .obj
 | 
			
		||||
 | 
			
		||||
all: .obj/build.ninja
 | 
			
		||||
	@ninja -f .obj/build.ninja
 | 
			
		||||
	@ninja -f .obj/build.ninja -k 0
 | 
			
		||||
	@if command -v cscope > /dev/null; then cscope -bRq; fi
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	@echo CLEAN
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										81
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								README.md
									
									
									
									
									
								
							@@ -4,6 +4,11 @@ FluxEngine
 | 
			
		||||
(If you're reading this on GitHub, the formatting's a bit messed up. [Try the
 | 
			
		||||
version on cowlark.com instead.](http://cowlark.com/fluxengine/)
 | 
			
		||||
 | 
			
		||||
**Breaking news!** As of 2021-05-21, the command line environment has changed
 | 
			
		||||
_substantially_ (to make it more consistent and flexible, and allow some new
 | 
			
		||||
backend features like multi-format IBM scheme disks, which are popular with
 | 
			
		||||
CP/M). If things don't work the way you expect, please check the documentation.
 | 
			
		||||
 | 
			
		||||
What?
 | 
			
		||||
-----
 | 
			
		||||
 | 
			
		||||
@@ -24,6 +29,14 @@ Don't believe me? Watch the demo reel!
 | 
			
		||||
<iframe width="373" height="210" src="https://www.youtube.com/embed/m_s1iw8eW7o" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
**New!** The FluxEngine client software now works with
 | 
			
		||||
[GreaseWeazle](https://github.com/keirf/Greaseweazle/wiki) hardware. So, if you
 | 
			
		||||
can't find a PSoC5 development kit, or don't want to use the Cypress Windows
 | 
			
		||||
tools for programming it, you can use one of these instead. Very nearly all
 | 
			
		||||
FluxEngine features are available with the GreaseWeazle and it works out-of-the
 | 
			
		||||
box. See the [dedicated GreaseWeazle documentation page](doc/greaseweazle.md)
 | 
			
		||||
for more information.
 | 
			
		||||
 | 
			
		||||
**Important note.** On 2020-04-02 I changed the bytecode format (and firmware).
 | 
			
		||||
Flux files will need to be upgraded with `fluxengine upgradefluxfile`. The new
 | 
			
		||||
format should be more reliable and use way, way less bandwidth. Sorry for the
 | 
			
		||||
@@ -52,8 +65,15 @@ following friendly articles:
 | 
			
		||||
  - [Using a FluxEngine](doc/using.md) ∾ what to do with your new hardware ∾
 | 
			
		||||
    flux files and image files ∾ knowing what you're doing
 | 
			
		||||
 | 
			
		||||
  - [Troubleshooting dubious disks](doc/problems.md) ∾ it's not an exact science ∾
 | 
			
		||||
    the sector map ∾ clock detection and the histogram
 | 
			
		||||
  - [Using GreaseWeazle hardware with the FluxEngine client
 | 
			
		||||
	software](doc/greaseweazle.md) ∾ what works ∾ what doesn't work ∾ where to
 | 
			
		||||
	go for help
 | 
			
		||||
 | 
			
		||||
  - [Troubleshooting dubious disks](doc/problems.md) ∾ it's not an exact
 | 
			
		||||
	science ∾ the sector map ∾ clock detection and the histogram
 | 
			
		||||
 | 
			
		||||
  - [Checking your drive](doc/driveresponse.md) ∾ you can't do that with that ∾
 | 
			
		||||
	measuring your drive's ability to work with exotic formats
 | 
			
		||||
 | 
			
		||||
Which?
 | 
			
		||||
------
 | 
			
		||||
@@ -70,20 +90,20 @@ people who've had it work).
 | 
			
		||||
 | 
			
		||||
### Old disk formats
 | 
			
		||||
 | 
			
		||||
| Format                                   | Read? | Write? | Notes |
 | 
			
		||||
|:-----------------------------------------|:-----:|:------:|-------|
 | 
			
		||||
| [IBM PC compatible](doc/disk-ibm.md)     |  🦄   |   🦄   | and compatibles (like the Atari ST) |
 | 
			
		||||
| [Acorn ADFS](doc/disk-acornadfs.md)      |  🦄   |   🦖*  | single- and double- sided           |
 | 
			
		||||
| [Acorn DFS](doc/disk-acorndfs.md)        |  🦄   |   🦖*  |                                     |
 | 
			
		||||
| [Ampro Little Board](doc/disk-ampro.md)  |  🦖   |   🦖*   |                                     |
 | 
			
		||||
| [Apple II DOS 3.3](doc/disk-apple2.md)   |  🦄   |        | doesn't do logical sector remapping |
 | 
			
		||||
| [Amiga](doc/disk-amiga.md)               |  🦄   |        |                                     |
 | 
			
		||||
| [Commodore 64 1541](doc/disk-c64.md)     |  🦖   |        | and probably the other GCR formats  |
 | 
			
		||||
| [Brother 120kB](doc/disk-brother.md)     |  🦄   |        |                                     |
 | 
			
		||||
| [Brother 240kB](doc/disk-brother.md)     |  🦄   |   🦄   |                                     |
 | 
			
		||||
| [Brother FB-100](doc/disk-fb100.md)      |  🦖   |        | Tandy Model 100, Husky Hunter, knitting machines |
 | 
			
		||||
| [Macintosh 800kB](doc/disk-macintosh.md) |  🦖   |        | and probably the 400kB too          |
 | 
			
		||||
| [TRS-80](doc/disk-trs80.md)              |  🦖   |   🦖*  | a minor variation of the IBM scheme |
 | 
			
		||||
| Format                                    | Read? | Write? | Notes |
 | 
			
		||||
|:------------------------------------------|:-----:|:------:|-------|
 | 
			
		||||
| [IBM PC compatible](doc/disk-ibm.md)      |  🦄   |   🦄   | and compatibles (like the Atari ST) |
 | 
			
		||||
| [Acorn ADFS](doc/disk-acornadfs.md)       |  🦄   |   🦖*  | single- and double- sided           |
 | 
			
		||||
| [Acorn DFS](doc/disk-acorndfs.md)         |  🦄   |   🦖*  |                                     |
 | 
			
		||||
| [Ampro Little Board](doc/disk-ampro.md)   |  🦖   |   🦖*  |                                     |
 | 
			
		||||
| [Apple II DOS 3.3](doc/disk-apple2.md)    |  🦄   |        | doesn't do logical sector remapping |
 | 
			
		||||
| [Amiga](doc/disk-amiga.md)                |  🦄   |   🦄   |                                     |
 | 
			
		||||
| [Commodore 64 1541/1581](doc/disk-c64.md) |  🦄   |   🦄   | and probably the other formats      |
 | 
			
		||||
| [Brother 120kB](doc/disk-brother.md)      |  🦄   |   🦖   |                                     |
 | 
			
		||||
| [Brother 240kB](doc/disk-brother.md)      |  🦄   |   🦄   |                                     |
 | 
			
		||||
| [Brother FB-100](doc/disk-fb100.md)       |  🦖   |        | Tandy Model 100, Husky Hunter, knitting machines |
 | 
			
		||||
| [Macintosh 800kB](doc/disk-macintosh.md)  |  🦄   |   🦄   | and probably the 400kB too          |
 | 
			
		||||
| [TRS-80](doc/disk-trs80.md)               |  🦖   |   🦖*  | a minor variation of the IBM scheme |
 | 
			
		||||
{: .datatable }
 | 
			
		||||
 | 
			
		||||
`*`: these formats are variations of the generic IBM format, and since the
 | 
			
		||||
@@ -103,8 +123,12 @@ at least, check the CRC so what data's there is probably good.
 | 
			
		||||
| [AES Superplus / No Problem](doc/disk-aeslanier.md) |  🦖   | | hard sectors! |
 | 
			
		||||
| [Durango F85](doc/disk-durangof85.md)    |  🦖   |        | 5.25" |
 | 
			
		||||
| [DVK MX](doc/disk-mx.md)                 |  🦖   |        | Soviet PDP-11 clone |
 | 
			
		||||
| [Victor 9000](doc/disk-victor9k.md)      |  🦖   |        | 8-inch        |
 | 
			
		||||
| [Zilog MCZ](doc/disk-zilogmcz.md)        |  🦖   |        | 8-inch _and_ hard sectors |
 | 
			
		||||
| [VDS Eco1](doc/disk-eco1.md)             |  🦖   |        | 8" mixed format |
 | 
			
		||||
| [Micropolis](doc/disk-micropolis.md)     |  🦄   |        | Micropolis 100tpi drives |
 | 
			
		||||
| [Northstar(doc/disk-northstar.md)        |  🦖   |   🦖   | 5.25" hard sectors |
 | 
			
		||||
| [TI DS990 FD1000](doc/disk-tids990.md)   |  🦄   |  🦄    | 8" |
 | 
			
		||||
| [Victor 9000](doc/disk-victor9k.md)      |  🦖   |        | 8" |
 | 
			
		||||
| [Zilog MCZ](doc/disk-zilogmcz.md)        |  🦖   |        | 8" _and_ hard sectors |
 | 
			
		||||
{: .datatable }
 | 
			
		||||
 | 
			
		||||
### Notes
 | 
			
		||||
@@ -188,6 +212,25 @@ contributions from many other people. It is licensed under the terms of the
 | 
			
		||||
BSD license. Please see the contents of the directory for the full text.
 | 
			
		||||
 | 
			
		||||
As an exception, `dep/emu` contains parts of the OpenBSD C library
 | 
			
		||||
code, Todd Miller and William A. Rowe (and probably others). It is licensed
 | 
			
		||||
code, maintained by Todd Miller and William A. Rowe (and probably others). It is licensed
 | 
			
		||||
under the terms of the 3-clause BSD license. Please see the contents of the
 | 
			
		||||
directory for the full text. It's been lightly modified by me.
 | 
			
		||||
 | 
			
		||||
As an exception, `dep/agg` contains parts of the Anti-Grain Antialiasing
 | 
			
		||||
library, written by Maxim Semanarev (and others). It is licensed under the
 | 
			
		||||
terms of the 3-clause BSD license. Please see the contents of the directory for
 | 
			
		||||
the full text. It's been lightly modified by me.
 | 
			
		||||
 | 
			
		||||
As an exception, `dep/stb` contains parts of the libstb utility library,
 | 
			
		||||
written by Sean T Barett (and others). It is public domain/Unlicense/MIT
 | 
			
		||||
licensed, at your choice. Please see the contents of the directory for the full
 | 
			
		||||
text.
 | 
			
		||||
 | 
			
		||||
As an exception, `dep/snowhouse` contains the snowhouse assertion library,
 | 
			
		||||
taken from https://github.com/banditcpp/snowhouse. It is Boost Standard License
 | 
			
		||||
1.0 licensed. Please see the contents of the directory for the full text.
 | 
			
		||||
 | 
			
		||||
As an exception, `dep/libui` contains the libui GUI library, taken from
 | 
			
		||||
https://github.com/andlabs/libui. It is MIT licensed. Please see the contents
 | 
			
		||||
of the directory for the full text.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,16 +5,6 @@
 | 
			
		||||
#define AESLANIER_SECTOR_LENGTH    256
 | 
			
		||||
#define AESLANIER_RECORD_SIZE      (AESLANIER_SECTOR_LENGTH + 5)
 | 
			
		||||
 | 
			
		||||
class Sector;
 | 
			
		||||
class Fluxmap;
 | 
			
		||||
 | 
			
		||||
class AesLanierDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~AesLanierDecoder() {}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord();
 | 
			
		||||
    void decodeSectorRecord();
 | 
			
		||||
};
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createAesLanierDecoder(const DecoderProto& config);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								arch/aeslanier/aeslanier.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/aeslanier/aeslanier.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
message AesLanierDecoderProto {}
 | 
			
		||||
 | 
			
		||||
@@ -6,7 +6,6 @@
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "bytes.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "fmt/format.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
@@ -24,42 +23,57 @@ static Bytes reverse_bits(const Bytes& input)
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AbstractDecoder::RecordType AesLanierDecoder::advanceToNextRecord()
 | 
			
		||||
class AesLanierDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
    _sector->clock = _fmr->seekToPattern(SECTOR_PATTERN);
 | 
			
		||||
    if (_fmr->eof() || !_sector->clock)
 | 
			
		||||
        return UNKNOWN_RECORD;
 | 
			
		||||
    return SECTOR_RECORD;
 | 
			
		||||
public:
 | 
			
		||||
	AesLanierDecoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord()
 | 
			
		||||
	{
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(SECTOR_PATTERN);
 | 
			
		||||
		if (_fmr->eof() || !_sector->clock)
 | 
			
		||||
			return UNKNOWN_RECORD;
 | 
			
		||||
		return SECTOR_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeSectorRecord()
 | 
			
		||||
	{
 | 
			
		||||
		/* Skip ID mark. */
 | 
			
		||||
 | 
			
		||||
		readRawBits(16);
 | 
			
		||||
 | 
			
		||||
		const auto& rawbits = readRawBits(AESLANIER_RECORD_SIZE*16);
 | 
			
		||||
		const auto& bytes = decodeFmMfm(rawbits).slice(0, AESLANIER_RECORD_SIZE);
 | 
			
		||||
		const auto& reversed = reverse_bits(bytes);
 | 
			
		||||
 | 
			
		||||
		_sector->logicalTrack = reversed[1];
 | 
			
		||||
		_sector->logicalSide = 0;
 | 
			
		||||
		_sector->logicalSector = reversed[2];
 | 
			
		||||
 | 
			
		||||
		/* Check header 'checksum' (which seems far too simple to mean much). */
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			uint8_t wanted = reversed[3];
 | 
			
		||||
			uint8_t got = reversed[1] + reversed[2];
 | 
			
		||||
			if (wanted != got)
 | 
			
		||||
				return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Check data checksum, which also includes the header and is
 | 
			
		||||
			* significantly better. */
 | 
			
		||||
 | 
			
		||||
		_sector->data = reversed.slice(1, AESLANIER_SECTOR_LENGTH);
 | 
			
		||||
		uint16_t wanted = reversed.reader().seek(0x101).read_le16();
 | 
			
		||||
		uint16_t got = crc16ref(MODBUS_POLY_REF, _sector->data);
 | 
			
		||||
		_sector->status = (wanted == got) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createAesLanierDecoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new AesLanierDecoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AesLanierDecoder::decodeSectorRecord()
 | 
			
		||||
{
 | 
			
		||||
    /* Skip ID mark. */
 | 
			
		||||
 | 
			
		||||
    readRawBits(16);
 | 
			
		||||
 | 
			
		||||
    const auto& rawbits = readRawBits(AESLANIER_RECORD_SIZE*16);
 | 
			
		||||
    const auto& bytes = decodeFmMfm(rawbits).slice(0, AESLANIER_RECORD_SIZE);
 | 
			
		||||
    const auto& reversed = reverse_bits(bytes);
 | 
			
		||||
 | 
			
		||||
    _sector->logicalTrack = reversed[1];
 | 
			
		||||
    _sector->logicalSide = 0;
 | 
			
		||||
    _sector->logicalSector = reversed[2];
 | 
			
		||||
 | 
			
		||||
    /* Check header 'checksum' (which seems far too simple to mean much). */
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t wanted = reversed[3];
 | 
			
		||||
        uint8_t got = reversed[1] + reversed[2];
 | 
			
		||||
        if (wanted != got)
 | 
			
		||||
            return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Check data checksum, which also includes the header and is
 | 
			
		||||
        * significantly better. */
 | 
			
		||||
 | 
			
		||||
    _sector->data = reversed.slice(1, AESLANIER_SECTOR_LENGTH);
 | 
			
		||||
    uint16_t wanted = reversed.reader().seek(0x101).read_le16();
 | 
			
		||||
    uint16_t got = crc16ref(MODBUS_POLY_REF, _sector->data);
 | 
			
		||||
    _sector->status = (wanted == got) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "amiga.h"
 | 
			
		||||
#include "bytes.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -9,31 +9,8 @@
 | 
			
		||||
#define AMIGA_SECTORS_PER_TRACK 11
 | 
			
		||||
#define AMIGA_RECORD_SIZE 0x21f
 | 
			
		||||
 | 
			
		||||
class Sector;
 | 
			
		||||
class Fluxmap;
 | 
			
		||||
class SectorSet;
 | 
			
		||||
 | 
			
		||||
class AmigaDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~AmigaDecoder() {}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord();
 | 
			
		||||
    void decodeSectorRecord();
 | 
			
		||||
 | 
			
		||||
	std::set<unsigned> requiredSectors(Track& track) const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class AmigaEncoder : public AbstractEncoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual ~AmigaEncoder() {}
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern FlagGroup amigaEncoderFlags;
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createAmigaDecoder(const DecoderProto& config);
 | 
			
		||||
extern std::unique_ptr<AbstractEncoder> createAmigaEncoder(const EncoderProto& config);
 | 
			
		||||
 | 
			
		||||
extern uint32_t amigaChecksum(const Bytes& bytes);
 | 
			
		||||
extern Bytes amigaInterleave(const Bytes& input);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								arch/amiga/amiga.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								arch/amiga/amiga.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
import "lib/common.proto";
 | 
			
		||||
 | 
			
		||||
message AmigaDecoderProto {}
 | 
			
		||||
 | 
			
		||||
message AmigaEncoderProto {
 | 
			
		||||
	optional double clock_rate_us = 1
 | 
			
		||||
		[default=2.00, (help)="Encoded data clock rate."];
 | 
			
		||||
	optional double post_index_gap_ms = 2
 | 
			
		||||
		[default=0.5, (help)="Post-index gap before first sector header."];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2,12 +2,12 @@
 | 
			
		||||
#include "fluxmap.h"
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "protocol.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "amiga.h"
 | 
			
		||||
#include "bytes.h"
 | 
			
		||||
#include "fmt/format.h"
 | 
			
		||||
#include "lib/decoders/decoders.pb.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
@@ -21,47 +21,65 @@
 | 
			
		||||
         
 | 
			
		||||
static const FluxPattern SECTOR_PATTERN(48, AMIGA_SECTOR_RECORD);
 | 
			
		||||
 | 
			
		||||
AbstractDecoder::RecordType AmigaDecoder::advanceToNextRecord()
 | 
			
		||||
class AmigaDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
    _sector->clock = _fmr->seekToPattern(SECTOR_PATTERN);
 | 
			
		||||
    if (_fmr->eof() || !_sector->clock)
 | 
			
		||||
        return UNKNOWN_RECORD;
 | 
			
		||||
    return SECTOR_RECORD;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AmigaDecoder::decodeSectorRecord()
 | 
			
		||||
{
 | 
			
		||||
    const auto& rawbits = readRawBits(AMIGA_RECORD_SIZE*16);
 | 
			
		||||
	if (rawbits.size() < (AMIGA_RECORD_SIZE*16))
 | 
			
		||||
		return;
 | 
			
		||||
    const auto& rawbytes = toBytes(rawbits).slice(0, AMIGA_RECORD_SIZE*2);
 | 
			
		||||
    const auto& bytes = decodeFmMfm(rawbits).slice(0, AMIGA_RECORD_SIZE);
 | 
			
		||||
 | 
			
		||||
    const uint8_t* ptr = bytes.begin() + 3;
 | 
			
		||||
 | 
			
		||||
    Bytes header = amigaDeinterleave(ptr, 4);
 | 
			
		||||
    Bytes recoveryinfo = amigaDeinterleave(ptr, 16);
 | 
			
		||||
 | 
			
		||||
    _sector->logicalTrack = header[1] >> 1;
 | 
			
		||||
    _sector->logicalSide = header[1] & 1;
 | 
			
		||||
    _sector->logicalSector = header[2];
 | 
			
		||||
 | 
			
		||||
    uint32_t wantedheaderchecksum = amigaDeinterleave(ptr, 4).reader().read_be32();
 | 
			
		||||
    uint32_t gotheaderchecksum = amigaChecksum(rawbytes.slice(6, 40));
 | 
			
		||||
    if (gotheaderchecksum != wantedheaderchecksum)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    uint32_t wanteddatachecksum = amigaDeinterleave(ptr, 4).reader().read_be32();
 | 
			
		||||
    uint32_t gotdatachecksum = amigaChecksum(rawbytes.slice(62, 1024));
 | 
			
		||||
 | 
			
		||||
    _sector->data.clear();
 | 
			
		||||
    _sector->data.writer().append(amigaDeinterleave(ptr, 512)).append(recoveryinfo);
 | 
			
		||||
    _sector->status = (gotdatachecksum == wanteddatachecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::set<unsigned> AmigaDecoder::requiredSectors(Track& track) const
 | 
			
		||||
{
 | 
			
		||||
	static std::set<unsigned> sectors = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
 | 
			
		||||
	return sectors;
 | 
			
		||||
public:
 | 
			
		||||
	AmigaDecoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config),
 | 
			
		||||
		_config(config.amiga())
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord() override
 | 
			
		||||
	{
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(SECTOR_PATTERN);
 | 
			
		||||
		if (_fmr->eof() || !_sector->clock)
 | 
			
		||||
			return UNKNOWN_RECORD;
 | 
			
		||||
		return SECTOR_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeSectorRecord() override
 | 
			
		||||
	{
 | 
			
		||||
		const auto& rawbits = readRawBits(AMIGA_RECORD_SIZE*16);
 | 
			
		||||
		if (rawbits.size() < (AMIGA_RECORD_SIZE*16))
 | 
			
		||||
			return;
 | 
			
		||||
		const auto& rawbytes = toBytes(rawbits).slice(0, AMIGA_RECORD_SIZE*2);
 | 
			
		||||
		const auto& bytes = decodeFmMfm(rawbits).slice(0, AMIGA_RECORD_SIZE);
 | 
			
		||||
 | 
			
		||||
		const uint8_t* ptr = bytes.begin() + 3;
 | 
			
		||||
 | 
			
		||||
		Bytes header = amigaDeinterleave(ptr, 4);
 | 
			
		||||
		Bytes recoveryinfo = amigaDeinterleave(ptr, 16);
 | 
			
		||||
 | 
			
		||||
		_sector->logicalTrack = header[1] >> 1;
 | 
			
		||||
		_sector->logicalSide = header[1] & 1;
 | 
			
		||||
		_sector->logicalSector = header[2];
 | 
			
		||||
 | 
			
		||||
		uint32_t wantedheaderchecksum = amigaDeinterleave(ptr, 4).reader().read_be32();
 | 
			
		||||
		uint32_t gotheaderchecksum = amigaChecksum(rawbytes.slice(6, 40));
 | 
			
		||||
		if (gotheaderchecksum != wantedheaderchecksum)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		uint32_t wanteddatachecksum = amigaDeinterleave(ptr, 4).reader().read_be32();
 | 
			
		||||
		uint32_t gotdatachecksum = amigaChecksum(rawbytes.slice(62, 1024));
 | 
			
		||||
 | 
			
		||||
		Bytes data;
 | 
			
		||||
		data.writer().append(amigaDeinterleave(ptr, 512)).append(recoveryinfo);
 | 
			
		||||
		_sector->data = data;
 | 
			
		||||
		_sector->status = (gotdatachecksum == wanteddatachecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::set<unsigned> requiredSectors(unsigned cylinder, unsigned head) const override
 | 
			
		||||
	{
 | 
			
		||||
		static std::set<unsigned> sectors = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
 | 
			
		||||
		return sectors;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	const AmigaDecoderProto& _config;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createAmigaDecoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new AmigaDecoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,23 +1,12 @@
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "encoders/encoders.h"
 | 
			
		||||
#include "amiga.h"
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "sectorset.h"
 | 
			
		||||
#include "writer.h"
 | 
			
		||||
 | 
			
		||||
FlagGroup amigaEncoderFlags;
 | 
			
		||||
 | 
			
		||||
static DoubleFlag clockRateUs(
 | 
			
		||||
	{ "--clock-rate" },
 | 
			
		||||
	"Encoded data clock rate (microseconds).",
 | 
			
		||||
	2.00);
 | 
			
		||||
 | 
			
		||||
static DoubleFlag postIndexGapMs(
 | 
			
		||||
	{ "--post-index-gap" },
 | 
			
		||||
	"Post-index gap before first sector header (milliseconds).",
 | 
			
		||||
	0.5);
 | 
			
		||||
#include "image.h"
 | 
			
		||||
#include "arch/amiga/amiga.pb.h"
 | 
			
		||||
#include "lib/encoders/encoders.pb.h"
 | 
			
		||||
 | 
			
		||||
static bool lastBit;
 | 
			
		||||
 | 
			
		||||
@@ -33,13 +22,14 @@ static void write_bits(std::vector<bool>& bits, unsigned& cursor, const std::vec
 | 
			
		||||
	for (bool bit : src)
 | 
			
		||||
	{
 | 
			
		||||
		if (cursor < bits.size())
 | 
			
		||||
			bits[cursor++] = bit;
 | 
			
		||||
			lastBit = bits[cursor++] = bit;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_t data, int width)
 | 
			
		||||
{
 | 
			
		||||
	cursor += width;
 | 
			
		||||
	lastBit = data & 1;
 | 
			
		||||
	for (int i=0; i<width; i++)
 | 
			
		||||
	{
 | 
			
		||||
		unsigned pos = cursor - i - 1;
 | 
			
		||||
@@ -49,31 +39,44 @@ static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_t data,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_interleaved_bytes(std::vector<bool>& bits, unsigned& cursor, const Bytes& bytes)
 | 
			
		||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, const Bytes& bytes)
 | 
			
		||||
{
 | 
			
		||||
	assert(!(bytes.size() & 3));
 | 
			
		||||
	Bytes interleaved = amigaInterleave(bytes);
 | 
			
		||||
	encodeMfm(bits, cursor, interleaved, lastBit);
 | 
			
		||||
	ByteReader br(bytes);
 | 
			
		||||
	BitReader bitr(br);
 | 
			
		||||
 | 
			
		||||
	while (!bitr.eof())
 | 
			
		||||
	{
 | 
			
		||||
		if (cursor < bits.size())
 | 
			
		||||
			bits[cursor++] = bitr.get();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_interleaved_bytes(std::vector<bool>& bits, unsigned& cursor, uint32_t data)
 | 
			
		||||
{
 | 
			
		||||
	Bytes b(4);
 | 
			
		||||
	ByteWriter bw(b);
 | 
			
		||||
	bw.write_be32(data);
 | 
			
		||||
	write_interleaved_bytes(bits, cursor, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector)
 | 
			
		||||
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const std::shared_ptr<Sector>& sector)
 | 
			
		||||
{
 | 
			
		||||
	if ((sector->data.size() != 512) && (sector->data.size() != 528))
 | 
			
		||||
		Error() << "unsupported sector size --- you must pick 512 or 528";
 | 
			
		||||
 | 
			
		||||
	uint32_t checksum = 0;
 | 
			
		||||
 | 
			
		||||
	auto write_interleaved_bytes = [&](const Bytes& bytes)
 | 
			
		||||
	{
 | 
			
		||||
		Bytes interleaved = amigaInterleave(bytes);
 | 
			
		||||
		Bytes mfm = encodeMfm(interleaved, lastBit);
 | 
			
		||||
		checksum ^= amigaChecksum(mfm);
 | 
			
		||||
		checksum &= 0x55555555;
 | 
			
		||||
		write_bits(bits, cursor, mfm);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	auto write_interleaved_word = [&](uint32_t word)
 | 
			
		||||
	{
 | 
			
		||||
		Bytes b(4);
 | 
			
		||||
		b.writer().write_be32(word);
 | 
			
		||||
		write_interleaved_bytes(b);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
    write_bits(bits, cursor, AMIGA_SECTOR_RECORD, 6*8);
 | 
			
		||||
 | 
			
		||||
	std::vector<bool> headerBits(20*16);
 | 
			
		||||
	unsigned headerCursor = 0;
 | 
			
		||||
 | 
			
		||||
	checksum = 0;
 | 
			
		||||
	Bytes header = 
 | 
			
		||||
		{
 | 
			
		||||
			0xff, /* Amiga 1.0 format byte */
 | 
			
		||||
@@ -81,49 +84,79 @@ static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector
 | 
			
		||||
			(uint8_t) sector->logicalSector,
 | 
			
		||||
			(uint8_t) (AMIGA_SECTORS_PER_TRACK - sector->logicalSector)
 | 
			
		||||
		};
 | 
			
		||||
	write_interleaved_bytes(headerBits, headerCursor, header);
 | 
			
		||||
	write_interleaved_bytes(header);
 | 
			
		||||
	Bytes recoveryInfo(16);
 | 
			
		||||
	if (sector->data.size() == 528)
 | 
			
		||||
		recoveryInfo = sector->data.slice(512, 16);
 | 
			
		||||
	write_interleaved_bytes(headerBits, headerCursor, recoveryInfo);
 | 
			
		||||
	write_interleaved_bytes(recoveryInfo);
 | 
			
		||||
	write_interleaved_word(checksum);
 | 
			
		||||
 | 
			
		||||
	std::vector<bool> dataBits(512*16);
 | 
			
		||||
	unsigned dataCursor = 0;
 | 
			
		||||
	write_interleaved_bytes(dataBits, dataCursor, sector->data);
 | 
			
		||||
 | 
			
		||||
	write_bits(bits, cursor, headerBits);
 | 
			
		||||
	uint32_t headerChecksum = amigaChecksum(toBytes(headerBits));
 | 
			
		||||
	write_interleaved_bytes(bits, cursor, headerChecksum);
 | 
			
		||||
	uint32_t dataChecksum = amigaChecksum(toBytes(dataBits));
 | 
			
		||||
	write_interleaved_bytes(bits, cursor, dataChecksum);
 | 
			
		||||
	write_bits(bits, cursor, dataBits);
 | 
			
		||||
	Bytes data = sector->data.slice(0, 512);
 | 
			
		||||
	write_interleaved_word(amigaChecksum(encodeMfm(amigaInterleave(data), lastBit)));
 | 
			
		||||
	write_interleaved_bytes(data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<Fluxmap> AmigaEncoder::encode(
 | 
			
		||||
	int physicalTrack, int physicalSide, const SectorSet& allSectors)
 | 
			
		||||
class AmigaEncoder : public AbstractEncoder
 | 
			
		||||
{
 | 
			
		||||
	if ((physicalTrack < 0) || (physicalTrack >= AMIGA_TRACKS_PER_DISK))
 | 
			
		||||
		return std::unique_ptr<Fluxmap>();
 | 
			
		||||
public:
 | 
			
		||||
	AmigaEncoder(const EncoderProto& config):
 | 
			
		||||
		AbstractEncoder(config),
 | 
			
		||||
		_config(config.amiga()) {}
 | 
			
		||||
 | 
			
		||||
	int bitsPerRevolution = 200000.0 / clockRateUs;
 | 
			
		||||
	std::vector<bool> bits(bitsPerRevolution);
 | 
			
		||||
	unsigned cursor = 0;
 | 
			
		||||
 | 
			
		||||
    fillBitmapTo(bits, cursor, postIndexGapMs * 1000 / clockRateUs, { true, false });
 | 
			
		||||
	lastBit = false;
 | 
			
		||||
 | 
			
		||||
	for (int sectorId=0; sectorId<AMIGA_SECTORS_PER_TRACK; sectorId++)
 | 
			
		||||
public:
 | 
			
		||||
	std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId);
 | 
			
		||||
		write_sector(bits, cursor, sectorData);
 | 
			
		||||
    }
 | 
			
		||||
		std::vector<std::shared_ptr<Sector>> sectors;
 | 
			
		||||
 | 
			
		||||
	if (cursor >= bits.size())
 | 
			
		||||
		Error() << "track data overrun";
 | 
			
		||||
	fillBitmapTo(bits, cursor, bits.size(), { true, false });
 | 
			
		||||
		if ((physicalTrack >= 0) && (physicalTrack < AMIGA_TRACKS_PER_DISK))
 | 
			
		||||
		{
 | 
			
		||||
			for (int sectorId=0; sectorId<AMIGA_SECTORS_PER_TRACK; sectorId++)
 | 
			
		||||
			{
 | 
			
		||||
				const auto& sector = image.get(physicalTrack, physicalSide, sectorId);
 | 
			
		||||
				if (sector)
 | 
			
		||||
					sectors.push_back(sector);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
 | 
			
		||||
	fluxmap->appendBits(bits, clockRateUs*1e3);
 | 
			
		||||
	return fluxmap;
 | 
			
		||||
		return sectors;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide,
 | 
			
		||||
			const std::vector<std::shared_ptr<Sector>>& sectors, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		if ((physicalTrack < 0) || (physicalTrack >= AMIGA_TRACKS_PER_DISK))
 | 
			
		||||
			return std::unique_ptr<Fluxmap>();
 | 
			
		||||
 | 
			
		||||
		int bitsPerRevolution = 200000.0 / _config.clock_rate_us();
 | 
			
		||||
		std::vector<bool> bits(bitsPerRevolution);
 | 
			
		||||
		unsigned cursor = 0;
 | 
			
		||||
 | 
			
		||||
		fillBitmapTo(bits, cursor, _config.post_index_gap_ms() * 1000 / _config.clock_rate_us(), { true, false });
 | 
			
		||||
		lastBit = false;
 | 
			
		||||
 | 
			
		||||
		for (int sectorId=0; sectorId<AMIGA_SECTORS_PER_TRACK; sectorId++)
 | 
			
		||||
		{
 | 
			
		||||
			const auto& sectorData = image.get(physicalTrack, physicalSide, sectorId);
 | 
			
		||||
			if (sectorData)
 | 
			
		||||
				write_sector(bits, cursor, sectorData);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cursor >= bits.size())
 | 
			
		||||
			Error() << "track data overrun";
 | 
			
		||||
		fillBitmapTo(bits, cursor, bits.size(), { true, false });
 | 
			
		||||
 | 
			
		||||
		std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
 | 
			
		||||
		fluxmap->appendBits(bits, _config.clock_rate_us()*1e3);
 | 
			
		||||
		return fluxmap;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	const AmigaEncoderProto& _config;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractEncoder> createAmigaEncoder(const EncoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractEncoder>(new AmigaEncoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,19 +7,7 @@
 | 
			
		||||
#define APPLE2_SECTOR_LENGTH   256
 | 
			
		||||
#define APPLE2_ENCODED_SECTOR_LENGTH 342
 | 
			
		||||
 | 
			
		||||
class Sector;
 | 
			
		||||
class Fluxmap;
 | 
			
		||||
 | 
			
		||||
class Apple2Decoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~Apple2Decoder() {}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord();
 | 
			
		||||
    void decodeSectorRecord();
 | 
			
		||||
    void decodeDataRecord();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createApple2Decoder(const DecoderProto& config);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								arch/apple2/apple2.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/apple2/apple2.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
message Apple2DecoderProto {}
 | 
			
		||||
 | 
			
		||||
@@ -2,7 +2,6 @@
 | 
			
		||||
#include "fluxmap.h"
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "protocol.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "apple2.h"
 | 
			
		||||
@@ -25,7 +24,7 @@ static int decode_data_gcr(uint8_t gcr)
 | 
			
		||||
		#undef GCR_ENTRY
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is extremely inspired by the MESS implementation, written by Nathan Woods
 | 
			
		||||
 * and R. Belmont: https://github.com/mamedev/mame/blob/7914a6083a3b3a8c243ae6c3b8cb50b023f21e0e/src/lib/formats/ap2_dsk.cpp
 | 
			
		||||
@@ -60,53 +59,68 @@ static Bytes decode_crazy_data(const uint8_t* inp, Sector::Status& status)
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t combine(uint16_t word)
 | 
			
		||||
static uint8_t combine(uint16_t word)
 | 
			
		||||
{
 | 
			
		||||
    return word & (word >> 7);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AbstractDecoder::RecordType Apple2Decoder::advanceToNextRecord()
 | 
			
		||||
class Apple2Decoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
	const FluxMatcher* matcher = nullptr;
 | 
			
		||||
	_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
	if (matcher == &SECTOR_RECORD_PATTERN)
 | 
			
		||||
		return RecordType::SECTOR_RECORD;
 | 
			
		||||
	if (matcher == &DATA_RECORD_PATTERN)
 | 
			
		||||
		return RecordType::DATA_RECORD;
 | 
			
		||||
	return RecordType::UNKNOWN_RECORD;
 | 
			
		||||
public:
 | 
			
		||||
	Apple2Decoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord()
 | 
			
		||||
	{
 | 
			
		||||
		const FluxMatcher* matcher = nullptr;
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
		if (matcher == &SECTOR_RECORD_PATTERN)
 | 
			
		||||
			return RecordType::SECTOR_RECORD;
 | 
			
		||||
		if (matcher == &DATA_RECORD_PATTERN)
 | 
			
		||||
			return RecordType::DATA_RECORD;
 | 
			
		||||
		return RecordType::UNKNOWN_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeSectorRecord()
 | 
			
		||||
	{
 | 
			
		||||
		/* Skip ID (as we know it's a APPLE2_SECTOR_RECORD). */
 | 
			
		||||
		readRawBits(24);
 | 
			
		||||
 | 
			
		||||
		/* Read header. */
 | 
			
		||||
 | 
			
		||||
		auto header = toBytes(readRawBits(8*8)).slice(0, 8);
 | 
			
		||||
		ByteReader br(header);
 | 
			
		||||
 | 
			
		||||
		uint8_t volume = combine(br.read_be16());
 | 
			
		||||
		_sector->logicalTrack = combine(br.read_be16());
 | 
			
		||||
		_sector->logicalSector = combine(br.read_be16());
 | 
			
		||||
		uint8_t checksum = combine(br.read_be16());
 | 
			
		||||
		if (checksum == (volume ^ _sector->logicalTrack ^ _sector->logicalSector))
 | 
			
		||||
			_sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeDataRecord()
 | 
			
		||||
	{
 | 
			
		||||
		/* Check ID. */
 | 
			
		||||
 | 
			
		||||
		Bytes bytes = toBytes(readRawBits(3*8)).slice(0, 3);
 | 
			
		||||
		if (bytes.reader().read_be24() != APPLE2_DATA_RECORD)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		/* Read and decode data. */
 | 
			
		||||
 | 
			
		||||
		unsigned recordLength = APPLE2_ENCODED_SECTOR_LENGTH + 2;
 | 
			
		||||
		bytes = toBytes(readRawBits(recordLength*8)).slice(0, recordLength);
 | 
			
		||||
 | 
			
		||||
		_sector->status = Sector::BAD_CHECKSUM;
 | 
			
		||||
		_sector->data = decode_crazy_data(&bytes[0], _sector->status);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createApple2Decoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new Apple2Decoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Apple2Decoder::decodeSectorRecord()
 | 
			
		||||
{
 | 
			
		||||
    /* Skip ID (as we know it's a APPLE2_SECTOR_RECORD). */
 | 
			
		||||
    readRawBits(24);
 | 
			
		||||
 | 
			
		||||
    /* Read header. */
 | 
			
		||||
 | 
			
		||||
    auto header = toBytes(readRawBits(8*8)).slice(0, 8);
 | 
			
		||||
    ByteReader br(header);
 | 
			
		||||
 | 
			
		||||
    uint8_t volume = combine(br.read_be16());
 | 
			
		||||
    _sector->logicalTrack = combine(br.read_be16());
 | 
			
		||||
    _sector->logicalSector = combine(br.read_be16());
 | 
			
		||||
    uint8_t checksum = combine(br.read_be16());
 | 
			
		||||
    if (checksum == (volume ^ _sector->logicalTrack ^ _sector->logicalSector))
 | 
			
		||||
        _sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Apple2Decoder::decodeDataRecord()
 | 
			
		||||
{
 | 
			
		||||
    /* Check ID. */
 | 
			
		||||
 | 
			
		||||
    Bytes bytes = toBytes(readRawBits(3*8)).slice(0, 3);
 | 
			
		||||
    if (bytes.reader().read_be24() != APPLE2_DATA_RECORD)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    /* Read and decode data. */
 | 
			
		||||
 | 
			
		||||
    unsigned recordLength = APPLE2_ENCODED_SECTOR_LENGTH + 2;
 | 
			
		||||
    bytes = toBytes(readRawBits(recordLength*8)).slice(0, recordLength);
 | 
			
		||||
 | 
			
		||||
    _sector->status = Sector::BAD_CHECKSUM;
 | 
			
		||||
    _sector->data = decode_crazy_data(&bytes[0], _sector->status);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,36 +13,7 @@
 | 
			
		||||
#define BROTHER_TRACKS_PER_120KB_DISK    39
 | 
			
		||||
#define BROTHER_SECTORS_PER_TRACK        12
 | 
			
		||||
 | 
			
		||||
class Sector;
 | 
			
		||||
class Fluxmap;
 | 
			
		||||
 | 
			
		||||
class BrotherDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~BrotherDecoder() {}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord();
 | 
			
		||||
    void decodeSectorRecord();
 | 
			
		||||
    void decodeDataRecord();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class BrotherEncoder : public AbstractEncoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	BrotherEncoder(int format, int bias):
 | 
			
		||||
		_format(format),
 | 
			
		||||
		_bias(bias)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	virtual ~BrotherEncoder() {}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	int _format;
 | 
			
		||||
	int _bias;
 | 
			
		||||
public:
 | 
			
		||||
    std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern FlagGroup brotherEncoderFlags;
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createBrotherDecoder(const DecoderProto& config);
 | 
			
		||||
extern std::unique_ptr<AbstractEncoder> createBrotherEncoder(const EncoderProto& config);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								arch/brother/brother.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								arch/brother/brother.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
message BrotherDecoderProto {}
 | 
			
		||||
 | 
			
		||||
enum BrotherFormat {
 | 
			
		||||
	BROTHER240 = 0;
 | 
			
		||||
	BROTHER120 = 1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
message BrotherEncoderProto {
 | 
			
		||||
	optional double clock_rate_us = 1 [default = 3.83];
 | 
			
		||||
	optional double post_index_gap_ms = 2 [default = 1.0];
 | 
			
		||||
	optional double sector_spacing_ms = 3 [default = 16.2];
 | 
			
		||||
	optional double post_header_spacing_ms = 4 [default = 0.69];
 | 
			
		||||
	optional string sector_skew = 5 [default = "05a3816b4927"];
 | 
			
		||||
 | 
			
		||||
	optional BrotherFormat format = 6 [default = BROTHER240];
 | 
			
		||||
	optional int32 bias = 7 [default = 0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1,28 +0,0 @@
 | 
			
		||||
#ifndef BROTHER_H
 | 
			
		||||
#define BROTHER_H
 | 
			
		||||
 | 
			
		||||
/* Brother word processor format (or at least, one of them) */
 | 
			
		||||
 | 
			
		||||
#define BROTHER_SECTOR_RECORD 0xFFFFFD57
 | 
			
		||||
#define BROTHER_DATA_RECORD   0xFFFFFDDB
 | 
			
		||||
#define BROTHER_DATA_RECORD_PAYLOAD  256
 | 
			
		||||
#define BROTHER_DATA_RECORD_CHECKSUM 3
 | 
			
		||||
 | 
			
		||||
class Sector;
 | 
			
		||||
class Fluxmap;
 | 
			
		||||
 | 
			
		||||
class BrotherDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~BrotherDecoder() {}
 | 
			
		||||
 | 
			
		||||
    SectorVector decodeToSectors(const RawRecordVector& rawRecords);
 | 
			
		||||
    int recordMatcher(uint64_t fifo) const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern void writeBrotherSectorHeader(std::vector<bool>& bits, unsigned& cursor,
 | 
			
		||||
		int track, int sector);
 | 
			
		||||
extern void writeBrotherSectorData(std::vector<bool>& bits, unsigned& cursor,
 | 
			
		||||
		const std::vector<uint8_t>& data);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -4,7 +4,6 @@
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "encoders/encoders.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "brother.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "bytes.h"
 | 
			
		||||
@@ -40,7 +39,7 @@ static int decode_data_gcr(uint8_t gcr)
 | 
			
		||||
		#undef GCR_ENTRY
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int decode_header_gcr(uint16_t word)
 | 
			
		||||
{
 | 
			
		||||
@@ -52,58 +51,73 @@ static int decode_header_gcr(uint16_t word)
 | 
			
		||||
		#undef GCR_ENTRY
 | 
			
		||||
	}                       
 | 
			
		||||
	return -1;             
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class BrotherDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    BrotherDecoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord()
 | 
			
		||||
	{
 | 
			
		||||
		const FluxMatcher* matcher = nullptr;
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
		if (matcher == &SECTOR_RECORD_PATTERN)
 | 
			
		||||
			return RecordType::SECTOR_RECORD;
 | 
			
		||||
		if (matcher == &DATA_RECORD_PATTERN)
 | 
			
		||||
			return RecordType::DATA_RECORD;
 | 
			
		||||
		return RecordType::UNKNOWN_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeSectorRecord()
 | 
			
		||||
	{
 | 
			
		||||
		readRawBits(32);
 | 
			
		||||
		const auto& rawbits = readRawBits(32);
 | 
			
		||||
		const auto& bytes = toBytes(rawbits).slice(0, 4);
 | 
			
		||||
 | 
			
		||||
		ByteReader br(bytes);
 | 
			
		||||
		_sector->logicalTrack = decode_header_gcr(br.read_be16());
 | 
			
		||||
		_sector->logicalSector = decode_header_gcr(br.read_be16());
 | 
			
		||||
 | 
			
		||||
		/* Sanity check the values read; there's no header checksum and
 | 
			
		||||
			* occasionally we get garbage due to bit errors. */
 | 
			
		||||
		if (_sector->logicalSector > 11)
 | 
			
		||||
			return;
 | 
			
		||||
		if (_sector->logicalTrack > 79)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		_sector->status = Sector::DATA_MISSING;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
    void decodeDataRecord()
 | 
			
		||||
	{
 | 
			
		||||
		readRawBits(32);
 | 
			
		||||
 | 
			
		||||
		const auto& rawbits = readRawBits(BROTHER_DATA_RECORD_ENCODED_SIZE*8);
 | 
			
		||||
		const auto& rawbytes = toBytes(rawbits).slice(0, BROTHER_DATA_RECORD_ENCODED_SIZE);
 | 
			
		||||
 | 
			
		||||
		Bytes bytes;
 | 
			
		||||
		ByteWriter bw(bytes);
 | 
			
		||||
		BitWriter bitw(bw);
 | 
			
		||||
		for (uint8_t b : rawbytes)
 | 
			
		||||
		{
 | 
			
		||||
			uint32_t nibble = decode_data_gcr(b);
 | 
			
		||||
			bitw.push(nibble, 5);
 | 
			
		||||
		}
 | 
			
		||||
		bitw.flush();
 | 
			
		||||
 | 
			
		||||
		_sector->data = bytes.slice(0, BROTHER_DATA_RECORD_PAYLOAD);
 | 
			
		||||
		uint32_t realCrc = crcbrother(_sector->data);
 | 
			
		||||
		uint32_t wantCrc = bytes.reader().seek(BROTHER_DATA_RECORD_PAYLOAD).read_be24();
 | 
			
		||||
		_sector->status = (realCrc == wantCrc) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
AbstractDecoder::RecordType BrotherDecoder::advanceToNextRecord()
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createBrotherDecoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	const FluxMatcher* matcher = nullptr;
 | 
			
		||||
	_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
	if (matcher == &SECTOR_RECORD_PATTERN)
 | 
			
		||||
		return RecordType::SECTOR_RECORD;
 | 
			
		||||
	if (matcher == &DATA_RECORD_PATTERN)
 | 
			
		||||
		return RecordType::DATA_RECORD;
 | 
			
		||||
	return RecordType::UNKNOWN_RECORD;
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new BrotherDecoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BrotherDecoder::decodeSectorRecord()
 | 
			
		||||
{
 | 
			
		||||
	readRawBits(32);
 | 
			
		||||
	const auto& rawbits = readRawBits(32);
 | 
			
		||||
	const auto& bytes = toBytes(rawbits).slice(0, 4);
 | 
			
		||||
 | 
			
		||||
	ByteReader br(bytes);
 | 
			
		||||
	_sector->logicalTrack = decode_header_gcr(br.read_be16());
 | 
			
		||||
	_sector->logicalSector = decode_header_gcr(br.read_be16());
 | 
			
		||||
 | 
			
		||||
	/* Sanity check the values read; there's no header checksum and
 | 
			
		||||
		* occasionally we get garbage due to bit errors. */
 | 
			
		||||
	if (_sector->logicalSector > 11)
 | 
			
		||||
		return;
 | 
			
		||||
	if (_sector->logicalTrack > 79)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	_sector->status = Sector::DATA_MISSING;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BrotherDecoder::decodeDataRecord()
 | 
			
		||||
{
 | 
			
		||||
	readRawBits(32);
 | 
			
		||||
 | 
			
		||||
	const auto& rawbits = readRawBits(BROTHER_DATA_RECORD_ENCODED_SIZE*8);
 | 
			
		||||
	const auto& rawbytes = toBytes(rawbits).slice(0, BROTHER_DATA_RECORD_ENCODED_SIZE);
 | 
			
		||||
 | 
			
		||||
	Bytes bytes;
 | 
			
		||||
	ByteWriter bw(bytes);
 | 
			
		||||
	BitWriter bitw(bw);
 | 
			
		||||
	for (uint8_t b : rawbytes)
 | 
			
		||||
	{
 | 
			
		||||
		uint32_t nibble = decode_data_gcr(b);
 | 
			
		||||
		bitw.push(nibble, 5);
 | 
			
		||||
	}
 | 
			
		||||
	bitw.flush();
 | 
			
		||||
 | 
			
		||||
	_sector->data = bytes.slice(0, BROTHER_DATA_RECORD_PAYLOAD);
 | 
			
		||||
	uint32_t realCrc = crcbrother(_sector->data);
 | 
			
		||||
	uint32_t wantCrc = bytes.reader().seek(BROTHER_DATA_RECORD_PAYLOAD).read_be24();
 | 
			
		||||
	_sector->status = (realCrc == wantCrc) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,38 +1,12 @@
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "encoders/encoders.h"
 | 
			
		||||
#include "brother.h"
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "sectorset.h"
 | 
			
		||||
#include "writer.h"
 | 
			
		||||
 | 
			
		||||
FlagGroup brotherEncoderFlags;
 | 
			
		||||
 | 
			
		||||
static DoubleFlag clockRateUs(
 | 
			
		||||
	{ "--clock-rate" },
 | 
			
		||||
	"Encoded data clock rate (microseconds).",
 | 
			
		||||
	3.83);
 | 
			
		||||
 | 
			
		||||
static DoubleFlag postIndexGapMs(
 | 
			
		||||
	{ "--post-index-gap" },
 | 
			
		||||
	"Post-index gap before first sector header (milliseconds).",
 | 
			
		||||
	1.0);
 | 
			
		||||
 | 
			
		||||
static DoubleFlag sectorSpacingMs(
 | 
			
		||||
	{ "--sector-spacing" },
 | 
			
		||||
	"Time between successive sector headers (milliseconds).",
 | 
			
		||||
	16.2);
 | 
			
		||||
 | 
			
		||||
static DoubleFlag postHeaderSpacingMs(
 | 
			
		||||
	{ "--post-header-spacing" },
 | 
			
		||||
	"Time between a sector's header and data records (milliseconds).",
 | 
			
		||||
	0.69);
 | 
			
		||||
 | 
			
		||||
static StringFlag sectorSkew(
 | 
			
		||||
	{ "--sector-skew" },
 | 
			
		||||
	"Order in which to write sectors.",
 | 
			
		||||
	"05a3816b4927");
 | 
			
		||||
#include "image.h"
 | 
			
		||||
#include "arch/brother/brother.pb.h"
 | 
			
		||||
#include "lib/encoders/encoders.pb.h"
 | 
			
		||||
 | 
			
		||||
static int encode_header_gcr(uint16_t word)
 | 
			
		||||
{
 | 
			
		||||
@@ -44,7 +18,7 @@ static int encode_header_gcr(uint16_t word)
 | 
			
		||||
		#undef GCR_ENTRY
 | 
			
		||||
	}                       
 | 
			
		||||
	return -1;             
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int encode_data_gcr(uint8_t data)
 | 
			
		||||
{
 | 
			
		||||
@@ -56,7 +30,7 @@ static int encode_data_gcr(uint8_t data)
 | 
			
		||||
		#undef GCR_ENTRY
 | 
			
		||||
	}                       
 | 
			
		||||
	return -1;             
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint32_t data, int width)
 | 
			
		||||
{
 | 
			
		||||
@@ -126,58 +100,113 @@ static int charToInt(char c)
 | 
			
		||||
	return 10 + tolower(c) - 'a';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<Fluxmap> BrotherEncoder::encode(
 | 
			
		||||
	int physicalTrack, int physicalSide, const SectorSet& allSectors)
 | 
			
		||||
class BrotherEncoder : public AbstractEncoder
 | 
			
		||||
{
 | 
			
		||||
	int logicalTrack;
 | 
			
		||||
	if (physicalSide != 0)
 | 
			
		||||
		return std::unique_ptr<Fluxmap>();
 | 
			
		||||
	physicalTrack -= _bias;
 | 
			
		||||
	switch (_format)
 | 
			
		||||
	{
 | 
			
		||||
		case 120:
 | 
			
		||||
			if ((physicalTrack < 0) || (physicalTrack >= (BROTHER_TRACKS_PER_120KB_DISK*2))
 | 
			
		||||
					|| (physicalTrack & 1))
 | 
			
		||||
				return std::unique_ptr<Fluxmap>();
 | 
			
		||||
			logicalTrack = physicalTrack/2;
 | 
			
		||||
			break;
 | 
			
		||||
public:
 | 
			
		||||
	BrotherEncoder(const EncoderProto& config):
 | 
			
		||||
		AbstractEncoder(config),
 | 
			
		||||
		_config(config.brother())
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
		case 240:
 | 
			
		||||
			if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_240KB_DISK))
 | 
			
		||||
				return std::unique_ptr<Fluxmap>();
 | 
			
		||||
			logicalTrack = physicalTrack;
 | 
			
		||||
			break;
 | 
			
		||||
public:
 | 
			
		||||
	std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		std::vector<std::shared_ptr<Sector>> sectors;
 | 
			
		||||
 | 
			
		||||
		int logicalTrack;
 | 
			
		||||
		if (physicalSide != 0)
 | 
			
		||||
			return sectors;
 | 
			
		||||
		physicalTrack -= _config.bias();
 | 
			
		||||
		switch (_config.format())
 | 
			
		||||
		{
 | 
			
		||||
			case BROTHER120:
 | 
			
		||||
				if ((physicalTrack < 0) || (physicalTrack >= (BROTHER_TRACKS_PER_120KB_DISK*2))
 | 
			
		||||
						|| (physicalTrack & 1))
 | 
			
		||||
					return sectors;
 | 
			
		||||
				logicalTrack = physicalTrack/2;
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case BROTHER240:
 | 
			
		||||
				if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_240KB_DISK))
 | 
			
		||||
					return sectors;
 | 
			
		||||
				logicalTrack = physicalTrack;
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        for (int sectorId=0; sectorId<BROTHER_SECTORS_PER_TRACK; sectorId++)
 | 
			
		||||
        {
 | 
			
		||||
            const auto& sector = image.get(logicalTrack, 0, sectorId);
 | 
			
		||||
            if (sector)
 | 
			
		||||
                sectors.push_back(sector);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return sectors;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int bitsPerRevolution = 200000.0 / clockRateUs;
 | 
			
		||||
	const std::string& skew = sectorSkew.get();
 | 
			
		||||
	std::vector<bool> bits(bitsPerRevolution);
 | 
			
		||||
	unsigned cursor = 0;
 | 
			
		||||
 | 
			
		||||
	for (int sectorCount=0; sectorCount<BROTHER_SECTORS_PER_TRACK; sectorCount++)
 | 
			
		||||
    std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide,
 | 
			
		||||
			const std::vector<std::shared_ptr<Sector>>& sectors, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		int sectorId = charToInt(skew.at(sectorCount));
 | 
			
		||||
		double headerMs = postIndexGapMs + sectorCount*sectorSpacingMs;
 | 
			
		||||
		unsigned headerCursor = headerMs*1e3 / clockRateUs;
 | 
			
		||||
		double dataMs = headerMs + postHeaderSpacingMs;
 | 
			
		||||
		unsigned dataCursor = dataMs*1e3 / clockRateUs;
 | 
			
		||||
		int logicalTrack;
 | 
			
		||||
		if (physicalSide != 0)
 | 
			
		||||
			return std::unique_ptr<Fluxmap>();
 | 
			
		||||
		physicalTrack -= _config.bias();
 | 
			
		||||
		switch (_config.format())
 | 
			
		||||
		{
 | 
			
		||||
			case BROTHER120:
 | 
			
		||||
				if ((physicalTrack < 0) || (physicalTrack >= (BROTHER_TRACKS_PER_120KB_DISK*2))
 | 
			
		||||
						|| (physicalTrack & 1))
 | 
			
		||||
					return std::unique_ptr<Fluxmap>();
 | 
			
		||||
				logicalTrack = physicalTrack/2;
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
		const auto& sectorData = allSectors.get(logicalTrack, 0, sectorId);
 | 
			
		||||
			case BROTHER240:
 | 
			
		||||
				if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_240KB_DISK))
 | 
			
		||||
					return std::unique_ptr<Fluxmap>();
 | 
			
		||||
				logicalTrack = physicalTrack;
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		fillBitmapTo(bits, cursor, headerCursor, { true, false });
 | 
			
		||||
		write_sector_header(bits, cursor, logicalTrack, sectorId);
 | 
			
		||||
		fillBitmapTo(bits, cursor, dataCursor, { true, false });
 | 
			
		||||
		write_sector_data(bits, cursor, sectorData->data);
 | 
			
		||||
		int bitsPerRevolution = 200000.0 / _config.clock_rate_us();
 | 
			
		||||
		const std::string& skew = _config.sector_skew();
 | 
			
		||||
		std::vector<bool> bits(bitsPerRevolution);
 | 
			
		||||
		unsigned cursor = 0;
 | 
			
		||||
 | 
			
		||||
		for (int sectorCount=0; sectorCount<BROTHER_SECTORS_PER_TRACK; sectorCount++)
 | 
			
		||||
		{
 | 
			
		||||
			int sectorId = charToInt(skew.at(sectorCount));
 | 
			
		||||
			double headerMs = _config.post_index_gap_ms() + sectorCount*_config.sector_spacing_ms();
 | 
			
		||||
			unsigned headerCursor = headerMs*1e3 / _config.clock_rate_us();
 | 
			
		||||
			double dataMs = headerMs + _config.post_header_spacing_ms();
 | 
			
		||||
			unsigned dataCursor = dataMs*1e3 / _config.clock_rate_us();
 | 
			
		||||
 | 
			
		||||
			const auto& sectorData = image.get(logicalTrack, 0, sectorId);
 | 
			
		||||
 | 
			
		||||
			fillBitmapTo(bits, cursor, headerCursor, { true, false });
 | 
			
		||||
			write_sector_header(bits, cursor, logicalTrack, sectorId);
 | 
			
		||||
			fillBitmapTo(bits, cursor, dataCursor, { true, false });
 | 
			
		||||
			write_sector_data(bits, cursor, sectorData->data);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cursor >= bits.size())
 | 
			
		||||
			Error() << "track data overrun";
 | 
			
		||||
		fillBitmapTo(bits, cursor, bits.size(), { true, false });
 | 
			
		||||
 | 
			
		||||
		// The pre-index gap is not normally reported.
 | 
			
		||||
		// std::cerr << "pre-index gap " << 200.0 - (double)cursor*clockRateUs/1e3 << std::endl;
 | 
			
		||||
		
 | 
			
		||||
		std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
 | 
			
		||||
		fluxmap->appendBits(bits, _config.clock_rate_us()*1e3);
 | 
			
		||||
		return fluxmap;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cursor >= bits.size())
 | 
			
		||||
		Error() << "track data overrun";
 | 
			
		||||
	fillBitmapTo(bits, cursor, bits.size(), { true, false });
 | 
			
		||||
private:
 | 
			
		||||
	const BrotherEncoderProto& _config;
 | 
			
		||||
 | 
			
		||||
	// The pre-index gap is not normally reported.
 | 
			
		||||
	// std::cerr << "pre-index gap " << 200.0 - (double)cursor*clockRateUs/1e3 << std::endl;
 | 
			
		||||
	
 | 
			
		||||
	std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
 | 
			
		||||
	fluxmap->appendBits(bits, clockRateUs*1e3);
 | 
			
		||||
	return fluxmap;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractEncoder> createBrotherEncoder(const EncoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractEncoder>(new BrotherEncoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,33 @@
 | 
			
		||||
#ifndef C64_H
 | 
			
		||||
#define C64_H
 | 
			
		||||
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "encoders/encoders.h"
 | 
			
		||||
 | 
			
		||||
#define C64_SECTOR_RECORD    0xffd49
 | 
			
		||||
#define C64_DATA_RECORD      0xffd57
 | 
			
		||||
#define C64_SECTOR_LENGTH    256
 | 
			
		||||
 | 
			
		||||
class Sector;
 | 
			
		||||
class Fluxmap;
 | 
			
		||||
/* Source: http://www.unusedino.de/ec64/technical/formats/g64.html 
 | 
			
		||||
   1. Header sync       FF FF FF FF FF (40 'on' bits, not GCR)
 | 
			
		||||
   2. Header info       52 54 B5 29 4B 7A 5E 95 55 55 (10 GCR bytes)
 | 
			
		||||
   3. Header gap        55 55 55 55 55 55 55 55 55 (9 bytes, never read)
 | 
			
		||||
   4. Data sync         FF FF FF FF FF (40 'on' bits, not GCR)
 | 
			
		||||
   5. Data block        55...4A (325 GCR bytes)
 | 
			
		||||
   6. Inter-sector gap  55 55 55 55...55 55 (4 to 12 bytes, never read)
 | 
			
		||||
   1. Header sync       (SYNC for the next sector)
 | 
			
		||||
*/
 | 
			
		||||
#define C64_HEADER_DATA_SYNC        0xFF
 | 
			
		||||
#define C64_HEADER_BLOCK_ID         0x08
 | 
			
		||||
#define C64_DATA_BLOCK_ID           0x07
 | 
			
		||||
#define C64_HEADER_GAP              0x55
 | 
			
		||||
#define C64_INTER_SECTOR_GAP        0x55
 | 
			
		||||
#define C64_PADDING                 0x0F
 | 
			
		||||
 | 
			
		||||
class Commodore64Decoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~Commodore64Decoder() {}
 | 
			
		||||
#define C64_TRACKS_PER_DISK         40
 | 
			
		||||
#define C64_BAM_TRACK               17
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord();
 | 
			
		||||
    void decodeSectorRecord();
 | 
			
		||||
    void decodeDataRecord();
 | 
			
		||||
};
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createCommodore64Decoder(const DecoderProto& config);
 | 
			
		||||
extern std::unique_ptr<AbstractEncoder> createCommodore64Encoder(const EncoderProto& config);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								arch/c64/c64.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								arch/c64/c64.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
import "lib/common.proto";
 | 
			
		||||
 | 
			
		||||
message Commodore64DecoderProto {}
 | 
			
		||||
 | 
			
		||||
message Commodore64EncoderProto {
 | 
			
		||||
	optional double post_index_gap_us = 1 [default=0.0,
 | 
			
		||||
		(help) = "post-index gap before first sector header."];
 | 
			
		||||
	optional double clock_compensation_factor = 2 [default=1.0,
 | 
			
		||||
		(help) = "scale the output clock by this much."];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2,7 +2,6 @@
 | 
			
		||||
#include "fluxmap.h"
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "protocol.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "c64.h"
 | 
			
		||||
@@ -26,7 +25,7 @@ static int decode_data_gcr(uint8_t gcr)
 | 
			
		||||
		#undef GCR_ENTRY
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Bytes decode(const std::vector<bool>& bits)
 | 
			
		||||
{
 | 
			
		||||
@@ -52,41 +51,56 @@ static Bytes decode(const std::vector<bool>& bits)
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AbstractDecoder::RecordType Commodore64Decoder::advanceToNextRecord()
 | 
			
		||||
class Commodore64Decoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
	const FluxMatcher* matcher = nullptr;
 | 
			
		||||
	_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
	if (matcher == &SECTOR_RECORD_PATTERN)
 | 
			
		||||
		return RecordType::SECTOR_RECORD;
 | 
			
		||||
	if (matcher == &DATA_RECORD_PATTERN)
 | 
			
		||||
		return RecordType::DATA_RECORD;
 | 
			
		||||
	return RecordType::UNKNOWN_RECORD;
 | 
			
		||||
public:
 | 
			
		||||
	Commodore64Decoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord()
 | 
			
		||||
	{
 | 
			
		||||
		const FluxMatcher* matcher = nullptr;
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
		if (matcher == &SECTOR_RECORD_PATTERN)
 | 
			
		||||
			return RecordType::SECTOR_RECORD;
 | 
			
		||||
		if (matcher == &DATA_RECORD_PATTERN)
 | 
			
		||||
			return RecordType::DATA_RECORD;
 | 
			
		||||
		return RecordType::UNKNOWN_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeSectorRecord()
 | 
			
		||||
	{
 | 
			
		||||
		readRawBits(20);
 | 
			
		||||
 | 
			
		||||
		const auto& bits = readRawBits(5*10);
 | 
			
		||||
		const auto& bytes = decode(bits).slice(0, 5);
 | 
			
		||||
 | 
			
		||||
		uint8_t checksum = bytes[0];
 | 
			
		||||
		_sector->logicalSector = bytes[1];
 | 
			
		||||
		_sector->logicalSide = 0;
 | 
			
		||||
		_sector->logicalTrack = bytes[2] - 1;
 | 
			
		||||
		if (checksum == xorBytes(bytes.slice(1, 4)))
 | 
			
		||||
			_sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeDataRecord()
 | 
			
		||||
	{
 | 
			
		||||
		readRawBits(20);
 | 
			
		||||
 | 
			
		||||
		const auto& bits = readRawBits(259*10);
 | 
			
		||||
		const auto& bytes = decode(bits).slice(0, 259);
 | 
			
		||||
 | 
			
		||||
		_sector->data = bytes.slice(0, C64_SECTOR_LENGTH);
 | 
			
		||||
		uint8_t gotChecksum = xorBytes(_sector->data);
 | 
			
		||||
		uint8_t wantChecksum = bytes[256];
 | 
			
		||||
		_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createCommodore64Decoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new Commodore64Decoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Commodore64Decoder::decodeSectorRecord()
 | 
			
		||||
{
 | 
			
		||||
    readRawBits(20);
 | 
			
		||||
 | 
			
		||||
    const auto& bits = readRawBits(5*10);
 | 
			
		||||
    const auto& bytes = decode(bits).slice(0, 5);
 | 
			
		||||
 | 
			
		||||
    uint8_t checksum = bytes[0];
 | 
			
		||||
    _sector->logicalSector = bytes[1];
 | 
			
		||||
    _sector->logicalSide = 0;
 | 
			
		||||
    _sector->logicalTrack = bytes[2] - 1;
 | 
			
		||||
    if (checksum == xorBytes(bytes.slice(1, 4)))
 | 
			
		||||
        _sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Commodore64Decoder::decodeDataRecord()
 | 
			
		||||
{
 | 
			
		||||
    readRawBits(20);
 | 
			
		||||
 | 
			
		||||
    const auto& bits = readRawBits(259*10);
 | 
			
		||||
    const auto& bytes = decode(bits).slice(0, 259);
 | 
			
		||||
 | 
			
		||||
    _sector->data = bytes.slice(0, C64_SECTOR_LENGTH);
 | 
			
		||||
    uint8_t gotChecksum = xorBytes(_sector->data);
 | 
			
		||||
    uint8_t wantChecksum = bytes[256];
 | 
			
		||||
    _sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										381
									
								
								arch/c64/encoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										381
									
								
								arch/c64/encoder.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,381 @@
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "encoders/encoders.h"
 | 
			
		||||
#include "c64.h"
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "writer.h"
 | 
			
		||||
#include "image.h"
 | 
			
		||||
#include "fmt/format.h"
 | 
			
		||||
#include "arch/c64/c64.pb.h"
 | 
			
		||||
#include "lib/encoders/encoders.pb.h"
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include "bytes.h"
 | 
			
		||||
 | 
			
		||||
static bool lastBit;
 | 
			
		||||
 | 
			
		||||
static double clockRateUsForTrack(unsigned track)
 | 
			
		||||
{
 | 
			
		||||
    /*
 | 
			
		||||
     * Track   # Sectors/Track Speed Zone  bits/rotation       
 | 
			
		||||
     * 1 – 17          21          3       61,538.4
 | 
			
		||||
     * 18 – 24         19          2       57,142.8
 | 
			
		||||
     * 25 – 30         18          1       53,333.4
 | 
			
		||||
     * 31 – 35         17          0       50,000.0
 | 
			
		||||
    */
 | 
			
		||||
    if (track < 17)
 | 
			
		||||
        return 200000.0/61538.4;
 | 
			
		||||
    if (track < 24)
 | 
			
		||||
        return 200000.0/57142.8;
 | 
			
		||||
    if (track < 30)
 | 
			
		||||
        return 200000.0/53333.4;
 | 
			
		||||
    return 200000.0/50000.0;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned sectorsForTrack(unsigned track)
 | 
			
		||||
{
 | 
			
		||||
    /*
 | 
			
		||||
     * Track   Sectors/track   # Sectors   Storage in Bytes
 | 
			
		||||
     *   -----   -------------   ---------   ----------------
 | 
			
		||||
     *    1-17        21            357           7820
 | 
			
		||||
     *   18-24        19            133           7170
 | 
			
		||||
     *   25-30        18            108           6300
 | 
			
		||||
     *   31-40(*)     17             85           6020
 | 
			
		||||
     *                              ---
 | 
			
		||||
     *                              683 (for a 35 track image)
 | 
			
		||||
     */
 | 
			
		||||
    if (track < 17)
 | 
			
		||||
        return 21;
 | 
			
		||||
    if (track < 24)
 | 
			
		||||
        return 19;
 | 
			
		||||
    if (track < 30)
 | 
			
		||||
        return 18;
 | 
			
		||||
    return 17;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int encode_data_gcr(uint8_t data)
 | 
			
		||||
{
 | 
			
		||||
    switch (data)
 | 
			
		||||
    {
 | 
			
		||||
        #define GCR_ENTRY(gcr, data) \
 | 
			
		||||
            case data: return gcr;
 | 
			
		||||
        #include "data_gcr.h"
 | 
			
		||||
        #undef GCR_ENTRY
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, const std::vector<bool>& src)
 | 
			
		||||
{
 | 
			
		||||
    for (bool bit : src)  //Range-based for loop
 | 
			
		||||
    {
 | 
			
		||||
        if (cursor < bits.size())
 | 
			
		||||
            bits[cursor++] = bit;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_t data, int width)
 | 
			
		||||
{
 | 
			
		||||
    cursor += width;
 | 
			
		||||
    for (int i=0; i<width; i++)
 | 
			
		||||
    {
 | 
			
		||||
        unsigned pos = cursor - i - 1;              
 | 
			
		||||
        if (pos < bits.size())
 | 
			
		||||
            bits[pos] = data & 1;
 | 
			
		||||
        data >>= 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void bindump(std::ostream& stream, std::vector<bool>& buffer)
 | 
			
		||||
{
 | 
			
		||||
    size_t pos = 0;
 | 
			
		||||
 | 
			
		||||
    while ((pos < buffer.size()) and (pos <520))
 | 
			
		||||
    {
 | 
			
		||||
        stream << fmt::format("{:5d} : ", pos);
 | 
			
		||||
        for (int i=0; i<40; i++)
 | 
			
		||||
        {
 | 
			
		||||
            if ((pos+i) < buffer.size())
 | 
			
		||||
                stream << fmt::format("{:01b}", (buffer[pos+i]));
 | 
			
		||||
            else
 | 
			
		||||
                stream << "-- ";
 | 
			
		||||
            if ((((pos + i + 1) % 8) == 0) and i != 0)
 | 
			
		||||
                stream << "  ";
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        stream << std::endl;
 | 
			
		||||
        pos += 40;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
static std::vector<bool> encode_data(uint8_t input)
 | 
			
		||||
{
 | 
			
		||||
    /*
 | 
			
		||||
    * Four 8-bit data bytes are converted to four 10-bit GCR bytes at a time by
 | 
			
		||||
    * the 1541 DOS.  RAM is only an 8-bit storage device though. This hardware
 | 
			
		||||
    * limitation prevents a 10-bit GCR byte from being stored in a single
 | 
			
		||||
    * memory location. Four 10-bit GCR bytes total 40 bits - a number evenly
 | 
			
		||||
    * divisible by our overriding 8-bit constraint. Commodore sub- divides the
 | 
			
		||||
    * 40 GCR bits into five 8-bit bytes to solve this dilemma. This explains
 | 
			
		||||
    * why four 8-bit data bytes are converted to GCR form at a time. The
 | 
			
		||||
    * following step by step example demonstrates how this bit manipulation is
 | 
			
		||||
    * performed by the DOS.
 | 
			
		||||
    *
 | 
			
		||||
    * STEP 1. Four 8-bit Data Bytes
 | 
			
		||||
    * $08 $10 $00 $12
 | 
			
		||||
    *
 | 
			
		||||
    * STEP 2. Hexadecimal to Binary Conversion
 | 
			
		||||
    * 1. Binary Equivalents
 | 
			
		||||
    * $08       $10         $00         $12
 | 
			
		||||
    * 00001000  00010000    00000000    00010010
 | 
			
		||||
    *
 | 
			
		||||
    * STEP 3. Binary to GCR Conversion
 | 
			
		||||
    * 1. Four 8-bit Data Bytes
 | 
			
		||||
    * 00001000 00010000 00000000 00010010
 | 
			
		||||
    * 2. High and Low Nybbles
 | 
			
		||||
    * 0000 1000 0001 0000 0000 0000 0001 0010
 | 
			
		||||
    * 3. High and Low Nybble GCR Equivalents
 | 
			
		||||
    * 01010 01001 01011 01010 01010 01010 01011 10010
 | 
			
		||||
    * 4. Four 10-bit GCR Bytes
 | 
			
		||||
    * 0101001001 0101101010 0101001010 0101110010
 | 
			
		||||
    *
 | 
			
		||||
    * STEP 4. 10-bit GCR to 8-bit GCR Conversion
 | 
			
		||||
    *   1. Concatenate Four 10-bit GCR Bytes
 | 
			
		||||
    *   0101001001010110101001010010100101110010
 | 
			
		||||
    *   2. Five 8-bit Subdivisions
 | 
			
		||||
    *   01010010 01010110 10100101 00101001 01110010
 | 
			
		||||
    *
 | 
			
		||||
    * STEP 5. Binary to Hexadecimal Conversion
 | 
			
		||||
    * 1. Hexadecimal Equivalents
 | 
			
		||||
    *   01010010    01010110    10100101    00101001    01110010
 | 
			
		||||
    *   $52         $56         $A5         $29         $72
 | 
			
		||||
    *
 | 
			
		||||
    * STEP 6. Four 8-bit Data Bytes are Recorded as Five 8-bit GCR Bytes
 | 
			
		||||
    *   $08 $10 $00 $12
 | 
			
		||||
    *
 | 
			
		||||
    * are recorded as
 | 
			
		||||
    *   $52 $56 $A5 $29 $72
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    std::vector<bool> output(10, false);
 | 
			
		||||
    uint8_t hi = 0;
 | 
			
		||||
    uint8_t lo = 0;
 | 
			
		||||
    uint8_t lo_GCR = 0;
 | 
			
		||||
    uint8_t hi_GCR = 0;
 | 
			
		||||
 | 
			
		||||
    //Convert the byte in high and low nibble
 | 
			
		||||
    lo = input >> 4; //get the lo nibble shift the bits 4 to the right          
 | 
			
		||||
    hi = input & 15; //get the hi nibble bij masking the lo bits (00001111)     
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    lo_GCR = encode_data_gcr(lo);   //example value: 0000   GCR = 01010
 | 
			
		||||
    hi_GCR = encode_data_gcr(hi);   //example value: 1000   GCR = 01001
 | 
			
		||||
    //output = [0,1,2,3,4,5,6,7,8,9]
 | 
			
		||||
    //value  = [0,1,0,1,0,0,1,0,0,1]
 | 
			
		||||
    //          01010 01001
 | 
			
		||||
 | 
			
		||||
    int b = 4;
 | 
			
		||||
    for (int i = 0; i < 10; i++)
 | 
			
		||||
    {
 | 
			
		||||
        if (i < 5) //01234
 | 
			
		||||
        {       //i = 0 op 
 | 
			
		||||
            output[4-i] = (lo_GCR & 1); //01010
 | 
			
		||||
 | 
			
		||||
            //01010 -> & 00001 -> 00000 output[4] = 0
 | 
			
		||||
            //00101 -> & 00001 -> 00001 output[3] = 1
 | 
			
		||||
            //00010 -> & 00001 -> 00000 output[2] = 0
 | 
			
		||||
            //00001 -> & 00001 -> 00001 output[1] = 1
 | 
			
		||||
            //00000 -> & 00001 -> 00000 output[0] = 0
 | 
			
		||||
            lo_GCR >>= 1;
 | 
			
		||||
        } else  
 | 
			
		||||
        {
 | 
			
		||||
            output[i+b] = (hi_GCR & 1); //01001
 | 
			
		||||
            //01001 -> & 00001 -> 00001 output[9] = 1
 | 
			
		||||
            //00100 -> & 00001 -> 00000 output[8] = 0
 | 
			
		||||
            //00010 -> & 00001 -> 00000 output[7] = 0
 | 
			
		||||
            //00001 -> & 00001 -> 00001 output[6] = 1
 | 
			
		||||
            //00000 -> & 00001 -> 00000 output[5] = 0
 | 
			
		||||
            hi_GCR >>= 1;
 | 
			
		||||
            b = b-2;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Commodore64Encoder : public AbstractEncoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	Commodore64Encoder(const EncoderProto& config):
 | 
			
		||||
        AbstractEncoder(config),
 | 
			
		||||
		_config(config.c64())
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		std::vector<std::shared_ptr<Sector>> sectors;
 | 
			
		||||
 | 
			
		||||
        if (physicalSide == 0)
 | 
			
		||||
        {
 | 
			
		||||
            int logicalTrack = physicalTrack / 2;
 | 
			
		||||
            unsigned numSectors = sectorsForTrack(logicalTrack);
 | 
			
		||||
            for (int sectorId=0; sectorId<numSectors; sectorId++)
 | 
			
		||||
            {
 | 
			
		||||
                const auto& sector = image.get(logicalTrack, 0, sectorId);
 | 
			
		||||
                if (sector)
 | 
			
		||||
                    sectors.push_back(sector);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		return sectors;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide,
 | 
			
		||||
            const std::vector<std::shared_ptr<Sector>>& sectors, const Image& image) override
 | 
			
		||||
    {
 | 
			
		||||
        /* The format ID Character # 1 and # 2 are in the .d64 image only present
 | 
			
		||||
         * in track 18 sector zero which contains the BAM info in byte 162 and 163.
 | 
			
		||||
         * it is written in every header of every sector and track. headers are not
 | 
			
		||||
         * stored in a d64 disk image so we have to get it from track 18 which
 | 
			
		||||
         * contains the BAM.
 | 
			
		||||
        */
 | 
			
		||||
 | 
			
		||||
        if (physicalSide != 0)
 | 
			
		||||
            return std::unique_ptr<Fluxmap>();
 | 
			
		||||
 | 
			
		||||
        const auto& sectorData = image.get(C64_BAM_TRACK*2, 0, 0); //Read de BAM to get the DISK ID bytes
 | 
			
		||||
        if (sectorData)
 | 
			
		||||
        {
 | 
			
		||||
            ByteReader br(sectorData->data);
 | 
			
		||||
            br.seek(162); //goto position of the first Disk ID Byte
 | 
			
		||||
            _formatByte1 = br.read_8();
 | 
			
		||||
            _formatByte2 = br.read_8();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            _formatByte1 = _formatByte2 = 0;
 | 
			
		||||
        
 | 
			
		||||
        int logicalTrack = physicalTrack / 2;
 | 
			
		||||
        double clockRateUs = clockRateUsForTrack(logicalTrack) * _config.clock_compensation_factor();
 | 
			
		||||
 | 
			
		||||
        int bitsPerRevolution = 200000.0 / clockRateUs;
 | 
			
		||||
 | 
			
		||||
        std::vector<bool> bits(bitsPerRevolution);
 | 
			
		||||
        unsigned cursor = 0;
 | 
			
		||||
 | 
			
		||||
        fillBitmapTo(bits, cursor, _config.post_index_gap_us() / clockRateUs, { true, false });
 | 
			
		||||
        lastBit = false;
 | 
			
		||||
 | 
			
		||||
        for (const auto& sector : sectors)
 | 
			
		||||
            writeSector(bits, cursor, sector);
 | 
			
		||||
 | 
			
		||||
        if (cursor >= bits.size())
 | 
			
		||||
            Error() << fmt::format("track data overrun by {} bits", cursor - bits.size());
 | 
			
		||||
        fillBitmapTo(bits, cursor, bits.size(), { true, false });
 | 
			
		||||
 | 
			
		||||
        std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
 | 
			
		||||
        fluxmap->appendBits(bits, clockRateUs*1e3);
 | 
			
		||||
        return fluxmap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	void writeSector(std::vector<bool>& bits, unsigned& cursor, const std::shared_ptr<Sector>& sector) const
 | 
			
		||||
    {
 | 
			
		||||
        /* Source: http://www.unusedino.de/ec64/technical/formats/g64.html 
 | 
			
		||||
         * 1. Header sync       FF FF FF FF FF (40 'on' bits, not GCR)
 | 
			
		||||
         * 2. Header info       52 54 B5 29 4B 7A 5E 95 55 55 (10 GCR bytes)
 | 
			
		||||
         * 3. Header gap        55 55 55 55 55 55 55 55 55 (9 bytes, never read)
 | 
			
		||||
         * 4. Data sync         FF FF FF FF FF (40 'on' bits, not GCR)
 | 
			
		||||
         * 5. Data block        55...4A (325 GCR bytes)
 | 
			
		||||
         * 6. Inter-sector gap  55 55 55 55...55 55 (4 to 12 bytes, never read)
 | 
			
		||||
         * 1. Header sync       (SYNC for the next sector)
 | 
			
		||||
        */
 | 
			
		||||
        if ((sector->status == Sector::OK) or (sector->status == Sector::BAD_CHECKSUM))
 | 
			
		||||
        {
 | 
			
		||||
            // There is data to encode to disk.
 | 
			
		||||
            if ((sector->data.size() != C64_SECTOR_LENGTH))
 | 
			
		||||
                Error() << fmt::format("unsupported sector size {} --- you must pick 256", sector->data.size());    
 | 
			
		||||
 | 
			
		||||
            // 1. Write header Sync (not GCR)
 | 
			
		||||
            for (int i=0; i<6; i++)
 | 
			
		||||
                write_bits(bits, cursor, C64_HEADER_DATA_SYNC, 1*8); /* sync */
 | 
			
		||||
 | 
			
		||||
            // 2. Write Header info 10 GCR bytes
 | 
			
		||||
            /*
 | 
			
		||||
             * The 10 byte header info (#2) is GCR encoded and must be decoded  to
 | 
			
		||||
             * it's normal 8 bytes to be understood. Once decoded, its breakdown is
 | 
			
		||||
             * as follows:
 | 
			
		||||
             * 
 | 
			
		||||
             * Byte $00 - header block ID           ($08)
 | 
			
		||||
             *   01 - header block checksum 16  (EOR of $02-$05)
 | 
			
		||||
             *   02 - Sector
 | 
			
		||||
             *   03 - Track
 | 
			
		||||
             *   04 - Format ID byte #2
 | 
			
		||||
             *   05 - Format ID byte #1
 | 
			
		||||
             *   06-07 - $0F ("off" bytes)
 | 
			
		||||
             */
 | 
			
		||||
            uint8_t encodedTrack = ((sector->logicalTrack) + 1); // C64 track numbering starts with 1. Fluxengine with 0.
 | 
			
		||||
            uint8_t encodedSector = sector->logicalSector;
 | 
			
		||||
            // uint8_t formatByte1 = C64_FORMAT_ID_BYTE1;
 | 
			
		||||
            // uint8_t formatByte2 = C64_FORMAT_ID_BYTE2;
 | 
			
		||||
            uint8_t headerChecksum = (encodedTrack ^ encodedSector ^ _formatByte1 ^ _formatByte2);
 | 
			
		||||
            write_bits(bits, cursor, encode_data(C64_HEADER_BLOCK_ID));
 | 
			
		||||
            write_bits(bits, cursor, encode_data(headerChecksum));
 | 
			
		||||
            write_bits(bits, cursor, encode_data(encodedSector));
 | 
			
		||||
            write_bits(bits, cursor, encode_data(encodedTrack));
 | 
			
		||||
            write_bits(bits, cursor, encode_data(_formatByte2));
 | 
			
		||||
            write_bits(bits, cursor, encode_data(_formatByte1));
 | 
			
		||||
            write_bits(bits, cursor, encode_data(C64_PADDING));
 | 
			
		||||
            write_bits(bits, cursor, encode_data(C64_PADDING));
 | 
			
		||||
 | 
			
		||||
            // 3. Write header GAP not GCR
 | 
			
		||||
            for (int i=0; i<9; i++)
 | 
			
		||||
                write_bits(bits, cursor, C64_HEADER_GAP, 1*8); /* header gap */
 | 
			
		||||
 | 
			
		||||
            // 4. Write Data sync not GCR
 | 
			
		||||
            for (int i=0; i<6; i++)
 | 
			
		||||
                write_bits(bits, cursor, C64_HEADER_DATA_SYNC, 1*8); /* sync */
 | 
			
		||||
 | 
			
		||||
            // 5. Write data block 325 GCR bytes
 | 
			
		||||
            /*
 | 
			
		||||
             * The 325 byte data block (#5) is GCR encoded and must be  decoded  to  its
 | 
			
		||||
             * normal 260 bytes to be understood. The data block is made up of the following:
 | 
			
		||||
             * 
 | 
			
		||||
             * Byte    $00 - data block ID ($07)
 | 
			
		||||
             *      01-100 - 256 bytes data
 | 
			
		||||
             *      101 - data block checksum (EOR of $01-100)
 | 
			
		||||
             *      102-103 - $00 ("off" bytes, to make the sector size a multiple of 5)
 | 
			
		||||
             */
 | 
			
		||||
 | 
			
		||||
            write_bits(bits, cursor, encode_data(C64_DATA_BLOCK_ID));
 | 
			
		||||
            uint8_t dataChecksum = xorBytes(sector->data);
 | 
			
		||||
            ByteReader br(sector->data);
 | 
			
		||||
            int i = 0;
 | 
			
		||||
            for (i = 0; i < C64_SECTOR_LENGTH; i++)
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t val = br.read_8();
 | 
			
		||||
                write_bits(bits, cursor, encode_data(val));     
 | 
			
		||||
            }
 | 
			
		||||
            write_bits(bits, cursor, encode_data(dataChecksum));
 | 
			
		||||
            write_bits(bits, cursor, encode_data(C64_PADDING));
 | 
			
		||||
            write_bits(bits, cursor, encode_data(C64_PADDING));
 | 
			
		||||
 | 
			
		||||
            //6. Write inter-sector gap 9 - 12 bytes nor gcr
 | 
			
		||||
            for (int i=0; i<9; i++)
 | 
			
		||||
                write_bits(bits, cursor, C64_INTER_SECTOR_GAP, 1*8); /* sync */
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
        
 | 
			
		||||
private:
 | 
			
		||||
	const Commodore64EncoderProto& _config;
 | 
			
		||||
	uint8_t _formatByte1;
 | 
			
		||||
	uint8_t _formatByte2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractEncoder> createCommodore64Encoder(const EncoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractEncoder>(new Commodore64Encoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// vim: sw=4 ts=4 et
 | 
			
		||||
 | 
			
		||||
@@ -2,7 +2,6 @@
 | 
			
		||||
#include "fluxmap.h"
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "protocol.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "f85.h"
 | 
			
		||||
@@ -26,7 +25,7 @@ static int decode_data_gcr(uint8_t gcr)
 | 
			
		||||
		#undef GCR_ENTRY
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Bytes decode(const std::vector<bool>& bits)
 | 
			
		||||
{
 | 
			
		||||
@@ -52,49 +51,63 @@ static Bytes decode(const std::vector<bool>& bits)
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AbstractDecoder::RecordType DurangoF85Decoder::advanceToNextRecord()
 | 
			
		||||
class DurangoF85Decoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
	const FluxMatcher* matcher = nullptr;
 | 
			
		||||
	_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
	if (matcher == &SECTOR_RECORD_PATTERN)
 | 
			
		||||
		return RecordType::SECTOR_RECORD;
 | 
			
		||||
	if (matcher == &DATA_RECORD_PATTERN)
 | 
			
		||||
		return RecordType::DATA_RECORD;
 | 
			
		||||
	return RecordType::UNKNOWN_RECORD;
 | 
			
		||||
public:
 | 
			
		||||
	DurangoF85Decoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord()
 | 
			
		||||
	{
 | 
			
		||||
		const FluxMatcher* matcher = nullptr;
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
		if (matcher == &SECTOR_RECORD_PATTERN)
 | 
			
		||||
			return RecordType::SECTOR_RECORD;
 | 
			
		||||
		if (matcher == &DATA_RECORD_PATTERN)
 | 
			
		||||
			return RecordType::DATA_RECORD;
 | 
			
		||||
		return RecordType::UNKNOWN_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeSectorRecord()
 | 
			
		||||
	{
 | 
			
		||||
		/* Skip sync bits and ID byte. */
 | 
			
		||||
 | 
			
		||||
		readRawBits(24);
 | 
			
		||||
 | 
			
		||||
		/* Read header. */
 | 
			
		||||
 | 
			
		||||
		const auto& bytes = decode(readRawBits(6*10));
 | 
			
		||||
 | 
			
		||||
		_sector->logicalSector = bytes[2];
 | 
			
		||||
		_sector->logicalSide = 0;
 | 
			
		||||
		_sector->logicalTrack = bytes[0];
 | 
			
		||||
 | 
			
		||||
		uint16_t wantChecksum = bytes.reader().seek(4).read_be16();
 | 
			
		||||
		uint16_t gotChecksum = crc16(CCITT_POLY, 0xef21, bytes.slice(0, 4));
 | 
			
		||||
		if (wantChecksum == gotChecksum)
 | 
			
		||||
			_sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeDataRecord()
 | 
			
		||||
	{
 | 
			
		||||
		/* Skip sync bits ID byte. */
 | 
			
		||||
 | 
			
		||||
		readRawBits(24);
 | 
			
		||||
 | 
			
		||||
		const auto& bytes = decode(readRawBits((F85_SECTOR_LENGTH+3)*10))
 | 
			
		||||
			.slice(0, F85_SECTOR_LENGTH+3);
 | 
			
		||||
		ByteReader br(bytes);
 | 
			
		||||
 | 
			
		||||
		_sector->data = br.read(F85_SECTOR_LENGTH);
 | 
			
		||||
		uint16_t wantChecksum = br.read_be16();
 | 
			
		||||
		uint16_t gotChecksum = crc16(CCITT_POLY, 0xbf84, _sector->data);
 | 
			
		||||
		_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createDurangoF85Decoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new DurangoF85Decoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DurangoF85Decoder::decodeSectorRecord()
 | 
			
		||||
{
 | 
			
		||||
    /* Skip sync bits and ID byte. */
 | 
			
		||||
 | 
			
		||||
    readRawBits(24);
 | 
			
		||||
 | 
			
		||||
    /* Read header. */
 | 
			
		||||
 | 
			
		||||
    const auto& bytes = decode(readRawBits(6*10));
 | 
			
		||||
 | 
			
		||||
    _sector->logicalSector = bytes[2];
 | 
			
		||||
    _sector->logicalSide = 0;
 | 
			
		||||
    _sector->logicalTrack = bytes[0];
 | 
			
		||||
 | 
			
		||||
    uint16_t wantChecksum = bytes.reader().seek(4).read_be16();
 | 
			
		||||
    uint16_t gotChecksum = crc16(CCITT_POLY, 0xef21, bytes.slice(0, 4));
 | 
			
		||||
    if (wantChecksum == gotChecksum)
 | 
			
		||||
        _sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DurangoF85Decoder::decodeDataRecord()
 | 
			
		||||
{
 | 
			
		||||
    /* Skip sync bits ID byte. */
 | 
			
		||||
 | 
			
		||||
    readRawBits(24);
 | 
			
		||||
 | 
			
		||||
    const auto& bytes = decode(readRawBits((F85_SECTOR_LENGTH+3)*10))
 | 
			
		||||
        .slice(0, F85_SECTOR_LENGTH+3);
 | 
			
		||||
    ByteReader br(bytes);
 | 
			
		||||
 | 
			
		||||
    _sector->data = br.read(F85_SECTOR_LENGTH);
 | 
			
		||||
    uint16_t wantChecksum = br.read_be16();
 | 
			
		||||
    uint16_t gotChecksum = crc16(CCITT_POLY, 0xbf84, _sector->data);
 | 
			
		||||
    _sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,17 +5,6 @@
 | 
			
		||||
#define F85_DATA_RECORD 0xffffcb /* 1111 1111 1111 1111 1100 1101 */
 | 
			
		||||
#define F85_SECTOR_LENGTH    512
 | 
			
		||||
 | 
			
		||||
class Sector;
 | 
			
		||||
class Fluxmap;
 | 
			
		||||
 | 
			
		||||
class DurangoF85Decoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~DurangoF85Decoder() {}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord();
 | 
			
		||||
    void decodeSectorRecord();
 | 
			
		||||
    void decodeDataRecord();
 | 
			
		||||
};
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createDurangoF85Decoder(const DecoderProto& config);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								arch/f85/f85.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/f85/f85.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
message F85DecoderProto {}
 | 
			
		||||
 | 
			
		||||
@@ -2,14 +2,12 @@
 | 
			
		||||
#include "fluxmap.h"
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "protocol.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "fb100.h"
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "bytes.h"
 | 
			
		||||
#include "decoders/rawbits.h"
 | 
			
		||||
#include "track.h"
 | 
			
		||||
#include "fmt/format.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
@@ -99,37 +97,52 @@ static uint16_t checksum(const Bytes& bytes)
 | 
			
		||||
    return (crchi << 8) | crclo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AbstractDecoder::RecordType Fb100Decoder::advanceToNextRecord()
 | 
			
		||||
class Fb100Decoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
	const FluxMatcher* matcher = nullptr;
 | 
			
		||||
	_sector->clock = _fmr->seekToPattern(SECTOR_ID_PATTERN, matcher);
 | 
			
		||||
    if (matcher == &SECTOR_ID_PATTERN)
 | 
			
		||||
		return RecordType::SECTOR_RECORD;
 | 
			
		||||
	return RecordType::UNKNOWN_RECORD;
 | 
			
		||||
public:
 | 
			
		||||
	Fb100Decoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord()
 | 
			
		||||
	{
 | 
			
		||||
		const FluxMatcher* matcher = nullptr;
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(SECTOR_ID_PATTERN, matcher);
 | 
			
		||||
		if (matcher == &SECTOR_ID_PATTERN)
 | 
			
		||||
			return RecordType::SECTOR_RECORD;
 | 
			
		||||
		return RecordType::UNKNOWN_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeSectorRecord()
 | 
			
		||||
	{
 | 
			
		||||
		auto rawbits = readRawBits(FB100_RECORD_SIZE*16);
 | 
			
		||||
 | 
			
		||||
		const Bytes bytes = decodeFmMfm(rawbits).slice(0, FB100_RECORD_SIZE);
 | 
			
		||||
		ByteReader br(bytes);
 | 
			
		||||
		br.seek(1);
 | 
			
		||||
		const Bytes id = br.read(FB100_ID_SIZE);
 | 
			
		||||
		uint16_t wantIdCrc = br.read_be16();
 | 
			
		||||
		uint16_t gotIdCrc = checksum(id);
 | 
			
		||||
		const Bytes payload = br.read(FB100_PAYLOAD_SIZE);
 | 
			
		||||
		uint16_t wantPayloadCrc = br.read_be16();
 | 
			
		||||
		uint16_t gotPayloadCrc = checksum(payload);
 | 
			
		||||
 | 
			
		||||
		if (wantIdCrc != gotIdCrc)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		uint8_t abssector = id[2];
 | 
			
		||||
		_sector->logicalTrack = abssector >> 1;
 | 
			
		||||
		_sector->logicalSide = 0;
 | 
			
		||||
		_sector->logicalSector = abssector & 1;
 | 
			
		||||
		_sector->data.writer().append(id.slice(5, 12)).append(payload);
 | 
			
		||||
 | 
			
		||||
		_sector->status = (wantPayloadCrc == gotPayloadCrc) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createFb100Decoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new Fb100Decoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Fb100Decoder::decodeSectorRecord()
 | 
			
		||||
{
 | 
			
		||||
    auto rawbits = readRawBits(FB100_RECORD_SIZE*16);
 | 
			
		||||
 | 
			
		||||
    const Bytes bytes = decodeFmMfm(rawbits).slice(0, FB100_RECORD_SIZE);
 | 
			
		||||
    ByteReader br(bytes);
 | 
			
		||||
    br.seek(1);
 | 
			
		||||
    const Bytes id = br.read(FB100_ID_SIZE);
 | 
			
		||||
    uint16_t wantIdCrc = br.read_be16();
 | 
			
		||||
    uint16_t gotIdCrc = checksum(id);
 | 
			
		||||
    const Bytes payload = br.read(FB100_PAYLOAD_SIZE);
 | 
			
		||||
    uint16_t wantPayloadCrc = br.read_be16();
 | 
			
		||||
    uint16_t gotPayloadCrc = checksum(payload);
 | 
			
		||||
 | 
			
		||||
    if (wantIdCrc != gotIdCrc)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    uint8_t abssector = id[2];
 | 
			
		||||
    _sector->logicalTrack = abssector >> 1;
 | 
			
		||||
    _sector->logicalSide = 0;
 | 
			
		||||
    _sector->logicalSector = abssector & 1;
 | 
			
		||||
    _sector->data.writer().append(id.slice(5, 12)).append(payload);
 | 
			
		||||
 | 
			
		||||
    _sector->status = (wantPayloadCrc == gotPayloadCrc) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
}
 | 
			
		||||
@@ -5,18 +5,7 @@
 | 
			
		||||
#define FB100_ID_SIZE 17
 | 
			
		||||
#define FB100_PAYLOAD_SIZE 0x500
 | 
			
		||||
 | 
			
		||||
class Sector;
 | 
			
		||||
class Fluxmap;
 | 
			
		||||
class Track;
 | 
			
		||||
 | 
			
		||||
class Fb100Decoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~Fb100Decoder() {}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord();
 | 
			
		||||
    void decodeSectorRecord();
 | 
			
		||||
};
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createFb100Decoder(const DecoderProto& config);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								arch/fb100/fb100.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/fb100/fb100.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
message Fb100DecoderProto {}
 | 
			
		||||
 | 
			
		||||
@@ -5,7 +5,8 @@
 | 
			
		||||
#include "fluxmap.h"
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "arch/ibm/ibm.pb.h"
 | 
			
		||||
#include "proto.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
static_assert(std::is_trivially_copyable<IbmIdam>::value,
 | 
			
		||||
@@ -89,71 +90,104 @@ const FluxMatchers ANY_RECORD_PATTERN(
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
AbstractDecoder::RecordType IbmDecoder::advanceToNextRecord()
 | 
			
		||||
class IbmDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
	const FluxMatcher* matcher = nullptr;
 | 
			
		||||
	_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
public:
 | 
			
		||||
    IbmDecoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config),
 | 
			
		||||
		_config(config.ibm())
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    /* If this is the MFM prefix byte, the the decoder is going to expect three
 | 
			
		||||
     * extra bytes on the front of the header. */
 | 
			
		||||
    _currentHeaderLength = (matcher == &MFM_PATTERN) ? 3 : 0;
 | 
			
		||||
    RecordType advanceToNextRecord() override
 | 
			
		||||
	{
 | 
			
		||||
		const FluxMatcher* matcher = nullptr;
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
 | 
			
		||||
    Fluxmap::Position here = tell();
 | 
			
		||||
    if (_currentHeaderLength > 0)
 | 
			
		||||
        readRawBits(_currentHeaderLength*16);
 | 
			
		||||
    auto idbits = readRawBits(16);
 | 
			
		||||
    const Bytes idbytes = decodeFmMfm(idbits);
 | 
			
		||||
    uint8_t id = idbytes.slice(0, 1)[0];
 | 
			
		||||
    seek(here);
 | 
			
		||||
    
 | 
			
		||||
    switch (id)
 | 
			
		||||
    {
 | 
			
		||||
        case IBM_IDAM:
 | 
			
		||||
            return RecordType::SECTOR_RECORD;
 | 
			
		||||
		/* If this is the MFM prefix byte, the the decoder is going to expect three
 | 
			
		||||
		 * extra bytes on the front of the header. */
 | 
			
		||||
		_currentHeaderLength = (matcher == &MFM_PATTERN) ? 3 : 0;
 | 
			
		||||
 | 
			
		||||
        case IBM_DAM1:
 | 
			
		||||
        case IBM_DAM2:
 | 
			
		||||
        case IBM_TRS80DAM1:
 | 
			
		||||
        case IBM_TRS80DAM2:
 | 
			
		||||
            return RecordType::DATA_RECORD;
 | 
			
		||||
    }
 | 
			
		||||
    return RecordType::UNKNOWN_RECORD;
 | 
			
		||||
		Fluxmap::Position here = tell();
 | 
			
		||||
		resetFluxDecoder();
 | 
			
		||||
		if (_currentHeaderLength > 0)
 | 
			
		||||
			readRawBits(_currentHeaderLength*16);
 | 
			
		||||
		auto idbits = readRawBits(16);
 | 
			
		||||
		const Bytes idbytes = decodeFmMfm(idbits);
 | 
			
		||||
		uint8_t id = idbytes.slice(0, 1)[0];
 | 
			
		||||
		seek(here);
 | 
			
		||||
		
 | 
			
		||||
		switch (id)
 | 
			
		||||
		{
 | 
			
		||||
			case IBM_IDAM:
 | 
			
		||||
				return RecordType::SECTOR_RECORD;
 | 
			
		||||
 | 
			
		||||
			case IBM_DAM1:
 | 
			
		||||
			case IBM_DAM2:
 | 
			
		||||
			case IBM_TRS80DAM1:
 | 
			
		||||
			case IBM_TRS80DAM2:
 | 
			
		||||
				return RecordType::DATA_RECORD;
 | 
			
		||||
		}
 | 
			
		||||
		return RecordType::UNKNOWN_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeSectorRecord() override
 | 
			
		||||
	{
 | 
			
		||||
		unsigned recordSize = _currentHeaderLength + IBM_IDAM_LEN;
 | 
			
		||||
		auto bits = readRawBits(recordSize*16);
 | 
			
		||||
		auto bytes = decodeFmMfm(bits).slice(0, recordSize);
 | 
			
		||||
 | 
			
		||||
		ByteReader br(bytes);
 | 
			
		||||
		br.seek(_currentHeaderLength);
 | 
			
		||||
		br.read_8(); /* skip ID byte */
 | 
			
		||||
		_sector->logicalTrack = br.read_8();
 | 
			
		||||
		_sector->logicalSide = br.read_8();
 | 
			
		||||
		_sector->logicalSector = br.read_8();
 | 
			
		||||
		_currentSectorSize = 1 << (br.read_8() + 7);
 | 
			
		||||
		uint16_t wantCrc = br.read_be16();
 | 
			
		||||
		uint16_t gotCrc = crc16(CCITT_POLY, bytes.slice(0, _currentHeaderLength + 5));
 | 
			
		||||
		if (wantCrc == gotCrc)
 | 
			
		||||
			_sector->status = Sector::DATA_MISSING; /* correct but unintuitive */
 | 
			
		||||
 | 
			
		||||
		if (_config.swap_sides())
 | 
			
		||||
			_sector->logicalSide ^= 1;
 | 
			
		||||
		if (_config.ignore_side_byte())
 | 
			
		||||
			_sector->logicalSide = _sector->physicalHead;
 | 
			
		||||
		if (_config.ignore_track_byte())
 | 
			
		||||
			_sector->logicalTrack = _sector->physicalCylinder;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeDataRecord() override
 | 
			
		||||
	{
 | 
			
		||||
		unsigned recordLength = _currentHeaderLength + _currentSectorSize + 3;
 | 
			
		||||
		auto bits = readRawBits(recordLength*16);
 | 
			
		||||
		auto bytes = decodeFmMfm(bits).slice(0, recordLength);
 | 
			
		||||
 | 
			
		||||
		ByteReader br(bytes);
 | 
			
		||||
		br.seek(_currentHeaderLength);
 | 
			
		||||
		br.read_8(); /* skip ID byte */
 | 
			
		||||
 | 
			
		||||
		_sector->data = br.read(_currentSectorSize);
 | 
			
		||||
		uint16_t wantCrc = br.read_be16();
 | 
			
		||||
		uint16_t gotCrc = crc16(CCITT_POLY, bytes.slice(0, recordLength-2));
 | 
			
		||||
		_sector->status = (wantCrc == gotCrc) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::set<unsigned> requiredSectors(unsigned cylinder, unsigned head) const override
 | 
			
		||||
	{
 | 
			
		||||
		std::set<unsigned> s;
 | 
			
		||||
		for (int sectorId : _config.sectors().sector())
 | 
			
		||||
			s.insert(sectorId);
 | 
			
		||||
		return s;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	const IbmDecoderProto& _config;
 | 
			
		||||
    unsigned _currentSectorSize;
 | 
			
		||||
    unsigned _currentHeaderLength;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createIbmDecoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new IbmDecoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IbmDecoder::decodeSectorRecord()
 | 
			
		||||
{
 | 
			
		||||
    unsigned recordSize = _currentHeaderLength + IBM_IDAM_LEN;
 | 
			
		||||
    auto bits = readRawBits(recordSize*16);
 | 
			
		||||
    auto bytes = decodeFmMfm(bits).slice(0, recordSize);
 | 
			
		||||
 | 
			
		||||
    ByteReader br(bytes);
 | 
			
		||||
    br.seek(_currentHeaderLength);
 | 
			
		||||
    br.read_8(); /* skip ID byte */
 | 
			
		||||
    _sector->logicalTrack = br.read_8();
 | 
			
		||||
    _sector->logicalSide = br.read_8();
 | 
			
		||||
    _sector->logicalSector = br.read_8() - _sectorBase;
 | 
			
		||||
    _currentSectorSize = 1 << (br.read_8() + 7);
 | 
			
		||||
    uint16_t wantCrc = br.read_be16();
 | 
			
		||||
    uint16_t gotCrc = crc16(CCITT_POLY, bytes.slice(0, _currentHeaderLength + 5));
 | 
			
		||||
    if (wantCrc == gotCrc)
 | 
			
		||||
        _sector->status = Sector::DATA_MISSING; /* correct but unintuitive */
 | 
			
		||||
 | 
			
		||||
    if (_ignoreSideByte)
 | 
			
		||||
        _sector->logicalSide = _sector->physicalSide;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IbmDecoder::decodeDataRecord()
 | 
			
		||||
{
 | 
			
		||||
    unsigned recordLength = _currentHeaderLength + _currentSectorSize + 3;
 | 
			
		||||
    auto bits = readRawBits(recordLength*16);
 | 
			
		||||
    auto bytes = decodeFmMfm(bits).slice(0, recordLength);
 | 
			
		||||
 | 
			
		||||
    ByteReader br(bytes);
 | 
			
		||||
    br.seek(_currentHeaderLength);
 | 
			
		||||
    br.read_8(); /* skip ID byte */
 | 
			
		||||
 | 
			
		||||
    _sector->data = br.read(_currentSectorSize);
 | 
			
		||||
    uint16_t wantCrc = br.read_be16();
 | 
			
		||||
    uint16_t gotCrc = crc16(CCITT_POLY, bytes.slice(0, recordLength-2));
 | 
			
		||||
    _sector->status = (wantCrc == gotCrc) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,12 @@
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "encoders/encoders.h"
 | 
			
		||||
#include "ibm.h"
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "sectorset.h"
 | 
			
		||||
#include "writer.h"
 | 
			
		||||
#include "image.h"
 | 
			
		||||
#include "arch/ibm/ibm.pb.h"
 | 
			
		||||
#include "lib/encoders/encoders.pb.h"
 | 
			
		||||
#include "fmt/format.h"
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 | 
			
		||||
@@ -56,41 +57,6 @@
 | 
			
		||||
 * mfm:     01 01 01 01 01 00 01 01 = 0x5545
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static int charToInt(char c)
 | 
			
		||||
{
 | 
			
		||||
	if (isdigit(c))
 | 
			
		||||
		return c - '0';
 | 
			
		||||
	return 10 + tolower(c) - 'a';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IbmEncoder::writeRawBits(uint32_t data, int width)
 | 
			
		||||
{
 | 
			
		||||
	_cursor += width;
 | 
			
		||||
	_lastBit = data & 1;
 | 
			
		||||
	for (int i=0; i<width; i++)
 | 
			
		||||
	{
 | 
			
		||||
		unsigned pos = _cursor - i - 1;
 | 
			
		||||
		if (pos < _bits.size())
 | 
			
		||||
			_bits[pos] = data & 1;
 | 
			
		||||
		data >>= 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IbmEncoder::writeBytes(const Bytes& bytes)
 | 
			
		||||
{
 | 
			
		||||
	if (_parameters.useFm)
 | 
			
		||||
		encodeFm(_bits, _cursor, bytes);
 | 
			
		||||
	else
 | 
			
		||||
		encodeMfm(_bits, _cursor, bytes, _lastBit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IbmEncoder::writeBytes(int count, uint8_t byte)
 | 
			
		||||
{
 | 
			
		||||
	Bytes bytes = { byte };
 | 
			
		||||
	for (int i=0; i<count; i++)
 | 
			
		||||
		writeBytes(bytes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t decodeUint16(uint16_t raw)
 | 
			
		||||
{
 | 
			
		||||
	Bytes b;
 | 
			
		||||
@@ -99,138 +65,222 @@ static uint8_t decodeUint16(uint16_t raw)
 | 
			
		||||
	return decodeFmMfm(b.toBits())[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<Fluxmap> IbmEncoder::encode(
 | 
			
		||||
	int physicalTrack, int physicalSide, const SectorSet& allSectors)
 | 
			
		||||
class IbmEncoder : public AbstractEncoder
 | 
			
		||||
{
 | 
			
		||||
	double clockRateUs = 1e3 / _parameters.clockRateKhz;
 | 
			
		||||
	if (!_parameters.useFm)
 | 
			
		||||
		clockRateUs /= 2.0;
 | 
			
		||||
	int bitsPerRevolution = (_parameters.trackLengthMs * 1000.0) / clockRateUs;
 | 
			
		||||
	_bits.resize(bitsPerRevolution);
 | 
			
		||||
	_cursor = 0;
 | 
			
		||||
public:
 | 
			
		||||
	IbmEncoder(const EncoderProto& config):
 | 
			
		||||
		AbstractEncoder(config),
 | 
			
		||||
		_config(config.ibm())
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	uint8_t idamUnencoded = decodeUint16(_parameters.idamByte);
 | 
			
		||||
	uint8_t damUnencoded = decodeUint16(_parameters.damByte);
 | 
			
		||||
 | 
			
		||||
	uint8_t sectorSize = 0;
 | 
			
		||||
private:
 | 
			
		||||
	void writeRawBits(uint32_t data, int width)
 | 
			
		||||
	{
 | 
			
		||||
		int s = _parameters.sectorSize >> 7;
 | 
			
		||||
		while (s > 1)
 | 
			
		||||
		_cursor += width;
 | 
			
		||||
		_lastBit = data & 1;
 | 
			
		||||
		for (int i=0; i<width; i++)
 | 
			
		||||
		{
 | 
			
		||||
			s >>= 1;
 | 
			
		||||
			sectorSize += 1;
 | 
			
		||||
			unsigned pos = _cursor - i - 1;
 | 
			
		||||
			if (pos < _bits.size())
 | 
			
		||||
				_bits[pos] = data & 1;
 | 
			
		||||
			data >>= 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uint8_t gapFill = _parameters.useFm ? 0x00 : 0x4e;
 | 
			
		||||
 | 
			
		||||
	writeBytes(_parameters.gap0, gapFill);
 | 
			
		||||
	if (_parameters.emitIam)
 | 
			
		||||
	void getTrackFormat(IbmEncoderProto::TrackdataProto& trackdata, unsigned cylinder, unsigned head)
 | 
			
		||||
	{
 | 
			
		||||
		writeBytes(_parameters.useFm ? 6 : 12, 0x00);
 | 
			
		||||
		if (!_parameters.useFm)
 | 
			
		||||
		trackdata.Clear();
 | 
			
		||||
		for (const auto& f : _config.trackdata())
 | 
			
		||||
		{
 | 
			
		||||
			for (int i=0; i<3; i++)
 | 
			
		||||
				writeRawBits(MFM_IAM_SEPARATOR, 16);
 | 
			
		||||
			if (f.has_cylinder() && (f.cylinder() != cylinder))
 | 
			
		||||
				continue;
 | 
			
		||||
			if (f.has_head() && (f.head() != head))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			trackdata.MergeFrom(f);
 | 
			
		||||
		}
 | 
			
		||||
		writeRawBits(_parameters.useFm ? FM_IAM_RECORD : MFM_IAM_RECORD, 16);
 | 
			
		||||
		writeBytes(_parameters.gap1, gapFill);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool first = true;
 | 
			
		||||
	for (char sectorChar : _parameters.sectorSkew)
 | 
			
		||||
public:
 | 
			
		||||
	std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		int sectorId = charToInt(sectorChar);
 | 
			
		||||
		if (!first)
 | 
			
		||||
			writeBytes(_parameters.gap3, gapFill);
 | 
			
		||||
		first = false;
 | 
			
		||||
		std::vector<std::shared_ptr<Sector>> sectors;
 | 
			
		||||
		IbmEncoderProto::TrackdataProto trackdata;
 | 
			
		||||
		getTrackFormat(trackdata, physicalTrack, physicalSide);
 | 
			
		||||
 | 
			
		||||
		const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId);
 | 
			
		||||
		if (!sectorData)
 | 
			
		||||
			Error() << fmt::format("format tried to find sector {} which wasn't in the input file", sectorId);
 | 
			
		||||
		int logicalSide = physicalSide ^ trackdata.swap_sides();
 | 
			
		||||
		for (int sectorId : trackdata.sectors().sector())
 | 
			
		||||
        {
 | 
			
		||||
			const auto& sector = image.get(physicalTrack, logicalSide, sectorId);
 | 
			
		||||
			if (sector)
 | 
			
		||||
				sectors.push_back(sector);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		/* Writing the sector and data records are fantastically annoying.
 | 
			
		||||
		 * The CRC is calculated from the *very start* of the record, and
 | 
			
		||||
		 * include the malformed marker bytes. Our encoder doesn't know
 | 
			
		||||
		 * about this, of course, with the result that we have to construct
 | 
			
		||||
		 * the unencoded header, calculate the checksum, and then use the
 | 
			
		||||
		 * same logic to emit the bytes which require special encoding
 | 
			
		||||
		 * before encoding the rest of the header normally. */
 | 
			
		||||
		return sectors;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide,
 | 
			
		||||
			const std::vector<std::shared_ptr<Sector>>& sectors, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		IbmEncoderProto::TrackdataProto trackdata;
 | 
			
		||||
		getTrackFormat(trackdata, physicalTrack, physicalSide);
 | 
			
		||||
 | 
			
		||||
		auto writeBytes = [&](const Bytes& bytes)
 | 
			
		||||
		{
 | 
			
		||||
			Bytes header;
 | 
			
		||||
			ByteWriter bw(header);
 | 
			
		||||
			if (trackdata.use_fm())
 | 
			
		||||
				encodeFm(_bits, _cursor, bytes);
 | 
			
		||||
			else
 | 
			
		||||
				encodeMfm(_bits, _cursor, bytes, _lastBit);
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
			writeBytes(_parameters.useFm ? 6 : 12, 0x00);
 | 
			
		||||
			if (!_parameters.useFm)
 | 
			
		||||
		auto writeFillerBytes = [&](int count, uint8_t byte)
 | 
			
		||||
		{
 | 
			
		||||
			Bytes bytes = { byte };
 | 
			
		||||
			for (int i=0; i<count; i++)
 | 
			
		||||
				writeBytes(bytes);
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		double clockRateUs = 1e3 / trackdata.clock_rate_khz();
 | 
			
		||||
		if (!trackdata.use_fm())
 | 
			
		||||
			clockRateUs /= 2.0;
 | 
			
		||||
		int bitsPerRevolution = (trackdata.track_length_ms() * 1000.0) / clockRateUs;
 | 
			
		||||
		_bits.resize(bitsPerRevolution);
 | 
			
		||||
		_cursor = 0;
 | 
			
		||||
 | 
			
		||||
		uint8_t idamUnencoded = decodeUint16(trackdata.idam_byte());
 | 
			
		||||
		uint8_t damUnencoded = decodeUint16(trackdata.dam_byte());
 | 
			
		||||
 | 
			
		||||
		uint8_t sectorSize = 0;
 | 
			
		||||
		{
 | 
			
		||||
			int s = trackdata.sector_size() >> 7;
 | 
			
		||||
			while (s > 1)
 | 
			
		||||
			{
 | 
			
		||||
				for (int i=0; i<3; i++)
 | 
			
		||||
					bw.write_8(MFM_RECORD_SEPARATOR_BYTE);
 | 
			
		||||
				s >>= 1;
 | 
			
		||||
				sectorSize += 1;
 | 
			
		||||
			}
 | 
			
		||||
			bw.write_8(idamUnencoded);
 | 
			
		||||
			bw.write_8(sectorData->logicalTrack);
 | 
			
		||||
			bw.write_8(sectorData->logicalSide);
 | 
			
		||||
			bw.write_8(sectorData->logicalSector + _parameters.startSectorId);
 | 
			
		||||
			bw.write_8(sectorSize);
 | 
			
		||||
			uint16_t crc = crc16(CCITT_POLY, header);
 | 
			
		||||
			bw.write_be16(crc);
 | 
			
		||||
 | 
			
		||||
			int conventionalHeaderStart = 0;
 | 
			
		||||
			if (!_parameters.useFm)
 | 
			
		||||
			{
 | 
			
		||||
				for (int i=0; i<3; i++)
 | 
			
		||||
					writeRawBits(MFM_RECORD_SEPARATOR, 16);
 | 
			
		||||
				conventionalHeaderStart += 3;
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
			writeRawBits(_parameters.idamByte, 16);
 | 
			
		||||
			conventionalHeaderStart += 1;
 | 
			
		||||
 | 
			
		||||
			writeBytes(header.slice(conventionalHeaderStart));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		writeBytes(_parameters.gap2, gapFill);
 | 
			
		||||
		uint8_t gapFill = trackdata.use_fm() ? 0x00 : 0x4e;
 | 
			
		||||
 | 
			
		||||
		writeFillerBytes(trackdata.gap0(), gapFill);
 | 
			
		||||
		if (trackdata.emit_iam())
 | 
			
		||||
		{
 | 
			
		||||
			Bytes data;
 | 
			
		||||
			ByteWriter bw(data);
 | 
			
		||||
 | 
			
		||||
			writeBytes(_parameters.useFm ? 6 : 12, 0x00);
 | 
			
		||||
			if (!_parameters.useFm)
 | 
			
		||||
			writeFillerBytes(trackdata.use_fm() ? 6 : 12, 0x00);
 | 
			
		||||
			if (!trackdata.use_fm())
 | 
			
		||||
			{
 | 
			
		||||
				for (int i=0; i<3; i++)
 | 
			
		||||
					bw.write_8(MFM_RECORD_SEPARATOR_BYTE);
 | 
			
		||||
					writeRawBits(MFM_IAM_SEPARATOR, 16);
 | 
			
		||||
			}
 | 
			
		||||
			bw.write_8(damUnencoded);
 | 
			
		||||
 | 
			
		||||
			Bytes truncatedData = sectorData->data.slice(0, _parameters.sectorSize);
 | 
			
		||||
			bw += truncatedData;
 | 
			
		||||
			hexdump(std::cout, data.slice(0, 64));
 | 
			
		||||
			uint16_t crc = crc16(CCITT_POLY, data);
 | 
			
		||||
			bw.write_be16(crc);
 | 
			
		||||
 | 
			
		||||
			int conventionalHeaderStart = 0;
 | 
			
		||||
			if (!_parameters.useFm)
 | 
			
		||||
			{
 | 
			
		||||
				for (int i=0; i<3; i++)
 | 
			
		||||
					writeRawBits(MFM_RECORD_SEPARATOR, 16);
 | 
			
		||||
				conventionalHeaderStart += 3;
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
			writeRawBits(_parameters.damByte, 16);
 | 
			
		||||
			conventionalHeaderStart += 1;
 | 
			
		||||
 | 
			
		||||
			writeBytes(data.slice(conventionalHeaderStart));
 | 
			
		||||
			writeRawBits(trackdata.use_fm() ? FM_IAM_RECORD : MFM_IAM_RECORD, 16);
 | 
			
		||||
			writeFillerBytes(trackdata.gap1(), gapFill);
 | 
			
		||||
		}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	if (_cursor >= _bits.size())
 | 
			
		||||
		Error() << "track data overrun";
 | 
			
		||||
	while (_cursor < _bits.size())
 | 
			
		||||
		writeBytes(1, gapFill);
 | 
			
		||||
		int logicalSide = physicalSide ^ trackdata.swap_sides();
 | 
			
		||||
		bool first = true;
 | 
			
		||||
		for (int sectorId : trackdata.sectors().sector())
 | 
			
		||||
		{
 | 
			
		||||
			if (!first)
 | 
			
		||||
				writeFillerBytes(trackdata.gap3(), gapFill);
 | 
			
		||||
			first = false;
 | 
			
		||||
 | 
			
		||||
	std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
 | 
			
		||||
	fluxmap->appendBits(_bits, clockRateUs*1e3);
 | 
			
		||||
	return fluxmap;
 | 
			
		||||
			const auto& sectorData = image.get(physicalTrack, logicalSide, sectorId);
 | 
			
		||||
			if (!sectorData)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			/* Writing the sector and data records are fantastically annoying.
 | 
			
		||||
			 * The CRC is calculated from the *very start* of the record, and
 | 
			
		||||
			 * include the malformed marker bytes. Our encoder doesn't know
 | 
			
		||||
			 * about this, of course, with the result that we have to construct
 | 
			
		||||
			 * the unencoded header, calculate the checksum, and then use the
 | 
			
		||||
			 * same logic to emit the bytes which require special encoding
 | 
			
		||||
			 * before encoding the rest of the header normally. */
 | 
			
		||||
 | 
			
		||||
			{
 | 
			
		||||
				Bytes header;
 | 
			
		||||
				ByteWriter bw(header);
 | 
			
		||||
 | 
			
		||||
				writeFillerBytes(trackdata.use_fm() ? 6 : 12, 0x00);
 | 
			
		||||
				if (!trackdata.use_fm())
 | 
			
		||||
				{
 | 
			
		||||
					for (int i=0; i<3; i++)
 | 
			
		||||
						bw.write_8(MFM_RECORD_SEPARATOR_BYTE);
 | 
			
		||||
				}
 | 
			
		||||
				bw.write_8(idamUnencoded);
 | 
			
		||||
				bw.write_8(sectorData->logicalTrack);
 | 
			
		||||
				bw.write_8(sectorData->logicalSide);
 | 
			
		||||
				bw.write_8(sectorData->logicalSector);
 | 
			
		||||
				bw.write_8(sectorSize);
 | 
			
		||||
				uint16_t crc = crc16(CCITT_POLY, header);
 | 
			
		||||
				bw.write_be16(crc);
 | 
			
		||||
 | 
			
		||||
				int conventionalHeaderStart = 0;
 | 
			
		||||
				if (!trackdata.use_fm())
 | 
			
		||||
				{
 | 
			
		||||
					for (int i=0; i<3; i++)
 | 
			
		||||
						writeRawBits(MFM_RECORD_SEPARATOR, 16);
 | 
			
		||||
					conventionalHeaderStart += 3;
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
				writeRawBits(trackdata.idam_byte(), 16);
 | 
			
		||||
				conventionalHeaderStart += 1;
 | 
			
		||||
 | 
			
		||||
				writeBytes(header.slice(conventionalHeaderStart));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			writeFillerBytes(trackdata.gap2(), gapFill);
 | 
			
		||||
 | 
			
		||||
			{
 | 
			
		||||
				Bytes data;
 | 
			
		||||
				ByteWriter bw(data);
 | 
			
		||||
 | 
			
		||||
				writeFillerBytes(trackdata.use_fm() ? 6 : 12, 0x00);
 | 
			
		||||
				if (!trackdata.use_fm())
 | 
			
		||||
				{
 | 
			
		||||
					for (int i=0; i<3; i++)
 | 
			
		||||
						bw.write_8(MFM_RECORD_SEPARATOR_BYTE);
 | 
			
		||||
				}
 | 
			
		||||
				bw.write_8(damUnencoded);
 | 
			
		||||
 | 
			
		||||
				Bytes truncatedData = sectorData->data.slice(0, trackdata.sector_size());
 | 
			
		||||
				bw += truncatedData;
 | 
			
		||||
				uint16_t crc = crc16(CCITT_POLY, data);
 | 
			
		||||
				bw.write_be16(crc);
 | 
			
		||||
 | 
			
		||||
				int conventionalHeaderStart = 0;
 | 
			
		||||
				if (!trackdata.use_fm())
 | 
			
		||||
				{
 | 
			
		||||
					for (int i=0; i<3; i++)
 | 
			
		||||
						writeRawBits(MFM_RECORD_SEPARATOR, 16);
 | 
			
		||||
					conventionalHeaderStart += 3;
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
				writeRawBits(trackdata.dam_byte(), 16);
 | 
			
		||||
				conventionalHeaderStart += 1;
 | 
			
		||||
 | 
			
		||||
				writeBytes(data.slice(conventionalHeaderStart));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (_cursor >= _bits.size())
 | 
			
		||||
			Error() << "track data overrun";
 | 
			
		||||
		while (_cursor < _bits.size())
 | 
			
		||||
			writeFillerBytes(1, gapFill);
 | 
			
		||||
 | 
			
		||||
		std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
 | 
			
		||||
		fluxmap->appendBits(_bits, clockRateUs*1e3);
 | 
			
		||||
		return fluxmap;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	const IbmEncoderProto& _config;
 | 
			
		||||
	std::vector<bool> _bits;
 | 
			
		||||
	unsigned _cursor;
 | 
			
		||||
	bool _lastBit;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractEncoder> createIbmEncoder(const EncoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractEncoder>(new IbmEncoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,6 @@
 | 
			
		||||
#ifndef IBM_H
 | 
			
		||||
#define IBM_H
 | 
			
		||||
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "encoders/encoders.h"
 | 
			
		||||
 | 
			
		||||
/* IBM format (i.e. ordinary PC floppies). */
 | 
			
		||||
 | 
			
		||||
#define IBM_MFM_SYNC   0xA1   /* sync byte for MFM */
 | 
			
		||||
@@ -29,71 +26,12 @@ struct IbmIdam
 | 
			
		||||
    uint8_t crc[2];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class IbmDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    IbmDecoder(unsigned sectorBase, bool ignoreSideByte=false,
 | 
			
		||||
			const std::set<unsigned> requiredSectors=std::set<unsigned>()):
 | 
			
		||||
        _sectorBase(sectorBase),
 | 
			
		||||
        _ignoreSideByte(ignoreSideByte),
 | 
			
		||||
		_requiredSectors(requiredSectors)
 | 
			
		||||
    {}
 | 
			
		||||
class AbstractEncoder;
 | 
			
		||||
class AbstractDecoder;
 | 
			
		||||
class DecoderProto;
 | 
			
		||||
class EncoderProto;
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord();
 | 
			
		||||
    void decodeSectorRecord();
 | 
			
		||||
    void decodeDataRecord();
 | 
			
		||||
 | 
			
		||||
	std::set<unsigned> requiredSectors(Track& track) const
 | 
			
		||||
	{ return _requiredSectors; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    unsigned _sectorBase;
 | 
			
		||||
    bool _ignoreSideByte;
 | 
			
		||||
	std::set<unsigned> _requiredSectors;
 | 
			
		||||
    unsigned _currentSectorSize;
 | 
			
		||||
    unsigned _currentHeaderLength;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct IbmParameters
 | 
			
		||||
{
 | 
			
		||||
	int trackLengthMs;
 | 
			
		||||
	int sectorSize;
 | 
			
		||||
	bool emitIam;
 | 
			
		||||
	int startSectorId;
 | 
			
		||||
	int clockRateKhz;
 | 
			
		||||
	bool useFm;
 | 
			
		||||
	uint16_t idamByte;
 | 
			
		||||
	uint16_t damByte;
 | 
			
		||||
	int gap0;
 | 
			
		||||
	int gap1;
 | 
			
		||||
	int gap2;
 | 
			
		||||
	int gap3;
 | 
			
		||||
	std::string sectorSkew;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class IbmEncoder : public AbstractEncoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	IbmEncoder(const IbmParameters& parameters):
 | 
			
		||||
		_parameters(parameters)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	virtual ~IbmEncoder() {}
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	void writeRawBits(uint32_t data, int width);
 | 
			
		||||
	void writeBytes(const Bytes& bytes);
 | 
			
		||||
	void writeBytes(int count, uint8_t value);
 | 
			
		||||
	void writeSync();
 | 
			
		||||
	
 | 
			
		||||
private:
 | 
			
		||||
	IbmParameters _parameters;
 | 
			
		||||
	std::vector<bool> _bits;
 | 
			
		||||
	unsigned _cursor;
 | 
			
		||||
	bool _lastBit;
 | 
			
		||||
};
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createIbmDecoder(const DecoderProto& config);
 | 
			
		||||
extern std::unique_ptr<AbstractEncoder> createIbmEncoder(const EncoderProto& config);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										44
									
								
								arch/ibm/ibm.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								arch/ibm/ibm.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
import "lib/common.proto";
 | 
			
		||||
 | 
			
		||||
// Next: 7
 | 
			
		||||
message IbmDecoderProto {
 | 
			
		||||
	message SectorsProto {
 | 
			
		||||
		repeated int32 sector = 1            [(help) = "require these sectors to exist for a good read"];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	optional bool ignore_side_byte = 2       [default = false, (help) = "ignore side byte in sector header"];
 | 
			
		||||
	optional bool ignore_track_byte = 6      [default = false, (help) = "ignore track byte in sector header"];
 | 
			
		||||
	optional bool swap_sides = 4             [default = false, (help) = "put logical side 1 on physical side 0"];
 | 
			
		||||
	optional SectorsProto sectors = 5        [(help) = "require these sectors to exist for a good read"];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message IbmEncoderProto {
 | 
			
		||||
	// Next: 18
 | 
			
		||||
	message TrackdataProto {
 | 
			
		||||
		message SectorsProto {
 | 
			
		||||
			repeated int32 sector = 1		[(help) = "write these sectors (in order) on each track"];
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		optional int32 cylinder = 15        [(help) = "if set, the format applies only to this track"];
 | 
			
		||||
		optional int32 head = 16            [(help) = "if set, the format applies only to this head"];
 | 
			
		||||
 | 
			
		||||
		optional double track_length_ms = 1 [(help) = "length of track"];
 | 
			
		||||
		optional int32 sector_size = 2      [default=512, (help) = "number of bytes per sector"];
 | 
			
		||||
		optional bool emit_iam = 3          [default=true, (help) = "whether to emit an IAM record"];
 | 
			
		||||
		optional double clock_rate_khz = 5  [(help) = "data clock rate"];
 | 
			
		||||
		optional bool use_fm = 6            [default=false, (help) = "whether to use FM encoding rather than MFM"];
 | 
			
		||||
		optional int32 idam_byte = 7        [default=0x5554, (help) = "16-bit raw bit pattern of IDAM byte"];
 | 
			
		||||
		optional int32 dam_byte = 8         [default=0x5545, (help) = "16-bit raw bit pattern of DAM byte"];
 | 
			
		||||
		optional int32 gap0 = 9             [default=80, (help) = "size of gap 1 (the post-index gap)"];
 | 
			
		||||
		optional int32 gap1 = 10            [default=50, (help) = "size of gap 2 (the post-ID gap)"];
 | 
			
		||||
		optional int32 gap2 = 11            [default=22, (help) = "size of gap 3 (the pre-data gap)"];
 | 
			
		||||
		optional int32 gap3 = 12            [default=80, (help) = "size of gap 4 (the post-data or format gap)"];
 | 
			
		||||
		optional bool swap_sides = 14       [default=false, (help) = "swap side bytes when writing"];
 | 
			
		||||
		optional SectorsProto sectors = 17	[(help) = "write these sectors (in order) on each track"];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	repeated TrackdataProto trackdata = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2,10 +2,8 @@
 | 
			
		||||
#include "fluxmap.h"
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "protocol.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "track.h"
 | 
			
		||||
#include "macintosh.h"
 | 
			
		||||
#include "bytes.h"
 | 
			
		||||
#include "fmt/format.h"
 | 
			
		||||
@@ -26,7 +24,7 @@ static int decode_data_gcr(uint8_t gcr)
 | 
			
		||||
		#undef GCR_ENTRY
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is extremely inspired by the MESS implementation, written by Nathan Woods
 | 
			
		||||
 * and R. Belmont: https://github.com/mamedev/mame/blob/4263a71e64377db11392c458b580c5ae83556bc7/src/lib/formats/ap_dsk35.cpp
 | 
			
		||||
@@ -118,91 +116,103 @@ static Bytes decode_crazy_data(const Bytes& input, Sector::Status& status)
 | 
			
		||||
uint8_t decode_side(uint8_t side)
 | 
			
		||||
{
 | 
			
		||||
    /* Mac disks, being weird, use the side byte to encode both the side (in
 | 
			
		||||
     * bit 5) and also whether we're above track 0x3f (in bit 6).
 | 
			
		||||
     * bit 5) and also whether we're above track 0x3f (in bit 0).
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    return !!(side & 0x40);
 | 
			
		||||
    return !!(side & 0x20);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AbstractDecoder::RecordType MacintoshDecoder::advanceToNextRecord()
 | 
			
		||||
class MacintoshDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
	const FluxMatcher* matcher = nullptr;
 | 
			
		||||
	_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
	if (matcher == &SECTOR_RECORD_PATTERN)
 | 
			
		||||
		return SECTOR_RECORD;
 | 
			
		||||
	if (matcher == &DATA_RECORD_PATTERN)
 | 
			
		||||
		return DATA_RECORD;
 | 
			
		||||
	return UNKNOWN_RECORD;
 | 
			
		||||
}
 | 
			
		||||
public:
 | 
			
		||||
	MacintoshDecoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
void MacintoshDecoder::decodeSectorRecord()
 | 
			
		||||
    RecordType advanceToNextRecord()
 | 
			
		||||
	{
 | 
			
		||||
		const FluxMatcher* matcher = nullptr;
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
		if (matcher == &SECTOR_RECORD_PATTERN)
 | 
			
		||||
			return SECTOR_RECORD;
 | 
			
		||||
		if (matcher == &DATA_RECORD_PATTERN)
 | 
			
		||||
			return DATA_RECORD;
 | 
			
		||||
		return UNKNOWN_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeSectorRecord()
 | 
			
		||||
	{
 | 
			
		||||
		/* Skip ID (as we know it's a MAC_SECTOR_RECORD). */
 | 
			
		||||
		readRawBits(24);
 | 
			
		||||
 | 
			
		||||
		/* Read header. */
 | 
			
		||||
 | 
			
		||||
		auto header = toBytes(readRawBits(7*8)).slice(0, 7);
 | 
			
		||||
					
 | 
			
		||||
		uint8_t encodedTrack = decode_data_gcr(header[0]);
 | 
			
		||||
		if (encodedTrack != (_sector->physicalCylinder & 0x3f))
 | 
			
		||||
			return;
 | 
			
		||||
					
 | 
			
		||||
		uint8_t encodedSector = decode_data_gcr(header[1]);
 | 
			
		||||
		uint8_t encodedSide = decode_data_gcr(header[2]);
 | 
			
		||||
		uint8_t formatByte = decode_data_gcr(header[3]);
 | 
			
		||||
		uint8_t wantedsum = decode_data_gcr(header[4]);
 | 
			
		||||
 | 
			
		||||
		if (encodedSector > 11)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		_sector->logicalTrack = _sector->physicalCylinder;
 | 
			
		||||
		_sector->logicalSide = decode_side(encodedSide);
 | 
			
		||||
		_sector->logicalSector = encodedSector;
 | 
			
		||||
		uint8_t gotsum = (encodedTrack ^ encodedSector ^ encodedSide ^ formatByte) & 0x3f;
 | 
			
		||||
		if (wantedsum == gotsum)
 | 
			
		||||
			_sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeDataRecord()
 | 
			
		||||
	{
 | 
			
		||||
		auto id = toBytes(readRawBits(24)).reader().read_be24();
 | 
			
		||||
		if (id != MAC_DATA_RECORD)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		/* Read data. */
 | 
			
		||||
 | 
			
		||||
		readRawBits(8); /* skip spare byte */
 | 
			
		||||
		auto inputbuffer = toBytes(readRawBits(MAC_ENCODED_SECTOR_LENGTH*8))
 | 
			
		||||
			.slice(0, MAC_ENCODED_SECTOR_LENGTH);
 | 
			
		||||
 | 
			
		||||
		for (unsigned i=0; i<inputbuffer.size(); i++)
 | 
			
		||||
			inputbuffer[i] = decode_data_gcr(inputbuffer[i]);
 | 
			
		||||
			
 | 
			
		||||
		_sector->status = Sector::BAD_CHECKSUM;
 | 
			
		||||
		Bytes userData = decode_crazy_data(inputbuffer, _sector->status);
 | 
			
		||||
		_sector->data.clear();
 | 
			
		||||
		_sector->data.writer().append(userData.slice(12, 512)).append(userData.slice(0, 12));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::set<unsigned> requiredSectors(unsigned cylinder, unsigned head) const
 | 
			
		||||
	{
 | 
			
		||||
		int count;
 | 
			
		||||
		if (cylinder < 16)
 | 
			
		||||
			count = 12;
 | 
			
		||||
		else if (cylinder < 32)
 | 
			
		||||
			count = 11;
 | 
			
		||||
		else if (cylinder < 48)
 | 
			
		||||
			count = 10;
 | 
			
		||||
		else if (cylinder < 64)
 | 
			
		||||
			count = 9;
 | 
			
		||||
		else
 | 
			
		||||
			count = 8;
 | 
			
		||||
 | 
			
		||||
		std::set<unsigned> sectors;
 | 
			
		||||
		while (count--)
 | 
			
		||||
			sectors.insert(count);
 | 
			
		||||
		return sectors;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createMacintoshDecoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
    /* Skip ID (as we know it's a MAC_SECTOR_RECORD). */
 | 
			
		||||
    readRawBits(24);
 | 
			
		||||
 | 
			
		||||
    /* Read header. */
 | 
			
		||||
 | 
			
		||||
    auto header = toBytes(readRawBits(7*8)).slice(0, 7);
 | 
			
		||||
                
 | 
			
		||||
    uint8_t encodedTrack = decode_data_gcr(header[0]);
 | 
			
		||||
    if (encodedTrack != (_track->physicalTrack & 0x3f))
 | 
			
		||||
        return;
 | 
			
		||||
                
 | 
			
		||||
    uint8_t encodedSector = decode_data_gcr(header[1]);
 | 
			
		||||
    uint8_t encodedSide = decode_data_gcr(header[2]);
 | 
			
		||||
    uint8_t formatByte = decode_data_gcr(header[3]);
 | 
			
		||||
    uint8_t wantedsum = decode_data_gcr(header[4]);
 | 
			
		||||
 | 
			
		||||
    if (encodedSector > 11)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    _sector->logicalTrack = _track->physicalTrack;
 | 
			
		||||
    _sector->logicalSide = decode_side(encodedSide);
 | 
			
		||||
    _sector->logicalSector = encodedSector;
 | 
			
		||||
    uint8_t gotsum = (encodedTrack ^ encodedSector ^ encodedSide ^ formatByte) & 0x3f;
 | 
			
		||||
    if (wantedsum == gotsum)
 | 
			
		||||
        _sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new MacintoshDecoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MacintoshDecoder::decodeDataRecord()
 | 
			
		||||
{
 | 
			
		||||
    auto id = toBytes(readRawBits(24)).reader().read_be24();
 | 
			
		||||
    if (id != MAC_DATA_RECORD)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    /* Read data. */
 | 
			
		||||
 | 
			
		||||
    readRawBits(8); /* skip spare byte */
 | 
			
		||||
    auto inputbuffer = toBytes(readRawBits(MAC_ENCODED_SECTOR_LENGTH*8))
 | 
			
		||||
        .slice(0, MAC_ENCODED_SECTOR_LENGTH);
 | 
			
		||||
 | 
			
		||||
    for (unsigned i=0; i<inputbuffer.size(); i++)
 | 
			
		||||
        inputbuffer[i] = decode_data_gcr(inputbuffer[i]);
 | 
			
		||||
        
 | 
			
		||||
    _sector->status = Sector::BAD_CHECKSUM;
 | 
			
		||||
    Bytes userData = decode_crazy_data(inputbuffer, _sector->status);
 | 
			
		||||
    _sector->data.clear();
 | 
			
		||||
    _sector->data.writer().append(userData.slice(12, 512)).append(userData.slice(0, 12));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::set<unsigned> MacintoshDecoder::requiredSectors(Track& track) const
 | 
			
		||||
{
 | 
			
		||||
	int count;
 | 
			
		||||
	if (track.physicalTrack < 16)
 | 
			
		||||
		count = 12;
 | 
			
		||||
	else if (track.physicalTrack < 32)
 | 
			
		||||
		count = 11;
 | 
			
		||||
	else if (track.physicalTrack < 48)
 | 
			
		||||
		count = 10;
 | 
			
		||||
	else if (track.physicalTrack < 64)
 | 
			
		||||
		count = 9;
 | 
			
		||||
	else
 | 
			
		||||
		count = 8;
 | 
			
		||||
 | 
			
		||||
	std::set<unsigned> sectors;
 | 
			
		||||
	while (count--)
 | 
			
		||||
		sectors.insert(count);
 | 
			
		||||
	return sectors;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										263
									
								
								arch/macintosh/encoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								arch/macintosh/encoder.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,263 @@
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "encoders/encoders.h"
 | 
			
		||||
#include "macintosh.h"
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "writer.h"
 | 
			
		||||
#include "image.h"
 | 
			
		||||
#include "fmt/format.h"
 | 
			
		||||
#include "lib/encoders/encoders.pb.h"
 | 
			
		||||
#include "arch/macintosh/macintosh.pb.h"
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 | 
			
		||||
static bool lastBit;
 | 
			
		||||
 | 
			
		||||
static double clockRateUsForTrack(unsigned track)
 | 
			
		||||
{
 | 
			
		||||
	if (track < 16)
 | 
			
		||||
		return 2.623;
 | 
			
		||||
	if (track < 32)
 | 
			
		||||
		return 2.861;
 | 
			
		||||
	if (track < 48)
 | 
			
		||||
		return 3.148;
 | 
			
		||||
	if (track < 64)
 | 
			
		||||
		return 3.497;
 | 
			
		||||
	return 3.934;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned sectorsForTrack(unsigned track)
 | 
			
		||||
{
 | 
			
		||||
	if (track < 16)
 | 
			
		||||
		return 12;
 | 
			
		||||
	if (track < 32)
 | 
			
		||||
		return 11;
 | 
			
		||||
	if (track < 48)
 | 
			
		||||
		return 10;
 | 
			
		||||
	if (track < 64)
 | 
			
		||||
		return 9;
 | 
			
		||||
	return 8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int encode_data_gcr(uint8_t gcr)
 | 
			
		||||
{
 | 
			
		||||
    switch (gcr)
 | 
			
		||||
    {
 | 
			
		||||
		#define GCR_ENTRY(gcr, data) \
 | 
			
		||||
			case data: return gcr;
 | 
			
		||||
		#include "data_gcr.h"
 | 
			
		||||
		#undef GCR_ENTRY
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is extremely inspired by the MESS implementation, written by Nathan Woods
 | 
			
		||||
 * and R. Belmont: https://github.com/mamedev/mame/blob/4263a71e64377db11392c458b580c5ae83556bc7/src/lib/formats/ap_dsk35.cpp
 | 
			
		||||
 */
 | 
			
		||||
static Bytes encode_crazy_data(const Bytes& input)
 | 
			
		||||
{
 | 
			
		||||
    Bytes output;
 | 
			
		||||
    ByteWriter bw(output);
 | 
			
		||||
    ByteReader br(input);
 | 
			
		||||
 | 
			
		||||
	uint8_t w1, w2, w3, w4;
 | 
			
		||||
 | 
			
		||||
    static const int LOOKUP_LEN = MAC_SECTOR_LENGTH / 3;
 | 
			
		||||
 | 
			
		||||
    uint8_t b1[LOOKUP_LEN + 1];
 | 
			
		||||
    uint8_t b2[LOOKUP_LEN + 1];
 | 
			
		||||
    uint8_t b3[LOOKUP_LEN + 1];
 | 
			
		||||
 | 
			
		||||
	uint32_t c1 = 0;
 | 
			
		||||
	uint32_t c2 = 0;
 | 
			
		||||
	uint32_t c3 = 0;
 | 
			
		||||
	for (int j=0;; j++)
 | 
			
		||||
	{
 | 
			
		||||
		c1 = (c1 & 0xff) << 1;
 | 
			
		||||
		if (c1 & 0x0100)
 | 
			
		||||
			c1++;
 | 
			
		||||
 | 
			
		||||
		uint8_t val = br.read_8();
 | 
			
		||||
		c3 += val;
 | 
			
		||||
		if (c1 & 0x0100)
 | 
			
		||||
		{
 | 
			
		||||
			c3++;
 | 
			
		||||
			c1 &= 0xff;
 | 
			
		||||
		}
 | 
			
		||||
		b1[j] = (val ^ c1) & 0xff;
 | 
			
		||||
 | 
			
		||||
		val = br.read_8();
 | 
			
		||||
		c2 += val;
 | 
			
		||||
		if (c3 > 0xff)
 | 
			
		||||
		{
 | 
			
		||||
			c2++;
 | 
			
		||||
			c3 &= 0xff;
 | 
			
		||||
		}
 | 
			
		||||
		b2[j] = (val ^ c3) & 0xff;
 | 
			
		||||
 | 
			
		||||
		if (br.pos == 524)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		val = br.read_8();
 | 
			
		||||
		c1 += val;
 | 
			
		||||
		if (c2 > 0xff)
 | 
			
		||||
		{
 | 
			
		||||
			c1++;
 | 
			
		||||
			c2 &= 0xff;
 | 
			
		||||
		}
 | 
			
		||||
		b3[j] = (val ^ c2) & 0xff;
 | 
			
		||||
	}
 | 
			
		||||
	uint32_t c4 = ((c1 & 0xc0) >> 6) | ((c2 & 0xc0) >> 4) | ((c3 & 0xc0) >> 2);
 | 
			
		||||
	b3[LOOKUP_LEN] = 0;
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i <= LOOKUP_LEN; i++)
 | 
			
		||||
	{
 | 
			
		||||
		w1 = b1[i] & 0x3f;
 | 
			
		||||
		w2 = b2[i] & 0x3f;
 | 
			
		||||
		w3 = b3[i] & 0x3f;
 | 
			
		||||
		w4 =  ((b1[i] & 0xc0) >> 2);
 | 
			
		||||
		w4 |= ((b2[i] & 0xc0) >> 4);
 | 
			
		||||
		w4 |= ((b3[i] & 0xc0) >> 6);
 | 
			
		||||
 | 
			
		||||
		bw.write_8(w4);
 | 
			
		||||
		bw.write_8(w1);
 | 
			
		||||
		bw.write_8(w2);
 | 
			
		||||
 | 
			
		||||
		if (i != LOOKUP_LEN)
 | 
			
		||||
			bw.write_8(w3);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bw.write_8(c4 & 0x3f);
 | 
			
		||||
	bw.write_8(c3 & 0x3f);
 | 
			
		||||
	bw.write_8(c2 & 0x3f);
 | 
			
		||||
	bw.write_8(c1 & 0x3f);
 | 
			
		||||
 | 
			
		||||
	return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, const std::vector<bool>& src)
 | 
			
		||||
{
 | 
			
		||||
	for (bool bit : src)
 | 
			
		||||
	{
 | 
			
		||||
		if (cursor < bits.size())
 | 
			
		||||
			bits[cursor++] = bit;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_t data, int width)
 | 
			
		||||
{
 | 
			
		||||
	cursor += width;
 | 
			
		||||
	for (int i=0; i<width; i++)
 | 
			
		||||
	{
 | 
			
		||||
		unsigned pos = cursor - i - 1;
 | 
			
		||||
		if (pos < bits.size())
 | 
			
		||||
			bits[pos] = data & 1;
 | 
			
		||||
		data >>= 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t encode_side(uint8_t track, uint8_t side)
 | 
			
		||||
{
 | 
			
		||||
    /* Mac disks, being weird, use the side byte to encode both the side (in
 | 
			
		||||
     * bit 5) and also whether we're above track 0x3f (in bit 0).
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
	return (side ? 0x20 : 0x00) | ((track>0x3f) ? 0x01 : 0x00);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const std::shared_ptr<Sector>& sector)
 | 
			
		||||
{
 | 
			
		||||
	if ((sector->data.size() != 512) && (sector->data.size() != 524))
 | 
			
		||||
		Error() << "unsupported sector size --- you must pick 512 or 524";
 | 
			
		||||
 | 
			
		||||
	write_bits(bits, cursor, 0xff, 1*8); /* pad byte */
 | 
			
		||||
	for (int i=0; i<7; i++)
 | 
			
		||||
		write_bits(bits, cursor, 0xff3fcff3fcffLL, 6*8); /* sync */
 | 
			
		||||
	write_bits(bits, cursor, MAC_SECTOR_RECORD, 3*8);
 | 
			
		||||
 | 
			
		||||
    uint8_t encodedTrack = sector->logicalTrack & 0x3f;
 | 
			
		||||
	uint8_t encodedSector = sector->logicalSector;
 | 
			
		||||
	uint8_t encodedSide = encode_side(sector->logicalTrack, sector->logicalSide);
 | 
			
		||||
	uint8_t formatByte = MAC_FORMAT_BYTE;
 | 
			
		||||
	uint8_t headerChecksum = (encodedTrack ^ encodedSector ^ encodedSide ^ formatByte) & 0x3f;
 | 
			
		||||
 | 
			
		||||
	write_bits(bits, cursor, encode_data_gcr(encodedTrack), 1*8);
 | 
			
		||||
	write_bits(bits, cursor, encode_data_gcr(encodedSector), 1*8);
 | 
			
		||||
	write_bits(bits, cursor, encode_data_gcr(encodedSide), 1*8);
 | 
			
		||||
	write_bits(bits, cursor, encode_data_gcr(formatByte), 1*8);
 | 
			
		||||
	write_bits(bits, cursor, encode_data_gcr(headerChecksum), 1*8);
 | 
			
		||||
 | 
			
		||||
	write_bits(bits, cursor, 0xdeaaff, 3*8);
 | 
			
		||||
	write_bits(bits, cursor, 0xff3fcff3fcffLL, 6*8); /* sync */
 | 
			
		||||
	write_bits(bits, cursor, MAC_DATA_RECORD, 3*8);
 | 
			
		||||
	write_bits(bits, cursor, encode_data_gcr(sector->logicalSector), 1*8);
 | 
			
		||||
 | 
			
		||||
	Bytes wireData;
 | 
			
		||||
	wireData.writer().append(sector->data.slice(512, 12)).append(sector->data.slice(0, 512));
 | 
			
		||||
	for (uint8_t b : encode_crazy_data(wireData))
 | 
			
		||||
		write_bits(bits, cursor, encode_data_gcr(b), 1*8);
 | 
			
		||||
 | 
			
		||||
	write_bits(bits, cursor, 0xdeaaff, 3*8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class MacintoshEncoder : public AbstractEncoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	MacintoshEncoder(const EncoderProto& config):
 | 
			
		||||
		AbstractEncoder(config),
 | 
			
		||||
		_config(config.macintosh())
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		std::vector<std::shared_ptr<Sector>> sectors;
 | 
			
		||||
 | 
			
		||||
		if ((physicalTrack >= 0) && (physicalTrack < MAC_TRACKS_PER_DISK))
 | 
			
		||||
        {
 | 
			
		||||
            unsigned numSectors = sectorsForTrack(physicalTrack);
 | 
			
		||||
            for (int sectorId=0; sectorId<numSectors; sectorId++)
 | 
			
		||||
            {
 | 
			
		||||
                const auto& sector = image.get(physicalTrack, physicalSide, sectorId);
 | 
			
		||||
                if (sector)
 | 
			
		||||
                    sectors.push_back(sector);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		return sectors;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide,
 | 
			
		||||
			const std::vector<std::shared_ptr<Sector>>& sectors, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		if ((physicalTrack < 0) || (physicalTrack >= MAC_TRACKS_PER_DISK))
 | 
			
		||||
			return std::unique_ptr<Fluxmap>();
 | 
			
		||||
 | 
			
		||||
		double clockRateUs = clockRateUsForTrack(physicalTrack) * _config.clock_compensation_factor();
 | 
			
		||||
		int bitsPerRevolution = 200000.0 / clockRateUs;
 | 
			
		||||
		std::vector<bool> bits(bitsPerRevolution);
 | 
			
		||||
		unsigned cursor = 0;
 | 
			
		||||
 | 
			
		||||
		fillBitmapTo(bits, cursor, _config.post_index_gap_us() / clockRateUs, { true, false });
 | 
			
		||||
		lastBit = false;
 | 
			
		||||
 | 
			
		||||
		for (const auto& sector : sectors)
 | 
			
		||||
			write_sector(bits, cursor, sector);
 | 
			
		||||
 | 
			
		||||
		if (cursor >= bits.size())
 | 
			
		||||
			Error() << fmt::format("track data overrun by {} bits", cursor - bits.size());
 | 
			
		||||
		fillBitmapTo(bits, cursor, bits.size(), { true, false });
 | 
			
		||||
 | 
			
		||||
		std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
 | 
			
		||||
		fluxmap->appendBits(bits, clockRateUs*1e3);
 | 
			
		||||
		return fluxmap;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	const MacintoshEncoderProto& _config;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractEncoder> createMacintoshEncoder(const EncoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractEncoder>(new MacintoshEncoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -6,21 +6,17 @@
 | 
			
		||||
 | 
			
		||||
#define MAC_SECTOR_LENGTH   524 /* yes, really */
 | 
			
		||||
#define MAC_ENCODED_SECTOR_LENGTH 703
 | 
			
		||||
#define MAC_FORMAT_BYTE     0x22
 | 
			
		||||
 | 
			
		||||
class Sector;
 | 
			
		||||
class Fluxmap;
 | 
			
		||||
#define MAC_TRACKS_PER_DISK 80
 | 
			
		||||
 | 
			
		||||
class MacintoshDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~MacintoshDecoder() {}
 | 
			
		||||
class AbstractEncoder;
 | 
			
		||||
class AbstractDecoder;
 | 
			
		||||
class DecoderProto;
 | 
			
		||||
class EncoderProto;
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord();
 | 
			
		||||
    void decodeSectorRecord();
 | 
			
		||||
    void decodeDataRecord();
 | 
			
		||||
 | 
			
		||||
	std::set<unsigned> requiredSectors(Track& track) const;
 | 
			
		||||
};
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createMacintoshDecoder(const DecoderProto& config);
 | 
			
		||||
extern std::unique_ptr<AbstractEncoder> createMacintoshEncoder(const EncoderProto& config);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								arch/macintosh/macintosh.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								arch/macintosh/macintosh.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
import "lib/common.proto";
 | 
			
		||||
 | 
			
		||||
message MacintoshDecoderProto {}
 | 
			
		||||
 | 
			
		||||
message MacintoshEncoderProto {
 | 
			
		||||
	optional double post_index_gap_us = 1 [default = 0.0,
 | 
			
		||||
		(help) = "post-index gap before first sector header (microseconds)."];
 | 
			
		||||
 | 
			
		||||
	optional double clock_compensation_factor = 2 [default = 1.0,
 | 
			
		||||
		(help) = "scale the output clock by this much."];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										75
									
								
								arch/micropolis/decoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								arch/micropolis/decoder.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "fluxmap.h"
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "micropolis.h"
 | 
			
		||||
#include "bytes.h"
 | 
			
		||||
#include "fmt/format.h"
 | 
			
		||||
 | 
			
		||||
/* The sector has a preamble of MFM 0x00s and uses 0xFF as a sync pattern. */
 | 
			
		||||
static const FluxPattern SECTOR_SYNC_PATTERN(32, 0xaaaa5555);
 | 
			
		||||
 | 
			
		||||
/* Adds all bytes, with carry. */
 | 
			
		||||
uint8_t micropolisChecksum(const Bytes& bytes) {
 | 
			
		||||
	ByteReader br(bytes);
 | 
			
		||||
	uint16_t sum = 0;
 | 
			
		||||
	while (!br.eof()) {
 | 
			
		||||
		if (sum > 0xFF) {
 | 
			
		||||
			sum -= 0x100 - 1;
 | 
			
		||||
		}
 | 
			
		||||
		sum += br.read_8();
 | 
			
		||||
	}
 | 
			
		||||
	/* The last carry is ignored */
 | 
			
		||||
	return sum & 0xFF;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class MicropolisDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	MicropolisDecoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	RecordType advanceToNextRecord()
 | 
			
		||||
	{
 | 
			
		||||
		_fmr->seekToIndexMark();
 | 
			
		||||
		const FluxMatcher* matcher = nullptr;
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(SECTOR_SYNC_PATTERN, matcher);
 | 
			
		||||
		if (matcher == &SECTOR_SYNC_PATTERN) {
 | 
			
		||||
			readRawBits(16);
 | 
			
		||||
			return SECTOR_RECORD;
 | 
			
		||||
		}
 | 
			
		||||
		return UNKNOWN_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void decodeSectorRecord()
 | 
			
		||||
	{
 | 
			
		||||
		auto rawbits = readRawBits(MICROPOLIS_ENCODED_SECTOR_SIZE*16);
 | 
			
		||||
		auto bytes = decodeFmMfm(rawbits).slice(0, MICROPOLIS_ENCODED_SECTOR_SIZE);
 | 
			
		||||
		ByteReader br(bytes);
 | 
			
		||||
 | 
			
		||||
		br.read_8();  /* sync */
 | 
			
		||||
		_sector->logicalTrack = br.read_8();
 | 
			
		||||
		_sector->logicalSide = _sector->physicalHead;
 | 
			
		||||
		_sector->logicalSector = br.read_8();
 | 
			
		||||
		if (_sector->logicalSector > 15)
 | 
			
		||||
			return;
 | 
			
		||||
		if (_sector->logicalTrack > 77)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		br.read(10);  /* OS data or padding */
 | 
			
		||||
		_sector->data = br.read(256);
 | 
			
		||||
		uint8_t wantChecksum = br.read_8();
 | 
			
		||||
		uint8_t gotChecksum = micropolisChecksum(bytes.slice(1, 2+266));
 | 
			
		||||
		br.read(5);  /* 4 byte ECC and ECC-present flag */
 | 
			
		||||
 | 
			
		||||
		_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createMicropolisDecoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new MicropolisDecoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										113
									
								
								arch/micropolis/encoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								arch/micropolis/encoder.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "micropolis.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "encoders/encoders.h"
 | 
			
		||||
#include "image.h"
 | 
			
		||||
#include "lib/encoders/encoders.pb.h"
 | 
			
		||||
 | 
			
		||||
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const std::shared_ptr<Sector>& sector)
 | 
			
		||||
{
 | 
			
		||||
	if ((sector->data.size() != 256) && (sector->data.size() != MICROPOLIS_ENCODED_SECTOR_SIZE))
 | 
			
		||||
		Error() << "unsupported sector size --- you must pick 256 or 275";
 | 
			
		||||
 | 
			
		||||
	int fullSectorSize = 40 + MICROPOLIS_ENCODED_SECTOR_SIZE + 40 + 35;
 | 
			
		||||
	auto fullSector = std::make_shared<std::vector<uint8_t>>();
 | 
			
		||||
	fullSector->reserve(fullSectorSize);
 | 
			
		||||
	/* sector preamble */
 | 
			
		||||
	for (int i=0; i<40; i++)
 | 
			
		||||
		fullSector->push_back(0);
 | 
			
		||||
	Bytes sectorData;
 | 
			
		||||
	if (sector->data.size() == MICROPOLIS_ENCODED_SECTOR_SIZE)
 | 
			
		||||
		sectorData = sector->data;
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		ByteWriter writer(sectorData);
 | 
			
		||||
		writer.write_8(0xff); /* Sync */
 | 
			
		||||
		writer.write_8(sector->logicalTrack);
 | 
			
		||||
		writer.write_8(sector->logicalSector);
 | 
			
		||||
		for (int i=0; i<10; i++)
 | 
			
		||||
			writer.write_8(0); /* Padding */
 | 
			
		||||
		writer += sector->data;
 | 
			
		||||
		writer.write_8(micropolisChecksum(sectorData.slice(1)));
 | 
			
		||||
		for (int i=0; i<5; i++)
 | 
			
		||||
			writer.write_8(0); /* 4 byte ECC and ECC not present flag */
 | 
			
		||||
	}
 | 
			
		||||
	for (uint8_t b : sectorData)
 | 
			
		||||
		fullSector->push_back(b);
 | 
			
		||||
	/* sector postamble */
 | 
			
		||||
	for (int i=0; i<40; i++)
 | 
			
		||||
		fullSector->push_back(0);
 | 
			
		||||
	/* filler */
 | 
			
		||||
	for (int i=0; i<35; i++)
 | 
			
		||||
		fullSector->push_back(0);
 | 
			
		||||
 | 
			
		||||
	if (fullSector->size() != fullSectorSize)
 | 
			
		||||
		Error() << "sector mismatched length";
 | 
			
		||||
	bool lastBit = false;
 | 
			
		||||
	encodeMfm(bits, cursor, fullSector, lastBit);
 | 
			
		||||
	/* filler */
 | 
			
		||||
	for (int i=0; i<5; i++)
 | 
			
		||||
	{
 | 
			
		||||
		bits[cursor++] = 1;
 | 
			
		||||
		bits[cursor++] = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class MicropolisEncoder : public AbstractEncoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	MicropolisEncoder(const EncoderProto& config):
 | 
			
		||||
		AbstractEncoder(config),
 | 
			
		||||
		_config(config.micropolis())
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		std::vector<std::shared_ptr<Sector>> sectors;
 | 
			
		||||
 | 
			
		||||
		if ((physicalTrack >= 0) && (physicalTrack < 77))
 | 
			
		||||
		{
 | 
			
		||||
			for (int sectorId = 0; sectorId < 16; sectorId++)
 | 
			
		||||
			{
 | 
			
		||||
				const auto& sector = image.get(physicalTrack, physicalSide, sectorId);
 | 
			
		||||
				if (sector)
 | 
			
		||||
					sectors.push_back(sector);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return sectors;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide,
 | 
			
		||||
			const std::vector<std::shared_ptr<Sector>>& sectors, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		int bitsPerRevolution = 100000;
 | 
			
		||||
		double clockRateUs = 2.00;
 | 
			
		||||
 | 
			
		||||
		if ((physicalTrack < 0) || (physicalTrack >= 77) || sectors.empty())
 | 
			
		||||
			return std::unique_ptr<Fluxmap>();
 | 
			
		||||
 | 
			
		||||
		std::vector<bool> bits(bitsPerRevolution);
 | 
			
		||||
		unsigned cursor = 0;
 | 
			
		||||
 | 
			
		||||
		for (const auto& sectorData : sectors)
 | 
			
		||||
			write_sector(bits, cursor, sectorData);
 | 
			
		||||
 | 
			
		||||
		if (cursor != bits.size())
 | 
			
		||||
			Error() << "track data mismatched length";
 | 
			
		||||
 | 
			
		||||
		std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
 | 
			
		||||
		fluxmap->appendBits(bits, clockRateUs * 1e3);
 | 
			
		||||
		return fluxmap;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	const MicropolisEncoderProto& _config;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractEncoder> createMicropolisEncoder(const EncoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractEncoder>(new MicropolisEncoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								arch/micropolis/micropolis.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								arch/micropolis/micropolis.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
#ifndef MICROPOLIS_H
 | 
			
		||||
#define MICROPOLIS_H
 | 
			
		||||
 | 
			
		||||
#define MICROPOLIS_ENCODED_SECTOR_SIZE (1+2+266+6)
 | 
			
		||||
 | 
			
		||||
class AbstractDecoder;
 | 
			
		||||
class AbstractEncoder;
 | 
			
		||||
class EncoderProto;
 | 
			
		||||
class DecoderProto;
 | 
			
		||||
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createMicropolisDecoder(const DecoderProto& config);
 | 
			
		||||
extern std::unique_ptr<AbstractEncoder> createMicropolisEncoder(const EncoderProto& config);
 | 
			
		||||
 | 
			
		||||
extern uint8_t micropolisChecksum(const Bytes& bytes);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										5
									
								
								arch/micropolis/micropolis.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								arch/micropolis/micropolis.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
message MicropolisDecoderProto {}
 | 
			
		||||
message MicropolisEncoderProto {}
 | 
			
		||||
 | 
			
		||||
@@ -5,8 +5,6 @@
 | 
			
		||||
#include "fluxmap.h"
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "track.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
const int SECTOR_SIZE = 256;
 | 
			
		||||
@@ -23,53 +21,73 @@ const int SECTOR_SIZE = 256;
 | 
			
		||||
 */
 | 
			
		||||
const FluxPattern ID_PATTERN(32, 0xaaaaffaf);
 | 
			
		||||
 | 
			
		||||
void MxDecoder::beginTrack()
 | 
			
		||||
class MxDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
    _currentSector = -1;
 | 
			
		||||
    _clock = 0;
 | 
			
		||||
public:
 | 
			
		||||
	MxDecoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
    void beginTrack()
 | 
			
		||||
	{
 | 
			
		||||
		_currentSector = -1;
 | 
			
		||||
		_clock = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord()
 | 
			
		||||
	{
 | 
			
		||||
		if (_currentSector == -1)
 | 
			
		||||
		{
 | 
			
		||||
			/* First sector in the track: look for the sync marker. */
 | 
			
		||||
			const FluxMatcher* matcher = nullptr;
 | 
			
		||||
			_sector->clock = _clock = _fmr->seekToPattern(ID_PATTERN, matcher);
 | 
			
		||||
			readRawBits(32); /* skip the ID mark */
 | 
			
		||||
			_logicalTrack = decodeFmMfm(readRawBits(32)).slice(0, 32).reader().read_be16();
 | 
			
		||||
		}
 | 
			
		||||
		else if (_currentSector == 10)
 | 
			
		||||
		{
 | 
			
		||||
			/* That was the last sector on the disk. */
 | 
			
		||||
			return UNKNOWN_RECORD;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			/* Otherwise we assume the clock from the first sector is still valid.
 | 
			
		||||
			 * The decoder framwork will automatically stop when we hit the end of
 | 
			
		||||
			 * the track. */
 | 
			
		||||
			_sector->clock = _clock;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		_currentSector++;
 | 
			
		||||
		return SECTOR_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeSectorRecord()
 | 
			
		||||
	{
 | 
			
		||||
		auto bits = readRawBits((SECTOR_SIZE+2)*16);
 | 
			
		||||
		auto bytes = decodeFmMfm(bits).slice(0, SECTOR_SIZE+2).swab();
 | 
			
		||||
 | 
			
		||||
		uint16_t gotChecksum = 0;
 | 
			
		||||
		ByteReader br(bytes);
 | 
			
		||||
		for (int i=0; i<(SECTOR_SIZE/2); i++)
 | 
			
		||||
			gotChecksum += br.read_le16();
 | 
			
		||||
		uint16_t wantChecksum = br.read_le16();
 | 
			
		||||
 | 
			
		||||
		_sector->logicalTrack = _logicalTrack;
 | 
			
		||||
		_sector->logicalSide = _sector->physicalHead;
 | 
			
		||||
		_sector->logicalSector = _currentSector;
 | 
			
		||||
		_sector->data = bytes.slice(0, SECTOR_SIZE);
 | 
			
		||||
		_sector->status = (gotChecksum == wantChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    nanoseconds_t _clock;
 | 
			
		||||
    int _currentSector;
 | 
			
		||||
    int _logicalTrack;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createMxDecoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new MxDecoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AbstractDecoder::RecordType MxDecoder::advanceToNextRecord()
 | 
			
		||||
{
 | 
			
		||||
    if (_currentSector == -1)
 | 
			
		||||
    {
 | 
			
		||||
        /* First sector in the track: look for the sync marker. */
 | 
			
		||||
        const FluxMatcher* matcher = nullptr;
 | 
			
		||||
        _sector->clock = _clock = _fmr->seekToPattern(ID_PATTERN, matcher);
 | 
			
		||||
        readRawBits(32); /* skip the ID mark */
 | 
			
		||||
        _logicalTrack = decodeFmMfm(readRawBits(32)).reader().read_be16();
 | 
			
		||||
    }
 | 
			
		||||
    else if (_currentSector == 10)
 | 
			
		||||
    {
 | 
			
		||||
        /* That was the last sector on the disk. */
 | 
			
		||||
        return UNKNOWN_RECORD;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        /* Otherwise we assume the clock from the first sector is still valid.
 | 
			
		||||
         * The decoder framwork will automatically stop when we hit the end of
 | 
			
		||||
         * the track. */
 | 
			
		||||
        _sector->clock = _clock;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _currentSector++;
 | 
			
		||||
    return SECTOR_RECORD;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MxDecoder::decodeSectorRecord()
 | 
			
		||||
{
 | 
			
		||||
    auto bits = readRawBits((SECTOR_SIZE+2)*16);
 | 
			
		||||
    auto bytes = decodeFmMfm(bits).slice(0, SECTOR_SIZE+2).swab();
 | 
			
		||||
 | 
			
		||||
    uint16_t gotChecksum = 0;
 | 
			
		||||
    ByteReader br(bytes);
 | 
			
		||||
    for (int i=0; i<(SECTOR_SIZE/2); i++)
 | 
			
		||||
        gotChecksum += br.read_le16();
 | 
			
		||||
    uint16_t wantChecksum = br.read_le16();
 | 
			
		||||
 | 
			
		||||
    _sector->logicalTrack = _logicalTrack;
 | 
			
		||||
    _sector->logicalSide = _track->physicalSide;
 | 
			
		||||
    _sector->logicalSector = _currentSector;
 | 
			
		||||
    _sector->data = bytes.slice(0, SECTOR_SIZE);
 | 
			
		||||
    _sector->status = (gotChecksum == wantChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								arch/mx/mx.h
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								arch/mx/mx.h
									
									
									
									
									
								
							@@ -3,19 +3,6 @@
 | 
			
		||||
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
 | 
			
		||||
class MxDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~MxDecoder() {}
 | 
			
		||||
 | 
			
		||||
    void beginTrack();
 | 
			
		||||
    RecordType advanceToNextRecord();
 | 
			
		||||
    void decodeSectorRecord();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    nanoseconds_t _clock;
 | 
			
		||||
    int _currentSector;
 | 
			
		||||
    int _logicalTrack;
 | 
			
		||||
};
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createMxDecoder(const DecoderProto& config);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								arch/mx/mx.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/mx/mx.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
message MxDecoderProto {}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										196
									
								
								arch/northstar/decoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								arch/northstar/decoder.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,196 @@
 | 
			
		||||
/* Decoder for North Star 10-sector hard-sectored disks.
 | 
			
		||||
 *
 | 
			
		||||
 * Supports both single- and double-density.  For the sector format and
 | 
			
		||||
 * checksum algorithm, see pp. 33 of the North Star Double Density Controller
 | 
			
		||||
 * manual:
 | 
			
		||||
 *
 | 
			
		||||
 * http://bitsavers.org/pdf/northstar/boards/Northstar_MDS-A-D_1978.pdf
 | 
			
		||||
 *
 | 
			
		||||
 * North Star disks do not contain any track/head/sector information
 | 
			
		||||
 * encoded in the sector record.  For this reason, we have to be absolutely
 | 
			
		||||
 * sure that the hardSectorId is correct.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "fluxmap.h"
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "northstar.h"
 | 
			
		||||
#include "bytes.h"
 | 
			
		||||
#include "lib/decoders/decoders.pb.h"
 | 
			
		||||
#include "fmt/format.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MFM sectors have 32 bytes of 00's followed by two sync characters,
 | 
			
		||||
 * specified in the North Star MDS manual as 0xFBFB.
 | 
			
		||||
 *
 | 
			
		||||
 * This is true for most disks; however, I found a few disks, including an
 | 
			
		||||
 * original North Star DOS/BASIC v2.2.1 DQ disk) that uses 0xFBnn, where
 | 
			
		||||
 * nn is an incrementing pattern.
 | 
			
		||||
 *
 | 
			
		||||
 * 00        00        00        F         B
 | 
			
		||||
 * 0000 0000 0000 0000 0000 0000 0101 0101 0100 0101
 | 
			
		||||
 * A    A    A    A    A    A    5    5    4    5
 | 
			
		||||
 */
 | 
			
		||||
static const FluxPattern MFM_PATTERN(64, 0xAAAAAAAAAAAA5545LL);
 | 
			
		||||
 | 
			
		||||
/* FM sectors have 16 bytes of 00's followed by 0xFB.
 | 
			
		||||
 * 00        FB
 | 
			
		||||
 * 0000 0000 1111 1111 1110 1111
 | 
			
		||||
 * A    A    F    F    E    F
 | 
			
		||||
 */
 | 
			
		||||
static const FluxPattern FM_PATTERN(64, 0xAAAAAAAAAAAAFFEFLL);
 | 
			
		||||
 | 
			
		||||
const FluxMatchers ANY_SECTOR_PATTERN(
 | 
			
		||||
	{
 | 
			
		||||
		&MFM_PATTERN,
 | 
			
		||||
		&FM_PATTERN,
 | 
			
		||||
	}
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
/* Checksum is initially 0.
 | 
			
		||||
 * For each data byte, XOR with the current checksum.
 | 
			
		||||
 * Rotate checksum left, carrying bit 7 to bit 0.
 | 
			
		||||
 */
 | 
			
		||||
uint8_t northstarChecksum(const Bytes& bytes) {
 | 
			
		||||
	ByteReader br(bytes);
 | 
			
		||||
	uint8_t checksum = 0;
 | 
			
		||||
 | 
			
		||||
	while (!br.eof()) {
 | 
			
		||||
		checksum ^= br.read_8();
 | 
			
		||||
		checksum = ((checksum << 1) | ((checksum >> 7)));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return checksum;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class NorthstarDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	NorthstarDecoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config),
 | 
			
		||||
		_config(config.northstar())
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	/* Search for FM or MFM sector record */
 | 
			
		||||
	RecordType advanceToNextRecord() override
 | 
			
		||||
	{
 | 
			
		||||
		nanoseconds_t now = _fmr->tell().ns();
 | 
			
		||||
 | 
			
		||||
		/* For all but the first sector, seek to the next sector pulse.
 | 
			
		||||
		 * The first sector does not contain the sector pulse in the fluxmap.
 | 
			
		||||
		 */
 | 
			
		||||
		if (now != 0) {
 | 
			
		||||
			_fmr->seekToIndexMark();
 | 
			
		||||
			now = _fmr->tell().ns();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Discard a possible partial sector at the end of the track.
 | 
			
		||||
		 * This partial sector could be mistaken for a conflicted sector, if
 | 
			
		||||
		 * whatever data read happens to match the checksum of 0, which is
 | 
			
		||||
		 * rare, but has been observed on some disks.
 | 
			
		||||
		 */
 | 
			
		||||
		if (now > (_fmr->getDuration() - 21e6)) {
 | 
			
		||||
			_fmr->seekToIndexMark();
 | 
			
		||||
			return(UNKNOWN_RECORD);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		int msSinceIndex = std::round(now / 1e6);
 | 
			
		||||
 | 
			
		||||
		const FluxMatcher* matcher = nullptr;
 | 
			
		||||
 | 
			
		||||
		/* Note that the seekToPattern ignores the sector pulses, so if
 | 
			
		||||
		 * a sector is not found for some reason, the seek will advance
 | 
			
		||||
		 * past one or more sector pulses.  For this reason, calculate
 | 
			
		||||
		 * _hardSectorId after the sector header is found.
 | 
			
		||||
		 */
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(ANY_SECTOR_PATTERN, matcher);
 | 
			
		||||
 | 
			
		||||
		int sectorFoundTimeRaw = std::round((_fmr->tell().ns()) / 1e6);
 | 
			
		||||
		int sectorFoundTime;
 | 
			
		||||
 | 
			
		||||
		/* Round time to the nearest 20ms */
 | 
			
		||||
		if ((sectorFoundTimeRaw % 20) < 10) {
 | 
			
		||||
			sectorFoundTime = (sectorFoundTimeRaw / 20) * 20;
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			sectorFoundTime = ((sectorFoundTimeRaw + 20) / 20) * 20;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Calculate the sector ID based on time since the index */
 | 
			
		||||
		_hardSectorId = (sectorFoundTime / 20) % 10;
 | 
			
		||||
 | 
			
		||||
	//	std::cout << fmt::format(
 | 
			
		||||
	//		"Sector ID {}: hole at {}ms, sector start at {}ms",
 | 
			
		||||
	//		_hardSectorId, msSinceIndex, sectorFoundTimeRaw) << std::endl;
 | 
			
		||||
 | 
			
		||||
		if (matcher == &MFM_PATTERN) {
 | 
			
		||||
			_sectorType = SECTOR_TYPE_MFM;
 | 
			
		||||
			readRawBits(48);
 | 
			
		||||
			return SECTOR_RECORD;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (matcher == &FM_PATTERN) {
 | 
			
		||||
			_sectorType = SECTOR_TYPE_FM;
 | 
			
		||||
			readRawBits(48);
 | 
			
		||||
			return SECTOR_RECORD;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return UNKNOWN_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void decodeSectorRecord() override
 | 
			
		||||
	{
 | 
			
		||||
		unsigned recordSize, payloadSize, headerSize;
 | 
			
		||||
 | 
			
		||||
		if (_sectorType == SECTOR_TYPE_MFM) {
 | 
			
		||||
			recordSize = NORTHSTAR_ENCODED_SECTOR_SIZE_DD;
 | 
			
		||||
			payloadSize = NORTHSTAR_PAYLOAD_SIZE_DD;
 | 
			
		||||
			headerSize = NORTHSTAR_HEADER_SIZE_DD;
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			recordSize = NORTHSTAR_ENCODED_SECTOR_SIZE_SD;
 | 
			
		||||
			payloadSize = NORTHSTAR_PAYLOAD_SIZE_SD;
 | 
			
		||||
			headerSize = NORTHSTAR_HEADER_SIZE_SD;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		auto rawbits = readRawBits(recordSize * 16);
 | 
			
		||||
		auto bytes = decodeFmMfm(rawbits).slice(0, recordSize);
 | 
			
		||||
		ByteReader br(bytes);
 | 
			
		||||
		uint8_t sync_char;
 | 
			
		||||
 | 
			
		||||
		_sector->logicalSide = _sector->physicalHead;
 | 
			
		||||
		_sector->logicalSector = _hardSectorId;
 | 
			
		||||
		_sector->logicalTrack = _sector->physicalCylinder;
 | 
			
		||||
 | 
			
		||||
		sync_char = br.read_8();	/* Sync char: 0xFB */
 | 
			
		||||
		if (_sectorType == SECTOR_TYPE_MFM) {
 | 
			
		||||
			sync_char = br.read_8();/* MFM second Sync char, usually 0xFB */
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		_sector->data = br.read(payloadSize);
 | 
			
		||||
 | 
			
		||||
		uint8_t wantChecksum = br.read_8();
 | 
			
		||||
		uint8_t gotChecksum = northstarChecksum(bytes.slice(headerSize, payloadSize));
 | 
			
		||||
 | 
			
		||||
		_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::set<unsigned> requiredSectors(unsigned cylinder, unsigned head) const override
 | 
			
		||||
	{
 | 
			
		||||
		static std::set<unsigned> sectors = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 | 
			
		||||
		return sectors;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	const NorthstarDecoderProto& _config;
 | 
			
		||||
	uint8_t _sectorType = SECTOR_TYPE_MFM;
 | 
			
		||||
	uint8_t _hardSectorId;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createNorthstarDecoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new NorthstarDecoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										166
									
								
								arch/northstar/encoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								arch/northstar/encoder.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,166 @@
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "northstar.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "bytes.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "encoders/encoders.h"
 | 
			
		||||
#include "image.h"
 | 
			
		||||
#include "lib/encoders/encoders.pb.h"
 | 
			
		||||
 | 
			
		||||
#define GAP_FILL_SIZE_SD 30
 | 
			
		||||
#define PRE_HEADER_GAP_FILL_SIZE_SD 9
 | 
			
		||||
#define GAP_FILL_SIZE_DD 62
 | 
			
		||||
#define PRE_HEADER_GAP_FILL_SIZE_DD 16
 | 
			
		||||
 | 
			
		||||
#define GAP1_FILL_BYTE	(0x4F)
 | 
			
		||||
#define GAP2_FILL_BYTE	(0x4F)
 | 
			
		||||
 | 
			
		||||
#define TOTAL_SECTOR_BYTES ()
 | 
			
		||||
 | 
			
		||||
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const std::shared_ptr<Sector>& sector)
 | 
			
		||||
{
 | 
			
		||||
	int preambleSize = 0;
 | 
			
		||||
	int encodedSectorSize = 0;
 | 
			
		||||
	int gapFillSize = 0;
 | 
			
		||||
	int preHeaderGapFillSize = 0;
 | 
			
		||||
 | 
			
		||||
	bool doubleDensity;
 | 
			
		||||
 | 
			
		||||
	switch (sector->data.size()) {
 | 
			
		||||
	case NORTHSTAR_PAYLOAD_SIZE_SD:
 | 
			
		||||
		preambleSize = NORTHSTAR_PREAMBLE_SIZE_SD;
 | 
			
		||||
		encodedSectorSize = PRE_HEADER_GAP_FILL_SIZE_SD + NORTHSTAR_ENCODED_SECTOR_SIZE_SD + GAP_FILL_SIZE_SD;
 | 
			
		||||
		gapFillSize = GAP_FILL_SIZE_SD;
 | 
			
		||||
		preHeaderGapFillSize = PRE_HEADER_GAP_FILL_SIZE_SD;
 | 
			
		||||
		doubleDensity = false;
 | 
			
		||||
		break;
 | 
			
		||||
	case NORTHSTAR_PAYLOAD_SIZE_DD:
 | 
			
		||||
		preambleSize = NORTHSTAR_PREAMBLE_SIZE_DD;
 | 
			
		||||
		encodedSectorSize = PRE_HEADER_GAP_FILL_SIZE_DD + NORTHSTAR_ENCODED_SECTOR_SIZE_DD + GAP_FILL_SIZE_DD;
 | 
			
		||||
		gapFillSize = GAP_FILL_SIZE_DD;
 | 
			
		||||
		preHeaderGapFillSize = PRE_HEADER_GAP_FILL_SIZE_DD;
 | 
			
		||||
		doubleDensity = true;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		Error() << "unsupported sector size --- you must pick 256 or 512";
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int fullSectorSize = preambleSize + encodedSectorSize;
 | 
			
		||||
	auto fullSector = std::make_shared<std::vector<uint8_t>>();
 | 
			
		||||
	fullSector->reserve(fullSectorSize);
 | 
			
		||||
 | 
			
		||||
	/* sector gap after index pulse */
 | 
			
		||||
	for (int i = 0; i < preHeaderGapFillSize; i++)
 | 
			
		||||
		fullSector->push_back(GAP1_FILL_BYTE);
 | 
			
		||||
 | 
			
		||||
	/* sector preamble */
 | 
			
		||||
	for (int i = 0; i < preambleSize; i++)
 | 
			
		||||
		fullSector->push_back(0);
 | 
			
		||||
 | 
			
		||||
	Bytes sectorData;
 | 
			
		||||
	if (sector->data.size() == encodedSectorSize)
 | 
			
		||||
		sectorData = sector->data;
 | 
			
		||||
	else {
 | 
			
		||||
		ByteWriter writer(sectorData);
 | 
			
		||||
		writer.write_8(0xFB);     /* sync character */
 | 
			
		||||
		if (doubleDensity == true) {
 | 
			
		||||
			writer.write_8(0xFB); /* Double-density has two sync characters */
 | 
			
		||||
		}
 | 
			
		||||
		writer += sector->data;
 | 
			
		||||
		if (doubleDensity == true) {
 | 
			
		||||
			writer.write_8(northstarChecksum(sectorData.slice(2)));
 | 
			
		||||
		} else {
 | 
			
		||||
			writer.write_8(northstarChecksum(sectorData.slice(1)));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for (uint8_t b : sectorData)
 | 
			
		||||
		fullSector->push_back(b);
 | 
			
		||||
 | 
			
		||||
	if (sector->logicalSector != 9) {
 | 
			
		||||
		/* sector postamble */
 | 
			
		||||
		for (int i = 0; i < gapFillSize; i++)
 | 
			
		||||
			fullSector->push_back(GAP2_FILL_BYTE);
 | 
			
		||||
 | 
			
		||||
		if (fullSector->size() != fullSectorSize)
 | 
			
		||||
			Error() << "sector mismatched length (" << sector->data.size() << ") expected: " << fullSector->size() << " got " << fullSectorSize;
 | 
			
		||||
	} else {
 | 
			
		||||
		/* sector postamble */
 | 
			
		||||
		for (int i = 0; i < gapFillSize; i++)
 | 
			
		||||
			fullSector->push_back(GAP2_FILL_BYTE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool lastBit = false;
 | 
			
		||||
 | 
			
		||||
	if (doubleDensity == true) {
 | 
			
		||||
		encodeMfm(bits, cursor, fullSector, lastBit);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		encodeFm(bits, cursor, fullSector);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class NorthstarEncoder : public AbstractEncoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	NorthstarEncoder(const EncoderProto& config):
 | 
			
		||||
		AbstractEncoder(config),
 | 
			
		||||
		_config(config.northstar())
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		std::vector<std::shared_ptr<Sector>> sectors;
 | 
			
		||||
 | 
			
		||||
		if ((physicalTrack >= 0) && (physicalTrack < 35))
 | 
			
		||||
		{
 | 
			
		||||
			for (int sectorId = 0; sectorId < 10; sectorId++)
 | 
			
		||||
			{
 | 
			
		||||
				const auto& sector = image.get(physicalTrack, physicalSide, sectorId);
 | 
			
		||||
				if (sector)
 | 
			
		||||
					sectors.push_back(sector);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return sectors;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide,
 | 
			
		||||
			const std::vector<std::shared_ptr<Sector>>& sectors, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		int bitsPerRevolution = 100000;
 | 
			
		||||
		double clockRateUs = 4.00;
 | 
			
		||||
 | 
			
		||||
		if ((physicalTrack < 0) || (physicalTrack >= 35) || sectors.empty())
 | 
			
		||||
			return std::unique_ptr<Fluxmap>();
 | 
			
		||||
 | 
			
		||||
		const auto& sector = *sectors.begin();
 | 
			
		||||
		if (sector->data.size() == NORTHSTAR_PAYLOAD_SIZE_SD) {
 | 
			
		||||
			bitsPerRevolution /= 2;		// FM
 | 
			
		||||
		} else {
 | 
			
		||||
			clockRateUs /= 2.00;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		std::vector<bool> bits(bitsPerRevolution);
 | 
			
		||||
		unsigned cursor = 0;
 | 
			
		||||
 | 
			
		||||
		for (const auto& sectorData : sectors)
 | 
			
		||||
			write_sector(bits, cursor, sectorData);
 | 
			
		||||
 | 
			
		||||
		if (cursor > bits.size())
 | 
			
		||||
			Error() << "track data overrun";
 | 
			
		||||
 | 
			
		||||
		std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
 | 
			
		||||
		fluxmap->appendBits(bits, clockRateUs * 1e3);
 | 
			
		||||
		return fluxmap;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	const NorthstarEncoderProto& _config;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractEncoder> createNorthstarEncoder(const EncoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractEncoder>(new NorthstarEncoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								arch/northstar/northstar.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								arch/northstar/northstar.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
#ifndef NORTHSTAR_H
 | 
			
		||||
#define NORTHSTAR_H
 | 
			
		||||
 | 
			
		||||
/* Northstar floppies are 10-hard sectored disks with a sector format as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * |----------------------------------|
 | 
			
		||||
 * | SYNC Byte  | Payload  | Checksum |
 | 
			
		||||
 * |------------+----------+----------|
 | 
			
		||||
 * | 1 (0xFB)   | 256 (SD) |    1     |
 | 
			
		||||
 * | 2 (0xFBFB) | 512 (DD) |          |
 | 
			
		||||
 * |----------------------------------|
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define NORTHSTAR_PREAMBLE_SIZE_SD		(16)
 | 
			
		||||
#define NORTHSTAR_PREAMBLE_SIZE_DD		(32)
 | 
			
		||||
#define NORTHSTAR_HEADER_SIZE_SD		(1)
 | 
			
		||||
#define NORTHSTAR_HEADER_SIZE_DD		(2)
 | 
			
		||||
#define NORTHSTAR_PAYLOAD_SIZE_SD		(256)
 | 
			
		||||
#define NORTHSTAR_PAYLOAD_SIZE_DD		(512)
 | 
			
		||||
#define NORTHSTAR_CHECKSUM_SIZE		(1)
 | 
			
		||||
#define NORTHSTAR_ENCODED_SECTOR_SIZE_SD	(NORTHSTAR_HEADER_SIZE_SD + NORTHSTAR_PAYLOAD_SIZE_SD + NORTHSTAR_CHECKSUM_SIZE)
 | 
			
		||||
#define NORTHSTAR_ENCODED_SECTOR_SIZE_DD	(NORTHSTAR_HEADER_SIZE_DD + NORTHSTAR_PAYLOAD_SIZE_DD + NORTHSTAR_CHECKSUM_SIZE)
 | 
			
		||||
 | 
			
		||||
#define SECTOR_TYPE_MFM			(0)
 | 
			
		||||
#define SECTOR_TYPE_FM				(1)
 | 
			
		||||
 | 
			
		||||
class AbstractDecoder;
 | 
			
		||||
class AbstractEncoder;
 | 
			
		||||
class EncoderProto;
 | 
			
		||||
class DecoderProto;
 | 
			
		||||
 | 
			
		||||
extern uint8_t northstarChecksum(const Bytes& bytes);
 | 
			
		||||
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createNorthstarDecoder(const DecoderProto& config);
 | 
			
		||||
extern std::unique_ptr<AbstractEncoder> createNorthstarEncoder(const EncoderProto& config);
 | 
			
		||||
 | 
			
		||||
#endif /* NORTHSTAR */
 | 
			
		||||
							
								
								
									
										5
									
								
								arch/northstar/northstar.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								arch/northstar/northstar.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
message NorthstarDecoderProto {}
 | 
			
		||||
message NorthstarEncoderProto {}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										98
									
								
								arch/tids990/decoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								arch/tids990/decoder.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "encoders/encoders.h"
 | 
			
		||||
#include "tids990/tids990.h"
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "fluxmap.h"
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
 | 
			
		||||
/* The Texas Instruments DS990 uses MFM with a scheme similar to a simplified
 | 
			
		||||
 * version of the IBM record scheme (it's actually easier to parse than IBM).
 | 
			
		||||
 * There are 26 sectors per track, each holding a rather weird 288 bytes.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Sector record:
 | 
			
		||||
 * data:    0  1  0  1  0  1  0  1 .0  0  0  0  1  0  1  0  = 0x550a
 | 
			
		||||
 * mfm:     00 01 00 01 00 01 00 01.00 10 10 10 01 00 01 00 = 0x11112a44
 | 
			
		||||
 * special: 00 01 00 01 00 01 00 01.00 10 00 10 01 00 01 00 = 0x11112244
 | 
			
		||||
 *                                        ^^
 | 
			
		||||
 * When shifted out of phase, the special 0xa1 byte becomes an illegal
 | 
			
		||||
 * encoding (you can't do 10 00). So this can't be spoofed by user data.
 | 
			
		||||
 */
 | 
			
		||||
const FluxPattern SECTOR_RECORD_PATTERN(32, 0x11112244);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Data record:
 | 
			
		||||
 * data:    0  1  0  1  0  1  0  1 .0  0  0  0  1  0  1  1  = 0x550c
 | 
			
		||||
 * mfm:     00 01 00 01 00 01 00 01.00 10 10 10 01 00 01 01 = 0x11112a45
 | 
			
		||||
 * special: 00 01 00 01 00 01 00 01.00 10 00 10 01 00 01 01 = 0x11112245
 | 
			
		||||
 *                                        ^^
 | 
			
		||||
 * When shifted out of phase, the special 0xa1 byte becomes an illegal
 | 
			
		||||
 * encoding (you can't do 10 00). So this can't be spoofed by user data.
 | 
			
		||||
 */
 | 
			
		||||
const FluxPattern DATA_RECORD_PATTERN(32, 0x11112245);
 | 
			
		||||
 | 
			
		||||
const FluxMatchers ANY_RECORD_PATTERN({ &SECTOR_RECORD_PATTERN, &DATA_RECORD_PATTERN });
 | 
			
		||||
 | 
			
		||||
class Tids990Decoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	Tids990Decoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord()
 | 
			
		||||
	{
 | 
			
		||||
		const FluxMatcher* matcher = nullptr;
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
		if (matcher == &SECTOR_RECORD_PATTERN)
 | 
			
		||||
			return RecordType::SECTOR_RECORD;
 | 
			
		||||
		if (matcher == &DATA_RECORD_PATTERN)
 | 
			
		||||
			return RecordType::DATA_RECORD;
 | 
			
		||||
		return RecordType::UNKNOWN_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeSectorRecord()
 | 
			
		||||
	{
 | 
			
		||||
		auto bits = readRawBits(TIDS990_SECTOR_RECORD_SIZE*16);
 | 
			
		||||
		auto bytes = decodeFmMfm(bits).slice(0, TIDS990_SECTOR_RECORD_SIZE);
 | 
			
		||||
 | 
			
		||||
		ByteReader br(bytes);
 | 
			
		||||
		uint16_t gotChecksum = crc16(CCITT_POLY, bytes.slice(1, TIDS990_SECTOR_RECORD_SIZE-3));
 | 
			
		||||
 | 
			
		||||
		br.seek(2);
 | 
			
		||||
		_sector->logicalSide = br.read_8() >> 3;
 | 
			
		||||
		_sector->logicalTrack = br.read_8();
 | 
			
		||||
		br.read_8(); /* number of sectors per track */
 | 
			
		||||
		_sector->logicalSector = br.read_8();
 | 
			
		||||
		br.read_be16(); /* sector size */
 | 
			
		||||
		uint16_t wantChecksum = br.read_be16();
 | 
			
		||||
 | 
			
		||||
		if (wantChecksum == gotChecksum)
 | 
			
		||||
			_sector->status = Sector::DATA_MISSING; /* correct but unintuitive */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void decodeDataRecord()
 | 
			
		||||
	{
 | 
			
		||||
		auto bits = readRawBits(TIDS990_DATA_RECORD_SIZE*16);
 | 
			
		||||
		auto bytes = decodeFmMfm(bits).slice(0, TIDS990_DATA_RECORD_SIZE);
 | 
			
		||||
 | 
			
		||||
		ByteReader br(bytes);
 | 
			
		||||
		uint16_t gotChecksum = crc16(CCITT_POLY, bytes.slice(1, TIDS990_DATA_RECORD_SIZE-3));
 | 
			
		||||
 | 
			
		||||
		br.seek(2);
 | 
			
		||||
		_sector->data = br.read(TIDS990_PAYLOAD_SIZE);
 | 
			
		||||
		uint16_t wantChecksum = br.read_be16();
 | 
			
		||||
		_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createTids990Decoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new Tids990Decoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										168
									
								
								arch/tids990/encoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								arch/tids990/encoder.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,168 @@
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "encoders/encoders.h"
 | 
			
		||||
#include "tids990.h"
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "writer.h"
 | 
			
		||||
#include "image.h"
 | 
			
		||||
#include "arch/tids990/tids990.pb.h"
 | 
			
		||||
#include "lib/encoders/encoders.pb.h"
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
 | 
			
		||||
static int charToInt(char c)
 | 
			
		||||
{
 | 
			
		||||
	if (isdigit(c))
 | 
			
		||||
		return c - '0';
 | 
			
		||||
	return 10 + tolower(c) - 'a';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t decodeUint16(uint16_t raw)
 | 
			
		||||
{
 | 
			
		||||
	Bytes b;
 | 
			
		||||
	ByteWriter bw(b);
 | 
			
		||||
	bw.write_be16(raw);
 | 
			
		||||
	return decodeFmMfm(b.toBits())[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Tids990Encoder : public AbstractEncoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	Tids990Encoder(const EncoderProto& config):
 | 
			
		||||
		AbstractEncoder(config),
 | 
			
		||||
		_config(config.tids990())
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	void writeRawBits(uint32_t data, int width)
 | 
			
		||||
	{
 | 
			
		||||
		_cursor += width;
 | 
			
		||||
		_lastBit = data & 1;
 | 
			
		||||
		for (int i=0; i<width; i++)
 | 
			
		||||
		{
 | 
			
		||||
			unsigned pos = _cursor - i - 1;
 | 
			
		||||
			if (pos < _bits.size())
 | 
			
		||||
				_bits[pos] = data & 1;
 | 
			
		||||
			data >>= 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void writeBytes(const Bytes& bytes)
 | 
			
		||||
	{
 | 
			
		||||
		encodeMfm(_bits, _cursor, bytes, _lastBit);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void writeBytes(int count, uint8_t byte)
 | 
			
		||||
	{
 | 
			
		||||
		Bytes bytes = { byte };
 | 
			
		||||
		for (int i=0; i<count; i++)
 | 
			
		||||
			writeBytes(bytes);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		std::vector<std::shared_ptr<Sector>> sectors;
 | 
			
		||||
 | 
			
		||||
		for (char sectorChar : _config.sector_skew())
 | 
			
		||||
        {
 | 
			
		||||
			int sectorId = charToInt(sectorChar);
 | 
			
		||||
			const auto& sector = image.get(physicalTrack, physicalSide, sectorId);
 | 
			
		||||
			if (sector)
 | 
			
		||||
				sectors.push_back(sector);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		return sectors;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide,
 | 
			
		||||
			const std::vector<std::shared_ptr<Sector>>& sectors, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		double clockRateUs = 1e3 / _config.clock_rate_khz() / 2.0;
 | 
			
		||||
		int bitsPerRevolution = (_config.track_length_ms() * 1000.0) / clockRateUs;
 | 
			
		||||
		_bits.resize(bitsPerRevolution);
 | 
			
		||||
		_cursor = 0;
 | 
			
		||||
 | 
			
		||||
		uint8_t am1Unencoded = decodeUint16(_config.am1_byte());
 | 
			
		||||
		uint8_t am2Unencoded = decodeUint16(_config.am2_byte());
 | 
			
		||||
 | 
			
		||||
		writeBytes(_config.gap1_bytes(), 0x55);
 | 
			
		||||
 | 
			
		||||
		bool first = true;
 | 
			
		||||
		for (char sectorChar : _config.sector_skew())
 | 
			
		||||
		{
 | 
			
		||||
			int sectorId = charToInt(sectorChar);
 | 
			
		||||
			if (!first)
 | 
			
		||||
				writeBytes(_config.gap3_bytes(), 0x55);
 | 
			
		||||
			first = false;
 | 
			
		||||
 | 
			
		||||
			const auto& sectorData = image.get(physicalTrack, physicalSide, sectorId);
 | 
			
		||||
			if (!sectorData)
 | 
			
		||||
				Error() << fmt::format("format tried to find sector {} which wasn't in the input file", sectorId);
 | 
			
		||||
 | 
			
		||||
			/* Writing the sector and data records are fantastically annoying.
 | 
			
		||||
			 * The CRC is calculated from the *very start* of the record, and
 | 
			
		||||
			 * include the malformed marker bytes. Our encoder doesn't know
 | 
			
		||||
			 * about this, of course, with the result that we have to construct
 | 
			
		||||
			 * the unencoded header, calculate the checksum, and then use the
 | 
			
		||||
			 * same logic to emit the bytes which require special encoding
 | 
			
		||||
			 * before encoding the rest of the header normally. */
 | 
			
		||||
 | 
			
		||||
			{
 | 
			
		||||
				Bytes header;
 | 
			
		||||
				ByteWriter bw(header);
 | 
			
		||||
 | 
			
		||||
				writeBytes(12, 0x55);
 | 
			
		||||
				bw.write_8(am1Unencoded);
 | 
			
		||||
				bw.write_8(sectorData->logicalSide << 3);
 | 
			
		||||
				bw.write_8(sectorData->logicalTrack);
 | 
			
		||||
				bw.write_8(_config.sector_count());
 | 
			
		||||
				bw.write_8(sectorData->logicalSector);
 | 
			
		||||
				bw.write_be16(sectorData->data.size());
 | 
			
		||||
				uint16_t crc = crc16(CCITT_POLY, header);
 | 
			
		||||
				bw.write_be16(crc);
 | 
			
		||||
 | 
			
		||||
				writeRawBits(_config.am1_byte(), 16);
 | 
			
		||||
				writeBytes(header.slice(1));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			writeBytes(_config.gap2_bytes(), 0x55);
 | 
			
		||||
 | 
			
		||||
			{
 | 
			
		||||
				Bytes data;
 | 
			
		||||
				ByteWriter bw(data);
 | 
			
		||||
 | 
			
		||||
				writeBytes(12, 0x55);
 | 
			
		||||
				bw.write_8(am2Unencoded);
 | 
			
		||||
 | 
			
		||||
				bw += sectorData->data;
 | 
			
		||||
				uint16_t crc = crc16(CCITT_POLY, data);
 | 
			
		||||
				bw.write_be16(crc);
 | 
			
		||||
 | 
			
		||||
				writeRawBits(_config.am2_byte(), 16);
 | 
			
		||||
				writeBytes(data.slice(1));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (_cursor >= _bits.size())
 | 
			
		||||
			Error() << "track data overrun";
 | 
			
		||||
		while (_cursor < _bits.size())
 | 
			
		||||
			writeBytes(1, 0x55);
 | 
			
		||||
		
 | 
			
		||||
		std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
 | 
			
		||||
		fluxmap->appendBits(_bits, clockRateUs*1e3);
 | 
			
		||||
		return fluxmap;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	const Tids990EncoderProto& _config;
 | 
			
		||||
	std::vector<bool> _bits;
 | 
			
		||||
	unsigned _cursor;
 | 
			
		||||
	bool _lastBit;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractEncoder> createTids990Encoder(const EncoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractEncoder>(new Tids990Encoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								arch/tids990/tids990.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								arch/tids990/tids990.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
#ifndef TIDS990_H
 | 
			
		||||
#define TIDS990_H
 | 
			
		||||
 | 
			
		||||
#define TIDS990_PAYLOAD_SIZE       288 /* bytes */
 | 
			
		||||
#define TIDS990_SECTOR_RECORD_SIZE 10 /* bytes */
 | 
			
		||||
#define TIDS990_DATA_RECORD_SIZE   (TIDS990_PAYLOAD_SIZE + 4) /* bytes */
 | 
			
		||||
 | 
			
		||||
class AbstractEncoder;
 | 
			
		||||
class AbstractDecoder;
 | 
			
		||||
class DecoderProto;
 | 
			
		||||
class EncoderProto;
 | 
			
		||||
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createTids990Decoder(const DecoderProto& config);
 | 
			
		||||
extern std::unique_ptr<AbstractEncoder> createTids990Encoder(const EncoderProto& config);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								arch/tids990/tids990.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								arch/tids990/tids990.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
import "lib/common.proto";
 | 
			
		||||
 | 
			
		||||
message Tids990DecoderProto {}
 | 
			
		||||
message Tids990EncoderProto {
 | 
			
		||||
	optional double track_length_ms = 1 [ default = 166,
 | 
			
		||||
		(help) = "length of a track" ];
 | 
			
		||||
	optional int32 sector_count = 2 [ default = 26,
 | 
			
		||||
		(help) = "number of sectors per track" ];
 | 
			
		||||
	optional double clock_rate_khz = 3 [ default = 500,
 | 
			
		||||
		(help) = "clock rate of data to write" ];
 | 
			
		||||
	optional int32 am1_byte = 4 [ default = 0x2244,
 | 
			
		||||
		(help) = "16-bit RAW bit pattern to use for the AM1 ID byte" ];
 | 
			
		||||
	optional int32 am2_byte = 5 [ default = 0x2245,
 | 
			
		||||
		(help) = "16-bit RAW bit pattern to use for the AM2 ID byte" ];
 | 
			
		||||
	optional int32 gap1_bytes = 6 [ default = 80,
 | 
			
		||||
		(help) = "size of gap 1 (the post-index gap)" ];
 | 
			
		||||
	optional int32 gap2_bytes = 7 [ default = 21,
 | 
			
		||||
		(help) = "size of gap 2 (the post-ID gap)" ];
 | 
			
		||||
	optional int32 gap3_bytes = 8 [ default = 51,
 | 
			
		||||
		(help) = "size of gap 3 (the post-data or format gap)" ];
 | 
			
		||||
	optional string sector_skew = 9 [ default = "1mhc72nid83oje94pkfa50lgb6",
 | 
			
		||||
		(help) = "order to emit sectors" ];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2,13 +2,11 @@
 | 
			
		||||
#include "fluxmap.h"
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "protocol.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "victor9k.h"
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "bytes.h"
 | 
			
		||||
#include "track.h"
 | 
			
		||||
#include "fmt/format.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
@@ -27,7 +25,7 @@ static int decode_data_gcr(uint8_t gcr)
 | 
			
		||||
		#undef GCR_ENTRY
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Bytes decode(const std::vector<bool>& bits)
 | 
			
		||||
{
 | 
			
		||||
@@ -54,58 +52,73 @@ static Bytes decode(const std::vector<bool>& bits)
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AbstractDecoder::RecordType Victor9kDecoder::advanceToNextRecord()
 | 
			
		||||
class Victor9kDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
	const FluxMatcher* matcher = nullptr;
 | 
			
		||||
	_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
	if (matcher == &SECTOR_RECORD_PATTERN)
 | 
			
		||||
		return SECTOR_RECORD;
 | 
			
		||||
	if (matcher == &DATA_RECORD_PATTERN)
 | 
			
		||||
		return DATA_RECORD;
 | 
			
		||||
	return UNKNOWN_RECORD;
 | 
			
		||||
public:
 | 
			
		||||
	Victor9kDecoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord()
 | 
			
		||||
	{
 | 
			
		||||
		const FluxMatcher* matcher = nullptr;
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | 
			
		||||
		if (matcher == &SECTOR_RECORD_PATTERN)
 | 
			
		||||
			return SECTOR_RECORD;
 | 
			
		||||
		if (matcher == &DATA_RECORD_PATTERN)
 | 
			
		||||
			return DATA_RECORD;
 | 
			
		||||
		return UNKNOWN_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeSectorRecord()
 | 
			
		||||
	{
 | 
			
		||||
		/* Skip the sync marker bit. */
 | 
			
		||||
		readRawBits(22);
 | 
			
		||||
 | 
			
		||||
		/* Read header. */
 | 
			
		||||
 | 
			
		||||
		auto bytes = decode(readRawBits(4*10)).slice(0, 4);
 | 
			
		||||
 | 
			
		||||
		uint8_t rawTrack = bytes[1];
 | 
			
		||||
		_sector->logicalSector = bytes[2];
 | 
			
		||||
		uint8_t gotChecksum = bytes[3];
 | 
			
		||||
 | 
			
		||||
		_sector->logicalTrack = rawTrack & 0x7f;
 | 
			
		||||
		_sector->logicalSide = rawTrack >> 7;
 | 
			
		||||
		uint8_t wantChecksum = bytes[1] + bytes[2];
 | 
			
		||||
		if ((_sector->logicalSector > 20) || (_sector->logicalTrack > 85) || (_sector->logicalSide > 1))
 | 
			
		||||
			return;
 | 
			
		||||
					
 | 
			
		||||
		if (wantChecksum == gotChecksum)
 | 
			
		||||
			_sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeDataRecord()
 | 
			
		||||
	{
 | 
			
		||||
		/* Skip the sync marker bit. */
 | 
			
		||||
		readRawBits(22);
 | 
			
		||||
 | 
			
		||||
		/* Read data. */
 | 
			
		||||
 | 
			
		||||
		auto bytes = decode(readRawBits((VICTOR9K_SECTOR_LENGTH+5)*10))
 | 
			
		||||
			.slice(0, VICTOR9K_SECTOR_LENGTH+5);
 | 
			
		||||
		ByteReader br(bytes);
 | 
			
		||||
 | 
			
		||||
		/* Check that this is actually a data record. */
 | 
			
		||||
		
 | 
			
		||||
		if (br.read_8() != 8)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		_sector->data = br.read(VICTOR9K_SECTOR_LENGTH);
 | 
			
		||||
		uint16_t gotChecksum = sumBytes(_sector->data);
 | 
			
		||||
		uint16_t wantChecksum = br.read_le16();
 | 
			
		||||
		_sector->status = (gotChecksum == wantChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createVictor9kDecoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new Victor9kDecoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Victor9kDecoder::decodeSectorRecord()
 | 
			
		||||
{
 | 
			
		||||
    /* Skip the sync marker bit. */
 | 
			
		||||
    readRawBits(23);
 | 
			
		||||
 | 
			
		||||
    /* Read header. */
 | 
			
		||||
 | 
			
		||||
    auto bytes = decode(readRawBits(4*10)).slice(0, 4);
 | 
			
		||||
 | 
			
		||||
    uint8_t rawTrack = bytes[1];
 | 
			
		||||
    _sector->logicalSector = bytes[2];
 | 
			
		||||
    uint8_t gotChecksum = bytes[3];
 | 
			
		||||
 | 
			
		||||
    _sector->logicalTrack = rawTrack & 0x7f;
 | 
			
		||||
    _sector->logicalSide = rawTrack >> 7;
 | 
			
		||||
    uint8_t wantChecksum = bytes[1] + bytes[2];
 | 
			
		||||
    if ((_sector->logicalSector > 20) || (_sector->logicalTrack > 85) || (_sector->logicalSide > 1))
 | 
			
		||||
        return;
 | 
			
		||||
                
 | 
			
		||||
    if (wantChecksum == gotChecksum)
 | 
			
		||||
        _sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Victor9kDecoder::decodeDataRecord()
 | 
			
		||||
{
 | 
			
		||||
    /* Skip the sync marker bit. */
 | 
			
		||||
    readRawBits(23);
 | 
			
		||||
 | 
			
		||||
    /* Read data. */
 | 
			
		||||
 | 
			
		||||
    auto bytes = decode(readRawBits((VICTOR9K_SECTOR_LENGTH+5)*10))
 | 
			
		||||
        .slice(0, VICTOR9K_SECTOR_LENGTH+5);
 | 
			
		||||
    ByteReader br(bytes);
 | 
			
		||||
 | 
			
		||||
    /* Check that this is actually a data record. */
 | 
			
		||||
    
 | 
			
		||||
    if (br.read_8() != 8)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    _sector->data = br.read(VICTOR9K_SECTOR_LENGTH);
 | 
			
		||||
    uint16_t gotChecksum = sumBytes(_sector->data);
 | 
			
		||||
    uint16_t wantChecksum = br.read_le16();
 | 
			
		||||
    _sector->status = (gotChecksum == wantChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										200
									
								
								arch/victor9k/encoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								arch/victor9k/encoder.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,200 @@
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "encoders/encoders.h"
 | 
			
		||||
#include "victor9k.h"
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "writer.h"
 | 
			
		||||
#include "image.h"
 | 
			
		||||
#include "fmt/format.h"
 | 
			
		||||
#include "arch/victor9k/victor9k.pb.h"
 | 
			
		||||
#include "lib/encoders/encoders.pb.h"
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include "bytes.h"
 | 
			
		||||
 | 
			
		||||
static bool lastBit;
 | 
			
		||||
 | 
			
		||||
static void write_zero_bits(std::vector<bool>& bits, unsigned& cursor, unsigned count)
 | 
			
		||||
{
 | 
			
		||||
    while (count--)
 | 
			
		||||
	{
 | 
			
		||||
		if (cursor < bits.size())
 | 
			
		||||
			lastBit = bits[cursor++] = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_one_bits(std::vector<bool>& bits, unsigned& cursor, unsigned count)
 | 
			
		||||
{
 | 
			
		||||
    while (count--)
 | 
			
		||||
	{
 | 
			
		||||
		if (cursor < bits.size())
 | 
			
		||||
			lastBit = bits[cursor++] = 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, const std::vector<bool>& src)
 | 
			
		||||
{
 | 
			
		||||
	for (bool bit : src)
 | 
			
		||||
	{
 | 
			
		||||
		if (cursor < bits.size())
 | 
			
		||||
			lastBit = bits[cursor++] = bit;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_t data, int width)
 | 
			
		||||
{
 | 
			
		||||
	cursor += width;
 | 
			
		||||
	lastBit = data & 1;
 | 
			
		||||
	for (int i=0; i<width; i++)
 | 
			
		||||
	{
 | 
			
		||||
		unsigned pos = cursor - i - 1;
 | 
			
		||||
		if (pos < bits.size())
 | 
			
		||||
			bits[pos] = data & 1;
 | 
			
		||||
		data >>= 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, const Bytes& bytes)
 | 
			
		||||
{
 | 
			
		||||
	ByteReader br(bytes);
 | 
			
		||||
	BitReader bitr(br);
 | 
			
		||||
 | 
			
		||||
	while (!bitr.eof())
 | 
			
		||||
	{
 | 
			
		||||
		if (cursor < bits.size())
 | 
			
		||||
			bits[cursor++] = bitr.get();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int encode_data_gcr(uint8_t data)
 | 
			
		||||
{
 | 
			
		||||
    switch (data & 0x0f)
 | 
			
		||||
    {
 | 
			
		||||
        #define GCR_ENTRY(gcr, data) \
 | 
			
		||||
            case data: return gcr;
 | 
			
		||||
        #include "data_gcr.h"
 | 
			
		||||
        #undef GCR_ENTRY
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_bytes(std::vector<bool>& bits, unsigned& cursor, const Bytes& bytes)
 | 
			
		||||
{
 | 
			
		||||
    for (uint8_t b : bytes)
 | 
			
		||||
    {
 | 
			
		||||
        write_bits(bits, cursor, encode_data_gcr(b>>4), 5);
 | 
			
		||||
        write_bits(bits, cursor, encode_data_gcr(b),    5);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_sector(std::vector<bool>& bits, unsigned& cursor,
 | 
			
		||||
		const Victor9kEncoderProto::TrackdataProto& trackdata,
 | 
			
		||||
        const Sector& sector)
 | 
			
		||||
{
 | 
			
		||||
    write_one_bits(bits, cursor, trackdata.pre_header_sync_bits());
 | 
			
		||||
    write_bits(bits, cursor, VICTOR9K_SECTOR_RECORD, 10);
 | 
			
		||||
 | 
			
		||||
    uint8_t encodedTrack = sector.logicalTrack | (sector.logicalSide<<7);
 | 
			
		||||
    uint8_t encodedSector = sector.logicalSector;
 | 
			
		||||
    write_bytes(bits, cursor, Bytes {
 | 
			
		||||
        encodedTrack,
 | 
			
		||||
        encodedSector,
 | 
			
		||||
        (uint8_t)(encodedTrack + encodedSector),
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    write_zero_bits(bits, cursor, trackdata.post_header_gap_bits());
 | 
			
		||||
    write_one_bits(bits, cursor, trackdata.pre_data_sync_bits());
 | 
			
		||||
    write_bits(bits, cursor, VICTOR9K_DATA_RECORD, 10);
 | 
			
		||||
 | 
			
		||||
    write_bytes(bits, cursor, sector.data);
 | 
			
		||||
 | 
			
		||||
    Bytes checksum(2);
 | 
			
		||||
    checksum.writer().write_le16(sumBytes(sector.data));
 | 
			
		||||
    write_bytes(bits, cursor, checksum);
 | 
			
		||||
 | 
			
		||||
    write_zero_bits(bits, cursor, trackdata.post_data_gap_bits());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Victor9kEncoder : public AbstractEncoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	Victor9kEncoder(const EncoderProto& config):
 | 
			
		||||
        AbstractEncoder(config),
 | 
			
		||||
		_config(config.victor9k())
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
	void getTrackFormat(Victor9kEncoderProto::TrackdataProto& trackdata, unsigned cylinder, unsigned head)
 | 
			
		||||
	{
 | 
			
		||||
		trackdata.Clear();
 | 
			
		||||
		for (const auto& f : _config.trackdata())
 | 
			
		||||
		{
 | 
			
		||||
			if (f.has_min_cylinder() && (cylinder < f.min_cylinder()))
 | 
			
		||||
				continue;
 | 
			
		||||
			if (f.has_max_cylinder() && (cylinder > f.max_cylinder()))
 | 
			
		||||
				continue;
 | 
			
		||||
			if (f.has_head() && (head != f.head()))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			trackdata.MergeFrom(f);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override
 | 
			
		||||
	{
 | 
			
		||||
		std::vector<std::shared_ptr<Sector>> sectors;
 | 
			
		||||
 | 
			
		||||
		Victor9kEncoderProto::TrackdataProto trackdata;
 | 
			
		||||
		getTrackFormat(trackdata, physicalTrack, physicalSide);
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < trackdata.sector_range().sector_count(); i++)
 | 
			
		||||
        {
 | 
			
		||||
            int sectorId = trackdata.sector_range().start_sector() + i;
 | 
			
		||||
			const auto& sector = image.get(physicalTrack, physicalSide, sectorId);
 | 
			
		||||
			if (sector)
 | 
			
		||||
				sectors.push_back(sector);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		return sectors;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide,
 | 
			
		||||
            const std::vector<std::shared_ptr<Sector>>& sectors, const Image& image) override
 | 
			
		||||
    {
 | 
			
		||||
		Victor9kEncoderProto::TrackdataProto trackdata;
 | 
			
		||||
		getTrackFormat(trackdata, physicalTrack, physicalSide);
 | 
			
		||||
 | 
			
		||||
        unsigned bitsPerRevolution = trackdata.original_data_rate_khz() * trackdata.original_period_ms();
 | 
			
		||||
        std::vector<bool> bits(bitsPerRevolution);
 | 
			
		||||
        double clockRateUs = 166666.0 / bitsPerRevolution;
 | 
			
		||||
        unsigned cursor = 0;
 | 
			
		||||
 | 
			
		||||
        fillBitmapTo(bits, cursor, trackdata.post_index_gap_us() / clockRateUs, { true, false });
 | 
			
		||||
        lastBit = false;
 | 
			
		||||
 | 
			
		||||
        for (const auto& sector : sectors)
 | 
			
		||||
            write_sector(bits, cursor, trackdata, *sector);
 | 
			
		||||
 | 
			
		||||
        if (cursor >= bits.size())
 | 
			
		||||
            Error() << fmt::format("track data overrun by {} bits", cursor - bits.size());
 | 
			
		||||
        fillBitmapTo(bits, cursor, bits.size(), { true, false });
 | 
			
		||||
 | 
			
		||||
        std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
 | 
			
		||||
        fluxmap->appendBits(bits, clockRateUs*1e3);
 | 
			
		||||
        return fluxmap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	const Victor9kEncoderProto& _config;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractEncoder> createVictor9kEncoder(const EncoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractEncoder>(new Victor9kEncoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// vim: sw=4 ts=4 et
 | 
			
		||||
 | 
			
		||||
@@ -1,22 +1,22 @@
 | 
			
		||||
#ifndef VICTOR9K_H
 | 
			
		||||
#define VICTOR9K_H
 | 
			
		||||
 | 
			
		||||
#define VICTOR9K_SECTOR_RECORD 0xfffffeab
 | 
			
		||||
#define VICTOR9K_DATA_RECORD   0xfffffea4
 | 
			
		||||
class AbstractEncoder;
 | 
			
		||||
class AbstractDecoder;
 | 
			
		||||
class EncoderProto;
 | 
			
		||||
class DecoderProto;
 | 
			
		||||
 | 
			
		||||
/* ... 1101 0101 0111
 | 
			
		||||
 *       ^^ ^^^^ ^^^^ ten bit IO byte */
 | 
			
		||||
#define VICTOR9K_SECTOR_RECORD 0xfffffd57 
 | 
			
		||||
 | 
			
		||||
/* ... 1101 0100 1001
 | 
			
		||||
 *       ^^ ^^^^ ^^^^ ten bit IO byte */
 | 
			
		||||
#define VICTOR9K_DATA_RECORD   0xfffffd49
 | 
			
		||||
 | 
			
		||||
#define VICTOR9K_SECTOR_LENGTH 512
 | 
			
		||||
 | 
			
		||||
class Sector;
 | 
			
		||||
class Fluxmap;
 | 
			
		||||
 | 
			
		||||
class Victor9kDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~Victor9kDecoder() {}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord();
 | 
			
		||||
    void decodeSectorRecord();
 | 
			
		||||
    void decodeDataRecord();
 | 
			
		||||
};
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createVictor9kDecoder(const DecoderProto& config);
 | 
			
		||||
extern std::unique_ptr<AbstractEncoder> createVictor9kEncoder(const EncoderProto& config);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								arch/victor9k/victor9k.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								arch/victor9k/victor9k.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
import "lib/common.proto";
 | 
			
		||||
 | 
			
		||||
message Victor9kDecoderProto {}
 | 
			
		||||
 | 
			
		||||
// NEXT: 12
 | 
			
		||||
message Victor9kEncoderProto {
 | 
			
		||||
	message TrackdataProto {
 | 
			
		||||
		message SectorRangeProto {
 | 
			
		||||
			optional int32 start_sector = 1 [(help) = "first sector ID on track"];
 | 
			
		||||
			optional int32 sector_count = 2 [(help) = "number of sectors on track"];
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		optional int32 min_cylinder = 1            [(help) = "minimum cylinder this format applies to"];
 | 
			
		||||
		optional int32 max_cylinder = 2            [(help) = "maximum cylinder this format applies to"];
 | 
			
		||||
		optional int32 head = 3                    [(help) = "which head this format applies to"];
 | 
			
		||||
 | 
			
		||||
		optional double original_period_ms = 4     [(help) = "original rotational period of this cylinder"];
 | 
			
		||||
		optional double original_data_rate_khz = 5 [(help) = "original data rate of this cylinder"];
 | 
			
		||||
		optional double post_index_gap_us = 6      [(help) = "size of post-index gap"];
 | 
			
		||||
		optional int32 pre_header_sync_bits = 10   [(help) = "number of sync bits before the sector header"];
 | 
			
		||||
		optional int32 pre_data_sync_bits = 8      [(help) = "number of sync bits before the sector data"];
 | 
			
		||||
		optional int32 post_data_gap_bits = 9      [(help) = "size of gap between data and the next header"];
 | 
			
		||||
		optional int32 post_header_gap_bits = 11   [(help) = "size of gap between header and the data"];
 | 
			
		||||
 | 
			
		||||
		optional SectorRangeProto sector_range = 7 [(help) = "write these sectors on each track"];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	repeated TrackdataProto trackdata = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2,7 +2,6 @@
 | 
			
		||||
#include "fluxmap.h"
 | 
			
		||||
#include "decoders/fluxmapreader.h"
 | 
			
		||||
#include "protocol.h"
 | 
			
		||||
#include "record.h"
 | 
			
		||||
#include "decoders/decoders.h"
 | 
			
		||||
#include "sector.h"
 | 
			
		||||
#include "zilogmcz.h"
 | 
			
		||||
@@ -14,35 +13,49 @@
 | 
			
		||||
 | 
			
		||||
static const FluxPattern SECTOR_START_PATTERN(16, 0xaaab);
 | 
			
		||||
 | 
			
		||||
AbstractDecoder::RecordType ZilogMczDecoder::advanceToNextRecord()
 | 
			
		||||
class ZilogMczDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
	const FluxMatcher* matcher = nullptr;
 | 
			
		||||
    _fmr->seekToIndexMark();
 | 
			
		||||
	_sector->clock = _fmr->seekToPattern(SECTOR_START_PATTERN, matcher);
 | 
			
		||||
	if (matcher == &SECTOR_START_PATTERN)
 | 
			
		||||
		return SECTOR_RECORD;
 | 
			
		||||
	return UNKNOWN_RECORD;
 | 
			
		||||
public:
 | 
			
		||||
	ZilogMczDecoder(const DecoderProto& config):
 | 
			
		||||
		AbstractDecoder(config)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord()
 | 
			
		||||
	{
 | 
			
		||||
		const FluxMatcher* matcher = nullptr;
 | 
			
		||||
		_fmr->seekToIndexMark();
 | 
			
		||||
		_sector->clock = _fmr->seekToPattern(SECTOR_START_PATTERN, matcher);
 | 
			
		||||
		if (matcher == &SECTOR_START_PATTERN)
 | 
			
		||||
			return SECTOR_RECORD;
 | 
			
		||||
		return UNKNOWN_RECORD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void decodeSectorRecord()
 | 
			
		||||
	{
 | 
			
		||||
		readRawBits(14);
 | 
			
		||||
 | 
			
		||||
		auto rawbits = readRawBits(140*16);
 | 
			
		||||
		auto bytes = decodeFmMfm(rawbits).slice(0, 140);
 | 
			
		||||
		ByteReader br(bytes);
 | 
			
		||||
 | 
			
		||||
		_sector->logicalSector = br.read_8() & 0x1f;
 | 
			
		||||
		_sector->logicalSide = 0;
 | 
			
		||||
		_sector->logicalTrack = br.read_8() & 0x7f;
 | 
			
		||||
		if (_sector->logicalSector > 31)
 | 
			
		||||
			return;
 | 
			
		||||
		if (_sector->logicalTrack > 80)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		_sector->data = br.read(132);
 | 
			
		||||
		uint16_t wantChecksum = br.read_be16();
 | 
			
		||||
		uint16_t gotChecksum = crc16(MODBUS_POLY, 0x0000, bytes.slice(0, 134));
 | 
			
		||||
 | 
			
		||||
		_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<AbstractDecoder> createZilogMczDecoder(const DecoderProto& config)
 | 
			
		||||
{
 | 
			
		||||
	return std::unique_ptr<AbstractDecoder>(new ZilogMczDecoder(config));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ZilogMczDecoder::decodeSectorRecord()
 | 
			
		||||
{
 | 
			
		||||
    readRawBits(14);
 | 
			
		||||
 | 
			
		||||
    auto rawbits = readRawBits(140*16);
 | 
			
		||||
    auto bytes = decodeFmMfm(rawbits).slice(0, 140);
 | 
			
		||||
    ByteReader br(bytes);
 | 
			
		||||
 | 
			
		||||
    _sector->logicalSector = br.read_8() & 0x1f;
 | 
			
		||||
    _sector->logicalSide = 0;
 | 
			
		||||
    _sector->logicalTrack = br.read_8() & 0x7f;
 | 
			
		||||
    if (_sector->logicalSector > 31)
 | 
			
		||||
        return;
 | 
			
		||||
    if (_sector->logicalTrack > 80)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    _sector->data = br.read(132);
 | 
			
		||||
    uint16_t wantChecksum = br.read_be16();
 | 
			
		||||
    uint16_t gotChecksum = crc16(MODBUS_POLY, 0x0000, bytes.slice(0, 134));
 | 
			
		||||
 | 
			
		||||
    _sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,7 @@
 | 
			
		||||
#ifndef ZILOGMCZ_H
 | 
			
		||||
#define ZILOGMCZ_H
 | 
			
		||||
 | 
			
		||||
class Sector;
 | 
			
		||||
class Fluxmap;
 | 
			
		||||
 | 
			
		||||
class ZilogMczDecoder : public AbstractDecoder
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~ZilogMczDecoder() {}
 | 
			
		||||
 | 
			
		||||
    RecordType advanceToNextRecord();
 | 
			
		||||
    void decodeSectorRecord();
 | 
			
		||||
};
 | 
			
		||||
extern std::unique_ptr<AbstractDecoder> createZilogMczDecoder(const DecoderProto& config);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								arch/zilogmcz/zilogmcz.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/zilogmcz/zilogmcz.proto
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
syntax = "proto2";
 | 
			
		||||
 | 
			
		||||
message ZilogMczDecoderProto {}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								dep/agg/AUTHORS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								dep/agg/AUTHORS
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
Anti-Grain Geometry - Version 2.4
 | 
			
		||||
Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) 
 | 
			
		||||
							
								
								
									
										63
									
								
								dep/agg/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								dep/agg/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
The Anti-Grain Geometry Project
 | 
			
		||||
A high quality rendering engine for C++
 | 
			
		||||
http://antigrain.com
 | 
			
		||||
 | 
			
		||||
Anti-Grain Geometry - Version 2.4
 | 
			
		||||
Copyright (C) 2002-2005 Maxim Shemanarev (McSeem)
 | 
			
		||||
 | 
			
		||||
Permission to copy, use, modify, sell and distribute this software
 | 
			
		||||
is granted provided this copyright notice appears in all copies.
 | 
			
		||||
This software is provided "as is" without express or implied
 | 
			
		||||
warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
---------------------------------
 | 
			
		||||
 | 
			
		||||
Use automake to build the library.
 | 
			
		||||
 | 
			
		||||
If automake is not available you still can use the old make.
 | 
			
		||||
There is a very simple Makefile that can be used. Note that
 | 
			
		||||
if you use automake it will overwrite Makefile.
 | 
			
		||||
 | 
			
		||||
---------------------------------
 | 
			
		||||
 | 
			
		||||
If building on AmigaOS 4.0 or higher type the following for
 | 
			
		||||
instructions on what targets are available.
 | 
			
		||||
 make -f Makefile.AmigaOS
 | 
			
		||||
 | 
			
		||||
To just build and install AGG into the standard AmigaOS SDK
 | 
			
		||||
ready for use type:
 | 
			
		||||
 make -f Makefile.AmigaOS install
 | 
			
		||||
 | 
			
		||||
If you just want to build one demo (e.g. lion) use:
 | 
			
		||||
 make -f Makefile.AmigaOS bin/lion
 | 
			
		||||
 | 
			
		||||
If you have any questions about the AmigaOS port please
 | 
			
		||||
contact Steven Solie (ssolie@telus.net) for help.
 | 
			
		||||
 | 
			
		||||
---------------------------------
 | 
			
		||||
 | 
			
		||||
To build all examples using SDL (Mac or Linux) just type:
 | 
			
		||||
 | 
			
		||||
cd /examples/sdl
 | 
			
		||||
make
 | 
			
		||||
 | 
			
		||||
Individual examples can be built with
 | 
			
		||||
 | 
			
		||||
make aa_test
 | 
			
		||||
 | 
			
		||||
In the same way the native Carbon examples can be built with
 | 
			
		||||
 | 
			
		||||
cd /examples/macosx_carbon
 | 
			
		||||
make
 | 
			
		||||
 | 
			
		||||
In both cases the static library will be built (if it was not already) 
 | 
			
		||||
from the existing global Makefile in /src/.
 | 
			
		||||
 | 
			
		||||
The Makefiles for both SDL and Carbon will also attempt to download the 
 | 
			
		||||
required .bmp files if they are not found in the system for a given 
 | 
			
		||||
example. If the files could not be fetched (wget) the user will receive 
 | 
			
		||||
a message explaining where to download the samples from (sphere.bmp, 
 | 
			
		||||
etc.)  Since all programs reside in the same directory there is no need 
 | 
			
		||||
to duplicate the .bmp files for each program that needs to use them.
 | 
			
		||||
 | 
			
		||||
---------------------------------
 | 
			
		||||
							
								
								
									
										7
									
								
								dep/agg/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								dep/agg/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
This is a vary stripped down copy of the Anti-Grain Antialiasing graphics
 | 
			
		||||
rendering library --- I've removed all the platform-specific and control stuff
 | 
			
		||||
so that it can be used to generate memory images only.
 | 
			
		||||
 | 
			
		||||
The original AGG site is dead, so this version is cloned from
 | 
			
		||||
https://github.com/NNemec/antigrain.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								dep/agg/UPSTREAM.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								dep/agg/UPSTREAM.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
This is a vary stripped down copy of the Anti-Grain Antialiasing graphics
 | 
			
		||||
rendering library --- I've removed all the platform-specific and control stuff
 | 
			
		||||
so that it can be used to generate memory images only.
 | 
			
		||||
 | 
			
		||||
The original AGG site is dead, so this version is cloned from
 | 
			
		||||
https://github.com/NNemec/antigrain.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										49
									
								
								dep/agg/include/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								dep/agg/include/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
SUBDIRS = ctrl util platform 
 | 
			
		||||
 | 
			
		||||
aggincludedir = $(includedir)/agg2
 | 
			
		||||
agginclude_HEADERS = \
 | 
			
		||||
	agg_alpha_mask_u8.h          agg_glyph_raster_bin.h          agg_span_allocator.h \
 | 
			
		||||
	agg_arc.h                    agg_gsv_text.h                  agg_span_converter.h \
 | 
			
		||||
	agg_array.h                  agg_image_accessors.h           agg_span_gouraud.h \
 | 
			
		||||
	agg_arrowhead.h              agg_image_filters.h             agg_span_gouraud_gray.h \
 | 
			
		||||
	agg_basics.h                 agg_line_aa_basics.h            agg_span_gouraud_rgba.h \
 | 
			
		||||
	agg_bezier_arc.h             agg_math.h                      agg_span_gradient.h \
 | 
			
		||||
	agg_bitset_iterator.h        agg_blur.h                      agg_math_stroke.h \
 | 
			
		||||
	agg_span_gradient_alpha.h    agg_gradient_lut.h \
 | 
			
		||||
	agg_bounding_rect.h          agg_path_length.h               agg_span_image_filter.h \
 | 
			
		||||
	agg_bspline.h                agg_path_storage.h              agg_span_image_filter_gray.h \
 | 
			
		||||
	agg_clip_liang_barsky.h      agg_path_storage_integer.h      agg_span_image_filter_rgb.h \
 | 
			
		||||
	agg_color_gray.h             agg_pattern_filters_rgba.h      agg_span_image_filter_rgba.h \
 | 
			
		||||
	agg_color_rgba.h             agg_pixfmt_amask_adaptor.h      agg_span_interpolator_adaptor.h \
 | 
			
		||||
	agg_config.h                 agg_pixfmt_gray.h               agg_span_interpolator_linear.h \
 | 
			
		||||
	agg_conv_adaptor_vcgen.h     agg_pixfmt_rgb.h                agg_span_interpolator_persp.h \
 | 
			
		||||
	agg_conv_adaptor_vpgen.h     agg_pixfmt_rgb_packed.h         agg_span_interpolator_trans.h \
 | 
			
		||||
	agg_conv_bspline.h           agg_pixfmt_rgba.h               agg_pixfmt_transposer.h \
 | 
			
		||||
	agg_span_pattern_gray.h \
 | 
			
		||||
	agg_conv_clip_polygon.h      agg_rasterizer_cells_aa.h       agg_span_pattern_rgb.h \
 | 
			
		||||
	agg_conv_clip_polyline.h     agg_rasterizer_compound_aa.h    agg_span_pattern_rgba.h \
 | 
			
		||||
	agg_conv_close_polygon.h     agg_rasterizer_outline.h        agg_span_solid.h \
 | 
			
		||||
	agg_conv_concat.h            agg_rasterizer_outline_aa.h     agg_span_subdiv_adaptor.h \
 | 
			
		||||
	agg_conv_contour.h           agg_rasterizer_scanline_aa.h    agg_trans_affine.h \
 | 
			
		||||
	agg_conv_curve.h             agg_rasterizer_sl_clip.h        agg_trans_bilinear.h \
 | 
			
		||||
	agg_conv_dash.h              agg_renderer_base.h             agg_trans_double_path.h \
 | 
			
		||||
	agg_conv_gpc.h               agg_renderer_markers.h \
 | 
			
		||||
	agg_conv_marker.h            agg_renderer_mclip.h            agg_trans_perspective.h \
 | 
			
		||||
	agg_conv_marker_adaptor.h    agg_renderer_outline_aa.h       agg_trans_single_path.h \
 | 
			
		||||
	agg_conv_segmentator.h       agg_renderer_outline_image.h    agg_trans_viewport.h \
 | 
			
		||||
	agg_conv_shorten_path.h      agg_renderer_primitives.h       agg_trans_warp_magnifier.h \
 | 
			
		||||
	agg_conv_smooth_poly1.h      agg_renderer_raster_text.h      agg_vcgen_bspline.h \
 | 
			
		||||
	agg_conv_stroke.h            agg_renderer_scanline.h         agg_vcgen_contour.h \
 | 
			
		||||
	agg_conv_transform.h         agg_rendering_buffer.h          agg_vcgen_dash.h \
 | 
			
		||||
	agg_conv_unclose_polygon.h   agg_rendering_buffer_dynarow.h  agg_vcgen_markers_term.h \
 | 
			
		||||
	agg_curves.h                 agg_rounded_rect.h              agg_vcgen_smooth_poly1.h \
 | 
			
		||||
	                             agg_scanline_bin.h              agg_vcgen_stroke.h \
 | 
			
		||||
	agg_dda_line.h               agg_scanline_boolean_algebra.h  agg_vcgen_vertex_sequence.h \
 | 
			
		||||
	agg_ellipse.h                agg_scanline_p.h                agg_vertex_sequence.h \
 | 
			
		||||
	agg_ellipse_bresenham.h      agg_scanline_storage_aa.h       agg_vpgen_clip_polygon.h \
 | 
			
		||||
	agg_embedded_raster_fonts.h  agg_scanline_storage_bin.h      agg_vpgen_clip_polyline.h \
 | 
			
		||||
	agg_font_cache_manager.h     agg_scanline_u.h                agg_vpgen_segmentator.h \
 | 
			
		||||
	agg_gamma_functions.h        agg_shorten_path.h \
 | 
			
		||||
	agg_gamma_lut.h              agg_simul_eq.h \
 | 
			
		||||
	agg_font_cache_manager2.h    agg_pixfmt_base.h               agg_rasterizer_scanline_aa_nogamma.h \
 | 
			
		||||
	agg_span_gradient_contour.h  agg_span_gradient_image.h
 | 
			
		||||
							
								
								
									
										568
									
								
								dep/agg/include/agg2d.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										568
									
								
								dep/agg/include/agg2d.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,568 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Agg2D - Version 1.0
 | 
			
		||||
// Based on Anti-Grain Geometry
 | 
			
		||||
// Copyright (C) 2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software
 | 
			
		||||
// is granted provided this copyright notice appears in all copies.
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
//	25 Jan 2007 - Ported to AGG 2.4 Jerry Evans (jerry@novadsp.com)
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef AGG2D_INCLUDED
 | 
			
		||||
#define AGG2D_INCLUDED
 | 
			
		||||
 | 
			
		||||
// With this define uncommented you can use floating-point pixel format
 | 
			
		||||
//#define AGG2D_USE_FLOAT_FORMAT
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
#include "agg_trans_affine.h"
 | 
			
		||||
#include "agg_trans_viewport.h"
 | 
			
		||||
#include "agg_path_storage.h"
 | 
			
		||||
#include "agg_conv_stroke.h"
 | 
			
		||||
#include "agg_conv_transform.h"
 | 
			
		||||
#include "agg_conv_curve.h"
 | 
			
		||||
#include "agg_rendering_buffer.h"
 | 
			
		||||
#include "agg_renderer_base.h"
 | 
			
		||||
#include "agg_renderer_scanline.h"
 | 
			
		||||
#include "agg_span_gradient.h"
 | 
			
		||||
#include "agg_span_image_filter_rgba.h"
 | 
			
		||||
#include "agg_span_allocator.h"
 | 
			
		||||
#include "agg_span_converter.h"
 | 
			
		||||
#include "agg_span_interpolator_linear.h"
 | 
			
		||||
#include "agg_rasterizer_scanline_aa.h"
 | 
			
		||||
#include "agg_gamma_functions.h"
 | 
			
		||||
#include "agg_scanline_u.h"
 | 
			
		||||
#include "agg_bezier_arc.h"
 | 
			
		||||
#include "agg_rounded_rect.h"
 | 
			
		||||
#include "agg_font_cache_manager.h"
 | 
			
		||||
 | 
			
		||||
#include "agg_pixfmt_rgba.h"
 | 
			
		||||
#include "agg_image_accessors.h"
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
class Agg2D
 | 
			
		||||
{
 | 
			
		||||
#ifdef AGG2D_USE_FLOAT_FORMAT
 | 
			
		||||
    typedef agg::rgba32 ColorType;
 | 
			
		||||
#else
 | 
			
		||||
    typedef agg::rgba8  ColorType;
 | 
			
		||||
#endif
 | 
			
		||||
    typedef agg::order_bgra ComponentOrder; // Platform dependent!
 | 
			
		||||
    typedef agg::blender_rgba<ColorType, ComponentOrder>             Blender;
 | 
			
		||||
    typedef agg::comp_op_adaptor_rgba<ColorType, ComponentOrder>     BlenderComp;
 | 
			
		||||
    typedef agg::blender_rgba_pre<ColorType, ComponentOrder>         BlenderPre;
 | 
			
		||||
    typedef agg::comp_op_adaptor_rgba_pre<ColorType, ComponentOrder> BlenderCompPre;
 | 
			
		||||
 | 
			
		||||
    typedef agg::pixfmt_alpha_blend_rgba<Blender, agg::rendering_buffer>         PixFormat;
 | 
			
		||||
    typedef agg::pixfmt_custom_blend_rgba<BlenderComp, agg::rendering_buffer>    PixFormatComp;
 | 
			
		||||
    typedef agg::pixfmt_alpha_blend_rgba<BlenderPre, agg::rendering_buffer>      PixFormatPre;
 | 
			
		||||
    typedef agg::pixfmt_custom_blend_rgba<BlenderCompPre, agg::rendering_buffer> PixFormatCompPre;
 | 
			
		||||
 | 
			
		||||
    typedef agg::renderer_base<PixFormat>        RendererBase;
 | 
			
		||||
    typedef agg::renderer_base<PixFormatComp>    RendererBaseComp;
 | 
			
		||||
    typedef agg::renderer_base<PixFormatPre>     RendererBasePre;
 | 
			
		||||
    typedef agg::renderer_base<PixFormatCompPre> RendererBaseCompPre;
 | 
			
		||||
 | 
			
		||||
    typedef agg::renderer_scanline_aa_solid<RendererBase>     RendererSolid;
 | 
			
		||||
    typedef agg::renderer_scanline_aa_solid<RendererBaseComp> RendererSolidComp;
 | 
			
		||||
 | 
			
		||||
    typedef agg::span_allocator<ColorType> SpanAllocator;
 | 
			
		||||
    typedef agg::pod_auto_array<ColorType, 256> GradientArray;
 | 
			
		||||
 | 
			
		||||
    typedef agg::span_gradient<ColorType, agg::span_interpolator_linear<>, agg::gradient_x,      GradientArray> LinearGradientSpan;
 | 
			
		||||
    typedef agg::span_gradient<ColorType, agg::span_interpolator_linear<>, agg::gradient_circle, GradientArray> RadialGradientSpan;
 | 
			
		||||
 | 
			
		||||
    typedef agg::conv_curve<agg::path_storage>    ConvCurve;
 | 
			
		||||
    typedef agg::conv_stroke<ConvCurve>           ConvStroke;
 | 
			
		||||
    typedef agg::conv_transform<ConvCurve>        PathTransform;
 | 
			
		||||
    typedef agg::conv_transform<ConvStroke>       StrokeTransform;
 | 
			
		||||
 | 
			
		||||
    enum Gradient
 | 
			
		||||
    {
 | 
			
		||||
        Solid,
 | 
			
		||||
        Linear,
 | 
			
		||||
        Radial
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    friend class Agg2DRenderer;
 | 
			
		||||
 | 
			
		||||
    // Use srgba8 as the "user" color type, even though the underlying color type 
 | 
			
		||||
    // might be something else, such as rgba32. This allows code based on 
 | 
			
		||||
    // 8-bit sRGB values to carry on working as before.
 | 
			
		||||
    typedef agg::srgba8       Color;
 | 
			
		||||
    typedef agg::rect_i       Rect;
 | 
			
		||||
    typedef agg::rect_d       RectD;
 | 
			
		||||
    typedef agg::trans_affine Affine;
 | 
			
		||||
 | 
			
		||||
    enum LineJoin
 | 
			
		||||
    {
 | 
			
		||||
        JoinMiter = agg::miter_join,
 | 
			
		||||
        JoinRound = agg::round_join,
 | 
			
		||||
        JoinBevel = agg::bevel_join
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum LineCap
 | 
			
		||||
    {
 | 
			
		||||
        CapButt   = agg::butt_cap,
 | 
			
		||||
        CapSquare = agg::square_cap,
 | 
			
		||||
        CapRound  = agg::round_cap
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum TextAlignment
 | 
			
		||||
    {
 | 
			
		||||
        AlignLeft,
 | 
			
		||||
        AlignRight,
 | 
			
		||||
        AlignCenter,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    enum DrawPathFlag
 | 
			
		||||
    {
 | 
			
		||||
        FillOnly,
 | 
			
		||||
        StrokeOnly,
 | 
			
		||||
        FillAndStroke,
 | 
			
		||||
        FillWithLineColor
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum ViewportOption
 | 
			
		||||
    {
 | 
			
		||||
        Anisotropic,
 | 
			
		||||
        XMinYMin,
 | 
			
		||||
        XMidYMin,
 | 
			
		||||
        XMaxYMin,
 | 
			
		||||
        XMinYMid,
 | 
			
		||||
        XMidYMid,
 | 
			
		||||
        XMaxYMid,
 | 
			
		||||
        XMinYMax,
 | 
			
		||||
        XMidYMax,
 | 
			
		||||
        XMaxYMax
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct Transformations
 | 
			
		||||
    {
 | 
			
		||||
        double affineMatrix[6];
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    struct Image
 | 
			
		||||
    {
 | 
			
		||||
        agg::rendering_buffer renBuf;
 | 
			
		||||
 | 
			
		||||
        Image() {}
 | 
			
		||||
        Image(unsigned char* buf, unsigned width, unsigned height, int stride) :
 | 
			
		||||
            renBuf(buf, width, height, stride) {}
 | 
			
		||||
        void attach(unsigned char* buf, unsigned width, unsigned height, int stride)
 | 
			
		||||
        {
 | 
			
		||||
            renBuf.attach(buf, width, height, stride);
 | 
			
		||||
        }
 | 
			
		||||
        int width()  const { return renBuf.width(); }
 | 
			
		||||
        int height() const { return renBuf.height(); }
 | 
			
		||||
        void premultiply();
 | 
			
		||||
        void demultiply();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum ImageFilter
 | 
			
		||||
    {
 | 
			
		||||
        NoFilter,
 | 
			
		||||
        Bilinear,
 | 
			
		||||
        Hanning,
 | 
			
		||||
        Hermite,
 | 
			
		||||
        Quadric,
 | 
			
		||||
        Bicubic,
 | 
			
		||||
        Catrom,
 | 
			
		||||
        Spline16,
 | 
			
		||||
        Spline36,
 | 
			
		||||
        Blackman144
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum ImageResample
 | 
			
		||||
    {
 | 
			
		||||
        NoResample,
 | 
			
		||||
        ResampleAlways,
 | 
			
		||||
        ResampleOnZoomOut
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum FontCacheType
 | 
			
		||||
    {
 | 
			
		||||
        RasterFontCache,
 | 
			
		||||
        VectorFontCache
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum BlendMode
 | 
			
		||||
    {
 | 
			
		||||
        BlendAlpha      = agg::end_of_comp_op_e,
 | 
			
		||||
        BlendClear      = agg::comp_op_clear,
 | 
			
		||||
        BlendSrc        = agg::comp_op_src,
 | 
			
		||||
        BlendDst        = agg::comp_op_dst,
 | 
			
		||||
        BlendSrcOver    = agg::comp_op_src_over,
 | 
			
		||||
        BlendDstOver    = agg::comp_op_dst_over,
 | 
			
		||||
        BlendSrcIn      = agg::comp_op_src_in,
 | 
			
		||||
        BlendDstIn      = agg::comp_op_dst_in,
 | 
			
		||||
        BlendSrcOut     = agg::comp_op_src_out,
 | 
			
		||||
        BlendDstOut     = agg::comp_op_dst_out,
 | 
			
		||||
        BlendSrcAtop    = agg::comp_op_src_atop,
 | 
			
		||||
        BlendDstAtop    = agg::comp_op_dst_atop,
 | 
			
		||||
        BlendXor        = agg::comp_op_xor,
 | 
			
		||||
        BlendAdd        = agg::comp_op_plus,
 | 
			
		||||
        BlendMultiply   = agg::comp_op_multiply,
 | 
			
		||||
        BlendScreen     = agg::comp_op_screen,
 | 
			
		||||
        BlendOverlay    = agg::comp_op_overlay,
 | 
			
		||||
        BlendDarken     = agg::comp_op_darken,
 | 
			
		||||
        BlendLighten    = agg::comp_op_lighten,
 | 
			
		||||
        BlendColorDodge = agg::comp_op_color_dodge,
 | 
			
		||||
        BlendColorBurn  = agg::comp_op_color_burn,
 | 
			
		||||
        BlendHardLight  = agg::comp_op_hard_light,
 | 
			
		||||
        BlendSoftLight  = agg::comp_op_soft_light,
 | 
			
		||||
        BlendDifference = agg::comp_op_difference,
 | 
			
		||||
        BlendExclusion  = agg::comp_op_exclusion,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum Direction
 | 
			
		||||
    {
 | 
			
		||||
        CW, CCW
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ~Agg2D();
 | 
			
		||||
    Agg2D();
 | 
			
		||||
 | 
			
		||||
    // Setup
 | 
			
		||||
    //-----------------------
 | 
			
		||||
    void  attach(unsigned char* buf, unsigned width, unsigned height, int stride);
 | 
			
		||||
    void  attach(Image& img);
 | 
			
		||||
 | 
			
		||||
    void  clipBox(double x1, double y1, double x2, double y2);
 | 
			
		||||
    RectD clipBox() const;
 | 
			
		||||
 | 
			
		||||
    void  clearAll(Color c);
 | 
			
		||||
    void  clearAll(unsigned r, unsigned g, unsigned b, unsigned a = 255);
 | 
			
		||||
 | 
			
		||||
    void  clearClipBox(Color c);
 | 
			
		||||
    void  clearClipBox(unsigned r, unsigned g, unsigned b, unsigned a = 255);
 | 
			
		||||
 | 
			
		||||
    // Conversions
 | 
			
		||||
    //-----------------------
 | 
			
		||||
    void   worldToScreen(double& x, double& y) const;
 | 
			
		||||
    void   screenToWorld(double& x, double& y) const;
 | 
			
		||||
    double worldToScreen(double scalar) const;
 | 
			
		||||
    double screenToWorld(double scalar) const;
 | 
			
		||||
    void   alignPoint(double& x, double& y) const;
 | 
			
		||||
    bool   inBox(double worldX, double worldY) const;
 | 
			
		||||
 | 
			
		||||
    // General Attributes
 | 
			
		||||
    //-----------------------
 | 
			
		||||
    void blendMode(BlendMode m);
 | 
			
		||||
    BlendMode blendMode() const;
 | 
			
		||||
 | 
			
		||||
    void imageBlendMode(BlendMode m);
 | 
			
		||||
    BlendMode imageBlendMode() const;
 | 
			
		||||
 | 
			
		||||
    void imageBlendColor(Color c);
 | 
			
		||||
    void imageBlendColor(unsigned r, unsigned g, unsigned b, unsigned a = 255);
 | 
			
		||||
    Color imageBlendColor() const;
 | 
			
		||||
 | 
			
		||||
    void masterAlpha(double a);
 | 
			
		||||
    double masterAlpha() const;
 | 
			
		||||
 | 
			
		||||
    void antiAliasGamma(double g);
 | 
			
		||||
    double antiAliasGamma() const;
 | 
			
		||||
 | 
			
		||||
    void fillColor(Color c);
 | 
			
		||||
    void fillColor(unsigned r, unsigned g, unsigned b, unsigned a = 255);
 | 
			
		||||
    void noFill();
 | 
			
		||||
 | 
			
		||||
    void lineColor(Color c);
 | 
			
		||||
    void lineColor(unsigned r, unsigned g, unsigned b, unsigned a = 255);
 | 
			
		||||
    void noLine();
 | 
			
		||||
 | 
			
		||||
    Color fillColor() const;
 | 
			
		||||
    Color lineColor() const;
 | 
			
		||||
 | 
			
		||||
    void fillLinearGradient(double x1, double y1, double x2, double y2, Color c1, Color c2, double profile=1.0);
 | 
			
		||||
    void lineLinearGradient(double x1, double y1, double x2, double y2, Color c1, Color c2, double profile=1.0);
 | 
			
		||||
 | 
			
		||||
    void fillRadialGradient(double x, double y, double r, Color c1, Color c2, double profile=1.0);
 | 
			
		||||
    void lineRadialGradient(double x, double y, double r, Color c1, Color c2, double profile=1.0);
 | 
			
		||||
 | 
			
		||||
    void fillRadialGradient(double x, double y, double r, Color c1, Color c2, Color c3);
 | 
			
		||||
    void lineRadialGradient(double x, double y, double r, Color c1, Color c2, Color c3);
 | 
			
		||||
 | 
			
		||||
    void fillRadialGradient(double x, double y, double r);
 | 
			
		||||
    void lineRadialGradient(double x, double y, double r);
 | 
			
		||||
 | 
			
		||||
    void lineWidth(double w);
 | 
			
		||||
    double lineWidth(double w) const;
 | 
			
		||||
 | 
			
		||||
    void lineCap(LineCap cap);
 | 
			
		||||
    LineCap lineCap() const;
 | 
			
		||||
 | 
			
		||||
    void lineJoin(LineJoin join);
 | 
			
		||||
    LineJoin lineJoin() const;
 | 
			
		||||
 | 
			
		||||
    void fillEvenOdd(bool evenOddFlag);
 | 
			
		||||
    bool fillEvenOdd() const;
 | 
			
		||||
 | 
			
		||||
	void textAlignment(TextAlignment alignment);
 | 
			
		||||
	void textSize(double sizeX, double sizeY);
 | 
			
		||||
	inline void textSize(double size) { textSize(size, size); }
 | 
			
		||||
 | 
			
		||||
    // Transformations
 | 
			
		||||
    //-----------------------
 | 
			
		||||
    Transformations transformations() const;
 | 
			
		||||
    void transformations(const Transformations& tr);
 | 
			
		||||
    void resetTransformations();
 | 
			
		||||
    void affine(const Affine& tr);
 | 
			
		||||
    void affine(const Transformations& tr);
 | 
			
		||||
    void rotate(double angle);
 | 
			
		||||
    void scale(double sx, double sy);
 | 
			
		||||
    void skew(double sx, double sy);
 | 
			
		||||
    void translate(double x, double y);
 | 
			
		||||
    void parallelogram(double x1, double y1, double x2, double y2, const double* para);
 | 
			
		||||
    void viewport(double worldX1,  double worldY1,  double worldX2,  double worldY2,
 | 
			
		||||
                  double screenX1, double screenY1, double screenX2, double screenY2,
 | 
			
		||||
                  ViewportOption opt=XMidYMid);
 | 
			
		||||
 | 
			
		||||
    // Basic Shapes
 | 
			
		||||
    //-----------------------
 | 
			
		||||
    void line(double x1, double y1, double x2, double y2);
 | 
			
		||||
    void triangle(double x1, double y1, double x2, double y2, double x3, double y3);
 | 
			
		||||
    void rectangle(double x1, double y1, double x2, double y2);
 | 
			
		||||
    void roundedRect(double x1, double y1, double x2, double y2, double r);
 | 
			
		||||
    void roundedRect(double x1, double y1, double x2, double y2, double rx, double ry);
 | 
			
		||||
    void roundedRect(double x1, double y1, double x2, double y2,
 | 
			
		||||
                     double rxBottom, double ryBottom,
 | 
			
		||||
                     double rxTop,    double ryTop);
 | 
			
		||||
    void ellipse(double cx, double cy, double rx, double ry);
 | 
			
		||||
    void arc(double cx, double cy, double rx, double ry, double start, double sweep);
 | 
			
		||||
    void star(double cx, double cy, double r1, double r2, double startAngle, int numRays);
 | 
			
		||||
    void curve(double x1, double y1, double x2, double y2, double x3, double y3);
 | 
			
		||||
    void curve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4);
 | 
			
		||||
    void polygon(double* xy, int numPoints);
 | 
			
		||||
    void polyline(double* xy, int numPoints);
 | 
			
		||||
 | 
			
		||||
    // Path commands
 | 
			
		||||
    //-----------------------
 | 
			
		||||
    void resetPath();
 | 
			
		||||
 | 
			
		||||
    void moveTo(double x, double y);
 | 
			
		||||
    void moveRel(double dx, double dy);
 | 
			
		||||
 | 
			
		||||
    void lineTo(double x, double y);
 | 
			
		||||
    void lineRel(double dx, double dy);
 | 
			
		||||
 | 
			
		||||
    void horLineTo(double x);
 | 
			
		||||
    void horLineRel(double dx);
 | 
			
		||||
 | 
			
		||||
    void verLineTo(double y);
 | 
			
		||||
    void verLineRel(double dy);
 | 
			
		||||
 | 
			
		||||
    void arcTo(double rx, double ry,
 | 
			
		||||
               double angle,
 | 
			
		||||
               bool largeArcFlag,
 | 
			
		||||
               bool sweepFlag,
 | 
			
		||||
               double x, double y);
 | 
			
		||||
 | 
			
		||||
    void arcRel(double rx, double ry,
 | 
			
		||||
                double angle,
 | 
			
		||||
                bool largeArcFlag,
 | 
			
		||||
                bool sweepFlag,
 | 
			
		||||
                double dx, double dy);
 | 
			
		||||
 | 
			
		||||
    void quadricCurveTo(double xCtrl, double yCtrl,
 | 
			
		||||
                         double xTo,   double yTo);
 | 
			
		||||
    void quadricCurveRel(double dxCtrl, double dyCtrl,
 | 
			
		||||
                         double dxTo,   double dyTo);
 | 
			
		||||
    void quadricCurveTo(double xTo, double yTo);
 | 
			
		||||
    void quadricCurveRel(double dxTo, double dyTo);
 | 
			
		||||
 | 
			
		||||
    void cubicCurveTo(double xCtrl1, double yCtrl1,
 | 
			
		||||
                      double xCtrl2, double yCtrl2,
 | 
			
		||||
                      double xTo,    double yTo);
 | 
			
		||||
 | 
			
		||||
    void cubicCurveRel(double dxCtrl1, double dyCtrl1,
 | 
			
		||||
                       double dxCtrl2, double dyCtrl2,
 | 
			
		||||
                       double dxTo,    double dyTo);
 | 
			
		||||
 | 
			
		||||
    void cubicCurveTo(double xCtrl2, double yCtrl2,
 | 
			
		||||
                      double xTo,    double yTo);
 | 
			
		||||
 | 
			
		||||
    void cubicCurveRel(double xCtrl2, double yCtrl2,
 | 
			
		||||
                       double xTo,    double yTo);
 | 
			
		||||
 | 
			
		||||
    void addEllipse(double cx, double cy, double rx, double ry, Direction dir);
 | 
			
		||||
	void text(double x, double y, const std::string& text);
 | 
			
		||||
    void closePolygon();
 | 
			
		||||
 | 
			
		||||
    void drawPath(DrawPathFlag flag = FillAndStroke);
 | 
			
		||||
    void drawPathNoTransform(DrawPathFlag flag = FillAndStroke);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Image Transformations
 | 
			
		||||
    //-----------------------
 | 
			
		||||
    void imageFilter(ImageFilter f);
 | 
			
		||||
    ImageFilter imageFilter() const;
 | 
			
		||||
 | 
			
		||||
    void imageResample(ImageResample f);
 | 
			
		||||
    ImageResample imageResample() const;
 | 
			
		||||
 | 
			
		||||
    void transformImage(const Image& img,
 | 
			
		||||
                           int imgX1,    int imgY1,    int imgX2,    int imgY2,
 | 
			
		||||
                        double dstX1, double dstY1, double dstX2, double dstY2);
 | 
			
		||||
 | 
			
		||||
    void transformImage(const Image& img,
 | 
			
		||||
                        double dstX1, double dstY1, double dstX2, double dstY2);
 | 
			
		||||
 | 
			
		||||
    void transformImage(const Image& img,
 | 
			
		||||
                        int imgX1, int imgY1, int imgX2, int imgY2,
 | 
			
		||||
                        const double* parallelogram);
 | 
			
		||||
 | 
			
		||||
    void transformImage(const Image& img, const double* parallelogram);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    void transformImagePath(const Image& img,
 | 
			
		||||
                               int imgX1,    int imgY1,    int imgX2,    int imgY2,
 | 
			
		||||
                            double dstX1, double dstY1, double dstX2, double dstY2);
 | 
			
		||||
 | 
			
		||||
    void transformImagePath(const Image& img,
 | 
			
		||||
                            double dstX1, double dstY1, double dstX2, double dstY2);
 | 
			
		||||
 | 
			
		||||
    void transformImagePath(const Image& img,
 | 
			
		||||
                            int imgX1, int imgY1, int imgX2, int imgY2,
 | 
			
		||||
                            const double* parallelogram);
 | 
			
		||||
 | 
			
		||||
    void transformImagePath(const Image& img, const double* parallelogram);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Image Blending (no transformations available)
 | 
			
		||||
    void blendImage(Image& img,
 | 
			
		||||
                    int imgX1, int imgY1, int imgX2, int imgY2,
 | 
			
		||||
                    double dstX, double dstY, unsigned alpha=255);
 | 
			
		||||
    void blendImage(Image& img, double dstX, double dstY, unsigned alpha=255);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Copy image directly, together with alpha-channel
 | 
			
		||||
    void copyImage(Image& img,
 | 
			
		||||
                   int imgX1, int imgY1, int imgX2, int imgY2,
 | 
			
		||||
                   double dstX, double dstY);
 | 
			
		||||
    void copyImage(Image& img, double dstX, double dstY);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Auxiliary
 | 
			
		||||
    //-----------------------
 | 
			
		||||
    static double pi() { return agg::pi; }
 | 
			
		||||
    static double deg2Rad(double v) { return v * agg::pi / 180.0; }
 | 
			
		||||
    static double rad2Deg(double v) { return v * 180.0 / agg::pi; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void render(bool fillColor);
 | 
			
		||||
#ifdef AGG_USE_FONTS
 | 
			
		||||
    void render(FontRasterizer& ras, FontScanline& sl);
 | 
			
		||||
#endif // AGG_USE_FONTS
 | 
			
		||||
 | 
			
		||||
    void addLine(double x1, double y1, double x2, double y2);
 | 
			
		||||
    void updateRasterizerGamma();
 | 
			
		||||
    void renderImage(const Image& img, int x1, int y1, int x2, int y2, const double* parl);
 | 
			
		||||
 | 
			
		||||
    agg::rendering_buffer           m_rbuf;
 | 
			
		||||
    PixFormat                       m_pixFormat;
 | 
			
		||||
    PixFormatComp                   m_pixFormatComp;
 | 
			
		||||
    PixFormatPre                    m_pixFormatPre;
 | 
			
		||||
    PixFormatCompPre                m_pixFormatCompPre;
 | 
			
		||||
    RendererBase                    m_renBase;
 | 
			
		||||
    RendererBaseComp                m_renBaseComp;
 | 
			
		||||
    RendererBasePre                 m_renBasePre;
 | 
			
		||||
    RendererBaseCompPre             m_renBaseCompPre;
 | 
			
		||||
    RendererSolid                   m_renSolid;
 | 
			
		||||
    RendererSolidComp               m_renSolidComp;
 | 
			
		||||
 | 
			
		||||
    SpanAllocator                   m_allocator;
 | 
			
		||||
    RectD                           m_clipBox;
 | 
			
		||||
 | 
			
		||||
    BlendMode                       m_blendMode;
 | 
			
		||||
    BlendMode                       m_imageBlendMode;
 | 
			
		||||
    Color                           m_imageBlendColor;
 | 
			
		||||
 | 
			
		||||
    agg::scanline_u8                m_scanline;
 | 
			
		||||
    agg::rasterizer_scanline_aa<>   m_rasterizer;
 | 
			
		||||
 | 
			
		||||
    double                          m_masterAlpha;
 | 
			
		||||
    double                          m_antiAliasGamma;
 | 
			
		||||
 | 
			
		||||
    Color                           m_fillColor;
 | 
			
		||||
    Color                           m_lineColor;
 | 
			
		||||
    GradientArray                   m_fillGradient;
 | 
			
		||||
    GradientArray                   m_lineGradient;
 | 
			
		||||
 | 
			
		||||
    LineCap                         m_lineCap;
 | 
			
		||||
    LineJoin                        m_lineJoin;
 | 
			
		||||
 | 
			
		||||
    Gradient                        m_fillGradientFlag;
 | 
			
		||||
    Gradient                        m_lineGradientFlag;
 | 
			
		||||
    agg::trans_affine               m_fillGradientMatrix;
 | 
			
		||||
    agg::trans_affine               m_lineGradientMatrix;
 | 
			
		||||
    double                          m_fillGradientD1;
 | 
			
		||||
    double                          m_lineGradientD1;
 | 
			
		||||
    double                          m_fillGradientD2;
 | 
			
		||||
    double                          m_lineGradientD2;
 | 
			
		||||
 | 
			
		||||
    TextAlignment                   m_textAlignment;
 | 
			
		||||
    double                          m_textSizeX;
 | 
			
		||||
    double                          m_textSizeY;
 | 
			
		||||
 | 
			
		||||
    ImageFilter                     m_imageFilter;
 | 
			
		||||
    ImageResample                   m_imageResample;
 | 
			
		||||
    agg::image_filter_lut           m_imageFilterLut;
 | 
			
		||||
 | 
			
		||||
    agg::span_interpolator_linear<> m_fillGradientInterpolator;
 | 
			
		||||
    agg::span_interpolator_linear<> m_lineGradientInterpolator;
 | 
			
		||||
 | 
			
		||||
    agg::gradient_x                 m_linearGradientFunction;
 | 
			
		||||
    agg::gradient_circle            m_radialGradientFunction;
 | 
			
		||||
 | 
			
		||||
    double                          m_lineWidth;
 | 
			
		||||
    bool                            m_evenOddFlag;
 | 
			
		||||
 | 
			
		||||
    agg::path_storage               m_path;
 | 
			
		||||
    agg::trans_affine               m_transform;
 | 
			
		||||
 | 
			
		||||
    ConvCurve                       m_convCurve;
 | 
			
		||||
    ConvStroke                      m_convStroke;
 | 
			
		||||
 | 
			
		||||
    PathTransform                   m_pathTransform;
 | 
			
		||||
    StrokeTransform                 m_strokeTransform;
 | 
			
		||||
 | 
			
		||||
#ifdef AGG_USE_FONTS
 | 
			
		||||
#ifndef AGG2D_USE_FREETYPE
 | 
			
		||||
    HDC                             m_fontDC;
 | 
			
		||||
#endif
 | 
			
		||||
    FontEngine                      m_fontEngine;
 | 
			
		||||
    FontCacheManager                m_fontCacheManager;
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline bool operator == (const Agg2D::Color& c1, const Agg2D::Color& c2)
 | 
			
		||||
{
 | 
			
		||||
   return c1.r == c2.r && c1.g == c2.g && c1.b == c2.b && c1.a == c2.a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool operator != (const Agg2D::Color& c1, const Agg2D::Color& c2)
 | 
			
		||||
{
 | 
			
		||||
   return !(c1 == c2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										499
									
								
								dep/agg/include/agg_alpha_mask_u8.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										499
									
								
								dep/agg/include/agg_alpha_mask_u8.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,499 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// scanline_u8 class
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
#ifndef AGG_ALPHA_MASK_U8_INCLUDED
 | 
			
		||||
#define AGG_ALPHA_MASK_U8_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
#include "agg_rendering_buffer.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
    //===================================================one_component_mask_u8
 | 
			
		||||
    struct one_component_mask_u8
 | 
			
		||||
    {
 | 
			
		||||
        static unsigned calculate(const int8u* p) { return *p; }
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    //=====================================================rgb_to_gray_mask_u8
 | 
			
		||||
    template<unsigned R, unsigned G, unsigned B>
 | 
			
		||||
    struct rgb_to_gray_mask_u8
 | 
			
		||||
    {
 | 
			
		||||
        static unsigned calculate(const int8u* p) 
 | 
			
		||||
        { 
 | 
			
		||||
            return (p[R]*77 + p[G]*150 + p[B]*29) >> 8; 
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //==========================================================alpha_mask_u8
 | 
			
		||||
    template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
 | 
			
		||||
    class alpha_mask_u8
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        typedef int8u cover_type;
 | 
			
		||||
        typedef alpha_mask_u8<Step, Offset, MaskF> self_type;
 | 
			
		||||
        enum cover_scale_e
 | 
			
		||||
        { 
 | 
			
		||||
            cover_shift = 8,
 | 
			
		||||
            cover_none  = 0,
 | 
			
		||||
            cover_full  = 255
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        alpha_mask_u8() : m_rbuf(0) {}
 | 
			
		||||
        explicit alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
 | 
			
		||||
 | 
			
		||||
        void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
 | 
			
		||||
 | 
			
		||||
        MaskF& mask_function() { return m_mask_function; }
 | 
			
		||||
        const MaskF& mask_function() const { return m_mask_function; }
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        cover_type pixel(int x, int y) const
 | 
			
		||||
        {
 | 
			
		||||
            if(x >= 0 && y >= 0 && 
 | 
			
		||||
               x < (int)m_rbuf->width() && 
 | 
			
		||||
               y < (int)m_rbuf->height())
 | 
			
		||||
            {
 | 
			
		||||
                return (cover_type)m_mask_function.calculate(
 | 
			
		||||
                                        m_rbuf->row_ptr(y) + x * Step + Offset);
 | 
			
		||||
            }
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        cover_type combine_pixel(int x, int y, cover_type val) const
 | 
			
		||||
        {
 | 
			
		||||
            if(x >= 0 && y >= 0 && 
 | 
			
		||||
               x < (int)m_rbuf->width() && 
 | 
			
		||||
               y < (int)m_rbuf->height())
 | 
			
		||||
            {
 | 
			
		||||
                return (cover_type)((cover_full + val * 
 | 
			
		||||
                                     m_mask_function.calculate(
 | 
			
		||||
                                        m_rbuf->row_ptr(y) + x * Step + Offset)) >> 
 | 
			
		||||
                                     cover_shift);
 | 
			
		||||
            }
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
 | 
			
		||||
        {
 | 
			
		||||
            int xmax = m_rbuf->width() - 1;
 | 
			
		||||
            int ymax = m_rbuf->height() - 1;
 | 
			
		||||
 | 
			
		||||
            int count = num_pix;
 | 
			
		||||
            cover_type* covers = dst;
 | 
			
		||||
 | 
			
		||||
            if(y < 0 || y > ymax)
 | 
			
		||||
            {
 | 
			
		||||
                std::memset(dst, 0, num_pix * sizeof(cover_type));
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(x < 0)
 | 
			
		||||
            {
 | 
			
		||||
                count += x;
 | 
			
		||||
                if(count <= 0) 
 | 
			
		||||
                {
 | 
			
		||||
                    std::memset(dst, 0, num_pix * sizeof(cover_type));
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                std::memset(covers, 0, -x * sizeof(cover_type));
 | 
			
		||||
                covers -= x;
 | 
			
		||||
                x = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(x + count > xmax)
 | 
			
		||||
            {
 | 
			
		||||
                int rest = x + count - xmax - 1;
 | 
			
		||||
                count -= rest;
 | 
			
		||||
                if(count <= 0) 
 | 
			
		||||
                {
 | 
			
		||||
                    std::memset(dst, 0, num_pix * sizeof(cover_type));
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                std::memset(covers + count, 0, rest * sizeof(cover_type));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
 | 
			
		||||
            do
 | 
			
		||||
            {
 | 
			
		||||
                *covers++ = (cover_type)m_mask_function.calculate(mask);
 | 
			
		||||
                mask += Step;
 | 
			
		||||
            }
 | 
			
		||||
            while(--count);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
 | 
			
		||||
        {
 | 
			
		||||
            int xmax = m_rbuf->width() - 1;
 | 
			
		||||
            int ymax = m_rbuf->height() - 1;
 | 
			
		||||
 | 
			
		||||
            int count = num_pix;
 | 
			
		||||
            cover_type* covers = dst;
 | 
			
		||||
 | 
			
		||||
            if(y < 0 || y > ymax)
 | 
			
		||||
            {
 | 
			
		||||
                std::memset(dst, 0, num_pix * sizeof(cover_type));
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(x < 0)
 | 
			
		||||
            {
 | 
			
		||||
                count += x;
 | 
			
		||||
                if(count <= 0) 
 | 
			
		||||
                {
 | 
			
		||||
                    std::memset(dst, 0, num_pix * sizeof(cover_type));
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                std::memset(covers, 0, -x * sizeof(cover_type));
 | 
			
		||||
                covers -= x;
 | 
			
		||||
                x = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(x + count > xmax)
 | 
			
		||||
            {
 | 
			
		||||
                int rest = x + count - xmax - 1;
 | 
			
		||||
                count -= rest;
 | 
			
		||||
                if(count <= 0) 
 | 
			
		||||
                {
 | 
			
		||||
                    std::memset(dst, 0, num_pix * sizeof(cover_type));
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                std::memset(covers + count, 0, rest * sizeof(cover_type));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
 | 
			
		||||
            do
 | 
			
		||||
            {
 | 
			
		||||
                *covers = (cover_type)((cover_full + (*covers) * 
 | 
			
		||||
                                       m_mask_function.calculate(mask)) >> 
 | 
			
		||||
                                       cover_shift);
 | 
			
		||||
                ++covers;
 | 
			
		||||
                mask += Step;
 | 
			
		||||
            }
 | 
			
		||||
            while(--count);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
 | 
			
		||||
        {
 | 
			
		||||
            int xmax = m_rbuf->width() - 1;
 | 
			
		||||
            int ymax = m_rbuf->height() - 1;
 | 
			
		||||
 | 
			
		||||
            int count = num_pix;
 | 
			
		||||
            cover_type* covers = dst;
 | 
			
		||||
 | 
			
		||||
            if(x < 0 || x > xmax)
 | 
			
		||||
            {
 | 
			
		||||
                std::memset(dst, 0, num_pix * sizeof(cover_type));
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(y < 0)
 | 
			
		||||
            {
 | 
			
		||||
                count += y;
 | 
			
		||||
                if(count <= 0) 
 | 
			
		||||
                {
 | 
			
		||||
                    std::memset(dst, 0, num_pix * sizeof(cover_type));
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                std::memset(covers, 0, -y * sizeof(cover_type));
 | 
			
		||||
                covers -= y;
 | 
			
		||||
                y = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(y + count > ymax)
 | 
			
		||||
            {
 | 
			
		||||
                int rest = y + count - ymax - 1;
 | 
			
		||||
                count -= rest;
 | 
			
		||||
                if(count <= 0) 
 | 
			
		||||
                {
 | 
			
		||||
                    std::memset(dst, 0, num_pix * sizeof(cover_type));
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                std::memset(covers + count, 0, rest * sizeof(cover_type));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
 | 
			
		||||
            do
 | 
			
		||||
            {
 | 
			
		||||
                *covers++ = (cover_type)m_mask_function.calculate(mask);
 | 
			
		||||
                mask += m_rbuf->stride();
 | 
			
		||||
            }
 | 
			
		||||
            while(--count);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
 | 
			
		||||
        {
 | 
			
		||||
            int xmax = m_rbuf->width() - 1;
 | 
			
		||||
            int ymax = m_rbuf->height() - 1;
 | 
			
		||||
 | 
			
		||||
            int count = num_pix;
 | 
			
		||||
            cover_type* covers = dst;
 | 
			
		||||
 | 
			
		||||
            if(x < 0 || x > xmax)
 | 
			
		||||
            {
 | 
			
		||||
                std::memset(dst, 0, num_pix * sizeof(cover_type));
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(y < 0)
 | 
			
		||||
            {
 | 
			
		||||
                count += y;
 | 
			
		||||
                if(count <= 0) 
 | 
			
		||||
                {
 | 
			
		||||
                    std::memset(dst, 0, num_pix * sizeof(cover_type));
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                std::memset(covers, 0, -y * sizeof(cover_type));
 | 
			
		||||
                covers -= y;
 | 
			
		||||
                y = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(y + count > ymax)
 | 
			
		||||
            {
 | 
			
		||||
                int rest = y + count - ymax - 1;
 | 
			
		||||
                count -= rest;
 | 
			
		||||
                if(count <= 0) 
 | 
			
		||||
                {
 | 
			
		||||
                    std::memset(dst, 0, num_pix * sizeof(cover_type));
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                std::memset(covers + count, 0, rest * sizeof(cover_type));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
 | 
			
		||||
            do
 | 
			
		||||
            {
 | 
			
		||||
                *covers = (cover_type)((cover_full + (*covers) * 
 | 
			
		||||
                                       m_mask_function.calculate(mask)) >> 
 | 
			
		||||
                                       cover_shift);
 | 
			
		||||
                ++covers;
 | 
			
		||||
                mask += m_rbuf->stride();
 | 
			
		||||
            }
 | 
			
		||||
            while(--count);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        alpha_mask_u8(const self_type&);
 | 
			
		||||
        const self_type& operator = (const self_type&);
 | 
			
		||||
 | 
			
		||||
        rendering_buffer* m_rbuf;
 | 
			
		||||
        MaskF             m_mask_function;
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    typedef alpha_mask_u8<1, 0> alpha_mask_gray8;   //----alpha_mask_gray8
 | 
			
		||||
 | 
			
		||||
    typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r;  //----alpha_mask_rgb24r
 | 
			
		||||
    typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g;  //----alpha_mask_rgb24g
 | 
			
		||||
    typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b;  //----alpha_mask_rgb24b
 | 
			
		||||
 | 
			
		||||
    typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r;  //----alpha_mask_bgr24r
 | 
			
		||||
    typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g;  //----alpha_mask_bgr24g
 | 
			
		||||
    typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b;  //----alpha_mask_bgr24b
 | 
			
		||||
 | 
			
		||||
    typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r
 | 
			
		||||
    typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g
 | 
			
		||||
    typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b
 | 
			
		||||
    typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a
 | 
			
		||||
 | 
			
		||||
    typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r
 | 
			
		||||
    typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g
 | 
			
		||||
    typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b
 | 
			
		||||
    typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a
 | 
			
		||||
 | 
			
		||||
    typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r
 | 
			
		||||
    typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g
 | 
			
		||||
    typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b
 | 
			
		||||
    typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a
 | 
			
		||||
 | 
			
		||||
    typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r
 | 
			
		||||
    typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g
 | 
			
		||||
    typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b
 | 
			
		||||
    typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a
 | 
			
		||||
 | 
			
		||||
    typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray;  //----alpha_mask_rgb24gray
 | 
			
		||||
    typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray;  //----alpha_mask_bgr24gray
 | 
			
		||||
    typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray
 | 
			
		||||
    typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray
 | 
			
		||||
    typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray
 | 
			
		||||
    typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //==========================================================amask_no_clip_u8
 | 
			
		||||
    template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
 | 
			
		||||
    class amask_no_clip_u8
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        typedef int8u cover_type;
 | 
			
		||||
        typedef amask_no_clip_u8<Step, Offset, MaskF> self_type;
 | 
			
		||||
        enum cover_scale_e
 | 
			
		||||
        { 
 | 
			
		||||
            cover_shift = 8,
 | 
			
		||||
            cover_none  = 0,
 | 
			
		||||
            cover_full  = 255
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        amask_no_clip_u8() : m_rbuf(0) {}
 | 
			
		||||
        explicit amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
 | 
			
		||||
 | 
			
		||||
        void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
 | 
			
		||||
 | 
			
		||||
        MaskF& mask_function() { return m_mask_function; }
 | 
			
		||||
        const MaskF& mask_function() const { return m_mask_function; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        cover_type pixel(int x, int y) const
 | 
			
		||||
        {
 | 
			
		||||
            return (cover_type)m_mask_function.calculate(
 | 
			
		||||
                                   m_rbuf->row_ptr(y) + x * Step + Offset);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        cover_type combine_pixel(int x, int y, cover_type val) const
 | 
			
		||||
        {
 | 
			
		||||
            return (cover_type)((cover_full + val * 
 | 
			
		||||
                                 m_mask_function.calculate(
 | 
			
		||||
                                    m_rbuf->row_ptr(y) + x * Step + Offset)) >> 
 | 
			
		||||
                                 cover_shift);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
 | 
			
		||||
        {
 | 
			
		||||
            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
 | 
			
		||||
            do
 | 
			
		||||
            {
 | 
			
		||||
                *dst++ = (cover_type)m_mask_function.calculate(mask);
 | 
			
		||||
                mask += Step;
 | 
			
		||||
            }
 | 
			
		||||
            while(--num_pix);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
 | 
			
		||||
        {
 | 
			
		||||
            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
 | 
			
		||||
            do
 | 
			
		||||
            {
 | 
			
		||||
                *dst = (cover_type)((cover_full + (*dst) * 
 | 
			
		||||
                                    m_mask_function.calculate(mask)) >> 
 | 
			
		||||
                                    cover_shift);
 | 
			
		||||
                ++dst;
 | 
			
		||||
                mask += Step;
 | 
			
		||||
            }
 | 
			
		||||
            while(--num_pix);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
 | 
			
		||||
        {
 | 
			
		||||
            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
 | 
			
		||||
            do
 | 
			
		||||
            {
 | 
			
		||||
                *dst++ = (cover_type)m_mask_function.calculate(mask);
 | 
			
		||||
                mask += m_rbuf->stride();
 | 
			
		||||
            }
 | 
			
		||||
            while(--num_pix);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
 | 
			
		||||
        {
 | 
			
		||||
            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
 | 
			
		||||
            do
 | 
			
		||||
            {
 | 
			
		||||
                *dst = (cover_type)((cover_full + (*dst) * 
 | 
			
		||||
                                    m_mask_function.calculate(mask)) >> 
 | 
			
		||||
                                    cover_shift);
 | 
			
		||||
                ++dst;
 | 
			
		||||
                mask += m_rbuf->stride();
 | 
			
		||||
            }
 | 
			
		||||
            while(--num_pix);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        amask_no_clip_u8(const self_type&);
 | 
			
		||||
        const self_type& operator = (const self_type&);
 | 
			
		||||
 | 
			
		||||
        rendering_buffer* m_rbuf;
 | 
			
		||||
        MaskF             m_mask_function;
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8;   //----amask_no_clip_gray8
 | 
			
		||||
 | 
			
		||||
    typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r;  //----amask_no_clip_rgb24r
 | 
			
		||||
    typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g;  //----amask_no_clip_rgb24g
 | 
			
		||||
    typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b;  //----amask_no_clip_rgb24b
 | 
			
		||||
 | 
			
		||||
    typedef amask_no_clip_u8<3, 2> amask_no_clip_bgr24r;  //----amask_no_clip_bgr24r
 | 
			
		||||
    typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g;  //----amask_no_clip_bgr24g
 | 
			
		||||
    typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b;  //----amask_no_clip_bgr24b
 | 
			
		||||
 | 
			
		||||
    typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r
 | 
			
		||||
    typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g
 | 
			
		||||
    typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b
 | 
			
		||||
    typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a
 | 
			
		||||
 | 
			
		||||
    typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r
 | 
			
		||||
    typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g
 | 
			
		||||
    typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b
 | 
			
		||||
    typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a
 | 
			
		||||
 | 
			
		||||
    typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r
 | 
			
		||||
    typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g
 | 
			
		||||
    typedef amask_no_clip_u8<4, 0> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b
 | 
			
		||||
    typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a
 | 
			
		||||
 | 
			
		||||
    typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r
 | 
			
		||||
    typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g
 | 
			
		||||
    typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b
 | 
			
		||||
    typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a
 | 
			
		||||
 | 
			
		||||
    typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgb24gray;  //----amask_no_clip_rgb24gray
 | 
			
		||||
    typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray;  //----amask_no_clip_bgr24gray
 | 
			
		||||
    typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgba32gray; //----amask_no_clip_rgba32gray
 | 
			
		||||
    typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_argb32gray; //----amask_no_clip_argb32gray
 | 
			
		||||
    typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgra32gray; //----amask_no_clip_bgra32gray
 | 
			
		||||
    typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_abgr32gray; //----amask_no_clip_abgr32gray
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										73
									
								
								dep/agg/include/agg_arc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								dep/agg/include/agg_arc.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// Arc vertex generator
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_ARC_INCLUDED
 | 
			
		||||
#define AGG_ARC_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    //=====================================================================arc
 | 
			
		||||
    //
 | 
			
		||||
    // See Implementation agg_arc.cpp 
 | 
			
		||||
    //
 | 
			
		||||
    class arc
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        arc() : m_scale(1.0), m_initialized(false) {}
 | 
			
		||||
        arc(double x,  double y, 
 | 
			
		||||
            double rx, double ry, 
 | 
			
		||||
            double a1, double a2, 
 | 
			
		||||
            bool ccw=true);
 | 
			
		||||
 | 
			
		||||
        void init(double x,  double y, 
 | 
			
		||||
                  double rx, double ry, 
 | 
			
		||||
                  double a1, double a2, 
 | 
			
		||||
                  bool ccw=true);
 | 
			
		||||
 | 
			
		||||
        void approximation_scale(double s);
 | 
			
		||||
        double approximation_scale() const { return m_scale;  }
 | 
			
		||||
 | 
			
		||||
        void rewind(unsigned);
 | 
			
		||||
        unsigned vertex(double* x, double* y);
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        void normalize(double a1, double a2, bool ccw);
 | 
			
		||||
 | 
			
		||||
        double   m_x;
 | 
			
		||||
        double   m_y;
 | 
			
		||||
        double   m_rx;
 | 
			
		||||
        double   m_ry;
 | 
			
		||||
        double   m_angle;
 | 
			
		||||
        double   m_start;
 | 
			
		||||
        double   m_end;
 | 
			
		||||
        double   m_scale;
 | 
			
		||||
        double   m_da;
 | 
			
		||||
        bool     m_ccw;
 | 
			
		||||
        bool     m_initialized;
 | 
			
		||||
        unsigned m_path_cmd;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										1119
									
								
								dep/agg/include/agg_array.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1119
									
								
								dep/agg/include/agg_array.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										82
									
								
								dep/agg/include/agg_arrowhead.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								dep/agg/include/agg_arrowhead.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// Simple arrowhead/arrowtail generator 
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
#ifndef AGG_ARROWHEAD_INCLUDED
 | 
			
		||||
#define AGG_ARROWHEAD_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    //===============================================================arrowhead
 | 
			
		||||
    //
 | 
			
		||||
    // See implementation agg_arrowhead.cpp 
 | 
			
		||||
    //
 | 
			
		||||
    class arrowhead
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        arrowhead();
 | 
			
		||||
 | 
			
		||||
        void head(double d1, double d2, double d3, double d4)
 | 
			
		||||
        {
 | 
			
		||||
            m_head_d1 = d1;
 | 
			
		||||
            m_head_d2 = d2;
 | 
			
		||||
            m_head_d3 = d3;
 | 
			
		||||
            m_head_d4 = d4;
 | 
			
		||||
            m_head_flag = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void head()    { m_head_flag = true; }
 | 
			
		||||
        void no_head() { m_head_flag = false; }
 | 
			
		||||
 | 
			
		||||
        void tail(double d1, double d2, double d3, double d4)
 | 
			
		||||
        {
 | 
			
		||||
            m_tail_d1 = d1;
 | 
			
		||||
            m_tail_d2 = d2;
 | 
			
		||||
            m_tail_d3 = d3;
 | 
			
		||||
            m_tail_d4 = d4;
 | 
			
		||||
            m_tail_flag = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void tail()    { m_tail_flag = true;  }
 | 
			
		||||
        void no_tail() { m_tail_flag = false; }
 | 
			
		||||
 | 
			
		||||
        void rewind(unsigned path_id);
 | 
			
		||||
        unsigned vertex(double* x, double* y);
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        double   m_head_d1;
 | 
			
		||||
        double   m_head_d2;
 | 
			
		||||
        double   m_head_d3;
 | 
			
		||||
        double   m_head_d4;
 | 
			
		||||
        double   m_tail_d1;
 | 
			
		||||
        double   m_tail_d2;
 | 
			
		||||
        double   m_tail_d3;
 | 
			
		||||
        double   m_tail_d4;
 | 
			
		||||
        bool     m_head_flag;
 | 
			
		||||
        bool     m_tail_flag;
 | 
			
		||||
        double   m_coord[16];
 | 
			
		||||
        unsigned m_cmd[8];
 | 
			
		||||
        unsigned m_curr_id;
 | 
			
		||||
        unsigned m_curr_coord;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										574
									
								
								dep/agg/include/agg_basics.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										574
									
								
								dep/agg/include/agg_basics.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,574 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_BASICS_INCLUDED
 | 
			
		||||
#define AGG_BASICS_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <cmath>
 | 
			
		||||
#include "agg_config.h"
 | 
			
		||||
 | 
			
		||||
//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR
 | 
			
		||||
#ifdef AGG_CUSTOM_ALLOCATOR
 | 
			
		||||
#include "agg_allocator.h"
 | 
			
		||||
#else
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
    // The policy of all AGG containers and memory allocation strategy 
 | 
			
		||||
    // in general is that no allocated data requires explicit construction.
 | 
			
		||||
    // It means that the allocator can be really simple; you can even
 | 
			
		||||
    // replace new/delete to malloc/free. The constructors and destructors 
 | 
			
		||||
    // won't be called in this case, however everything will remain working. 
 | 
			
		||||
    // The second argument of deallocate() is the size of the allocated 
 | 
			
		||||
    // block. You can use this information if you wish.
 | 
			
		||||
    //------------------------------------------------------------pod_allocator
 | 
			
		||||
    template<class T> struct pod_allocator
 | 
			
		||||
    {
 | 
			
		||||
        static T*   allocate(unsigned num)       { return new T [num]; }
 | 
			
		||||
        static void deallocate(T* ptr, unsigned) { delete [] ptr;      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Single object allocator. It's also can be replaced with your custom
 | 
			
		||||
    // allocator. The difference is that it can only allocate a single 
 | 
			
		||||
    // object and the constructor and destructor must be called. 
 | 
			
		||||
    // In AGG there is no need to allocate an array of objects with
 | 
			
		||||
    // calling their constructors (only single ones). So that, if you
 | 
			
		||||
    // replace these new/delete to malloc/free make sure that the in-place
 | 
			
		||||
    // new is called and take care of calling the destructor too.
 | 
			
		||||
    //------------------------------------------------------------obj_allocator
 | 
			
		||||
    template<class T> struct obj_allocator
 | 
			
		||||
    {
 | 
			
		||||
        static T*   allocate()         { return new T; }
 | 
			
		||||
        static void deallocate(T* ptr) { delete ptr;   }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//-------------------------------------------------------- Default basic types
 | 
			
		||||
//
 | 
			
		||||
// If the compiler has different capacity of the basic types you can redefine
 | 
			
		||||
// them via the compiler command line or by generating agg_config.h that is
 | 
			
		||||
// empty by default.
 | 
			
		||||
//
 | 
			
		||||
#ifndef AGG_INT8
 | 
			
		||||
#define AGG_INT8 signed char
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_INT8U
 | 
			
		||||
#define AGG_INT8U unsigned char
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_INT16
 | 
			
		||||
#define AGG_INT16 short
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_INT16U
 | 
			
		||||
#define AGG_INT16U unsigned short
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_INT32
 | 
			
		||||
#define AGG_INT32 int
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_INT32U
 | 
			
		||||
#define AGG_INT32U unsigned
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_INT64
 | 
			
		||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
 | 
			
		||||
#define AGG_INT64 signed __int64
 | 
			
		||||
#else
 | 
			
		||||
#define AGG_INT64 signed long long
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_INT64U
 | 
			
		||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
 | 
			
		||||
#define AGG_INT64U unsigned __int64
 | 
			
		||||
#else
 | 
			
		||||
#define AGG_INT64U unsigned long long
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------ Some fixes for MS Visual C++
 | 
			
		||||
#if defined(_MSC_VER)
 | 
			
		||||
#pragma warning(disable:4786) // Identifier was truncated...
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER)
 | 
			
		||||
#define AGG_INLINE __forceinline
 | 
			
		||||
#else
 | 
			
		||||
#define AGG_INLINE inline
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
    //-------------------------------------------------------------------------
 | 
			
		||||
    typedef AGG_INT8   int8;         //----int8
 | 
			
		||||
    typedef AGG_INT8U  int8u;        //----int8u
 | 
			
		||||
    typedef AGG_INT16  int16;        //----int16
 | 
			
		||||
    typedef AGG_INT16U int16u;       //----int16u
 | 
			
		||||
    typedef AGG_INT32  int32;        //----int32
 | 
			
		||||
    typedef AGG_INT32U int32u;       //----int32u
 | 
			
		||||
    typedef AGG_INT64  int64;        //----int64
 | 
			
		||||
    typedef AGG_INT64U int64u;       //----int64u
 | 
			
		||||
 | 
			
		||||
#if defined(AGG_FISTP)
 | 
			
		||||
#pragma warning(push)
 | 
			
		||||
#pragma warning(disable : 4035) //Disable warning "no return value"
 | 
			
		||||
    AGG_INLINE int iround(double v)              //-------iround
 | 
			
		||||
    {
 | 
			
		||||
        int t;
 | 
			
		||||
        __asm fld   qword ptr [v]
 | 
			
		||||
        __asm fistp dword ptr [t]
 | 
			
		||||
        __asm mov eax, dword ptr [t]
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE unsigned uround(double v)         //-------uround
 | 
			
		||||
    {
 | 
			
		||||
        unsigned t;
 | 
			
		||||
        __asm fld   qword ptr [v]
 | 
			
		||||
        __asm fistp dword ptr [t]
 | 
			
		||||
        __asm mov eax, dword ptr [t]
 | 
			
		||||
    }
 | 
			
		||||
#pragma warning(pop)
 | 
			
		||||
    AGG_INLINE int ifloor(double v)
 | 
			
		||||
    {
 | 
			
		||||
        return int(floor(v));
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE unsigned ufloor(double v)         //-------ufloor
 | 
			
		||||
    {
 | 
			
		||||
        return unsigned(floor(v));
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE int iceil(double v)
 | 
			
		||||
    {
 | 
			
		||||
        return int(ceil(v));
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE unsigned uceil(double v)          //--------uceil
 | 
			
		||||
    {
 | 
			
		||||
        return unsigned(ceil(v));
 | 
			
		||||
    }
 | 
			
		||||
#elif defined(AGG_QIFIST)
 | 
			
		||||
    AGG_INLINE int iround(double v)
 | 
			
		||||
    {
 | 
			
		||||
        return int(v);
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE int uround(double v)
 | 
			
		||||
    {
 | 
			
		||||
        return unsigned(v);
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE int ifloor(double v)
 | 
			
		||||
    {
 | 
			
		||||
        return int(std::floor(v));
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE unsigned ufloor(double v)
 | 
			
		||||
    {
 | 
			
		||||
        return unsigned(std::floor(v));
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE int iceil(double v)
 | 
			
		||||
    {
 | 
			
		||||
        return int(std::ceil(v));
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE unsigned uceil(double v)
 | 
			
		||||
    {
 | 
			
		||||
        return unsigned(std::ceil(v));
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    AGG_INLINE int iround(double v)
 | 
			
		||||
    {
 | 
			
		||||
        return int((v < 0.0) ? v - 0.5 : v + 0.5);
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE int uround(double v)
 | 
			
		||||
    {
 | 
			
		||||
        return unsigned(v + 0.5);
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE int ifloor(double v)
 | 
			
		||||
    {
 | 
			
		||||
        int i = int(v);
 | 
			
		||||
        return i - (i > v);
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE unsigned ufloor(double v)
 | 
			
		||||
    {
 | 
			
		||||
        return unsigned(v);
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE int iceil(double v)
 | 
			
		||||
    {
 | 
			
		||||
        return int(std::ceil(v));
 | 
			
		||||
    }
 | 
			
		||||
    AGG_INLINE unsigned uceil(double v)
 | 
			
		||||
    {
 | 
			
		||||
        return unsigned(std::ceil(v));
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    //---------------------------------------------------------------saturation
 | 
			
		||||
    template<int Limit> struct saturation
 | 
			
		||||
    {
 | 
			
		||||
        AGG_INLINE static int iround(double v)
 | 
			
		||||
        {
 | 
			
		||||
            if(v < double(-Limit)) return -Limit;
 | 
			
		||||
            if(v > double( Limit)) return  Limit;
 | 
			
		||||
            return agg::iround(v);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------mul_one
 | 
			
		||||
    template<unsigned Shift> struct mul_one
 | 
			
		||||
    {
 | 
			
		||||
        AGG_INLINE static unsigned mul(unsigned a, unsigned b)
 | 
			
		||||
        {
 | 
			
		||||
            unsigned q = a * b + (1 << (Shift-1));
 | 
			
		||||
            return (q + (q >> Shift)) >> Shift;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //-------------------------------------------------------------------------
 | 
			
		||||
    typedef unsigned char cover_type;    //----cover_type
 | 
			
		||||
    enum cover_scale_e
 | 
			
		||||
    {
 | 
			
		||||
        cover_shift = 8,                 //----cover_shift
 | 
			
		||||
        cover_size  = 1 << cover_shift,  //----cover_size 
 | 
			
		||||
        cover_mask  = cover_size - 1,    //----cover_mask 
 | 
			
		||||
        cover_none  = 0,                 //----cover_none 
 | 
			
		||||
        cover_full  = cover_mask         //----cover_full 
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------poly_subpixel_scale_e
 | 
			
		||||
    // These constants determine the subpixel accuracy, to be more precise, 
 | 
			
		||||
    // the number of bits of the fractional part of the coordinates. 
 | 
			
		||||
    // The possible coordinate capacity in bits can be calculated by formula:
 | 
			
		||||
    // sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and
 | 
			
		||||
    // 8-bits fractional part the capacity is 24 bits.
 | 
			
		||||
    enum poly_subpixel_scale_e
 | 
			
		||||
    {
 | 
			
		||||
        poly_subpixel_shift = 8,                      //----poly_subpixel_shift
 | 
			
		||||
        poly_subpixel_scale = 1<<poly_subpixel_shift, //----poly_subpixel_scale 
 | 
			
		||||
        poly_subpixel_mask  = poly_subpixel_scale-1   //----poly_subpixel_mask 
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------filling_rule_e
 | 
			
		||||
    enum filling_rule_e
 | 
			
		||||
    {
 | 
			
		||||
        fill_non_zero,
 | 
			
		||||
        fill_even_odd
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //-----------------------------------------------------------------------pi
 | 
			
		||||
    const double pi = 3.14159265358979323846;
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------deg2rad
 | 
			
		||||
    inline double deg2rad(double deg)
 | 
			
		||||
    {
 | 
			
		||||
        return deg * pi / 180.0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------rad2deg
 | 
			
		||||
    inline double rad2deg(double rad)
 | 
			
		||||
    {
 | 
			
		||||
        return rad * 180.0 / pi;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
    //----------------------------------------------------------------rect_base
 | 
			
		||||
    template<class T> struct rect_base
 | 
			
		||||
    {
 | 
			
		||||
        typedef T            value_type;
 | 
			
		||||
        typedef rect_base<T> self_type;
 | 
			
		||||
        T x1, y1, x2, y2;
 | 
			
		||||
 | 
			
		||||
        rect_base() {}
 | 
			
		||||
        rect_base(T x1_, T y1_, T x2_, T y2_) :
 | 
			
		||||
            x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
 | 
			
		||||
 | 
			
		||||
        void init(T x1_, T y1_, T x2_, T y2_) 
 | 
			
		||||
        {
 | 
			
		||||
            x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_; 
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const self_type& normalize()
 | 
			
		||||
        {
 | 
			
		||||
            T t;
 | 
			
		||||
            if(x1 > x2) { t = x1; x1 = x2; x2 = t; }
 | 
			
		||||
            if(y1 > y2) { t = y1; y1 = y2; y2 = t; }
 | 
			
		||||
            return *this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bool clip(const self_type& r)
 | 
			
		||||
        {
 | 
			
		||||
            if(x2 > r.x2) x2 = r.x2;
 | 
			
		||||
            if(y2 > r.y2) y2 = r.y2;
 | 
			
		||||
            if(x1 < r.x1) x1 = r.x1;
 | 
			
		||||
            if(y1 < r.y1) y1 = r.y1;
 | 
			
		||||
            return x1 <= x2 && y1 <= y2;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bool is_valid() const
 | 
			
		||||
        {
 | 
			
		||||
            return x1 <= x2 && y1 <= y2;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bool hit_test(T x, T y) const
 | 
			
		||||
        {
 | 
			
		||||
            return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        bool overlaps(const self_type& r) const
 | 
			
		||||
        {
 | 
			
		||||
            return !(r.x1 > x2 || r.x2 < x1
 | 
			
		||||
                  || r.y1 > y2 || r.y2 < y1);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //-----------------------------------------------------intersect_rectangles
 | 
			
		||||
    template<class Rect> 
 | 
			
		||||
    inline Rect intersect_rectangles(const Rect& r1, const Rect& r2)
 | 
			
		||||
    {
 | 
			
		||||
        Rect r = r1;
 | 
			
		||||
 | 
			
		||||
        // First process x2,y2 because the other order 
 | 
			
		||||
        // results in Internal Compiler Error under 
 | 
			
		||||
        // Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in 
 | 
			
		||||
        // case of "Maximize Speed" optimization option.
 | 
			
		||||
        //-----------------
 | 
			
		||||
        if(r.x2 > r2.x2) r.x2 = r2.x2; 
 | 
			
		||||
        if(r.y2 > r2.y2) r.y2 = r2.y2;
 | 
			
		||||
        if(r.x1 < r2.x1) r.x1 = r2.x1;
 | 
			
		||||
        if(r.y1 < r2.y1) r.y1 = r2.y1;
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //---------------------------------------------------------unite_rectangles
 | 
			
		||||
    template<class Rect> 
 | 
			
		||||
    inline Rect unite_rectangles(const Rect& r1, const Rect& r2)
 | 
			
		||||
    {
 | 
			
		||||
        Rect r = r1;
 | 
			
		||||
        if(r.x2 < r2.x2) r.x2 = r2.x2;
 | 
			
		||||
        if(r.y2 < r2.y2) r.y2 = r2.y2;
 | 
			
		||||
        if(r.x1 > r2.x1) r.x1 = r2.x1;
 | 
			
		||||
        if(r.y1 > r2.y1) r.y1 = r2.y1;
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    typedef rect_base<int>    rect_i; //----rect_i
 | 
			
		||||
    typedef rect_base<float>  rect_f; //----rect_f
 | 
			
		||||
    typedef rect_base<double> rect_d; //----rect_d
 | 
			
		||||
 | 
			
		||||
    //---------------------------------------------------------path_commands_e
 | 
			
		||||
    enum path_commands_e
 | 
			
		||||
    {
 | 
			
		||||
        path_cmd_stop     = 0,        //----path_cmd_stop    
 | 
			
		||||
        path_cmd_move_to  = 1,        //----path_cmd_move_to 
 | 
			
		||||
        path_cmd_line_to  = 2,        //----path_cmd_line_to 
 | 
			
		||||
        path_cmd_curve3   = 3,        //----path_cmd_curve3  
 | 
			
		||||
        path_cmd_curve4   = 4,        //----path_cmd_curve4  
 | 
			
		||||
        path_cmd_curveN   = 5,        //----path_cmd_curveN
 | 
			
		||||
        path_cmd_catrom   = 6,        //----path_cmd_catrom
 | 
			
		||||
        path_cmd_ubspline = 7,        //----path_cmd_ubspline
 | 
			
		||||
        path_cmd_end_poly = 0x0F,     //----path_cmd_end_poly
 | 
			
		||||
        path_cmd_mask     = 0x0F      //----path_cmd_mask    
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------path_flags_e
 | 
			
		||||
    enum path_flags_e
 | 
			
		||||
    {
 | 
			
		||||
        path_flags_none  = 0,         //----path_flags_none 
 | 
			
		||||
        path_flags_ccw   = 0x10,      //----path_flags_ccw  
 | 
			
		||||
        path_flags_cw    = 0x20,      //----path_flags_cw   
 | 
			
		||||
        path_flags_close = 0x40,      //----path_flags_close
 | 
			
		||||
        path_flags_mask  = 0xF0       //----path_flags_mask 
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //---------------------------------------------------------------is_vertex
 | 
			
		||||
    inline bool is_vertex(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return c >= path_cmd_move_to && c < path_cmd_end_poly;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //--------------------------------------------------------------is_drawing
 | 
			
		||||
    inline bool is_drawing(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return c >= path_cmd_line_to && c < path_cmd_end_poly;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //-----------------------------------------------------------------is_stop
 | 
			
		||||
    inline bool is_stop(unsigned c)
 | 
			
		||||
    { 
 | 
			
		||||
        return c == path_cmd_stop;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //--------------------------------------------------------------is_move_to
 | 
			
		||||
    inline bool is_move_to(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return c == path_cmd_move_to;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //--------------------------------------------------------------is_line_to
 | 
			
		||||
    inline bool is_line_to(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return c == path_cmd_line_to;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------is_curve
 | 
			
		||||
    inline bool is_curve(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return c == path_cmd_curve3 || c == path_cmd_curve4;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //---------------------------------------------------------------is_curve3
 | 
			
		||||
    inline bool is_curve3(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return c == path_cmd_curve3;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //---------------------------------------------------------------is_curve4
 | 
			
		||||
    inline bool is_curve4(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return c == path_cmd_curve4;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //-------------------------------------------------------------is_end_poly
 | 
			
		||||
    inline bool is_end_poly(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return (c & path_cmd_mask) == path_cmd_end_poly;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------is_close
 | 
			
		||||
    inline bool is_close(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return (c & ~(path_flags_cw | path_flags_ccw)) ==
 | 
			
		||||
               (path_cmd_end_poly | path_flags_close); 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------is_next_poly
 | 
			
		||||
    inline bool is_next_poly(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return is_stop(c) || is_move_to(c) || is_end_poly(c);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //-------------------------------------------------------------------is_cw
 | 
			
		||||
    inline bool is_cw(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return (c & path_flags_cw) != 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------is_ccw
 | 
			
		||||
    inline bool is_ccw(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return (c & path_flags_ccw) != 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //-------------------------------------------------------------is_oriented
 | 
			
		||||
    inline bool is_oriented(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return (c & (path_flags_cw | path_flags_ccw)) != 0; 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //---------------------------------------------------------------is_closed
 | 
			
		||||
    inline bool is_closed(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return (c & path_flags_close) != 0; 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------get_close_flag
 | 
			
		||||
    inline unsigned get_close_flag(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return c & path_flags_close; 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //-------------------------------------------------------clear_orientation
 | 
			
		||||
    inline unsigned clear_orientation(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return c & ~(path_flags_cw | path_flags_ccw);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //---------------------------------------------------------get_orientation
 | 
			
		||||
    inline unsigned get_orientation(unsigned c)
 | 
			
		||||
    {
 | 
			
		||||
        return c & (path_flags_cw | path_flags_ccw);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //---------------------------------------------------------set_orientation
 | 
			
		||||
    inline unsigned set_orientation(unsigned c, unsigned o)
 | 
			
		||||
    {
 | 
			
		||||
        return clear_orientation(c) | o;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //--------------------------------------------------------------point_base
 | 
			
		||||
    template<class T> struct point_base
 | 
			
		||||
    {
 | 
			
		||||
        typedef T value_type;
 | 
			
		||||
        T x,y;
 | 
			
		||||
        point_base() {}
 | 
			
		||||
        point_base(T x_, T y_) : x(x_), y(y_) {}
 | 
			
		||||
    };
 | 
			
		||||
    typedef point_base<int>    point_i; //-----point_i
 | 
			
		||||
    typedef point_base<float>  point_f; //-----point_f
 | 
			
		||||
    typedef point_base<double> point_d; //-----point_d
 | 
			
		||||
 | 
			
		||||
    //-------------------------------------------------------------vertex_base
 | 
			
		||||
    template<class T> struct vertex_base
 | 
			
		||||
    {
 | 
			
		||||
        typedef T value_type;
 | 
			
		||||
        T x,y;
 | 
			
		||||
        unsigned cmd;
 | 
			
		||||
        vertex_base() {}
 | 
			
		||||
        vertex_base(T x_, T y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {}
 | 
			
		||||
    };
 | 
			
		||||
    typedef vertex_base<int>    vertex_i; //-----vertex_i
 | 
			
		||||
    typedef vertex_base<float>  vertex_f; //-----vertex_f
 | 
			
		||||
    typedef vertex_base<double> vertex_d; //-----vertex_d
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------row_info
 | 
			
		||||
    template<class T> struct row_info
 | 
			
		||||
    {
 | 
			
		||||
        int x1, x2;
 | 
			
		||||
        T* ptr;
 | 
			
		||||
        row_info() {}
 | 
			
		||||
        row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------const_row_info
 | 
			
		||||
    template<class T> struct const_row_info
 | 
			
		||||
    {
 | 
			
		||||
        int x1, x2;
 | 
			
		||||
        const T* ptr;
 | 
			
		||||
        const_row_info() {}
 | 
			
		||||
        const_row_info(int x1_, int x2_, const T* ptr_) : 
 | 
			
		||||
            x1(x1_), x2(x2_), ptr(ptr_) {}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------is_equal_eps
 | 
			
		||||
    template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon)
 | 
			
		||||
    {
 | 
			
		||||
	bool neg1 = v1 < 0.0;
 | 
			
		||||
	bool neg2 = v2 < 0.0;
 | 
			
		||||
 | 
			
		||||
	if (neg1 != neg2)
 | 
			
		||||
	    return std::fabs(v1) < epsilon && std::fabs(v2) < epsilon;
 | 
			
		||||
 | 
			
		||||
        int int1, int2;
 | 
			
		||||
	std::frexp(v1, &int1);
 | 
			
		||||
	std::frexp(v2, &int2);
 | 
			
		||||
	int min12 = int1 < int2 ? int1 : int2;
 | 
			
		||||
 | 
			
		||||
	v1 = std::ldexp(v1, -min12);
 | 
			
		||||
	v2 = std::ldexp(v2, -min12);
 | 
			
		||||
 | 
			
		||||
	return std::fabs(v1 - v2) < epsilon;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										159
									
								
								dep/agg/include/agg_bezier_arc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								dep/agg/include/agg_bezier_arc.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e., 
 | 
			
		||||
// 4, 7, 10, or 13 vertices.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_BEZIER_ARC_INCLUDED
 | 
			
		||||
#define AGG_BEZIER_ARC_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_conv_transform.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    //-----------------------------------------------------------------------
 | 
			
		||||
    void arc_to_bezier(double cx, double cy, double rx, double ry, 
 | 
			
		||||
                       double start_angle, double sweep_angle,
 | 
			
		||||
                       double* curve);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //==============================================================bezier_arc
 | 
			
		||||
    // 
 | 
			
		||||
    // See implemantaion agg_bezier_arc.cpp
 | 
			
		||||
    //
 | 
			
		||||
    class bezier_arc
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        bezier_arc() : m_vertex(26), m_num_vertices(0), m_cmd(path_cmd_line_to) {}
 | 
			
		||||
        bezier_arc(double x,  double y, 
 | 
			
		||||
                   double rx, double ry, 
 | 
			
		||||
                   double start_angle, 
 | 
			
		||||
                   double sweep_angle)
 | 
			
		||||
        {
 | 
			
		||||
            init(x, y, rx, ry, start_angle, sweep_angle);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        void init(double x,  double y, 
 | 
			
		||||
                  double rx, double ry, 
 | 
			
		||||
                  double start_angle, 
 | 
			
		||||
                  double sweep_angle);
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        void rewind(unsigned)
 | 
			
		||||
        {
 | 
			
		||||
            m_vertex = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        unsigned vertex(double* x, double* y)
 | 
			
		||||
        {
 | 
			
		||||
            if(m_vertex >= m_num_vertices) return path_cmd_stop;
 | 
			
		||||
            *x = m_vertices[m_vertex];
 | 
			
		||||
            *y = m_vertices[m_vertex + 1];
 | 
			
		||||
            m_vertex += 2;
 | 
			
		||||
            return (m_vertex == 2) ? unsigned(path_cmd_move_to) : m_cmd;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Supplemantary functions. num_vertices() actually returns doubled 
 | 
			
		||||
        // number of vertices. That is, for 1 vertex it returns 2.
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        unsigned  num_vertices() const { return m_num_vertices; }
 | 
			
		||||
        const double* vertices() const { return m_vertices;     }
 | 
			
		||||
        double*       vertices()       { return m_vertices;     }
 | 
			
		||||
 
 | 
			
		||||
    private:
 | 
			
		||||
        unsigned m_vertex;
 | 
			
		||||
        unsigned m_num_vertices;
 | 
			
		||||
        double   m_vertices[26];
 | 
			
		||||
        unsigned m_cmd;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //==========================================================bezier_arc_svg
 | 
			
		||||
    // Compute an SVG-style bezier arc. 
 | 
			
		||||
    //
 | 
			
		||||
    // Computes an elliptical arc from (x1, y1) to (x2, y2). The size and 
 | 
			
		||||
    // orientation of the ellipse are defined by two radii (rx, ry) 
 | 
			
		||||
    // and an x-axis-rotation, which indicates how the ellipse as a whole 
 | 
			
		||||
    // is rotated relative to the current coordinate system. The center 
 | 
			
		||||
    // (cx, cy) of the ellipse is calculated automatically to satisfy the 
 | 
			
		||||
    // constraints imposed by the other parameters. 
 | 
			
		||||
    // large-arc-flag and sweep-flag contribute to the automatic calculations 
 | 
			
		||||
    // and help determine how the arc is drawn.
 | 
			
		||||
    class bezier_arc_svg
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        bezier_arc_svg() : m_arc(), m_radii_ok(false) {}
 | 
			
		||||
 | 
			
		||||
        bezier_arc_svg(double x1, double y1, 
 | 
			
		||||
                       double rx, double ry, 
 | 
			
		||||
                       double angle,
 | 
			
		||||
                       bool large_arc_flag,
 | 
			
		||||
                       bool sweep_flag,
 | 
			
		||||
                       double x2, double y2) : 
 | 
			
		||||
            m_arc(), m_radii_ok(false)
 | 
			
		||||
        {
 | 
			
		||||
            init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        void init(double x1, double y1, 
 | 
			
		||||
                  double rx, double ry, 
 | 
			
		||||
                  double angle,
 | 
			
		||||
                  bool large_arc_flag,
 | 
			
		||||
                  bool sweep_flag,
 | 
			
		||||
                  double x2, double y2);
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        bool radii_ok() const { return m_radii_ok; }
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        void rewind(unsigned)
 | 
			
		||||
        {
 | 
			
		||||
            m_arc.rewind(0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        unsigned vertex(double* x, double* y)
 | 
			
		||||
        {
 | 
			
		||||
            return m_arc.vertex(x, y);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Supplemantary functions. num_vertices() actually returns doubled 
 | 
			
		||||
        // number of vertices. That is, for 1 vertex it returns 2.
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        unsigned  num_vertices() const { return m_arc.num_vertices(); }
 | 
			
		||||
        const double* vertices() const { return m_arc.vertices();     }
 | 
			
		||||
        double*       vertices()       { return m_arc.vertices();     }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        bezier_arc m_arc;
 | 
			
		||||
        bool       m_radii_ok;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										54
									
								
								dep/agg/include/agg_bitset_iterator.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								dep/agg/include/agg_bitset_iterator.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_BITSET_ITERATOR_INCLUDED
 | 
			
		||||
#define AGG_BITSET_ITERATOR_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
    class bitset_iterator
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        bitset_iterator(const int8u* bits, unsigned offset = 0) :
 | 
			
		||||
            m_bits(bits + (offset >> 3)),
 | 
			
		||||
            m_mask(0x80 >> (offset & 7))
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
        void operator ++ ()
 | 
			
		||||
        {
 | 
			
		||||
            m_mask >>= 1;
 | 
			
		||||
            if(m_mask == 0)
 | 
			
		||||
            {
 | 
			
		||||
                ++m_bits;
 | 
			
		||||
                m_mask = 0x80;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        unsigned bit() const
 | 
			
		||||
        {
 | 
			
		||||
            return (*m_bits) & m_mask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        const int8u* m_bits;
 | 
			
		||||
        int8u        m_mask;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										1505
									
								
								dep/agg/include/agg_blur.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1505
									
								
								dep/agg/include/agg_blur.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										116
									
								
								dep/agg/include/agg_bounding_rect.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								dep/agg/include/agg_bounding_rect.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// bounding_rect function template
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
#ifndef AGG_BOUNDING_RECT_INCLUDED
 | 
			
		||||
#define AGG_BOUNDING_RECT_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    //-----------------------------------------------------------bounding_rect
 | 
			
		||||
    template<class VertexSource, class GetId, class CoordT>
 | 
			
		||||
    bool bounding_rect(VertexSource& vs, GetId& gi, 
 | 
			
		||||
                       unsigned start, unsigned num, 
 | 
			
		||||
                       CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
 | 
			
		||||
    {
 | 
			
		||||
        unsigned i;
 | 
			
		||||
        double x;
 | 
			
		||||
        double y;
 | 
			
		||||
        bool first = true;
 | 
			
		||||
 | 
			
		||||
        *x1 = CoordT(1);
 | 
			
		||||
        *y1 = CoordT(1);
 | 
			
		||||
        *x2 = CoordT(0);
 | 
			
		||||
        *y2 = CoordT(0);
 | 
			
		||||
 | 
			
		||||
        for(i = 0; i < num; i++)
 | 
			
		||||
        {
 | 
			
		||||
            vs.rewind(gi[start + i]);
 | 
			
		||||
            unsigned cmd;
 | 
			
		||||
            while(!is_stop(cmd = vs.vertex(&x, &y)))
 | 
			
		||||
            {
 | 
			
		||||
                if(is_vertex(cmd))
 | 
			
		||||
                {
 | 
			
		||||
                    if(first)
 | 
			
		||||
                    {
 | 
			
		||||
                        *x1 = CoordT(x);
 | 
			
		||||
                        *y1 = CoordT(y);
 | 
			
		||||
                        *x2 = CoordT(x);
 | 
			
		||||
                        *y2 = CoordT(y);
 | 
			
		||||
                        first = false;
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        if(CoordT(x) < *x1) *x1 = CoordT(x);
 | 
			
		||||
                        if(CoordT(y) < *y1) *y1 = CoordT(y);
 | 
			
		||||
                        if(CoordT(x) > *x2) *x2 = CoordT(x);
 | 
			
		||||
                        if(CoordT(y) > *y2) *y2 = CoordT(y);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return *x1 <= *x2 && *y1 <= *y2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //-----------------------------------------------------bounding_rect_single
 | 
			
		||||
    template<class VertexSource, class CoordT> 
 | 
			
		||||
    bool bounding_rect_single(VertexSource& vs, unsigned path_id,
 | 
			
		||||
                              CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
 | 
			
		||||
    {
 | 
			
		||||
        double x;
 | 
			
		||||
        double y;
 | 
			
		||||
        bool first = true;
 | 
			
		||||
 | 
			
		||||
        *x1 = CoordT(1);
 | 
			
		||||
        *y1 = CoordT(1);
 | 
			
		||||
        *x2 = CoordT(0);
 | 
			
		||||
        *y2 = CoordT(0);
 | 
			
		||||
 | 
			
		||||
        vs.rewind(path_id);
 | 
			
		||||
        unsigned cmd;
 | 
			
		||||
        while(!is_stop(cmd = vs.vertex(&x, &y)))
 | 
			
		||||
        {
 | 
			
		||||
            if(is_vertex(cmd))
 | 
			
		||||
            {
 | 
			
		||||
                if(first)
 | 
			
		||||
                {
 | 
			
		||||
                    *x1 = CoordT(x);
 | 
			
		||||
                    *y1 = CoordT(y);
 | 
			
		||||
                    *x2 = CoordT(x);
 | 
			
		||||
                    *y2 = CoordT(y);
 | 
			
		||||
                    first = false;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    if(CoordT(x) < *x1) *x1 = CoordT(x);
 | 
			
		||||
                    if(CoordT(y) < *y1) *y1 = CoordT(y);
 | 
			
		||||
                    if(CoordT(x) > *x2) *x2 = CoordT(x);
 | 
			
		||||
                    if(CoordT(y) > *y2) *y2 = CoordT(y);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return *x1 <= *x2 && *y1 <= *y2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										76
									
								
								dep/agg/include/agg_bspline.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								dep/agg/include/agg_bspline.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// class bspline
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_BSPLINE_INCLUDED
 | 
			
		||||
#define AGG_BSPLINE_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_array.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
    //----------------------------------------------------------------bspline
 | 
			
		||||
    // A very simple class of Bi-cubic Spline interpolation.
 | 
			
		||||
    // First call init(num, x[], y[]) where num - number of source points, 
 | 
			
		||||
    // x, y - arrays of X and Y values respectively. Here Y must be a function 
 | 
			
		||||
    // of X. It means that all the X-coordinates must be arranged in the ascending
 | 
			
		||||
    // order. 
 | 
			
		||||
    // Then call get(x) that calculates a value Y for the respective X. 
 | 
			
		||||
    // The class supports extrapolation, i.e. you can call get(x) where x is
 | 
			
		||||
    // outside the given with init() X-range. Extrapolation is a simple linear 
 | 
			
		||||
    // function.
 | 
			
		||||
    //
 | 
			
		||||
    //  See Implementation agg_bspline.cpp
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    class bspline 
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        bspline();
 | 
			
		||||
        bspline(int num);
 | 
			
		||||
        bspline(int num, const double* x, const double* y);
 | 
			
		||||
 | 
			
		||||
        void   init(int num);
 | 
			
		||||
        void   add_point(double x, double y);
 | 
			
		||||
        void   prepare();
 | 
			
		||||
 | 
			
		||||
        void   init(int num, const double* x, const double* y);
 | 
			
		||||
 | 
			
		||||
        double get(double x) const;
 | 
			
		||||
        double get_stateful(double x) const;
 | 
			
		||||
    
 | 
			
		||||
    private:
 | 
			
		||||
        bspline(const bspline&);
 | 
			
		||||
        const bspline& operator = (const bspline&);
 | 
			
		||||
 | 
			
		||||
        static void bsearch(int n, const double *x, double x0, int *i);
 | 
			
		||||
        double extrapolation_left(double x) const;
 | 
			
		||||
        double extrapolation_right(double x) const;
 | 
			
		||||
        double interpolation(double x, int i) const;
 | 
			
		||||
 | 
			
		||||
        int               m_max;
 | 
			
		||||
        int               m_num;
 | 
			
		||||
        double*           m_x;
 | 
			
		||||
        double*           m_y;
 | 
			
		||||
        pod_array<double> m_am;
 | 
			
		||||
        mutable int       m_last_idx;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										333
									
								
								dep/agg/include/agg_clip_liang_barsky.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								dep/agg/include/agg_clip_liang_barsky.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,333 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// Liang-Barsky clipping 
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED
 | 
			
		||||
#define AGG_CLIP_LIANG_BARSKY_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    enum clipping_flags_e
 | 
			
		||||
    {
 | 
			
		||||
        clipping_flags_x1_clipped = 4,
 | 
			
		||||
        clipping_flags_x2_clipped = 1,
 | 
			
		||||
        clipping_flags_y1_clipped = 8,
 | 
			
		||||
        clipping_flags_y2_clipped = 2,
 | 
			
		||||
        clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped,
 | 
			
		||||
        clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------clipping_flags
 | 
			
		||||
    // Determine the clipping code of the vertex according to the 
 | 
			
		||||
    // Cyrus-Beck line clipping algorithm
 | 
			
		||||
    //
 | 
			
		||||
    //        |        |
 | 
			
		||||
    //  0110  |  0010  | 0011
 | 
			
		||||
    //        |        |
 | 
			
		||||
    // -------+--------+-------- clip_box.y2
 | 
			
		||||
    //        |        |
 | 
			
		||||
    //  0100  |  0000  | 0001
 | 
			
		||||
    //        |        |
 | 
			
		||||
    // -------+--------+-------- clip_box.y1
 | 
			
		||||
    //        |        |
 | 
			
		||||
    //  1100  |  1000  | 1001
 | 
			
		||||
    //        |        |
 | 
			
		||||
    //  clip_box.x1  clip_box.x2
 | 
			
		||||
    //
 | 
			
		||||
    // 
 | 
			
		||||
    template<class T>
 | 
			
		||||
    inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box)
 | 
			
		||||
    {
 | 
			
		||||
        return  (x > clip_box.x2) |
 | 
			
		||||
               ((y > clip_box.y2) << 1) |
 | 
			
		||||
               ((x < clip_box.x1) << 2) |
 | 
			
		||||
               ((y < clip_box.y1) << 3);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //--------------------------------------------------------clipping_flags_x
 | 
			
		||||
    template<class T>
 | 
			
		||||
    inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box)
 | 
			
		||||
    {
 | 
			
		||||
        return  (x > clip_box.x2) | ((x < clip_box.x1) << 2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //--------------------------------------------------------clipping_flags_y
 | 
			
		||||
    template<class T>
 | 
			
		||||
    inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box)
 | 
			
		||||
    {
 | 
			
		||||
        return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //-------------------------------------------------------clip_liang_barsky
 | 
			
		||||
    template<class T>
 | 
			
		||||
    inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2,
 | 
			
		||||
                                      const rect_base<T>& clip_box,
 | 
			
		||||
                                      T* x, T* y)
 | 
			
		||||
    {
 | 
			
		||||
        const double nearzero = 1e-30;
 | 
			
		||||
 | 
			
		||||
        double deltax = x2 - x1;
 | 
			
		||||
        double deltay = y2 - y1; 
 | 
			
		||||
        double xin;
 | 
			
		||||
        double xout;
 | 
			
		||||
        double yin;
 | 
			
		||||
        double yout;
 | 
			
		||||
        double tinx;
 | 
			
		||||
        double tiny;
 | 
			
		||||
        double toutx;
 | 
			
		||||
        double touty;  
 | 
			
		||||
        double tin1;
 | 
			
		||||
        double tin2;
 | 
			
		||||
        double tout1;
 | 
			
		||||
        unsigned np = 0;
 | 
			
		||||
 | 
			
		||||
        if(deltax == 0.0) 
 | 
			
		||||
        {   
 | 
			
		||||
            // bump off of the vertical
 | 
			
		||||
            deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(deltay == 0.0) 
 | 
			
		||||
        { 
 | 
			
		||||
            // bump off of the horizontal 
 | 
			
		||||
            deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if(deltax > 0.0) 
 | 
			
		||||
        {                
 | 
			
		||||
            // points to right
 | 
			
		||||
            xin  = clip_box.x1;
 | 
			
		||||
            xout = clip_box.x2;
 | 
			
		||||
        }
 | 
			
		||||
        else 
 | 
			
		||||
        {
 | 
			
		||||
            xin  = clip_box.x2;
 | 
			
		||||
            xout = clip_box.x1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(deltay > 0.0) 
 | 
			
		||||
        {
 | 
			
		||||
            // points up
 | 
			
		||||
            yin  = clip_box.y1;
 | 
			
		||||
            yout = clip_box.y2;
 | 
			
		||||
        }
 | 
			
		||||
        else 
 | 
			
		||||
        {
 | 
			
		||||
            yin  = clip_box.y2;
 | 
			
		||||
            yout = clip_box.y1;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        tinx = (xin - x1) / deltax;
 | 
			
		||||
        tiny = (yin - y1) / deltay;
 | 
			
		||||
        
 | 
			
		||||
        if (tinx < tiny) 
 | 
			
		||||
        {
 | 
			
		||||
            // hits x first
 | 
			
		||||
            tin1 = tinx;
 | 
			
		||||
            tin2 = tiny;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            // hits y first
 | 
			
		||||
            tin1 = tiny;
 | 
			
		||||
            tin2 = tinx;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if(tin1 <= 1.0) 
 | 
			
		||||
        {
 | 
			
		||||
            if(0.0 < tin1) 
 | 
			
		||||
            {
 | 
			
		||||
                *x++ = (T)xin;
 | 
			
		||||
                *y++ = (T)yin;
 | 
			
		||||
                ++np;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(tin2 <= 1.0)
 | 
			
		||||
            {
 | 
			
		||||
                toutx = (xout - x1) / deltax;
 | 
			
		||||
                touty = (yout - y1) / deltay;
 | 
			
		||||
                
 | 
			
		||||
                tout1 = (toutx < touty) ? toutx : touty;
 | 
			
		||||
                
 | 
			
		||||
                if(tin2 > 0.0 || tout1 > 0.0) 
 | 
			
		||||
                {
 | 
			
		||||
                    if(tin2 <= tout1) 
 | 
			
		||||
                    {
 | 
			
		||||
                        if(tin2 > 0.0) 
 | 
			
		||||
                        {
 | 
			
		||||
                            if(tinx > tiny) 
 | 
			
		||||
                            {
 | 
			
		||||
                                *x++ = (T)xin;
 | 
			
		||||
                                *y++ = (T)(y1 + tinx * deltay);
 | 
			
		||||
                            }
 | 
			
		||||
                            else 
 | 
			
		||||
                            {
 | 
			
		||||
                                *x++ = (T)(x1 + tiny * deltax);
 | 
			
		||||
                                *y++ = (T)yin;
 | 
			
		||||
                            }
 | 
			
		||||
                            ++np;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if(tout1 < 1.0) 
 | 
			
		||||
                        {
 | 
			
		||||
                            if(toutx < touty) 
 | 
			
		||||
                            {
 | 
			
		||||
                                *x++ = (T)xout;
 | 
			
		||||
                                *y++ = (T)(y1 + toutx * deltay);
 | 
			
		||||
                            }
 | 
			
		||||
                            else 
 | 
			
		||||
                            {
 | 
			
		||||
                                *x++ = (T)(x1 + touty * deltax);
 | 
			
		||||
                                *y++ = (T)yout;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        else 
 | 
			
		||||
                        {
 | 
			
		||||
                            *x++ = x2;
 | 
			
		||||
                            *y++ = y2;
 | 
			
		||||
                        }
 | 
			
		||||
                        ++np;
 | 
			
		||||
                    }
 | 
			
		||||
                    else 
 | 
			
		||||
                    {
 | 
			
		||||
                        if(tinx > tiny) 
 | 
			
		||||
                        {
 | 
			
		||||
                            *x++ = (T)xin;
 | 
			
		||||
                            *y++ = (T)yout;
 | 
			
		||||
                        }
 | 
			
		||||
                        else 
 | 
			
		||||
                        {
 | 
			
		||||
                            *x++ = (T)xout;
 | 
			
		||||
                            *y++ = (T)yin;
 | 
			
		||||
                        }
 | 
			
		||||
                        ++np;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return np;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------------------
 | 
			
		||||
    template<class T>
 | 
			
		||||
    bool clip_move_point(T x1, T y1, T x2, T y2, 
 | 
			
		||||
                         const rect_base<T>& clip_box, 
 | 
			
		||||
                         T* x, T* y, unsigned flags)
 | 
			
		||||
    {
 | 
			
		||||
       T bound;
 | 
			
		||||
 | 
			
		||||
       if(flags & clipping_flags_x_clipped)
 | 
			
		||||
       {
 | 
			
		||||
           if(x1 == x2)
 | 
			
		||||
           {
 | 
			
		||||
               return false;
 | 
			
		||||
           }
 | 
			
		||||
           bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2;
 | 
			
		||||
           *y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1);
 | 
			
		||||
           *x = bound;
 | 
			
		||||
       }
 | 
			
		||||
 | 
			
		||||
       flags = clipping_flags_y(*y, clip_box);
 | 
			
		||||
       if(flags & clipping_flags_y_clipped)
 | 
			
		||||
       {
 | 
			
		||||
           if(y1 == y2)
 | 
			
		||||
           {
 | 
			
		||||
               return false;
 | 
			
		||||
           }
 | 
			
		||||
           bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2;
 | 
			
		||||
           *x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1);
 | 
			
		||||
           *y = bound;
 | 
			
		||||
       }
 | 
			
		||||
       return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //-------------------------------------------------------clip_line_segment
 | 
			
		||||
    // Returns: ret >= 4        - Fully clipped
 | 
			
		||||
    //          (ret & 1) != 0  - First point has been moved
 | 
			
		||||
    //          (ret & 2) != 0  - Second point has been moved
 | 
			
		||||
    //
 | 
			
		||||
    template<class T>
 | 
			
		||||
    unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2,
 | 
			
		||||
                               const rect_base<T>& clip_box)
 | 
			
		||||
    {
 | 
			
		||||
        unsigned f1 = clipping_flags(*x1, *y1, clip_box);
 | 
			
		||||
        unsigned f2 = clipping_flags(*x2, *y2, clip_box);
 | 
			
		||||
        unsigned ret = 0;
 | 
			
		||||
 | 
			
		||||
        if((f2 | f1) == 0)
 | 
			
		||||
        {
 | 
			
		||||
            // Fully visible
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if((f1 & clipping_flags_x_clipped) != 0 && 
 | 
			
		||||
           (f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped))
 | 
			
		||||
        {
 | 
			
		||||
            // Fully clipped
 | 
			
		||||
            return 4;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if((f1 & clipping_flags_y_clipped) != 0 && 
 | 
			
		||||
           (f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped))
 | 
			
		||||
        {
 | 
			
		||||
            // Fully clipped
 | 
			
		||||
            return 4;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        T tx1 = *x1;
 | 
			
		||||
        T ty1 = *y1;
 | 
			
		||||
        T tx2 = *x2;
 | 
			
		||||
        T ty2 = *y2;
 | 
			
		||||
        if(f1) 
 | 
			
		||||
        {   
 | 
			
		||||
            if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1)) 
 | 
			
		||||
            {
 | 
			
		||||
                return 4;
 | 
			
		||||
            }
 | 
			
		||||
            if(*x1 == *x2 && *y1 == *y2) 
 | 
			
		||||
            {
 | 
			
		||||
                return 4;
 | 
			
		||||
            }
 | 
			
		||||
            ret |= 1;
 | 
			
		||||
        }
 | 
			
		||||
        if(f2) 
 | 
			
		||||
        {
 | 
			
		||||
            if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2))
 | 
			
		||||
            {
 | 
			
		||||
                return 4;
 | 
			
		||||
            }
 | 
			
		||||
            if(*x1 == *x2 && *y1 == *y2) 
 | 
			
		||||
            {
 | 
			
		||||
                return 4;
 | 
			
		||||
            }
 | 
			
		||||
            ret |= 2;
 | 
			
		||||
        }
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										1047
									
								
								dep/agg/include/agg_color_gray.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1047
									
								
								dep/agg/include/agg_color_gray.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1380
									
								
								dep/agg/include/agg_color_rgba.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1380
									
								
								dep/agg/include/agg_color_rgba.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										44
									
								
								dep/agg/include/agg_config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								dep/agg/include/agg_config.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
#ifndef AGG_CONFIG_INCLUDED
 | 
			
		||||
#define AGG_CONFIG_INCLUDED
 | 
			
		||||
 | 
			
		||||
// This file can be used to redefine certain data types.
 | 
			
		||||
 | 
			
		||||
//---------------------------------------
 | 
			
		||||
// 1. Default basic types such as:
 | 
			
		||||
// 
 | 
			
		||||
// AGG_INT8
 | 
			
		||||
// AGG_INT8U
 | 
			
		||||
// AGG_INT16
 | 
			
		||||
// AGG_INT16U
 | 
			
		||||
// AGG_INT32
 | 
			
		||||
// AGG_INT32U
 | 
			
		||||
// AGG_INT64
 | 
			
		||||
// AGG_INT64U
 | 
			
		||||
//
 | 
			
		||||
// Just replace this file with new defines if necessary. 
 | 
			
		||||
// For example, if your compiler doesn't have a 64 bit integer type
 | 
			
		||||
// you can still use AGG if you define the follows:
 | 
			
		||||
//
 | 
			
		||||
// #define AGG_INT64  int
 | 
			
		||||
// #define AGG_INT64U unsigned
 | 
			
		||||
//
 | 
			
		||||
// It will result in overflow in 16 bit-per-component image/pattern resampling
 | 
			
		||||
// but it won't result any crash and the rest of the library will remain 
 | 
			
		||||
// fully functional.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//---------------------------------------
 | 
			
		||||
// 2. Default rendering_buffer type. Can be:
 | 
			
		||||
//
 | 
			
		||||
// Provides faster access for massive pixel operations, 
 | 
			
		||||
// such as blur, image filtering:
 | 
			
		||||
// #define AGG_RENDERING_BUFFER row_ptr_cache<int8u>
 | 
			
		||||
// 
 | 
			
		||||
// Provides cheaper creation and destruction (no mem allocs):
 | 
			
		||||
// #define AGG_RENDERING_BUFFER row_accessor<int8u>
 | 
			
		||||
//
 | 
			
		||||
// You can still use both of them simultaneously in your applications 
 | 
			
		||||
// This #define is used only for default rendering_buffer type,
 | 
			
		||||
// in short hand typedefs like pixfmt_rgba32.
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										157
									
								
								dep/agg/include/agg_conv_adaptor_vcgen.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								dep/agg/include/agg_conv_adaptor_vcgen.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,157 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_CONV_ADAPTOR_VCGEN_INCLUDED
 | 
			
		||||
#define AGG_CONV_ADAPTOR_VCGEN_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
    //------------------------------------------------------------null_markers
 | 
			
		||||
    struct null_markers
 | 
			
		||||
    {
 | 
			
		||||
        void remove_all() {}
 | 
			
		||||
        void add_vertex(double, double, unsigned) {}
 | 
			
		||||
        void prepare_src() {}
 | 
			
		||||
 | 
			
		||||
        void rewind(unsigned) {}
 | 
			
		||||
        unsigned vertex(double*, double*) { return path_cmd_stop; }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------conv_adaptor_vcgen
 | 
			
		||||
    template<class VertexSource, 
 | 
			
		||||
             class Generator, 
 | 
			
		||||
             class Markers=null_markers> class conv_adaptor_vcgen
 | 
			
		||||
    {
 | 
			
		||||
        enum status
 | 
			
		||||
        {
 | 
			
		||||
            initial,
 | 
			
		||||
            accumulate,
 | 
			
		||||
            generate
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        explicit conv_adaptor_vcgen(VertexSource& source) :
 | 
			
		||||
            m_source(&source), 
 | 
			
		||||
            m_status(initial)
 | 
			
		||||
        {}
 | 
			
		||||
        void attach(VertexSource& source) { m_source = &source; }
 | 
			
		||||
 | 
			
		||||
        Generator& generator() { return m_generator; }
 | 
			
		||||
        const Generator& generator() const { return m_generator; }
 | 
			
		||||
 | 
			
		||||
        Markers& markers() { return m_markers; }
 | 
			
		||||
        const Markers& markers() const { return m_markers; }
 | 
			
		||||
        
 | 
			
		||||
        void rewind(unsigned path_id) 
 | 
			
		||||
        { 
 | 
			
		||||
            m_source->rewind(path_id); 
 | 
			
		||||
            m_status = initial;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        unsigned vertex(double* x, double* y);
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        // Prohibit copying
 | 
			
		||||
        conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
 | 
			
		||||
        const conv_adaptor_vcgen<VertexSource, Generator, Markers>& 
 | 
			
		||||
            operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
 | 
			
		||||
 | 
			
		||||
        VertexSource* m_source;
 | 
			
		||||
        Generator     m_generator;
 | 
			
		||||
        Markers       m_markers;
 | 
			
		||||
        status        m_status;
 | 
			
		||||
        unsigned      m_last_cmd;
 | 
			
		||||
        double        m_start_x;
 | 
			
		||||
        double        m_start_y;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VertexSource, class Generator, class Markers> 
 | 
			
		||||
    unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y)
 | 
			
		||||
    {
 | 
			
		||||
        unsigned cmd = path_cmd_stop;
 | 
			
		||||
        bool done = false;
 | 
			
		||||
        while(!done)
 | 
			
		||||
        {
 | 
			
		||||
            switch(m_status)
 | 
			
		||||
            {
 | 
			
		||||
            case initial:
 | 
			
		||||
                m_markers.remove_all();
 | 
			
		||||
                m_last_cmd = m_source->vertex(&m_start_x, &m_start_y);
 | 
			
		||||
                m_status = accumulate;
 | 
			
		||||
 | 
			
		||||
            case accumulate:
 | 
			
		||||
                if(is_stop(m_last_cmd)) return path_cmd_stop;
 | 
			
		||||
 | 
			
		||||
                m_generator.remove_all();
 | 
			
		||||
                m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
 | 
			
		||||
                m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
 | 
			
		||||
 | 
			
		||||
                for(;;)
 | 
			
		||||
                {
 | 
			
		||||
                    cmd = m_source->vertex(x, y);
 | 
			
		||||
                    if(is_vertex(cmd))
 | 
			
		||||
                    {
 | 
			
		||||
                        m_last_cmd = cmd;
 | 
			
		||||
                        if(is_move_to(cmd))
 | 
			
		||||
                        {
 | 
			
		||||
                            m_start_x = *x;
 | 
			
		||||
                            m_start_y = *y;
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        m_generator.add_vertex(*x, *y, cmd);
 | 
			
		||||
                        m_markers.add_vertex(*x, *y, path_cmd_line_to);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        if(is_stop(cmd))
 | 
			
		||||
                        {
 | 
			
		||||
                            m_last_cmd = path_cmd_stop;
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        if(is_end_poly(cmd))
 | 
			
		||||
                        {
 | 
			
		||||
                            m_generator.add_vertex(*x, *y, cmd);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                m_generator.rewind(0);
 | 
			
		||||
                m_status = generate;
 | 
			
		||||
 | 
			
		||||
            case generate:
 | 
			
		||||
                cmd = m_generator.vertex(x, y);
 | 
			
		||||
                if(is_stop(cmd))
 | 
			
		||||
                {
 | 
			
		||||
                    m_status = accumulate;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                done = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return cmd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										159
									
								
								dep/agg/include/agg_conv_adaptor_vpgen.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								dep/agg/include/agg_conv_adaptor_vpgen.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_CONV_ADAPTOR_VPGEN_INCLUDED
 | 
			
		||||
#define AGG_CONV_ADAPTOR_VPGEN_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    //======================================================conv_adaptor_vpgen
 | 
			
		||||
    template<class VertexSource, class VPGen> class conv_adaptor_vpgen
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
 | 
			
		||||
        void attach(VertexSource& source) { m_source = &source; }
 | 
			
		||||
 | 
			
		||||
        VPGen& vpgen() { return m_vpgen; }
 | 
			
		||||
        const VPGen& vpgen() const { return m_vpgen; }
 | 
			
		||||
 | 
			
		||||
        void rewind(unsigned path_id);
 | 
			
		||||
        unsigned vertex(double* x, double* y);
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);
 | 
			
		||||
        const conv_adaptor_vpgen<VertexSource, VPGen>& 
 | 
			
		||||
            operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&);
 | 
			
		||||
 | 
			
		||||
        VertexSource* m_source;
 | 
			
		||||
        VPGen         m_vpgen;
 | 
			
		||||
        double        m_start_x;
 | 
			
		||||
        double        m_start_y;
 | 
			
		||||
        unsigned      m_poly_flags;
 | 
			
		||||
        int           m_vertices;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VertexSource, class VPGen>
 | 
			
		||||
    void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id) 
 | 
			
		||||
    { 
 | 
			
		||||
        m_source->rewind(path_id);
 | 
			
		||||
        m_vpgen.reset();
 | 
			
		||||
        m_start_x    = 0;
 | 
			
		||||
        m_start_y    = 0;
 | 
			
		||||
        m_poly_flags = 0;
 | 
			
		||||
        m_vertices   = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VertexSource, class VPGen>
 | 
			
		||||
    unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y)
 | 
			
		||||
    {
 | 
			
		||||
        unsigned cmd = path_cmd_stop;
 | 
			
		||||
        for(;;)
 | 
			
		||||
        {
 | 
			
		||||
            cmd = m_vpgen.vertex(x, y);
 | 
			
		||||
            if(!is_stop(cmd)) break;
 | 
			
		||||
 | 
			
		||||
            if(m_poly_flags && !m_vpgen.auto_unclose())
 | 
			
		||||
            {
 | 
			
		||||
                *x = 0.0;
 | 
			
		||||
                *y = 0.0;
 | 
			
		||||
                cmd = m_poly_flags;
 | 
			
		||||
                m_poly_flags = 0;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(m_vertices < 0)
 | 
			
		||||
            {
 | 
			
		||||
                if(m_vertices < -1) 
 | 
			
		||||
                {
 | 
			
		||||
                    m_vertices = 0;
 | 
			
		||||
                    return path_cmd_stop;
 | 
			
		||||
                }
 | 
			
		||||
                m_vpgen.move_to(m_start_x, m_start_y);
 | 
			
		||||
                m_vertices = 1;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            double tx, ty;
 | 
			
		||||
            cmd = m_source->vertex(&tx, &ty);
 | 
			
		||||
            if(is_vertex(cmd))
 | 
			
		||||
            {
 | 
			
		||||
                if(is_move_to(cmd)) 
 | 
			
		||||
                {
 | 
			
		||||
                    if(m_vpgen.auto_close() && m_vertices > 2)
 | 
			
		||||
                    {
 | 
			
		||||
                        m_vpgen.line_to(m_start_x, m_start_y);
 | 
			
		||||
                        m_poly_flags = path_cmd_end_poly | path_flags_close;
 | 
			
		||||
                        m_start_x    = tx;
 | 
			
		||||
                        m_start_y    = ty;
 | 
			
		||||
                        m_vertices   = -1;
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
                    m_vpgen.move_to(tx, ty);
 | 
			
		||||
                    m_start_x  = tx;
 | 
			
		||||
                    m_start_y  = ty;
 | 
			
		||||
                    m_vertices = 1;
 | 
			
		||||
                }
 | 
			
		||||
                else 
 | 
			
		||||
                {
 | 
			
		||||
                    m_vpgen.line_to(tx, ty);
 | 
			
		||||
                    ++m_vertices;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if(is_end_poly(cmd))
 | 
			
		||||
                {
 | 
			
		||||
                    m_poly_flags = cmd;
 | 
			
		||||
                    if(is_closed(cmd) || m_vpgen.auto_close())
 | 
			
		||||
                    {
 | 
			
		||||
                        if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close;
 | 
			
		||||
                        if(m_vertices > 2)
 | 
			
		||||
                        {
 | 
			
		||||
                            m_vpgen.line_to(m_start_x, m_start_y);
 | 
			
		||||
                        }
 | 
			
		||||
                        m_vertices = 0;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    // path_cmd_stop
 | 
			
		||||
                    if(m_vpgen.auto_close() && m_vertices > 2)
 | 
			
		||||
                    {
 | 
			
		||||
                        m_vpgen.line_to(m_start_x, m_start_y);
 | 
			
		||||
                        m_poly_flags = path_cmd_end_poly | path_flags_close;
 | 
			
		||||
                        m_vertices   = -2;
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return cmd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										48
									
								
								dep/agg/include/agg_conv_bspline.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								dep/agg/include/agg_conv_bspline.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
#ifndef AGG_CONV_BSPLINE_INCLUDED
 | 
			
		||||
#define AGG_CONV_BSPLINE_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
#include "agg_vcgen_bspline.h"
 | 
			
		||||
#include "agg_conv_adaptor_vcgen.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    //---------------------------------------------------------conv_bspline
 | 
			
		||||
    template<class VertexSource> 
 | 
			
		||||
    struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline>
 | 
			
		||||
    {
 | 
			
		||||
        typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type;
 | 
			
		||||
 | 
			
		||||
        conv_bspline(VertexSource& vs) : 
 | 
			
		||||
            conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) {}
 | 
			
		||||
 | 
			
		||||
        void   interpolation_step(double v) { base_type::generator().interpolation_step(v); }
 | 
			
		||||
        double interpolation_step() const { return base_type::generator().interpolation_step(); }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        conv_bspline(const conv_bspline<VertexSource>&);
 | 
			
		||||
        const conv_bspline<VertexSource>& 
 | 
			
		||||
            operator = (const conv_bspline<VertexSource>&);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										63
									
								
								dep/agg/include/agg_conv_clip_polygon.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								dep/agg/include/agg_conv_clip_polygon.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// Polygon clipping converter
 | 
			
		||||
// There an optimized Liang-Basky algorithm is used. 
 | 
			
		||||
// The algorithm doesn't optimize the degenerate edges, i.e. it will never
 | 
			
		||||
// break a closed polygon into two or more ones, instead, there will be 
 | 
			
		||||
// degenerate edges coinciding with the respective clipping boundaries.
 | 
			
		||||
// This is a sub-optimal solution, because that optimization would require 
 | 
			
		||||
// extra, rather expensive math while the rasterizer tolerates it quite well, 
 | 
			
		||||
// without any considerable overhead.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
#ifndef AGG_CONV_CLIP_POLYGON_INCLUDED
 | 
			
		||||
#define AGG_CONV_CLIP_POLYGON_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
#include "agg_conv_adaptor_vpgen.h"
 | 
			
		||||
#include "agg_vpgen_clip_polygon.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    //=======================================================conv_clip_polygon
 | 
			
		||||
    template<class VertexSource> 
 | 
			
		||||
    struct conv_clip_polygon : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>
 | 
			
		||||
    {
 | 
			
		||||
        typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> base_type;
 | 
			
		||||
 | 
			
		||||
        conv_clip_polygon(VertexSource& vs) : 
 | 
			
		||||
            conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) {}
 | 
			
		||||
 | 
			
		||||
        void clip_box(double x1, double y1, double x2, double y2)
 | 
			
		||||
        {
 | 
			
		||||
            base_type::vpgen().clip_box(x1, y1, x2, y2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        double x1() const { return base_type::vpgen().x1(); }
 | 
			
		||||
        double y1() const { return base_type::vpgen().y1(); }
 | 
			
		||||
        double x2() const { return base_type::vpgen().x2(); }
 | 
			
		||||
        double y2() const { return base_type::vpgen().y2(); }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        conv_clip_polygon(const conv_clip_polygon<VertexSource>&);
 | 
			
		||||
        const conv_clip_polygon<VertexSource>& 
 | 
			
		||||
            operator = (const conv_clip_polygon<VertexSource>&);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										63
									
								
								dep/agg/include/agg_conv_clip_polyline.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								dep/agg/include/agg_conv_clip_polyline.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// polyline clipping converter
 | 
			
		||||
// There an optimized Liang-Basky algorithm is used. 
 | 
			
		||||
// The algorithm doesn't optimize the degenerate edges, i.e. it will never
 | 
			
		||||
// break a closed polyline into two or more ones, instead, there will be 
 | 
			
		||||
// degenerate edges coinciding with the respective clipping boundaries.
 | 
			
		||||
// This is a sub-optimal solution, because that optimization would require 
 | 
			
		||||
// extra, rather expensive math while the rasterizer tolerates it quite well, 
 | 
			
		||||
// without any considerable overhead.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
#ifndef AGG_CONV_CLIP_polyline_INCLUDED
 | 
			
		||||
#define AGG_CONV_CLIP_polyline_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
#include "agg_conv_adaptor_vpgen.h"
 | 
			
		||||
#include "agg_vpgen_clip_polyline.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    //=======================================================conv_clip_polyline
 | 
			
		||||
    template<class VertexSource> 
 | 
			
		||||
    struct conv_clip_polyline : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>
 | 
			
		||||
    {
 | 
			
		||||
        typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> base_type;
 | 
			
		||||
 | 
			
		||||
        conv_clip_polyline(VertexSource& vs) : 
 | 
			
		||||
            conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(vs) {}
 | 
			
		||||
 | 
			
		||||
        void clip_box(double x1, double y1, double x2, double y2)
 | 
			
		||||
        {
 | 
			
		||||
            base_type::vpgen().clip_box(x1, y1, x2, y2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        double x1() const { return base_type::vpgen().x1(); }
 | 
			
		||||
        double y1() const { return base_type::vpgen().y1(); }
 | 
			
		||||
        double x2() const { return base_type::vpgen().x2(); }
 | 
			
		||||
        double y2() const { return base_type::vpgen().y2(); }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        conv_clip_polyline(const conv_clip_polyline<VertexSource>&);
 | 
			
		||||
        const conv_clip_polyline<VertexSource>& 
 | 
			
		||||
            operator = (const conv_clip_polyline<VertexSource>&);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										125
									
								
								dep/agg/include/agg_conv_close_polygon.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								dep/agg/include/agg_conv_close_polygon.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,125 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_CONV_CLOSE_POLYGON_INCLUDED
 | 
			
		||||
#define AGG_CONV_CLOSE_POLYGON_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    //======================================================conv_close_polygon
 | 
			
		||||
    template<class VertexSource> class conv_close_polygon
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
 | 
			
		||||
        void attach(VertexSource& source) { m_source = &source; }
 | 
			
		||||
 | 
			
		||||
        void rewind(unsigned path_id);
 | 
			
		||||
        unsigned vertex(double* x, double* y);
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        conv_close_polygon(const conv_close_polygon<VertexSource>&);
 | 
			
		||||
        const conv_close_polygon<VertexSource>& 
 | 
			
		||||
            operator = (const conv_close_polygon<VertexSource>&);
 | 
			
		||||
 | 
			
		||||
        VertexSource* m_source;
 | 
			
		||||
        unsigned      m_cmd[2];
 | 
			
		||||
        double        m_x[2];
 | 
			
		||||
        double        m_y[2];
 | 
			
		||||
        unsigned      m_vertex;
 | 
			
		||||
        bool          m_line_to;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VertexSource> 
 | 
			
		||||
    void conv_close_polygon<VertexSource>::rewind(unsigned path_id)
 | 
			
		||||
    {
 | 
			
		||||
        m_source->rewind(path_id);
 | 
			
		||||
        m_vertex = 2;
 | 
			
		||||
        m_line_to = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VertexSource> 
 | 
			
		||||
    unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y)
 | 
			
		||||
    {
 | 
			
		||||
        unsigned cmd = path_cmd_stop;
 | 
			
		||||
        for(;;)
 | 
			
		||||
        {
 | 
			
		||||
            if(m_vertex < 2)
 | 
			
		||||
            {
 | 
			
		||||
                *x = m_x[m_vertex];
 | 
			
		||||
                *y = m_y[m_vertex];
 | 
			
		||||
                cmd = m_cmd[m_vertex];
 | 
			
		||||
                ++m_vertex;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            cmd = m_source->vertex(x, y);
 | 
			
		||||
 | 
			
		||||
            if(is_end_poly(cmd))
 | 
			
		||||
            {
 | 
			
		||||
                cmd |= path_flags_close;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(is_stop(cmd))
 | 
			
		||||
            {
 | 
			
		||||
                if(m_line_to)
 | 
			
		||||
                {
 | 
			
		||||
                    m_cmd[0]  = path_cmd_end_poly | path_flags_close;
 | 
			
		||||
                    m_cmd[1]  = path_cmd_stop;
 | 
			
		||||
                    m_vertex  = 0;
 | 
			
		||||
                    m_line_to = false;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(is_move_to(cmd))
 | 
			
		||||
            {
 | 
			
		||||
                if(m_line_to)
 | 
			
		||||
                {
 | 
			
		||||
                    m_x[0]    = 0.0;
 | 
			
		||||
                    m_y[0]    = 0.0;
 | 
			
		||||
                    m_cmd[0]  = path_cmd_end_poly | path_flags_close;
 | 
			
		||||
                    m_x[1]    = *x;
 | 
			
		||||
                    m_y[1]    = *y;
 | 
			
		||||
                    m_cmd[1]  = cmd;
 | 
			
		||||
                    m_vertex  = 0;
 | 
			
		||||
                    m_line_to = false;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(is_vertex(cmd))
 | 
			
		||||
            {
 | 
			
		||||
                m_line_to = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return cmd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										73
									
								
								dep/agg/include/agg_conv_concat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								dep/agg/include/agg_conv_concat.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_CONV_CONCAT_INCLUDED
 | 
			
		||||
#define AGG_CONV_CONCAT_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
    //=============================================================conv_concat
 | 
			
		||||
    // Concatenation of two paths. Usually used to combine lines or curves 
 | 
			
		||||
    // with markers such as arrowheads
 | 
			
		||||
    template<class VS1, class VS2> class conv_concat
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        conv_concat(VS1& source1, VS2& source2) :
 | 
			
		||||
            m_source1(&source1), m_source2(&source2), m_status(2) {}
 | 
			
		||||
        void attach1(VS1& source) { m_source1 = &source; }
 | 
			
		||||
        void attach2(VS2& source) { m_source2 = &source; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        void rewind(unsigned path_id)
 | 
			
		||||
        { 
 | 
			
		||||
            m_source1->rewind(path_id);
 | 
			
		||||
            m_source2->rewind(0);
 | 
			
		||||
            m_status = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        unsigned vertex(double* x, double* y)
 | 
			
		||||
        {
 | 
			
		||||
            unsigned cmd;
 | 
			
		||||
            if(m_status == 0)
 | 
			
		||||
            {
 | 
			
		||||
                cmd = m_source1->vertex(x, y);
 | 
			
		||||
                if(!is_stop(cmd)) return cmd;
 | 
			
		||||
                m_status = 1;
 | 
			
		||||
            }
 | 
			
		||||
            if(m_status == 1)
 | 
			
		||||
            {
 | 
			
		||||
                cmd = m_source2->vertex(x, y);
 | 
			
		||||
                if(!is_stop(cmd)) return cmd;
 | 
			
		||||
                m_status = 2;
 | 
			
		||||
            }
 | 
			
		||||
            return path_cmd_stop;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        conv_concat(const conv_concat<VS1, VS2>&);
 | 
			
		||||
        const conv_concat<VS1, VS2>& 
 | 
			
		||||
            operator = (const conv_concat<VS1, VS2>&);
 | 
			
		||||
 | 
			
		||||
        VS1* m_source1;
 | 
			
		||||
        VS2* m_source2;
 | 
			
		||||
        int  m_status;
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										65
									
								
								dep/agg/include/agg_conv_contour.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								dep/agg/include/agg_conv_contour.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// conv_stroke
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
#ifndef AGG_CONV_CONTOUR_INCLUDED
 | 
			
		||||
#define AGG_CONV_CONTOUR_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
#include "agg_vcgen_contour.h"
 | 
			
		||||
#include "agg_conv_adaptor_vcgen.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    //-----------------------------------------------------------conv_contour
 | 
			
		||||
    template<class VertexSource> 
 | 
			
		||||
    struct conv_contour : public conv_adaptor_vcgen<VertexSource, vcgen_contour>
 | 
			
		||||
    {
 | 
			
		||||
        typedef conv_adaptor_vcgen<VertexSource, vcgen_contour> base_type;
 | 
			
		||||
 | 
			
		||||
        conv_contour(VertexSource& vs) : 
 | 
			
		||||
            conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
 | 
			
		||||
        void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
 | 
			
		||||
        void width(double w) { base_type::generator().width(w); }
 | 
			
		||||
        void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
 | 
			
		||||
        void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
 | 
			
		||||
        void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
 | 
			
		||||
        void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
 | 
			
		||||
        void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); }
 | 
			
		||||
 | 
			
		||||
        line_join_e line_join() const { return base_type::generator().line_join(); }
 | 
			
		||||
        inner_join_e inner_join() const { return base_type::generator().inner_join(); }
 | 
			
		||||
        double width() const { return base_type::generator().width(); }
 | 
			
		||||
        double miter_limit() const { return base_type::generator().miter_limit(); }
 | 
			
		||||
        double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
 | 
			
		||||
        double approximation_scale() const { return base_type::generator().approximation_scale(); }
 | 
			
		||||
        bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        conv_contour(const conv_contour<VertexSource>&);
 | 
			
		||||
        const conv_contour<VertexSource>& 
 | 
			
		||||
            operator = (const conv_contour<VertexSource>&);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										201
									
								
								dep/agg/include/agg_conv_curve.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								dep/agg/include/agg_conv_curve.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,201 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// classes conv_curve
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_CONV_CURVE_INCLUDED
 | 
			
		||||
#define AGG_CONV_CURVE_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
#include "agg_curves.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //---------------------------------------------------------------conv_curve
 | 
			
		||||
    // Curve converter class. Any path storage can have Bezier curves defined 
 | 
			
		||||
    // by their control points. There're two types of curves supported: curve3 
 | 
			
		||||
    // and curve4. Curve3 is a conic Bezier curve with 2 endpoints and 1 control
 | 
			
		||||
    // point. Curve4 has 2 control points (4 points in total) and can be used
 | 
			
		||||
    // to interpolate more complicated curves. Curve4, unlike curve3 can be used 
 | 
			
		||||
    // to approximate arcs, both circular and elliptical. Curves are approximated 
 | 
			
		||||
    // with straight lines and one of the approaches is just to store the whole 
 | 
			
		||||
    // sequence of vertices that approximate our curve. It takes additional 
 | 
			
		||||
    // memory, and at the same time the consecutive vertices can be calculated 
 | 
			
		||||
    // on demand. 
 | 
			
		||||
    //
 | 
			
		||||
    // Initially, path storages are not suppose to keep all the vertices of the
 | 
			
		||||
    // curves (although, nothing prevents us from doing so). Instead, path_storage
 | 
			
		||||
    // keeps only vertices, needed to calculate a curve on demand. Those vertices
 | 
			
		||||
    // are marked with special commands. So, if the path_storage contains curves 
 | 
			
		||||
    // (which are not real curves yet), and we render this storage directly, 
 | 
			
		||||
    // all we will see is only 2 or 3 straight line segments (for curve3 and 
 | 
			
		||||
    // curve4 respectively). If we need to see real curves drawn we need to 
 | 
			
		||||
    // include this class into the conversion pipeline. 
 | 
			
		||||
    //
 | 
			
		||||
    // Class conv_curve recognizes commands path_cmd_curve3 and path_cmd_curve4 
 | 
			
		||||
    // and converts these vertices into a move_to/line_to sequence. 
 | 
			
		||||
    //-----------------------------------------------------------------------
 | 
			
		||||
    template<class VertexSource, 
 | 
			
		||||
             class Curve3=curve3, 
 | 
			
		||||
             class Curve4=curve4> class conv_curve
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        typedef Curve3 curve3_type;
 | 
			
		||||
        typedef Curve4 curve4_type;
 | 
			
		||||
        typedef conv_curve<VertexSource, Curve3, Curve4> self_type;
 | 
			
		||||
 | 
			
		||||
        explicit conv_curve(VertexSource& source) :
 | 
			
		||||
          m_source(&source), m_last_x(0.0), m_last_y(0.0) {}
 | 
			
		||||
        void attach(VertexSource& source) { m_source = &source; }
 | 
			
		||||
 | 
			
		||||
        void approximation_method(curve_approximation_method_e v) 
 | 
			
		||||
        { 
 | 
			
		||||
            m_curve3.approximation_method(v);
 | 
			
		||||
            m_curve4.approximation_method(v);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        curve_approximation_method_e approximation_method() const 
 | 
			
		||||
        { 
 | 
			
		||||
            return m_curve4.approximation_method();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void approximation_scale(double s) 
 | 
			
		||||
        { 
 | 
			
		||||
            m_curve3.approximation_scale(s); 
 | 
			
		||||
            m_curve4.approximation_scale(s); 
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        double approximation_scale() const 
 | 
			
		||||
        { 
 | 
			
		||||
            return m_curve4.approximation_scale();  
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void angle_tolerance(double v) 
 | 
			
		||||
        { 
 | 
			
		||||
            m_curve3.angle_tolerance(v); 
 | 
			
		||||
            m_curve4.angle_tolerance(v); 
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        double angle_tolerance() const 
 | 
			
		||||
        { 
 | 
			
		||||
            return m_curve4.angle_tolerance();  
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void cusp_limit(double v) 
 | 
			
		||||
        { 
 | 
			
		||||
            m_curve3.cusp_limit(v); 
 | 
			
		||||
            m_curve4.cusp_limit(v); 
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        double cusp_limit() const 
 | 
			
		||||
        { 
 | 
			
		||||
            return m_curve4.cusp_limit();  
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void     rewind(unsigned path_id); 
 | 
			
		||||
        unsigned vertex(double* x, double* y);
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        conv_curve(const self_type&);
 | 
			
		||||
        const self_type& operator = (const self_type&);
 | 
			
		||||
 | 
			
		||||
        VertexSource* m_source;
 | 
			
		||||
        double        m_last_x;
 | 
			
		||||
        double        m_last_y;
 | 
			
		||||
        curve3_type   m_curve3;
 | 
			
		||||
        curve4_type   m_curve4;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VertexSource, class Curve3, class Curve4>
 | 
			
		||||
    void conv_curve<VertexSource, Curve3, Curve4>::rewind(unsigned path_id)
 | 
			
		||||
    {
 | 
			
		||||
        m_source->rewind(path_id);
 | 
			
		||||
        m_last_x = 0.0;
 | 
			
		||||
        m_last_y = 0.0;
 | 
			
		||||
        m_curve3.reset();
 | 
			
		||||
        m_curve4.reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VertexSource, class Curve3, class Curve4>
 | 
			
		||||
    unsigned conv_curve<VertexSource, Curve3, Curve4>::vertex(double* x, double* y)
 | 
			
		||||
    {
 | 
			
		||||
        if(!is_stop(m_curve3.vertex(x, y)))
 | 
			
		||||
        {
 | 
			
		||||
            m_last_x = *x;
 | 
			
		||||
            m_last_y = *y;
 | 
			
		||||
            return path_cmd_line_to;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(!is_stop(m_curve4.vertex(x, y)))
 | 
			
		||||
        {
 | 
			
		||||
            m_last_x = *x;
 | 
			
		||||
            m_last_y = *y;
 | 
			
		||||
            return path_cmd_line_to;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        double ct2_x = 0;
 | 
			
		||||
        double ct2_y = 0;
 | 
			
		||||
        double end_x = 0;
 | 
			
		||||
        double end_y = 0;
 | 
			
		||||
 | 
			
		||||
        unsigned cmd = m_source->vertex(x, y);
 | 
			
		||||
        switch(cmd)
 | 
			
		||||
        {
 | 
			
		||||
        case path_cmd_curve3:
 | 
			
		||||
            m_source->vertex(&end_x, &end_y);
 | 
			
		||||
 | 
			
		||||
            m_curve3.init(m_last_x, m_last_y, 
 | 
			
		||||
                          *x,       *y, 
 | 
			
		||||
                          end_x,     end_y);
 | 
			
		||||
 | 
			
		||||
            m_curve3.vertex(x, y);    // First call returns path_cmd_move_to
 | 
			
		||||
            m_curve3.vertex(x, y);    // This is the first vertex of the curve
 | 
			
		||||
            cmd = path_cmd_line_to;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case path_cmd_curve4:
 | 
			
		||||
            m_source->vertex(&ct2_x, &ct2_y);
 | 
			
		||||
            m_source->vertex(&end_x, &end_y);
 | 
			
		||||
 | 
			
		||||
            m_curve4.init(m_last_x, m_last_y, 
 | 
			
		||||
                          *x,       *y, 
 | 
			
		||||
                          ct2_x,    ct2_y, 
 | 
			
		||||
                          end_x,    end_y);
 | 
			
		||||
 | 
			
		||||
            m_curve4.vertex(x, y);    // First call returns path_cmd_move_to
 | 
			
		||||
            m_curve4.vertex(x, y);    // This is the first vertex of the curve
 | 
			
		||||
            cmd = path_cmd_line_to;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        m_last_x = *x;
 | 
			
		||||
        m_last_y = *y;
 | 
			
		||||
        return cmd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										68
									
								
								dep/agg/include/agg_conv_dash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								dep/agg/include/agg_conv_dash.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// conv_dash
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
#ifndef AGG_CONV_DASH_INCLUDED
 | 
			
		||||
#define AGG_CONV_DASH_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
#include "agg_vcgen_dash.h"
 | 
			
		||||
#include "agg_conv_adaptor_vcgen.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    //---------------------------------------------------------------conv_dash
 | 
			
		||||
    template<class VertexSource, class Markers=null_markers> 
 | 
			
		||||
    struct conv_dash : public conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>
 | 
			
		||||
    {
 | 
			
		||||
        typedef Markers marker_type;
 | 
			
		||||
        typedef conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers> base_type;
 | 
			
		||||
 | 
			
		||||
        conv_dash(VertexSource& vs) : 
 | 
			
		||||
            conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void remove_all_dashes() 
 | 
			
		||||
        { 
 | 
			
		||||
            base_type::generator().remove_all_dashes(); 
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void add_dash(double dash_len, double gap_len) 
 | 
			
		||||
        { 
 | 
			
		||||
            base_type::generator().add_dash(dash_len, gap_len); 
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void dash_start(double ds) 
 | 
			
		||||
        { 
 | 
			
		||||
            base_type::generator().dash_start(ds); 
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void shorten(double s) { base_type::generator().shorten(s); }
 | 
			
		||||
        double shorten() const { return base_type::generator().shorten(); }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        conv_dash(const conv_dash<VertexSource, Markers>&);
 | 
			
		||||
        const conv_dash<VertexSource, Markers>& 
 | 
			
		||||
            operator = (const conv_dash<VertexSource, Markers>&);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										432
									
								
								dep/agg/include/agg_conv_gpc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										432
									
								
								dep/agg/include/agg_conv_gpc.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,432 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// General Polygon Clipper based on the GPC library by Alan Murta 
 | 
			
		||||
// Union, Intersection, XOR, A-B, B-A
 | 
			
		||||
// Contact the author if you intend to use it in commercial applications!
 | 
			
		||||
// http://www.cs.man.ac.uk/aig/staff/alan/software/
 | 
			
		||||
// Alan Murta (email: gpc@cs.man.ac.uk)
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef AGG_CONV_GPC_INCLUDED
 | 
			
		||||
#define AGG_CONV_GPC_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
#include "agg_array.h"
 | 
			
		||||
 | 
			
		||||
extern "C" 
 | 
			
		||||
{ 
 | 
			
		||||
#include "gpc.h" 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
    enum gpc_op_e
 | 
			
		||||
    {
 | 
			
		||||
        gpc_or,
 | 
			
		||||
        gpc_and,
 | 
			
		||||
        gpc_xor,
 | 
			
		||||
        gpc_a_minus_b,
 | 
			
		||||
        gpc_b_minus_a
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //================================================================conv_gpc
 | 
			
		||||
    template<class VSA, class VSB> class conv_gpc
 | 
			
		||||
    {
 | 
			
		||||
        enum status
 | 
			
		||||
        {
 | 
			
		||||
            status_move_to,
 | 
			
		||||
            status_line_to,
 | 
			
		||||
            status_stop
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        struct contour_header_type
 | 
			
		||||
        {
 | 
			
		||||
            int num_vertices;
 | 
			
		||||
            int hole_flag;
 | 
			
		||||
            gpc_vertex* vertices;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        typedef pod_bvector<gpc_vertex, 8>          vertex_array_type;
 | 
			
		||||
        typedef pod_bvector<contour_header_type, 6> contour_header_array_type;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        typedef VSA source_a_type;
 | 
			
		||||
        typedef VSB source_b_type;
 | 
			
		||||
        typedef conv_gpc<source_a_type, source_b_type> self_type;
 | 
			
		||||
 | 
			
		||||
        ~conv_gpc()
 | 
			
		||||
        {
 | 
			
		||||
            free_gpc_data();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) :
 | 
			
		||||
            m_src_a(&a),
 | 
			
		||||
            m_src_b(&b),
 | 
			
		||||
            m_status(status_move_to),
 | 
			
		||||
            m_vertex(-1),
 | 
			
		||||
            m_contour(-1),
 | 
			
		||||
            m_operation(op)
 | 
			
		||||
        {
 | 
			
		||||
            std::memset(&m_poly_a, 0, sizeof(m_poly_a));
 | 
			
		||||
            std::memset(&m_poly_b, 0, sizeof(m_poly_b));
 | 
			
		||||
            std::memset(&m_result, 0, sizeof(m_result));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void attach1(VSA& source) { m_src_a = &source; }
 | 
			
		||||
        void attach2(VSB& source) { m_src_b = &source; }
 | 
			
		||||
 | 
			
		||||
        void operation(gpc_op_e v) { m_operation = v; }
 | 
			
		||||
 | 
			
		||||
        // Vertex Source Interface
 | 
			
		||||
        void     rewind(unsigned path_id);
 | 
			
		||||
        unsigned vertex(double* x, double* y);
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        conv_gpc(const conv_gpc<VSA, VSB>&);
 | 
			
		||||
        const conv_gpc<VSA, VSB>& operator = (const conv_gpc<VSA, VSB>&);
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        void free_polygon(gpc_polygon& p);
 | 
			
		||||
        void free_result();
 | 
			
		||||
        void free_gpc_data();
 | 
			
		||||
        void start_contour();
 | 
			
		||||
        void add_vertex(double x, double y);
 | 
			
		||||
        void end_contour(unsigned orientation);
 | 
			
		||||
        void make_polygon(gpc_polygon& p);
 | 
			
		||||
        void start_extracting();
 | 
			
		||||
        bool next_contour();
 | 
			
		||||
        bool next_vertex(double* x, double* y);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        template<class VS> void add(VS& src, gpc_polygon& p)
 | 
			
		||||
        {
 | 
			
		||||
            unsigned cmd;
 | 
			
		||||
            double x, y;
 | 
			
		||||
            double start_x = 0.0;
 | 
			
		||||
            double start_y = 0.0;
 | 
			
		||||
            bool line_to = false;
 | 
			
		||||
            unsigned orientation = 0;
 | 
			
		||||
 | 
			
		||||
            m_contour_accumulator.remove_all();
 | 
			
		||||
 | 
			
		||||
            while(!is_stop(cmd = src.vertex(&x, &y)))
 | 
			
		||||
            {
 | 
			
		||||
                if(is_vertex(cmd))
 | 
			
		||||
                {
 | 
			
		||||
                    if(is_move_to(cmd))
 | 
			
		||||
                    {
 | 
			
		||||
                        if(line_to)
 | 
			
		||||
                        {
 | 
			
		||||
                            end_contour(orientation);
 | 
			
		||||
                            orientation = 0;
 | 
			
		||||
                        }
 | 
			
		||||
                        start_contour();
 | 
			
		||||
                        start_x = x;
 | 
			
		||||
                        start_y = y;
 | 
			
		||||
                    }
 | 
			
		||||
                    add_vertex(x, y);
 | 
			
		||||
                    line_to = true;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    if(is_end_poly(cmd))
 | 
			
		||||
                    {
 | 
			
		||||
                        orientation = get_orientation(cmd);
 | 
			
		||||
                        if(line_to && is_closed(cmd))
 | 
			
		||||
                        {
 | 
			
		||||
                            add_vertex(start_x, start_y);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if(line_to)
 | 
			
		||||
            {
 | 
			
		||||
                end_contour(orientation);
 | 
			
		||||
            }
 | 
			
		||||
            make_polygon(p);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        //--------------------------------------------------------------------
 | 
			
		||||
        source_a_type*             m_src_a;
 | 
			
		||||
        source_b_type*             m_src_b;
 | 
			
		||||
        status                     m_status;
 | 
			
		||||
        int                        m_vertex;
 | 
			
		||||
        int                        m_contour;
 | 
			
		||||
        gpc_op_e                   m_operation;
 | 
			
		||||
        vertex_array_type          m_vertex_accumulator;
 | 
			
		||||
        contour_header_array_type  m_contour_accumulator;
 | 
			
		||||
        gpc_polygon                m_poly_a;
 | 
			
		||||
        gpc_polygon                m_poly_b;
 | 
			
		||||
        gpc_polygon                m_result;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VSA, class VSB> 
 | 
			
		||||
    void conv_gpc<VSA, VSB>::free_polygon(gpc_polygon& p)
 | 
			
		||||
    {
 | 
			
		||||
        int i;
 | 
			
		||||
        for(i = 0; i < p.num_contours; i++)
 | 
			
		||||
        {
 | 
			
		||||
            pod_allocator<gpc_vertex>::deallocate(p.contour[i].vertex, 
 | 
			
		||||
                                                  p.contour[i].num_vertices);
 | 
			
		||||
        }
 | 
			
		||||
        pod_allocator<gpc_vertex_list>::deallocate(p.contour, p.num_contours);
 | 
			
		||||
        std::memset(&p, 0, sizeof(gpc_polygon));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VSA, class VSB> 
 | 
			
		||||
    void conv_gpc<VSA, VSB>::free_result()
 | 
			
		||||
    {
 | 
			
		||||
        if(m_result.contour)
 | 
			
		||||
        {
 | 
			
		||||
            gpc_free_polygon(&m_result);
 | 
			
		||||
        }
 | 
			
		||||
        std::memset(&m_result, 0, sizeof(m_result));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VSA, class VSB> 
 | 
			
		||||
    void conv_gpc<VSA, VSB>::free_gpc_data()
 | 
			
		||||
    {
 | 
			
		||||
        free_polygon(m_poly_a);
 | 
			
		||||
        free_polygon(m_poly_b);
 | 
			
		||||
        free_result();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VSA, class VSB> 
 | 
			
		||||
    void conv_gpc<VSA, VSB>::start_contour()
 | 
			
		||||
    {
 | 
			
		||||
        contour_header_type h;
 | 
			
		||||
        std::memset(&h, 0, sizeof(h));
 | 
			
		||||
        m_contour_accumulator.add(h);
 | 
			
		||||
        m_vertex_accumulator.remove_all();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VSA, class VSB> 
 | 
			
		||||
    inline void conv_gpc<VSA, VSB>::add_vertex(double x, double y)
 | 
			
		||||
    {
 | 
			
		||||
        gpc_vertex v;
 | 
			
		||||
        v.x = x;
 | 
			
		||||
        v.y = y;
 | 
			
		||||
        m_vertex_accumulator.add(v);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VSA, class VSB> 
 | 
			
		||||
    void conv_gpc<VSA, VSB>::end_contour(unsigned /*orientation*/)
 | 
			
		||||
    {
 | 
			
		||||
        if(m_contour_accumulator.size())
 | 
			
		||||
        {
 | 
			
		||||
            if(m_vertex_accumulator.size() > 2)
 | 
			
		||||
            {
 | 
			
		||||
                contour_header_type& h = 
 | 
			
		||||
                    m_contour_accumulator[m_contour_accumulator.size() - 1];
 | 
			
		||||
 | 
			
		||||
                h.num_vertices = m_vertex_accumulator.size();
 | 
			
		||||
                h.hole_flag = 0;
 | 
			
		||||
 | 
			
		||||
                // TO DO: Clarify the "holes"
 | 
			
		||||
                //if(is_cw(orientation)) h.hole_flag = 1;
 | 
			
		||||
 | 
			
		||||
                h.vertices = pod_allocator<gpc_vertex>::allocate(h.num_vertices);
 | 
			
		||||
                gpc_vertex* d = h.vertices;
 | 
			
		||||
                int i;
 | 
			
		||||
                for(i = 0; i < h.num_vertices; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    const gpc_vertex& s = m_vertex_accumulator[i];
 | 
			
		||||
                    d->x = s.x;
 | 
			
		||||
                    d->y = s.y;
 | 
			
		||||
                    ++d;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                m_vertex_accumulator.remove_last();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VSA, class VSB> 
 | 
			
		||||
    void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p)
 | 
			
		||||
    {
 | 
			
		||||
        free_polygon(p);
 | 
			
		||||
        if(m_contour_accumulator.size())
 | 
			
		||||
        {
 | 
			
		||||
            p.num_contours = m_contour_accumulator.size();
 | 
			
		||||
 | 
			
		||||
            p.hole = 0;
 | 
			
		||||
            p.contour = pod_allocator<gpc_vertex_list>::allocate(p.num_contours);
 | 
			
		||||
 | 
			
		||||
            int i;
 | 
			
		||||
            gpc_vertex_list* pv = p.contour;
 | 
			
		||||
            for(i = 0; i < p.num_contours; i++)
 | 
			
		||||
            {
 | 
			
		||||
                const contour_header_type& h = m_contour_accumulator[i];
 | 
			
		||||
                pv->num_vertices = h.num_vertices;
 | 
			
		||||
                pv->vertex = h.vertices;
 | 
			
		||||
                ++pv;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VSA, class VSB> 
 | 
			
		||||
    void conv_gpc<VSA, VSB>::start_extracting()
 | 
			
		||||
    {
 | 
			
		||||
        m_status = status_move_to;
 | 
			
		||||
        m_contour = -1;
 | 
			
		||||
        m_vertex = -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VSA, class VSB> 
 | 
			
		||||
    bool conv_gpc<VSA, VSB>::next_contour()
 | 
			
		||||
    {
 | 
			
		||||
        if(++m_contour < m_result.num_contours)
 | 
			
		||||
        {
 | 
			
		||||
            m_vertex = -1;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VSA, class VSB> 
 | 
			
		||||
    inline bool conv_gpc<VSA, VSB>::next_vertex(double* x, double* y)
 | 
			
		||||
    {
 | 
			
		||||
        const gpc_vertex_list& vlist = m_result.contour[m_contour];
 | 
			
		||||
        if(++m_vertex < vlist.num_vertices)
 | 
			
		||||
        {
 | 
			
		||||
            const gpc_vertex& v = vlist.vertex[m_vertex];
 | 
			
		||||
            *x = v.x;
 | 
			
		||||
            *y = v.y;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VSA, class VSB> 
 | 
			
		||||
    void conv_gpc<VSA, VSB>::rewind(unsigned path_id)
 | 
			
		||||
    {
 | 
			
		||||
        free_result();
 | 
			
		||||
        m_src_a->rewind(path_id);
 | 
			
		||||
        m_src_b->rewind(path_id);
 | 
			
		||||
        add(*m_src_a, m_poly_a);
 | 
			
		||||
        add(*m_src_b, m_poly_b);
 | 
			
		||||
        switch(m_operation)
 | 
			
		||||
        {
 | 
			
		||||
           case gpc_or:
 | 
			
		||||
                gpc_polygon_clip(GPC_UNION,
 | 
			
		||||
                                 &m_poly_a,
 | 
			
		||||
                                 &m_poly_b,
 | 
			
		||||
                                 &m_result);
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
           case gpc_and:
 | 
			
		||||
                gpc_polygon_clip(GPC_INT,
 | 
			
		||||
                                 &m_poly_a,
 | 
			
		||||
                                 &m_poly_b,
 | 
			
		||||
                                 &m_result);
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
           case gpc_xor:
 | 
			
		||||
                gpc_polygon_clip(GPC_XOR,
 | 
			
		||||
                                 &m_poly_a,
 | 
			
		||||
                                 &m_poly_b,
 | 
			
		||||
                                 &m_result);
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
           case gpc_a_minus_b:
 | 
			
		||||
                gpc_polygon_clip(GPC_DIFF,
 | 
			
		||||
                                 &m_poly_a,
 | 
			
		||||
                                 &m_poly_b,
 | 
			
		||||
                                 &m_result);
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
           case gpc_b_minus_a:
 | 
			
		||||
                gpc_polygon_clip(GPC_DIFF,
 | 
			
		||||
                                 &m_poly_b,
 | 
			
		||||
                                 &m_poly_a,
 | 
			
		||||
                                 &m_result);
 | 
			
		||||
               break;
 | 
			
		||||
        }
 | 
			
		||||
        start_extracting();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class VSA, class VSB> 
 | 
			
		||||
    unsigned conv_gpc<VSA, VSB>::vertex(double* x, double* y)
 | 
			
		||||
    {
 | 
			
		||||
        if(m_status == status_move_to)
 | 
			
		||||
        {
 | 
			
		||||
            if(next_contour()) 
 | 
			
		||||
            {
 | 
			
		||||
                if(next_vertex(x, y))
 | 
			
		||||
                {
 | 
			
		||||
                    m_status = status_line_to;
 | 
			
		||||
                    return path_cmd_move_to;
 | 
			
		||||
                }
 | 
			
		||||
                m_status = status_stop;
 | 
			
		||||
                return path_cmd_end_poly | path_flags_close;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if(next_vertex(x, y))
 | 
			
		||||
            {
 | 
			
		||||
                return path_cmd_line_to;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                m_status = status_move_to;
 | 
			
		||||
            }
 | 
			
		||||
            return path_cmd_end_poly | path_flags_close;
 | 
			
		||||
        }
 | 
			
		||||
        return path_cmd_stop;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
   
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										149
									
								
								dep/agg/include/agg_conv_marker.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								dep/agg/include/agg_conv_marker.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Anti-Grain Geometry - Version 2.4
 | 
			
		||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, modify, sell and distribute this software 
 | 
			
		||||
// is granted provided this copyright notice appears in all copies. 
 | 
			
		||||
// This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
// Contact: mcseem@antigrain.com
 | 
			
		||||
//          mcseemagg@yahoo.com
 | 
			
		||||
//          http://www.antigrain.com
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
//
 | 
			
		||||
// conv_marker
 | 
			
		||||
//
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
#ifndef AGG_CONV_MARKER_INCLUDED
 | 
			
		||||
#define AGG_CONV_MARKER_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <cmath>
 | 
			
		||||
#include "agg_basics.h"
 | 
			
		||||
#include "agg_trans_affine.h"
 | 
			
		||||
 | 
			
		||||
namespace agg
 | 
			
		||||
{
 | 
			
		||||
    //-------------------------------------------------------------conv_marker
 | 
			
		||||
    template<class MarkerLocator, class MarkerShapes>
 | 
			
		||||
    class conv_marker
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        conv_marker(MarkerLocator& ml, MarkerShapes& ms);
 | 
			
		||||
 | 
			
		||||
        trans_affine& transform() { return m_transform; }
 | 
			
		||||
        const trans_affine& transform() const { return m_transform; }
 | 
			
		||||
 | 
			
		||||
        void rewind(unsigned path_id);
 | 
			
		||||
        unsigned vertex(double* x, double* y);
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        conv_marker(const conv_marker<MarkerLocator, MarkerShapes>&);
 | 
			
		||||
        const conv_marker<MarkerLocator, MarkerShapes>& 
 | 
			
		||||
            operator = (const conv_marker<MarkerLocator, MarkerShapes>&);
 | 
			
		||||
 | 
			
		||||
        enum status_e 
 | 
			
		||||
        {
 | 
			
		||||
            initial,
 | 
			
		||||
            markers,
 | 
			
		||||
            polygon,
 | 
			
		||||
            stop
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        MarkerLocator* m_marker_locator;
 | 
			
		||||
        MarkerShapes*  m_marker_shapes;
 | 
			
		||||
        trans_affine   m_transform;
 | 
			
		||||
        trans_affine   m_mtx;
 | 
			
		||||
        status_e       m_status;
 | 
			
		||||
        unsigned       m_marker;
 | 
			
		||||
        unsigned       m_num_markers;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class MarkerLocator, class MarkerShapes> 
 | 
			
		||||
    conv_marker<MarkerLocator, MarkerShapes>::conv_marker(MarkerLocator& ml, MarkerShapes& ms) :
 | 
			
		||||
        m_marker_locator(&ml),
 | 
			
		||||
        m_marker_shapes(&ms),
 | 
			
		||||
        m_status(initial),
 | 
			
		||||
        m_marker(0),
 | 
			
		||||
        m_num_markers(1)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class MarkerLocator, class MarkerShapes> 
 | 
			
		||||
    void conv_marker<MarkerLocator, MarkerShapes>::rewind(unsigned)
 | 
			
		||||
    {
 | 
			
		||||
        m_status = initial;
 | 
			
		||||
        m_marker = 0;
 | 
			
		||||
        m_num_markers = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //------------------------------------------------------------------------
 | 
			
		||||
    template<class MarkerLocator, class MarkerShapes> 
 | 
			
		||||
    unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y)
 | 
			
		||||
    {
 | 
			
		||||
        unsigned cmd = path_cmd_move_to;
 | 
			
		||||
        double x1, y1, x2, y2;
 | 
			
		||||
 | 
			
		||||
        while(!is_stop(cmd))
 | 
			
		||||
        {
 | 
			
		||||
            switch(m_status)
 | 
			
		||||
            {
 | 
			
		||||
            case initial:
 | 
			
		||||
                if(m_num_markers == 0)
 | 
			
		||||
                {
 | 
			
		||||
                   cmd = path_cmd_stop;
 | 
			
		||||
                   break;
 | 
			
		||||
                }
 | 
			
		||||
                m_marker_locator->rewind(m_marker);
 | 
			
		||||
                ++m_marker;
 | 
			
		||||
                m_num_markers = 0;
 | 
			
		||||
                m_status = markers;
 | 
			
		||||
 | 
			
		||||
            case markers:
 | 
			
		||||
                if(is_stop(m_marker_locator->vertex(&x1, &y1)))
 | 
			
		||||
                {
 | 
			
		||||
                    m_status = initial;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                if(is_stop(m_marker_locator->vertex(&x2, &y2)))
 | 
			
		||||
                {
 | 
			
		||||
                    m_status = initial;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                ++m_num_markers;
 | 
			
		||||
                m_mtx = m_transform;
 | 
			
		||||
                m_mtx *= trans_affine_rotation(std::atan2(y2 - y1, x2 - x1));
 | 
			
		||||
                m_mtx *= trans_affine_translation(x1, y1);
 | 
			
		||||
                m_marker_shapes->rewind(m_marker - 1);
 | 
			
		||||
                m_status = polygon;
 | 
			
		||||
 | 
			
		||||
            case polygon:
 | 
			
		||||
                cmd = m_marker_shapes->vertex(x, y);
 | 
			
		||||
                if(is_stop(cmd))
 | 
			
		||||
                {
 | 
			
		||||
                    cmd = path_cmd_move_to;
 | 
			
		||||
                    m_status = markers;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                m_mtx.transform(x, y);
 | 
			
		||||
                return cmd;
 | 
			
		||||
 | 
			
		||||
            case stop:
 | 
			
		||||
                cmd = path_cmd_stop;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return cmd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user