mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	Compare commits
	
		
			704 Commits
		
	
	
		
			FluxEngine
			...
			libui
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | f9b7c7f6c1 | ||
|  | 855d346b8a | ||
|  | 473e81a2da | ||
|  | d925391d57 | ||
|  | 63a5954dfa | ||
|  | 897931f273 | ||
|  | 03e80b2f1c | ||
|  | 53c8ec864c | ||
|  | 5d3002f118 | ||
|  | 5eeb52660c | ||
|  | 3dfafaa278 | ||
|  | 462bd9ae5e | ||
|  | dab0fcc7c0 | ||
|  | b8a3e8085e | ||
|  | c9d1d72ba3 | ||
|  | ccf5d513d2 | ||
|  | d157b7b05d | ||
|  | 05981ac46c | ||
|  | 08615a5954 | ||
|  | b6dbe26c7e | ||
|  | 8a460b3e56 | ||
|  | 012f1a872b | ||
|  | 4f0d61b379 | ||
|  | 9e5e494f88 | ||
|  | b15fd05e8d | ||
|  | faabc28d1b | ||
|  | 4b815846ee | ||
|  | fe8be18c4c | ||
|  | 519c30321d | ||
|  | 77be88a5bb | ||
|  | 8d04931f9f | ||
|  | 3d1ee7a43e | ||
|  | 2584a25527 | ||
|  | 0647a82d38 | ||
|  | c56459c98c | ||
|  | 3347d057fe | ||
|  | 7b0a4a057d | ||
|  | eb0bb2cc2f | ||
|  | 5ff7651218 | ||
|  | dcb3761c9b | ||
|  | 6fa83f4dcb | ||
|  | 001c65dba8 | ||
|  | 969a08bd9a | ||
|  | 3c3e520594 | ||
|  | ed9ffc9091 | ||
|  | 5d0750e835 | ||
|  | 3283d6e8c0 | ||
|  | 1b96f60b2a | ||
|  | a15d78c040 | ||
|  | 40b7f57116 | ||
|  | 68314cd44d | ||
|  | 17787b97d4 | ||
|  | da84297b2c | ||
|  | e3e3bb770d | ||
|  | 9d4f180741 | ||
|  | 91281bb58b | ||
|  | 4ddd7d04b5 | ||
|  | 316836d9f6 | ||
|  | aa3b0a117a | ||
|  | 0f7df3281f | ||
|  | 4a91a35799 | ||
|  | 36c2263675 | ||
|  | 28068d8d31 | ||
|  | 97cc54a07a | ||
|  | 0c3c08db36 | ||
|  | bb5d62fe69 | ||
|  | 376270dd53 | ||
|  | 9056b23eaa | ||
|  | 634be4ae51 | ||
|  | 99901f365e | ||
|  | 422620f4fe | ||
|  | dd3cb93ed9 | ||
|  | dbb422a410 | ||
|  | 68712b8be7 | ||
|  | da7e2b1b54 | ||
|  | 8cff85ad3d | ||
|  | 9ffde65bb0 | ||
|  | 5759bc602f | ||
|  | 4bb6fdc79a | ||
|  | bd019d5d70 | ||
|  | 0457282d47 | ||
|  | 06d8609200 | ||
|  | fa975b5511 | ||
|  | 194b9b1193 | ||
|  | 27fceb3f41 | ||
|  | 930e0bcd67 | ||
|  | d81e0a3ed4 | ||
|  | ebb5c17be4 | ||
|  | 1e99fe5b04 | ||
|  | 5f5f22c82b | ||
|  | 709e300960 | ||
|  | d2f677d84e | ||
|  | 18d90c44dd | ||
|  | 298f77f52e | ||
|  | 70b2f7efb4 | ||
|  | 78a070bd99 | ||
|  | c88ff973b1 | ||
|  | 66f82f764d | ||
|  | 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 | ||
|  | adba93ae0a | ||
|  | 98587d04a7 | ||
|  | 0051b64648 | ||
|  | 603009ba15 | ||
|  | adb9809692 | ||
|  | 06eb10d2a0 | ||
|  | 2244299bd9 | ||
|  | 6ca06ecafb | ||
|  | 9a5958f80b | ||
|  | 2b53ac057c | ||
|  | 5deba8af41 | ||
|  | 3c54a663b8 | ||
|  | 1fd65452c4 | ||
|  | 30646ccb07 | ||
|  | 5be7249a30 | ||
|  | 067af18103 | ||
|  | 8dbd2a72a7 | ||
|  | c29e131a3b | ||
|  | a9e30c1e49 | ||
|  | 972c8c6b61 | ||
|  | 2007ff7546 | ||
|  | 64694580cd | ||
|  | deaab94494 | ||
|  | 1509e1f89d | ||
|  | 29e1ddc2ff | ||
|  | 1fe6434563 | ||
|  | 0367b7e77d | ||
|  | e6da85bf64 | ||
|  | cd19fcdadd | ||
|  | 1954f02cfb | ||
|  | 39b23200b0 | ||
|  | 0644d6d965 | ||
|  | a075694d8e | ||
|  | b1ea5a9a35 | ||
|  | 00087cbb6b | ||
|  | 1b48ea20c4 | ||
|  | 3d0f019fc4 | ||
|  | a08bfc183f | ||
|  | c5aef9b051 | ||
|  | fc2655ecd6 | ||
|  | a737c723d3 | ||
|  | 37aa8b62b0 | ||
|  | a401173f6d | ||
|  | ce76dc4279 | ||
|  | 1025bd857b | ||
|  | 025802b2d0 | 
| @@ -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 | ||||
|  | ||||
							
								
								
									
										46
									
								
								.github/workflows/ccpp.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								.github/workflows/ccpp.yml
									
									
									
									
										vendored
									
									
								
							| @@ -10,32 +10,46 @@ jobs: | ||||
|       with: | ||||
|         fetch-depth: 1 | ||||
|     - name: apt | ||||
|       run: sudo apt install libusb-1.0-0-dev libsqlite3-dev ninja-build | ||||
|       run: sudo apt update && sudo apt install libudev-dev libsqlite3-dev ninja-build protobuf-compiler libgtk-3-dev | ||||
|     - 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 | ||||
|           diffutils | ||||
|     - uses: actions/checkout@v1 | ||||
|       with: | ||||
|         fetch-depth: 1 | ||||
|     - name: build | ||||
|       run: | | ||||
|         make | ||||
|  | ||||
|   | ||||
							
								
								
									
										64
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| 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 | ||||
|           diffutils | ||||
|     - 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,254 +1,254 @@ | ||||
| :4000000000800020110000006112000061120000064A08B5136843F020031360044B1A6803F53F5302331A6001F038F9E8460040FA46004010B5054C237833B9044B13B10E | ||||
| :400040000448AFF300800123237010BD6881FF1F00000000E03A0000084B10B51BB108490848AFF300800848036803B910BD074B002BFBD0BDE81040184700BF0000000027 | ||||
| :400080006C81FF1FE03A0000C880FF1F000000000A4A0B4B116801310B40002BBEBF03F1FF3363F03F030133136011685368994202BF024B01221A72704700BF8881FF1FA2 | ||||
| :4000C0003F0000800A4A0B4B516801310B40002BBEBF03F1FF3363F03F030133536051681368994202BF024B01221A72704700BF8881FF1F3F000080024B012200205A7293 | ||||
| :4001000002F072BA8881FF1F10B5C4B2204601F087FA0128FAD110BD08B572B60F4B0F49DA680132DA601A690132C82A08BF00221A615A6918690132A72A08BF00224A6178 | ||||
| :400140005B69002B0CBF02230023002814BF184643F0010002F0B0FF62B608BD8881FF1F38B50446C5B2284602F0E0F9062002F0FDFB44F00200C0B202F0D8F9062002F0D1 | ||||
| :40018000F5FB284602F0D2F9BDE83840062002F0D7BB10B5642402F0C3F930B90120FFF7DFFF013CF7D1204610BD012010BD70B5C4B220460E4601F03BFA314605460246D9 | ||||
| :4001C000204601F0F7FA204601F02AFA0128FAD0284670BD38B5044D0024285D013402F075FB402CF9D138BDA081FF1F08B502F08FFD002002F098FD02F0AAFD02F0B4FDA8 | ||||
| :4002000080B208BD10B50446012002F0A7F9642002F096FBFFF7EAFF2080002002F09EF9642002F08DFBFFF7E1FF608010BD08B502F09AFE002002F0A3FE02F0B5FE02F0C4 | ||||
| :40024000BFFE80B208BD10B50446FFF7A2FF322002F076FBFFF7EBFF20800020FFF780FF322002F06DFBFFF7E2FF608010BD0FB400B593B014AB53F8042B402102A8019397 | ||||
| :4002800003F016F802A802F0B6F902F0C0F913B05DF804EB04B0704710B5044601780648FFF7E5FF0420FFF72FFF62782146BDE81040042001F00CBAF43A000007B50023BF | ||||
| :4002C000ADF804308DF80600032301A88DF80530FFF7E2FF03B05DF804FB000010B5074C94F8583043B1002002F014F9002002F0A7FE002384F8583010BD00BF8881FF1F63 | ||||
| :4003000038B5104D837895F85B2004469A4204D0FFF7E4FF002385F85E302368C5F859302279094B1A71A378002B14BF0220012002F086FEE07802F07DFE2079BDE83840D7 | ||||
| :4003400002F0B4BE8881FF1FE181FF1F38B50D4C94F8585065B904F15900FFF7D1FF012002F0D8F84FF47A7002F0EAFA84F85E50E3682366012384F85830BDE8384002F0AB | ||||
| :400380001DBB00BF8881FF1FF8B51E4C0646FFF7DDFF94F85E3003B15EB91B48FFF767FFFFF7F7FE0120002384F85E00636602F0DDFA3246616E1548FFF759FF114D002794 | ||||
| :4003C000636E9E4216D002F0ABF800B16F66636E9E4205DD0020FFF7C3FE6B6E013305E005DA0120FFF7BCFE6B6E013B6B6602F0E5FAE5E7322002F0A3FABDE8F8400448B2 | ||||
| :40040000FFF735BF8881FF1F013B0000083B0000253B00002DE9F04F9BB062B602F038FB9B49042002F05CFB9A4802F085F89A4802F028FE994802F0B9F802F009FD02F0E5 | ||||
| :40044000DBFB002002F0FCFD02F0D4F80221002001F09CF803210846914C02F08FFA002384F85B30FFF772FFFFF793FE84F86800FFF734FF012384F85B30FFF767FFFFF7A9 | ||||
| :4004800088FE84F86900FFF729FF94F86800854B854994F869202546002A14BF0A461A46002808BF19468148FFF7E1FEA24602F085FA94F8583043B12A6EEB689B1A41F2D4 | ||||
| :4004C0008832934201D9FFF709FF01F097F818B97748FFF7CCFE04E001F096F80028F7D109E001F08BF80028FBD07248FFF7BFFE032001F0B3F9032001F092F80128D6D187 | ||||
| :400500006D48FFF7FDFE6D490320FFF750FE94F86A106B48FFF7ABFE94F86A30023B142B00F27684DFE813F0150074041E00740424007404480074046B007404D800740496 | ||||
| :40054000FE017404AC037404CC037404D3037404ED0303238DF828308DF829300C238DF82A30CAE394F86C00FFF70EFF554BC1E3FFF7ECFE00236372E068627A02F0FF018F | ||||
| :4005800032B9EB681B1AB3F57A7FF6DD0B460AE04BB100228AF80920DAF80C10627A12B9EB685B1AFAE707228DF8282004228DF82920ADF82A30A0E30220FFF7A5FD0027C5 | ||||
| :4005C0000DF1280902F0FAF94FF480780026C8EB07039A1906F809200136402EF9D10220FFF792FD32464946022001F071F8B8F10108EBD10137402FE4D1334B42E04FF0AD | ||||
| :400600000109002702F0DAF94FF00008012001F025F9012001F004F80128FAD10DF1280B4022594601F0C6F8012000F0F9FF0028FAD1064608EB07030593059B1BF80620B4 | ||||
| :400640003344DBB2934209D08DE80C003946334642461E48FFF70BFE4FF000090136402EEBD108F10108B8F5807FCFD10137402FC8D149461648FFF7FAFDB9F1000F00F0A8 | ||||
| :400680005981144B1B8809A8ADF8243036E300BF19010000F900000091000000C50000008881FF1F373B0000333B00003A3B0000523B0000653B0000E181FF1FF281FF1FB9 | ||||
| :4006C0006F3B0000E43A0000E63A00007E3B00009A3B0000E83A000094F86C0001F03EFF606EFFF751FE02F04FFD934B934F1A78002602F0FB021A701A7842F001021A70A9 | ||||
| :400700001A7802F0FE021A701A7802F0FE021A7002F03EFD0220FFF7F7FC41F6FF734FF480420121022002F091FC84F8AA0002F0B3F8B8550136402EF9D1DFF82082002616 | ||||
| :4007400008F1990B1FFA8BF70136402E14BF3246002218F8010F22440623127E402102F0CFF83A4646F2434198F8000002F0DAF84037402EBFB2E7D19AF86D3043B10023F2 | ||||
| :400780008AF80930637A002BFCD000238AF80930182200210AA802F057FD694B4FF0FF320C9340230D930023236062602372236894F8AA002344197E02F026F894F8AA00B1 | ||||
| :4007C00001F0E4FF012194F8AA0001F0B7FF2368002BFCD000239946CAF80430DAF80C200127059202F0EAF8059AE3689B1AB4F86E2093420ED36FB1042195F8AA0002F01E | ||||
| :400800000FF894F8AA0002F01BF80028F9D107468AF80800237A03F0FF08002B48D16A682B689A4202D1002FDCD141E063680AA80BEB831343440A93C8F140030B9300F00A | ||||
| :4008400001FB0B9B09F10109C3F1400398440D9B5FFA88F8E3B93B4E0220FFF755FCA6F1400EBEE80F000FC6BEE80F000FC6BEE80F000FC69EE80F0086E80F00A6F1300193 | ||||
| :400880004022022000F024FF703E40230C960D93B8F13F0FCAD962682B4B01321340002BBEBF03F1FF3363F03F030133636099E70AA8267A00F01CFB0220FFF725FC0D9BDA | ||||
| :4008C000F6B2402B07D0022040221E4900F000FF0220FFF719FC0D9B022033F040021DBFC3F1400292B21749114600F0F1FE0220FFF70AFCFFF76EFC36B11448FFF7B7FCC2 | ||||
| :400900000220FFF7DBFC06E0114B09A81B88ADF82430FFF7C1FC627A4946237A0D48FFF7A6FC78E20C48FFF7A2FCD4F86E6016F03F0615D003206CE293640040A081FF1F9E | ||||
| :400940003892FF1F7892FF1F3F000080A43B0000EA3A0000BE3B0000D13B00009F81FF1F012001F001FE95F86C0001F0F7FD02F00BFCB94BB94F1A7842F004021A701A7888 | ||||
| :4009800042F001021A701A7802F0FE021A701A7802F0FE021A7002F0FBFB686EFFF7F4FC01214FF4804341F6FF72084601F0E2FD85F8AA0001F070FFB8550136402EF9D1C7 | ||||
| :4009C000DFF8B882002708F199039EB207930137402F14BF3A46002218F8010F22440523127E402101F08CFF314646F2475298F8000001F097FF4036402FB6B2E7D1DAF8D3 | ||||
| :400A00006E3000269B09182231464FF0FF3B0AA8CAF800600593CAF804B0B1468AF80860B04602F011FC0D973746012000F016FF069601F0C3FFB8F1000F0AD14EB901201B | ||||
| :400A400000F0EEFD012804D14022854900F0B2FE06462268834B01321340002BBCBF03F1FF3363F03F036168B8BF01338B4200F09080069B3BB1237A002B40F09B806B7A7C | ||||
| :400A8000002B40F097800B9BBBBBB8F1000F09D0754A7F2199540133402BFBD1724A0B930A922AE04EB3012000F0BAFD28BBDFF8B8E13F2E0EF1400CBCE80F00AEE80F0034 | ||||
| :400AC000BCE80F00AEE80F00BCE80F00AEE80F009CE80F008EE80F00AEF130030A9307F101070B9607DD059BBB4204D0012000F0B5FE464601E04FF001080B9BDBB1236893 | ||||
| :400B0000079A0AA802EB83120D9BC3F1400313440C9300F0FCF90D9B6BB92A68514B01321340002BBEBF03F1FF3363F03F030133236040230D93636801332AD12B683F2BD2 | ||||
| :400B400027D14FF0000BC5F804B001F041FD85F808B06B6895F8AA002B44197E01F054FE95F8AA0001F012FE012195F8AA0001F0E5FD85F809B0637A002BFCD04FF0000B53 | ||||
| :400B800001208AF809B001F02FFD584601F0ECFC01E0069B2BB1237A63B96B7A53B90123069363685B453FF444AF09F10109D5F804B03EE761682D482268FFF758FB01F043 | ||||
| :400BC0000DFD012001F0D0FC002001F00DFD042194F8AA0001F024FE94F8AA0001F030FE0028F9D19AF8AA0001F0BEFD9AF809309AF808200293012303920193CDF80080A9 | ||||
| :400C00004B463A4605991A48FFF731FBB8F1000F16D1059BBB420AD0012000F001FD01280646F6D10E49FFF7C2FA3F2803DC012000F028FE04E0304600F010FE0137E8E73B | ||||
| :400C4000FFF7C8FA0B48FFF712FB237A0BB10220DFE0094B16E500BF97650040A081FF1F7892FF1F3F0000803892FF1FDB3B0000E63B0000163C0000EC3A00009F81FF1FE7 | ||||
| :400C800094F86C0001F06AFC606EFFF77DFB6648FFF7EDFA00236372637A002BFCD0012001F0A2FC00238AF80930637A002BFCD0002001F099FC5D48FFF7D9FA5C4B19E03C | ||||
| :400CC000002084F85E00FFF75FFB5A4B12E094F8683023B195F869200AB985F86C2094F869201AB113B9012385F86C305248FFF707FB524B1B88ADF828300AA8FFF7CCFA13 | ||||
| :400D000089E0FFF7EBFA02F021F9002002F0C4F82A2601F0EFFF002001F092FF324600210AA802F091FA17238DF828308DF8296001F044FE002001F0EDFB002002F080F920 | ||||
| :400D4000C82001F0FDFD0DEB0600FFF75BFA0DF13E00FFF778FA01F031FE012002F070F9322001F0EDFD0DF12E00FFF74BFA0DF14200FFF768FA012001F0CCFB4FF49670C9 | ||||
| :400D800001F0DEFD01F01AFE0DF13600FFF73AFA0DF14A00FFF757FA002001F0BBFB4FF4967001F0CDFD01F009FE022002F048F9322001F0C5FD0DF13200FFF723FA0DF113 | ||||
| :400DC0004600FFF740FA012001F0A4FB4FF4967001F0B6FD01F0F2FD0DF13A00FFF712FA0DF14E00FFF72FFA002001F093FB4FF4967001F0A5FD01F0E1FD002002F020F9E5 | ||||
| :400E0000002384F85E3002F023F801F0F5FE74E70120FFF753FA032000F020FD0848FFF726FAFFF744BB00BF253C0000333C0000EE3A0000F03A0000F281FF1FF23A0000AC | ||||
| :400E4000403C000070B5002401254268002A4ED0C368002B4BD00368013A591C01601B784260802B01D145752FE013F0800F467D0269017D12D036B1D20042F004020331E8 | ||||
| :400E8000026101754475026903F00103D20042F004021A43037D0261033315E046B13F2B06D9D20042F004020331026101754475026943EA0223427D036112B143F0C00320 | ||||
| :400EC0000361037D447508330375037D072BBCD90269083B22FA03F38268511C81601370C368013BC360037D083B0375ADE770BD07B5027D42B102AA002102F8011D0260E5 | ||||
| :400F000001224260FFF79EFF03B05DF804FBF0B5012100244368002B43D0C268002A40D0427D4AB183685A1C8260827D1A70C3684475013BC360EDE7027D072A0BD806687C | ||||
| :400F40000769751C05603578013B45EA07250832056143600275027D0369A2F10805EB40DBB203F0C006802E07D0C02E0ED103F03F0383754175802308E0C3F3401363F0F5 | ||||
| :400F80007F03033A03F08103027502E00575002BC0D08268551C85601370C368013BC360B8E7F0BD2DE9F04172B6884B61221A70A3F5F06301221A801924854A9C7092E84B | ||||
| :400FC00003008033062283F8002283E80300522203F580731A707F4B7F4A1B787F4EDBB2137040F618027E4B00251A8041F2512223F8022C33784FF4F07003F0010343EAE3 | ||||
| :40100000450502F0B9F8013C05F003052ED0032DF0D1744B4FF480721A8007221A70724A002548211570917002221D705D7103F8032C0422DA716D4A6D4C13786D4E43F086 | ||||
| :401040000103137012F8013C062743F0030302F8013C2378012243F0800323705B4B1A70654A137843F02003137000E0FEE707FB056300219A881868013502F0E5F8072D90 | ||||
| :40108000F5D15E485E4E002550F8041F05F1105303F1520221F0FF075333C9B20B4452005B0002329A4206D012F802EC12F801CC0EF807C0F5E7B0420D44E5D1514A0023BE | ||||
| :4010C00013609360136193614F4B504F1A68504BDFF888811A604F4B1A684F4B1A604F4A137843F002031370137C43F0020313742378A2F5863243F040032370413A13781C | ||||
| :4011000043F010031370464A464B07CA03C31A80454A2833106843F8250C127903F8212C424A07CA03C31A80414AE83B07CA03C31A80404A083307CA03C31A803E4A3F4B4F | ||||
| :40114000A2F5616203CBC2F8100EC2F8141E1378042043F008031370394B02F5AA521B783D78DBB298F80060EDB203F007010C321B091170F6B2537045F003033B7046F0D3 | ||||
| :40118000030388F800302F4B48221A702E4A402313702E49937013729372082382F81F3220220A7048710A72294A0A20137001F0DDFB284B88F8006044223D70264D1A7076 | ||||
| :4011C00094E80F0007C52B80BDE8F081004800404C0F00480F010049A146004025420040224200400440004006400040A2430040A0430040453C0000E8460040FCFFFF475F | ||||
| :40120000A000004800760040540F0048F846004020760040580F004828760040035001400C0F0048C0510040180F0048200F00482C0F0048380F004832510040440F0048E6 | ||||
| :40124000CF0100491D51004001590040235B0040585B004076580040B0430040F946004008B501F0C5FF03680C2B00D1FEE7FEE7084908B50B68084A1844821A802A01DC9B | ||||
| :40128000086005E001F0B4FF0C2303604FF0FF33184608BDCC80FF1FC893FF1F80B51148114B0025C0B1A3F1100192C922460439161BB74204D051F8046F42F8046BF7E7CE | ||||
| :4012C000114653F8046C8C1AA64202D041F8045BF9E701381033E5E701F090FFFFF79AF8FEE700BF01000000143E0000124A134B10B51A60124A134C1368134843F4007389 | ||||
| :4013000013600023032B98BF54F823204FEA830188BF0E4A0133302B4250F3D10C4B1A780C4B1A700C4B084A1A60FFF73BFEBDE8104001F0EDB900BF0004FA050CED00E07F | ||||
| :4013400014ED00E0000000000080FF1F61120000BC760040C080FF1F08ED00E0F8B501F013FF4B4A01271378022643F001031370137C484C43F001031374474B02F5E3525D | ||||
| :401380001F700B3203F8946C1378054603F07F031370002001F0EAFA2378404A03F0F90323701378384603F0DF03137023783B43237001F0DBFA282001F0D8FA384B304625 | ||||
| :4013C0001A7802F07F021A701A7802F0BF021A7023783343237001F0C9FA2378314A43F0040323700023137053702F4AFF2199540133092BFBD1284601F0CAFE07211720AB | ||||
| :4014000001F0FCFA2949172001F0EAFA0721182001F0F4FA2649182001F0E2FA0721152001F0ECFA2349152001F0DAFA0721052001F0E4FA2049052001F0D2FA0721062045 | ||||
| :4014400001F0DCFA1D49062001F0CAFA0721084601F0D4FA1A49072001F0C2FA0721082001F0CCFA1749082001F0BAFA0021162001F0C4FA1449162001F0B2FA07210C203A | ||||
| :4014800001F0BCFABDE8F84010490C2001F0A8BAA5430040944300409D60004012600040F851004084600040ED92FF1F2B1D0000651B0000291D00005D1C0000891C00002C | ||||
| :4014C000B91C0000F11C0000311D0000A51D0000214B224A10B5187000231370204A40201370204A0F2413701F4A13701F4A13701F4A13701F4A13701F4B4FF400021A60E9 | ||||
| :401500004FF080721A604FF400121A6020221A601860802018604FF480701860174804704FF480001860164B1A70933B19B91A7802F0FE0202E01A7842F001021A70114B8E | ||||
| :4015400003221A70802203F8202C012001F014FE0D4B04221A7010BD0893FF1F0E93FF1F0C93FF1F0D93FF1F0993FF1FF892FF1F0B93FF1F8093FF1F00E100E09E60004099 | ||||
| :401580009C600040286000401260004070B5074C054623780E461BB9FFF7E0FE0123237031462846BDE87040FFF792BFB892FF1F0A4A002313700A4A13700A4A13700A4A7F | ||||
| :4015C00013700A4A13700A4A13700A4A13700A4B03221A70802203F8202C70470E93FF1F0C93FF1F0D93FF1F0993FF1FF892FF1F0B93FF1F8093FF1F28600040014B187812 | ||||
| :40160000704700BF0D93FF1F044B1A7802F0FF001AB118780022C0B21A7070470C93FF1F024A0C2303FB0020407870471493FF1F431E072B0CD8074A064B00010344805CAD | ||||
| :401640005B7800F00F0043EA0020023880B2704700207047FC5F00401A4A38B50C2303FB00231B79090C13F0800F00F1FF35044619BF8AB24FF480438BB24FF48042032DDF | ||||
| :4016800018D8DFE805F002070C110021084601F01BF80DE00021084600F0FAFF08E00021084600F0D9FF03E00021084600F0B8FF054B1855EDB2072D03D801F0EDF8034BF9 | ||||
| :4016C000185538BD1493FF1FE492FF1FED92FF1F431E072B2DE9F0470446894615465CD82F4F0C2202FB0072D388DFF8B8A09BB2C3F500739D424FF00C0303FB007388BF08 | ||||
| :40170000D588DB7884BFC5F50075ADB2254A43EA15230601B354B244EBB28AF80130224B1A5C9846FF2A01D1FFF796FF0C2303FB047200215170B9F1000F28D03DB31B4F29 | ||||
| :40174000385D01F011F811232946FE2218F8040001F0D6F806F5C04278321FFA89F118F8040001F0DFF8124D18F80410385D01F04BF80121385D00F0E1FF735D43F0020353 | ||||
| :401780007355735D03F0FD037355BDE8F08703FB04746379DBB28AF80230BDE8F08700BF1493FF1FFC5F0040ED92FF1FE492FF1F706000402DE9F0470446154688460029C2 | ||||
| :4017C00040D0431E072B3FD8FFF732FFA84203D22046FFF72DFF05461D4E335DFF2B03D141462046FFF738FFDFF868A027011AF8040000F0B9FF1223FE222946305D01F05C | ||||
| :401800007FF807F5C0411FFA88F27831305D01F089F8DFF84490315D1AF8040000F0F4FF01211AF8040000F089FF17F8093043F0020307F8093017F8093003F0FD0307F825 | ||||
| :40184000093002E00D4600E000252846BDE8F087ED92FF1FE492FF1F70600040431E072B0AD8064A0C2303FB002300225A705A79034BD2B200011A54704700BF1493FF1FDA | ||||
| :40188000FE5F0040431E072B9FBF024B000108221A547047FE5F004030B51A4A1A491B4D0878138803449BB21380194A00231488D8B2A4B27CB1082B0CD050680078C0B22A | ||||
| :4018C000E85450680133013050601088013880B21080ECE718460B780E4C082B0E4A00D040B10E4D2B7883F080032B700F232370022301E0022323701370094B1870087009 | ||||
| :4019000030BD00BF8493FF1F8093FF1F00600040FC92FF1FF992FF1F0E93FF1F0A93FF1F8193FF1F074B02221A70074B80221A70064B0F221A70064A00231370054A012004 | ||||
| :40194000137070470E93FF1F0A93FF1FF992FF1F8093FF1F8193FF1F30B5164B16491B780A8803F00F03023BDBB21A4492B20A80124C134A0020118889B279B173B1556828 | ||||
| :40198000215C013BC9B229705168DBB20131516011880130013989B21180ECE7094A1370094A137883F080031370084B0B221A7030BD00BF296000408493FF1F006000400D | ||||
| :4019C000FC92FF1F8193FF1F0A93FF1FF992FF1F064A06231370064A01201370054B80221A70054B00221A70704700BF0E93FF1FF992FF1F0A93FF1F8193FF1F054B9A6820 | ||||
| :401A00003AB19A68044910709A680988518000229A607047FC92FF1F8493FF1F08B5124B1A78D2B21A701B78DBB21A0602D50F4A137008BD0220FFF7E1FF0D4B1B7803F08C | ||||
| :401A40006003202B05D0402B06D043B900F012FC04E001F0A1FB01E000F046FD10B9034B03221A7008BD00BF28600040F992FF1F0060004008B5084A084B01201978138819 | ||||
| :401A80000B449BB21380064B00221A70FFF7B6FF044B03221A7008BD8493FF1F8093FF1F0E93FF1FF992FF1F08B50C4B1B78DBB2042B07D0062B09D0022B0DD1BDE8084082 | ||||
| :401AC000FFF7D8BFBDE80840FFF746BF0320FFF795FF034B03221A7008BD00BF0E93FF1FF992FF1F08B5054B002201201A70FFF785FF034B03221A7008BD00BF0E93FF1F47 | ||||
| :401B0000F992FF1F08B50A4B1A7832B11A78094942F080020A7000221A70074B002201201A70FFF76BFF054B03221A7008BD00BFF892FF1F086000400E93FF1FF992FF1FFD | ||||
| :401B4000074B1B78DBB2042B05D0062B05D0022B05D1FFF7A1BEFFF7C5BFFFF7D3BF70470E93FF1F38B51D4C2378DBB2DD0634D518060AD503F00F03012B2ED1FFF74EFF3F | ||||
| :401B8000174B1B78190609D538BD5A0602D5FFF7D7FF03E09D0620D5FFF786FF23781B061BD4104B1A78104B1B7813430F4A13701278934211D10A4A084915461378207829 | ||||
| :401BC000DBB2000605D41378DBB20B700B7803F00F0328788342F1D138BD38BD28600040F992FF1F0A93FF1F8193FF1F29600040054A00231380054A916819B191680B709B | ||||
| :401C000092685380704700BF8493FF1FFC92FF1F0E4808B503889BB213B9FFF783FE13E00B4B02221A700B4B00221A70FFF7E0FF094AD1799379028843EA012392B29342E7 | ||||
| :401C400038BF0380FFF728FE012008BDFC92FF1F0E93FF1F0A93FF1F00600040084B01221A700F3B9B7C074B1A7B02F00302012A1EBFDA7B82F08002DA7301225A7370479E | ||||
| :401C80000B6000401493FF1F094B02221A700F3B93F82230074B1A7E02F00302012A1EBFDA7E82F08002DA7601225A76704700BF0B6000401493FF1F0B4B04221A700F3BDD | ||||
| :401CC00093F83230094B93F8242002F00302012A1EBF93F8272082F0800283F82720012283F82520704700BF0B6000401493FF1F0B4B08221A700F3B93F84230094B93F854 | ||||
| :401D0000302002F00302012A1EBF93F8332082F0800283F83320012283F83120704700BF0B6000401493FF1F7047FFF741BC0000F0B5184B184E19780C27C9B201234FF025 | ||||
| :401D4000000C31B3CA0720D5144A4FEA031E7244947850782040C5070DD507FB03652C79240608D5147804F0FE0414706D790C4CEDB204F80E50840706D507FB036425799D | ||||
| :401D80002D0658BF84F801C090700133DBB24908D7E7F0BD9F6000401493FF1F70600040FE5F004000F0ACBC70B50446184B88B003AA03F11006154618685968083303C5B6 | ||||
| :401DC000B3422A46F7D11B782B70FCB12223237001AD03232846637000F08AFE002220461146AB5C08AC04EB131414F8144C03F00F03847008AC234413F8143C0132082A86 | ||||
| :401E0000C1700371417100F10400EAD108B070BD6F3C00002DE9F0431C4D01222E460C201F274FF0800E4FF0080C194B00FB02581401234418705F70164998F805902144BB | ||||
| :401E4000B9F1000F07D098F8044024064CBF887081F802C001E081F802E000FB0261CC880132E4B29C71CC88092AC4F30724DC71CC88E4B21C71C988C1F307215971D4D109 | ||||
| :401E8000054BFF221A70BDE8F08300BF1493FF1F70600040FC5F00400A600040064B074A1B7802EBC30253681A7C824286BF03EBC0035869002070470893FF1FD03C0000E7 | ||||
| :401EC0002DE9F84F424B1A78002A7ED01878414D0138C0B2FFF7E2FFA8463F4AC3681478007ADFF800C1E4B203EBC0000C2600274FF0010E834268D01A78A24263D11CF868 | ||||
| :401F00000420597891425ED19A7893F8039002F07F0206FB02FA05EB0A01CF7093F802B009F0030981F804B093F803B005F80AB0B3F804A0A1F808A093F902A0BAF1000FF4 | ||||
| :401F40000BDAB9F1010F0CBF4FF007094FF00D0981F8059081F801E009E0B9F1010F0CBF4FF005094FF0090981F805904F704FEA02191A4906FB0282494481F802E0B2F844 | ||||
| :401F800008A0CAF3072A81F800A0B2F808A05FFA8AFA81F801A0B2F806A011495FFA8AFA494481F806A0B2F80690C9F3072981F80790B2F806905FFA89F981F80490D28838 | ||||
| :401FC000C2F307224A71083394E7BDE8F88F00BF0D93FF1F1493FF1F0993FF1FFC5F004070600040FA92FF1F08B5064B18780138C0B2FFF753FF20B143681B7900EBC300C6 | ||||
| :40200000406908BD0D93FF1F00212DE9F84F0B464E4E0C2707FB01F401313219092933554FF000059370494CD3701381937253705371EFD118B1464B1D70464B1D70464B13 | ||||
| :402040001A78002A7FD0187801250138C0B2FFF725FFA8464368DFF8F8E0DB790C2713F0400F3E4B4FF0000C1A7814BF42F0010202F0FE021A70027AD20007FB0541C3680E | ||||
| :4020800003EB02094B4531D093F802A00AF07F06AE4229D10E89B3F804B0B6B25E4538BFA1F808B01E7893F801B01EF80660B3451AD181F804A0DE780E7093F902A0DE7811 | ||||
| :4020C000BAF1000F06F0030607DA012E0CBF07260D264E7181F8018006E0012E0CBF052609264E7181F801C00833CBE70135092DC3D1C1680A328B1C0A440C20083393427D | ||||
| :4021000009D013F8081C13F80A5C01F07F0100FB01418D72F2E7FFF767FF114B0121186000230C2000FB0142D3801289013113449BB203F00102134409299BB2F2D1BDE8C9 | ||||
| :40214000F84FFFF767BEBDE8F88F00BF1493FF1FFA92FF1F8293FF1F0D93FF1F0B93FF1F1093FF1F114B1B7903F07F035A1E072A19D80F490C2202FB031291781B0141F048 | ||||
| :40218000010191700021D170517841F002015170127912F0800F074A1A4414BF8D2389239370FFF715BC0020704700BF006000401493FF1FFC5F004030B4194B1A7902F0D5 | ||||
| :4021C0007F02531E072B27D8164B0C2404FB02339978154D01F0FE0199700021D97029461201505D114400F07F0050555A7802F0FD025A701A795B78120605D5012B01D1A6 | ||||
| :402200008C7006E00D2303E0012B0CBF082309238B7030BCFFF7DCBB002030BC704700BF006000401493FF1FFC5F004010B50D4B0D4C21791878C9B20138C0B2FFF72EFE7D | ||||
| :4022400043681B798B4201D2012909D8074A0848535CDBB24354A3780120DBB2535410BD002010BD0D93FF1F00600040FA92FF1F8293FF1F38B58A4A8A4C13780021DBB2CB | ||||
| :4022800021801806517840F18D800A2900F20581DFE811F05D00030103010301030103010B0003017E0003018200D3787C49012B09D17D4B1A787D4B03EBC2035B685B68F0 | ||||
| :4022C0006360122310E0CB78022B12D18878FFF7E5FD002800F0E180436863606368DA7863689B7843EA02232380BDE83840FFF78FBCCB78032B26D16D4B00228878D5B2CD | ||||
| :40230000854209D3664A91786A4AEE2908BF1346634A917881B106E0187801320028F1D018780344EAE764499278097C914203D16248FFF739FD614B1A78002A00F0AD80F6 | ||||
| :402340001A78228018E0BDE8384000F025BF13F0030313D0022B40F0A0802380504B0C211B7903F07F02564B01FB02339A78554BD2B21A7000225A706360B6E702222280C0 | ||||
| :40238000514A11784F4AC9B2117053706260ACE7012323804D4BEFE70123238013794C4A1344E9E701390A2977D8DFE801F037764F76067676760A7620009378454ADBB2F2 | ||||
| :4023C0005AE0937803F0FF0153B9404B1A7891425FD01970404B01201870FFF715FE58E0481EC0B2FFF75AFD0028EED155E0FFF71DFF002851D02A4A384913791279DBB247 | ||||
| :40240000D2B20A70364A3249D25CCB5C9A4240D0314B01221A70FFF753FD3AE003F00303012B2BD009D3022B37D11D4B9B78002B33D1BDE83840FFF7BFBE194B9B78012BCB | ||||
| :402440002BD1214A137803F0FD0315E003F00303012B13D008D3022B1FD1114B9B78E3B9BDE83840FFF77EBE0D4B9B78012B14D1154A137843F0020313700AE0084B1A7937 | ||||
| :402480005AB998781B791749DBB2CA5C22EA0002CA54BDE83840FFF79BBA002038BD00BF00600040FC92FF1F0893FF1FD03C0000343D0000BC3C0000A73D0000A093FF1F3B | ||||
| :4024C0001493FF1FB992FF1F0B93FF1F0D93FF1FFA92FF1FF892FF1F0C93FF1F0993FF1F8293FF1F0F93FF1F074B1A78120609D55B78012B06D1054B054A5A6012781A804B | ||||
| :40250000FFF786BB0020704700600040FC92FF1F943C0000014B1870704700BF7F640040014B1878704700BF69640040014B1870704700BF78650040064A0123136002F65F | ||||
| :4025400088321268E0211064034A1170A2F540721360704780E100E000E400E0014B1870704700BF72640040014B1870704700BF7665004073B515461E460B4C052300221F | ||||
| :40258000019200920A4601461846237000F064F932462946207800F01FF90221207800F009F9207802B070BDD080FF1F064A0423136002F688321268E0219064034A11702F | ||||
| :4025C000A2F202321360704780E100E002E400E0014B04221A60704700E100E0014B04221A60704780E100E0014B1870704700BF78640040704738B505460078012428B1CF | ||||
| :4026000000F062FD285D0134E4B2F8E738BD08B50D2000F059FDBDE808400A2000F054BDF7B516461F460B4C00230325019300930A4601462846257000F00EF93A46314621 | ||||
| :40264000207800F0C9F80221207800F0B3F8207803B0F0BDE080FF1FF7B516461F460B4C00230225019300930A4601462846257000F0F2F83A463146207800F0ADF8294609 | ||||
| :40268000207800F097F8207803B0F0BDE180FF1FF7B516461F460B4C00230125019300930A4601462846257000F0D6F83A463146207800F091F80221207800F07BF8207842 | ||||
| :4026C00003B0F0BDE280FF1F73B515461E460B4C0023019300930A4601461846237000F0BBF832462946207800F076F80221207800F060F8207802B070BD00BFE380FF1FB0 | ||||
| :40270000024B1878C0F38010704700BF8F450040074A7F23802113705170064A013BDBB202F80839002BF9D1034A1370704700BFE480FF1FF87B00400078004017280FD875 | ||||
| :40274000084B0001C25C11B142F0200201E002F0DF02C254C25C42F00102C25400207047012070471070004017280BD8064B0001C25C02F0FE02C254C25C02F0DF02C2548E | ||||
| :4027800000207047012070471070004017280DD8074900010B4603441A7942F004021A71435C43F00103435400207047012070471070004017280BD8064A0001835C4900D0 | ||||
| :4027C00003F0F10301F00E011943815400207047012070471070004041F6FF73994208BF4FF400519A4208BF4FF4005217289FBFC00000F1804000F5EC4081809ABFC28070 | ||||
| :40280000002001207047000017289FBF034B00011954002088BF0120704700BF1970004017289FBF054B00011A5C01F007019DBF1143195400200120704700BF147000408B | ||||
| :4028400017289FBF034B0001185C00F0070088BFFF20704714700040172810B51AD8C00001F07F0100F1804441EAC21204F5EC44D2B222709DF8082003F00F0343EA021302 | ||||
| :40288000DBB263709DF80C30002003F00F03A370E07010BD012010BD10B500F075FC0A4A5378182B0AD91478013B5370E30003F1804303F5F0431B78137000E0FF2400F0E0 | ||||
| :4028C00067FC204610BD00BFE480FF1F030610B5044611D400F058FC084AE300117803F1804303F5F04319705378147001335370BDE8104000F04CBC10BD00BFE480FF1F56 | ||||
| :4029000030B504060CD411F4704509D1C40004F1804404F5F0442180A270E370284630BD012030BD03065FBFC00000F1804000F5F04081805ABFC28000200120704700000A | ||||
| :4029400038B50446084DB4F5004F05D9286800F013FCA4F50044F6E7034B58686043BDE8384000F009BC00BFEC80FF1F024B1B7A584300F001BC00BFEC80FF1F0E4B00F024 | ||||
| :4029800003001A78490102F0FC02104318701A7801F0600142F080021A701A7802F07F021A701A7802F09F020A431A701A7842F010021A70704700BF83430040014B012275 | ||||
| :4029C0001A70704784430040044B00F00F021B6853F8220043F82210704700BF08ED00E0054A00F01F00126800F1100352F8230042F82310704700BF08ED00E000F01F0087 | ||||
| :402A000000F16040490100F56440C9B2017070470F4B10B50F4900240F205C609C60DC601C615C61FFF7D0FF0B4A136843F0040313600A4B4FF47A72DB68B3FBF2F3084A99 | ||||
| :402A40001360084B4FF400421C60C3F8E82010BDBC92FF1FBD2A000010E000E0EC80FF1F14E000E018E000E0024A136843F002031360704710E000E008B5FFF7F5FF034AB9 | ||||
| :402A8000136843F00103136008BD00BF10E000E010B5054CA3691BB9FFF7BAFF0123A361BDE81040FFF7E8BFBC92FF1F024B1868C0F30040704700BF10E000E038B5FFF7E9 | ||||
| :402AC000F5FF012808D1054D002455F8243003B198470134052CF8D138BD00BFC092FF1F024B03EB8003586859607047BC92FF1F134B144A1B78DBB20360127843EA02236E | ||||
| :402B0000114A0360127843EA0243104A0360127843EA026303600E4B0E4A1B78DBB24360127843EA02230C4A4360127843EA02430A4A4360127843EA02634360704700BF2E | ||||
| :402B40000301004904010049EC460040020100490101004900010049050100490601004910B500F011FB204A044613780A2043F002031370137C43F00203137412F80A3C45 | ||||
| :402B800043F0010302F80A3C937943F00103937102F5AB52137843F003031370134B18221A7013F8012C42F0400203F8012C13F8012C02F0FC0203F8012CCE2203F8062CB9 | ||||
| :402BC000A3F597530222183B1A70094A137843F008031370FFF7CAFE064B10222046BDE810401A6000F0D4BAAB4300400E5900402F5B004080E200E008B500F0C5FA0F4A79 | ||||
| :402C0000137803F0FE031370A2F5AA521D3A137803F0FD031370137C03F0FD03137412F80A3C03F0FE0302F80A3C937903F0FE039371BDE8084000F0ABBA00BF0859004074 | ||||
| :402C4000044A137803F03F0343EA8010C0B21070704700BF08590040082804D00A280CBF8223C22300E0422308380E4AC0B20428137098BF0C4B4FF0000298BF33F9101065 | ||||
| :402C80000A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B1A8070470A590040803C00008A93FF1F8C93FF1F9093FF1F08B5102000F0A6F926 | ||||
| :402CC00007210420FFF79AFE07490420FFF788FE064A0C20137843F006031370FFF7BCFF034B00221A8008BDB12D0000095900408893FF1F10B5054C23781BB9FFF7DCFFB5 | ||||
| :402D000001232370BDE81040FFF72ABFD892FF1F044B1A7802F0FB021A701A7842F001021A7070470859004010B5084B1C7814F0010403D10028F9D0002404E02046FFF79F | ||||
| :402D400015FE024B1B78204610BD00BF09590040034A044B1B881088181A00B2704700BF9093FF1FA25B00400E4A13881BB223B111880A2309B2594301E00B4B19680B4B5E | ||||
| :402D80001B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270478A93FF1F8C93FF1F8893FF1F7047000010B500F0E7F9214A04461378DE | ||||
| :402DC0000A2043F001031370137C43F00103137412F80A3C43F0020302F80A3C937943F00203937102F5AA521832137843F003031370144B18221A7013F8012C42F040023F | ||||
| :402E000003F8012C13F8012C02F0FC0203F8012CCE2203F8062CA3F597530222123B1A70094A137843F008031370FFF79FFD074B08222046BDE810401A6000F0A9B900BFED | ||||
| :402E4000AB43004006590040275B004080E200E008B500F099F90F4A137803F0FE031370A2F5AA52153A137803F0FE031370137C03F0FE03137412F80A3C03F0FD0302F8BC | ||||
| :402E80000A3C937903F0FD039371BDE8084000F07FB900BF00590040044A137803F03F0343EA8010C0B21070704700BF00590040082804D00A280CBF8223C22300E04223C0 | ||||
| :402EC00008380E4AC0B20428137098BF0C4B4FF0000298BF33F910100A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B1A8070470259004092 | ||||
| :402F00008A3C00009693FF1F9C93FF1F9493FF1F08B5102000F084F807210320FFF76EFD07490320FFF75CFD064A0C20137843F006031370FFF7BCFF034B00221A8008BDE5 | ||||
| :402F400009300000015900409893FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040FFF728BFD992FF1F044B1A7802F0FB021A701A7842F001021A70704700590040D2 | ||||
| :402F800010B5084B1C7814F0010403D10028F9D0002404E02046FFF7E9FC024B1B78204610BD00BF01590040034A044B1B881088181A00B2704700BF9493FF1FA05B004031 | ||||
| :402FC0000E4A13881BB223B111880A2309B2594301E00B4B19680B4B1B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270479693FF1FD3 | ||||
| :403000009C93FF1F9893FF1F70470000034A00F0F800137803431370704700BF02410040034A00F0F800137803431370704700BF06410040014B1870704700BF76640040D7 | ||||
| :40304000014B1870704700BF7C64004073B515461E460B4C04230022019200920A46014618462370FFF7F8FB324629462078FFF7B3FB02212078FFF79DFB207802B070BDE6 | ||||
| :40308000FC80FF1F074A0223136002F688321268E0215064044A11706FF440710A441360704700BF80E100E001E400E0014B1870704700BF74650040014B1870704700BFDF | ||||
| :4030C0007764004000000000FEB5494652465B460EB40746244909688A46244A12682448022100F071F8030020480068C018204900F06AF8143883460121C9430C4601258C | ||||
| :40310000002600F041F8814651460B7823400B705846013000F030F83800F04028400B78234003430B70584600F026F80136072EF2D9002001300138013001200B7823407E | ||||
| :4031400003430B705846043000F016F8484600F01FF800BF00BF00BF0EBC894692469B46FEBD00BFAFF30080D480FF1FF880FF1F00C20100000000000230800803D000BFE7 | ||||
| :4031800001380046FCD17047EFF3108072B6704780F31088704700BF094A137803F00303012B0AD0022B09D113790C2103F07F02044B01FB02339B7A00E013790020704751 | ||||
| :4031C000006000401493FF1F002902D0B0FBF1F0704708B14FF0FF3000F008B80029F8D00246B0FBF1F000FB11217047704700BF014B1868704700BF6081FF1F0E4B70B577 | ||||
| :403200001E460E4C0025E41AA410A54204D056F8253098470135F8E700F0E2FD084B094C1E46E41AA4100025A54204D056F8253098470135F8E770BDEC3D0000EC3D000024 | ||||
| :40324000EC3D0000F43D000003460244934202D003F8011BFAE7704730B5141E05469BB0184604DA8B232B604FF0FF301DE04FF40273ADF80C300CBF234604F1FF330293F9 | ||||
| :4032800005934FF6FF7300910491ADF80E3002461E9B6946284600F073F8431CBCBF8B232B6014B1009B00221A701BB030BD000007B5009313460A46014603480068FFF77E | ||||
| :4032C000CBFF03B05DF804FB6081FF1F2DE9F0478E6882469E420C46914698463ED88A8912F4906F3AD02568096902236F1A656905EB450595FBF3F57B1C43449D4238BFB3 | ||||
| :403300001D4653050FD5294600F04AFB064698B13A46216900F0D2FAA38923F4906343F08003A38113E02A4600F098FB064670B92169504600F0E8FA0C23CAF80030A38945 | ||||
| :403340004FF0FF3043F04003A381BDE8F08726613E44266046466561ED1BA560464528BF464649463246206800F0B3FAA36800209B1BA36023681E442660BDE8F08700009E | ||||
| :403380002DE9F04F9DB003938B8980461C060D4616460DD50B695BB9402100F001FB2860286118B90C23C8F80030CDE040236B610023099320238DF82930DFF89CB130233F | ||||
| :4033C0008DF82A3037463C4614F8013B1BB9B7EB060910D003E0252BF9D02746F3E74B46324629464046FFF771FF013000F0A780099B4B4409933B78002B00F0A080002373 | ||||
| :403400004FF0FF3204930793059206938DF853301A930126052221784E4800F041FA671C049B38B14B4A3C46801A06FA00F018430490EFE7D90644BF20228DF853201A07B0 | ||||
| :4034400044BF2B228DF8532022782A2A03D0079A00210A200BE0039A111D12680391002A10DA524243F00200079204900BE027463B780134303B092B03D800FB023201217E | ||||
| :40348000F5E701B107923B782E2B1ED17B782A2B0AD1039B02371A1D1B680392002BB8BF4FF0FF33059310E0002319460593781C0A2407463A780130303A092A03D804FB83 | ||||
| :4034C00001210123F5E703B1059103223978224800F0E6F940B14023CBEB000003FA00F0049B013718430490397806221B487E1C8DF8281000F0D4F988B1194B33B9039B1D | ||||
| :40350000073323F007030833039314E003AB00932A46144B04A94046AFF3008007E003AB00932A460F4B04A9404600F093F8B0F1FF3F824603D0099B5344099342E7AB89BC | ||||
| :403540005B0601D4099801E04FF0FF301DB0BDE8F08F00BFBB3D0000C13D0000C53D000000000000CD3200002DE9F04791461F460A698B6806469342B8BF1346C9F80030AD | ||||
| :4035800091F843200C46DDF8208012B10133C9F800302368990642BFD9F800300233C9F80030256815F0060510D104F1190A07E00123524639463046C04701301AD0013598 | ||||
| :4035C000E368D9F800209B1A9D42F1DB94F843302268003318BF012392060FD5E118302081F843005A1C94F845102244023382F8431003E04FF0FF30BDE8F08704F1430291 | ||||
| :4036000039463046C0470130F4D02268D9F80050E36802F00602042A08BF5D1B2269A3680CBF25EAE57500259342C4BF9B1AED184FF000091A344D4509D00123224639462F | ||||
| :403640003046C0470130D5D009F10109F3E70020BDE8F0872DE9F04317460A7E85B06E2A984606460C460C9B01F1430E00F0AE8011D8632A22D009D8002A00F0BB80582A3E | ||||
| :4036800040F0CA8081F84520834955E0642A1ED0692A1CD0C0E0732A00F0B08009D86F2A2ED0702A40F0B8800A6842F020020A603EE0752A24D0782A3AD0ADE01A6801F151 | ||||
| :4036C0004205111D1960136884F84230A8E021681A6811F0800F02D0111D196008E011F0400F02F10401196002D0B2F9003000E01368002B3CDA2D225B4284F8432037E003 | ||||
| :4037000021681A6811F0800F02D0111D196007E011F0400F02F10401196001D0138800E01368227E5C496F2A14BF0A2208221BE078225A4984F845202268186812F0800F4B | ||||
| :4037400000F104051D6003D1550601D5038800E00368D00744BF42F0200222601BB9226822F0200222601022002084F8430001E049490A226568002DA56008DB206820F009 | ||||
| :40378000040020602BB9002D7DD175460CE0002B79D07546B3FBF2F002FB1033CB5C05F8013D03460028F5D1082A0BD12368DA0708D5236962689A42DEBF302305F8013C34 | ||||
| :4037C00005F1FF35C5EB0E0323612EE008681A6810F0800F496903D0101D1860136808E010F0400F02F104001860136801D0198000E0196000232361754616E01A68111D3A | ||||
| :403800001960156800216268284600F049F808B1401B6060636804E004F1420584F8422001232361002384F84330CDF800803B4603AA21463046FFF797FE013002D14FF093 | ||||
| :40384000FF3026E023692A4639463046C0470130F5D023689B0710D5002504F1190907E001234A4639463046C0470130E7D00135E368039A9B1A9D42F2DBE068039B984219 | ||||
| :40388000B8BF184605E00B7804F1420584F842308AE705B0BDE8F0836F3C0000CC3D000010B5C9B202449042034605D01C7801308C42F8D1184610BD002010BD10B5431E9F | ||||
| :4038C0000A44914204D011F8014B03F8014FF8E710BD884210B501EB020301D8421E0BE09842FBD28118D21AD34204D013F8014D01F8014DF8E710BD994204D011F8014B7E | ||||
| :4039000002F8014FF8E710BD38B50546002944D051F8043C0C1F002BB8BFE41800F0D4F81E4A1368114613B96360146030E0A3420DD92268A018834201BF18685B681218C2 | ||||
| :40394000226063600C6023E0A24203D813465A68002AF9D118681918A1420BD12168014458188242196013D110685268014419605A600DE002D90C232B6009E021686018E0 | ||||
| :40398000824201BF106852680918216062605C602846BDE8384000F098B838BDE092FF1F70B5CD1C25F0030508350C2D38BF0C25002D064601DBA94202D90C23336046E015 | ||||
| :4039C00000F082F8234B1C681A462146A1B10B685B1B0ED40B2B03D90B60CC18CD501EE08C420BBF63684B681360636018BF0C4615E00C464968E9E7174C23681BB9304696 | ||||
| :403A000000F052F820602946304600F04DF8431C18D0C41C24F00304A0420DD12560304600F053F804F10B00231D20F00700C31A0ED05A42E25070BD211A304600F034F8A0 | ||||
| :403A40000130EBD10C233360304600F03EF8002070BD00BFE092FF1FDC92FF1FF8B5074615460E4621B91146BDE8F840FFF798BF1AB9FFF749FF2846F8BD00F027F88542C5 | ||||
| :403A80000ED929463846FFF78BFF044650B131462A46FFF713FF31463846FFF735FF01E03046F8BD2046F8BD38B5064C0023054608462360FDF7DCFB431C02D1236803B178 | ||||
| :403AC0002B6038BDC493FF1F7047704751F8040C0028BEBF091851F8043CC0180438704700000000050209020B020D020F021102130215027265706C79203078253032787F | ||||
| :403B000000686F6D696E6700626567696E6E696E67207365656B2066726F6D20256420746F2025640066696E6973686564207365656B00796573006E6F00647269766520E7 | ||||
| :403B4000303A20257320647269766520313A2025730057616974696E6720666F72205553422E2E2E0055534220726561647900636F6D6D616E64203078253032780066614C | ||||
| :403B8000696C2025642B25642B2564203D3D2025642C206E6F74202564007061737365643D256400756E64657272756E206166746572202564207061636B65747300636F25 | ||||
| :403BC000756E743D256420693D256420643D256400636D645F777269746500646F6E6520256420256400703D25642063723D25642063773D256420663D256420773D2564FF | ||||
| :403C000020696E6465783D256420756E64657272756E3D25640077726974652066696E69736865640073746172742065726173696E670073746F702065726173696E670092 | ||||
| :403C400069646C650000510040100040510040300000000140001000140140000800400140000A004C014000020050014020003031323334353637383941424344454600E9 | ||||
| :403C8000000100000004000000100001000000040000001028000000000104000100000000000000000157494E5553420000303030303100000000000000000012034D0080 | ||||
| :403CC0005300460054003100300030000100000001000000D83C000001000000A73D0000000000000000000001000000F03C000001000000793D000004000000123D000014 | ||||
| :403D0000000000000000000000000000103D0000FF00000001024000FF00000082024000FF00000003034000FF00000084034000FF00020304030904160346006C007500CE | ||||
| :403D4000780045006E00670069006E0065002A0343006F0077006C00610072006B00200054006500630068006E006F006C006F0067006900650073000009022E0001010036 | ||||
| :403D800080320904000004FF00000107050102400000070582024000000705030340000A0705840340000A12010002FF0001080912006E0100020180014300232D302B20AF | ||||
| :403DC00000686C4C00656667454647003031323334353637383961626364656600000000F8B500BFF8BC08BC9E46704759000000ED120000F8B500BFF8BC08BC9E467047E7 | ||||
| :403E000035000000183E0000C880FF1FA0000000601200000000000000000000C893FF1FFF000000675000400C00000007000000FFFFFFFF7F8000003F0000000000007D46 | ||||
| :403E400000FA0000400000000090D003FF0000000000000000000000000000000000000000000000000000000000000000000000B93D0000000000000000000000000000B0 | ||||
| :403E80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081FF1F00000000000000000000000063 | ||||
| :4000000000800020110000009D1000009D100000064A08B5136843F020031360044B1A6803F53F5302331A6001F056F8E8460040FA46004010B5054C237833B9044B13B17D | ||||
| :400040000448AFF300800123237010BD6881FF1F00000000E8380000084B10B51BB108490848AFF300800848036803B910BD074B002BFBD0BDE81040184700BF0000000021 | ||||
| :400080006C81FF1FE8380000C880FF1F000000000A4A0B4B116801310B40002BBEBF03F1FF3363F03F030133136011685368994202BF024B01221A72704700BF8881FF1F9C | ||||
| :4000C0003F0000800A4A0B4B516801310B40002BBEBF03F1FF3363F03F030133536051681368994202BF024B01221A72704700BF8881FF1F3F000080114BDA68196919B9FD | ||||
| :4001000001221A75597514E09969521A19698A4294BF587D00201875187D094908B1002204E0086982428CBF002201224A75DA689A611B7D13B1002002F056B9704700BF60 | ||||
| :400140008881FF1F10B5C4B2204601F087F90128FAD110BD08B572B60F4B0F49DA680132DA60DA690132C82A08BF0022DA611A6AD8690132A72A08BF00220A621B6A002BE5 | ||||
| :400180000CBF02230023002814BF184643F0010002F092FE62B608BD8881FF1F38B50446C5B2284602F0C2F8062002F0DFFA44F00200C0B202F0BAF8062002F0D7FA2846BD | ||||
| :4001C00002F0B4F8BDE83840062002F0B9BA10B5642402F0A5F828B9FFF7E0FF013CF8D1204610BD012010BD70B5C4B2054620460E4601F033F9012805D0204601F04CFAA8 | ||||
| :400200002846FFF79FFF204601F030F9314605460246204601F0ECF9204601F01FF90028FAD1284670BD000038B5044D0024285D013402F04BFA402CF9D138BDAC81FF1F30 | ||||
| :4002400008B502F065FC002002F06EFC02F080FC02F08AFC80B208BD10B50446012002F07DF8642002F06CFAFFF7EAFF2080002002F074F8642002F063FAFFF7E1FF60801C | ||||
| :4002800010BD08B502F070FD002002F079FD02F08BFD02F095FD80B208BD10B50446FFF796FF322002F04CFAFFF7EBFF20800120FFF774FF322002F043FAFFF7E2FF608072 | ||||
| :4002C00010BD0FB400B593B014AB53F8042B402102A8019302F0F0FE02A802F08CF802F096F813B05DF804EB04B0704710B5044601780648FFF7E5FF0420FFF723FF6278E6 | ||||
| :400300002146BDE81040042001F000B9043A000007B50023ADF804308DF80600032301A88DF80530FFF7E2FF03B05DF804FB000010B5074C94F8643043B1002001F0EAFF85 | ||||
| :40034000002002F07DFD002384F8643010BD00BF8881FF1F38B5124D837895F8672004469A4204D0FFF7E4FF002385F86A302368C5F8653022790B4B1A71A378002B14BF31 | ||||
| :400380000220012002F05CFDE078B0FA80F0400902F050FD2079BDE8384002F087BD00BF8881FF1FED81FF1F38B50D4C94F8645065B904F16500FFF7CDFF012001F0AAFFDC | ||||
| :4003C0004FF47A7002F0BCF984F86A50E368E366012384F86430BDE8384002F0EFB900BF8881FF1FF8B5214C0546FFF7DDFF94F86A3003B15DB91E48FFF763FFFFF7E7FECE | ||||
| :400400000120002384F86A00236702F0AFF92A46216F1848FFF755FF144E0027236F9D4216D001F07DFF00B13767236F9D4205DD0120FFF7B3FE336F013305E005DA002053 | ||||
| :40044000FFF7ACFE336F013B336702F0B7F9E5E7322002F075F92A2DCCBF0020012002F031FDBDE8F8400448FFF72BBF8881FF1F113A0000183A0000353A00002DE9F04F70 | ||||
| :4004800099B062B602F004FA9E49042002F028FA9D4801F051FF9D4802F0F4FC9C4801F085FF02F0D5FB02F0A7FA002002F0C8FC01F0A0FF0221002000F086FF954C012011 | ||||
| :4004C00001F0FEF8002384F86730FFF76DFFFFF77EFE84F87400FFF72BFF012384F86730FFF762FFFFF773FE84F87500FFF720FF894B94F87400894994F875202546002AA4 | ||||
| :4005000014BF0A461A46002808BF19468448FFF7D8FE0321084602F031F9264602F04EF994F8643043B1EA6EEB689B1A41F28832934201D9FFF7FCFE00F07EFF18B9794820 | ||||
| :40054000FFF7BFFE04E000F07DFF0028F7D10BE000F072FF10B902F031F9F9E77248FFF7B0FE032001F098F8032000F077FF0128D4D16E48FFF7EEFE6D490320FFF734FE85 | ||||
| :4005800094F876106B48FFF79CFE94F87630023B142B00F2D683DFE813F01500D4031E00D4032400D4035000D4037600D403D900D403C101D4030803D4032C03D40333036C | ||||
| :4005C000D4034D0303238DF820308DF821300F238DF822302AE394F87800FFF703FF564B21E340F2DC57FFF7DFFE00232375E068227D02F0FF012AB9EB681B1ABB42F7DD44 | ||||
| :400600000B4611E083B10022174696F87810F068277594F814E0BEF1000F02D1EB681B1AF7E701329142F3DA07228DF8202004228DF82120ADF82230F8E20220FFF782FD2F | ||||
| :400640004FF000080DF1200A02F0B8F84FF480790027C9EB0803DA1907F80A200137402FF9D10220FFF76EFD3A465146022000F04DFFB9F10109EBD108F10108B8F1400F58 | ||||
| :40068000E2D12E4B38E04FF0010A4FF000080DF1200B02F093F84FF0000959460120FFF7A3FD08EB090300270493049B1BF807203B44DBB29A4209D08DE80C0041463B4641 | ||||
| :4006C0004A461F48FFF7FDFD4FF0000A0137402FEBD109F10109B9F5807FDED108F10108B8F1400FD5D151461648FFF7EAFDBAF1000F00F01B81144B1B8807A8ADF81C30AD | ||||
| :4007000095E200BF55010000F900000091000000C50000008881FF1F473A0000433A00004A3A0000623A0000753A0000ED81FF1FFE81FF1F7F3A0000EC380000EE380000BE | ||||
| :400740008E3A0000AA3A0000F0380000206FFFF749FE94F8780001F001FE94F8780001F0E5FD02F015FCB94BDFF8FC821A78002702F0FB021A701A7842F001021A701A789D | ||||
| :4007800002F0FE021A701A7802F0FE021A7002F003FC0220FFF7D6FC012141F6FF734FF48042084602F052FB84F8B60001F074FF08F807000137402FF8D1DFF8B0A200271A | ||||
| :4007C0000AF195091FFA89F80137402F14BF3A4600221AF8010F2244062392F82420402101F08EFF424646F24B419AF8000001F099FF08F14008402F1FFA88F8E4D196F859 | ||||
| :40080000793053B196F87C30336100233375237D002BFCD000233375336100234FF0FF32236062602372236894F8B600234493F8241001F0E9FE94F8B60001F0A7FE01214A | ||||
| :4008400094F8B60001F07AFE2368002BFCD0002398467360D6F80CA0012701F0AFFFE368B4F87A20CAEB030393420DD367B1042195F8B60001F0D4FE94F8B60001F0E0FEE1 | ||||
| :400880000028F9D107463072237AFBB96A682B689A4202D1002FE0D118E00220FFF752FC6968402209EB8111022000F02FFE6A68674B01321340002BBEBF03F1FF3363F091 | ||||
| :4008C0003F03013308F101086360C6E70220277AFFF738FC00221146022000F017FE0220FFF730FCFFB2FFF79FFC002001F01EFD37B15848FFF7E5FC0220FFF709FD06E06E | ||||
| :40090000554B08A81B88ADF82030FFF7EFFC227D4146237A5148FFF7D4FC15E25048FFF7D0FCD4F87A7017F03F0701D0032009E2286FFFF757FD95F8780001F00FFD95F829 | ||||
| :40094000780001F0F3FC012001F00EFD02F020FB444BDFF814811A7842F004021A701A7842F001021A701A7802F0FE021A701A7802F0FE021A7002F00FFB01214FF4804315 | ||||
| :4009800041F6FF72084601F0F5FC85F8B60001F083FE08F807000137402FF8D1DFF8CC90002709F195031FFA83F804930137402F14BF3A46002219F8010F2244052392F8D7 | ||||
| :4009C0002420402101F09CFE414646F2495299F8000001F0A7FE08F14008402F1FFA88F8E4D100274FF0FF33376098467360BB463B46D6F87A9037725FEA99190CBF4FF060 | ||||
| :400A0000010A4FF0000A2168114A01310A40002ABCBF02F1FF3262F03F026068B8BF013282426FD02BB1227A002A7AD12A7D002A77D12068049A059302EB8010BAF1000F36 | ||||
| :400A400016D040223F2102F003FB1CE09B6400403F000080B43A0000F2380000CE3A0000E13A000099650040AC81FF1FAB81FF1F014601370120FFF7B7FBC7EB0903D3F10C | ||||
| :400A8000000A4AEB030A2168B34A01310A40002ABEBF02F1FF3262F03F02013222606268059B01322ED12A683F2A2BD14FF00008C5F8048001F08CFC85F808806B6895F8DC | ||||
| :400AC000B6002B4493F8241001F09EFD95F8B60001F05CFD012195F8B60001F02FFD95F87E302B6185F81480237D002BFCD04FF00008012086F8148001F076FC404601F0B4 | ||||
| :400B000033FC00E023B1237A5BB92B7D4BB90123626842453FF477AF0BF1010BD5F8048071E701F05BFC012001F01EFC002001F05BFC042194F8B60001F072FD94F8B60011 | ||||
| :400B400001F07EFD80460028F8D196F8B60001F00BFD337D327A0293012303920193CDF800A05B463A4649467C48FFF7AAFBC6F81080BAF1000F0BD0FFF756FB002001F028 | ||||
| :400B8000D5FB237A63B17648FFF79BFB0220D9E0B945F1D073490120FFF726FB0137F7E77148FFF78EFB714B3DE094F8780001F0D5FB206FFFF716FC6D48FFF782FB94F8A5 | ||||
| :400BC0007930236100232375237D002BFCD0012001F00AFC00233375237D002BFCD0002001F002FC002363483361FFF76AFB624B19E0002084F86A00FFF7F4FB5F4B12E003 | ||||
| :400C000094F8743023B195F875200AB985F8782094F875201AB113B9012385F878305848FFF798FB574B1B88ADF8203008A8FFF75DFB89E0FFF77CFB02F088F8002002F0FA | ||||
| :400C40002BF82A2701F056FF002001F0F9FE3A46002108A802F0FCF917238DF820308DF8217001F0ABFD002001F054FB002002F0E7F8C82001F064FD0DF12200FFF7ECFA35 | ||||
| :400C80000DF13600FFF709FB01F098FD012002F0D7F8322001F054FD0DF12600FFF7DCFA0DF13A00FFF7F9FA012001F033FB4FF4967001F045FD01F081FD0DF12E00FFF7AC | ||||
| :400CC000CBFA0DF14200FFF7E8FA002001F022FB4FF4967001F034FD01F070FD022002F0AFF8322001F02CFD0DEB0700FFF7B4FA0DF13E00FFF7D1FA012001F00BFB4FF4FE | ||||
| :400D0000967001F01DFD01F059FD0DF13200FFF7A3FA0DF14600FFF7C0FA002001F0FAFA4FF4967001F00CFD01F048FD002002F087F8002384F86A3001F08AFF01F05CFE97 | ||||
| :400D400074E70120FFF7E4FA032000F0A5FC0E48FFF7B7FAFFF7E2BB3F000080EB3A00001B3B00004092FF1F253B0000F43800002D3B00003B3B0000F6380000F8380000ED | ||||
| :400D8000FE81FF1FFA380000483B00000F4B1A78120616D55878C0B2012814D11B79DBB2042B02D0052B05D07047094A094B5A60282203E0084A074B5A60E0221A8000F04C | ||||
| :400DC00045BE002070470120704700BF00600040FC380000C492FF1F243900002DE9F04172B68A4B61221A70A3F5F06301221A801924874A9C7092E803008033062283F8F7 | ||||
| :400E0000002283E80300522203F580731A70814B814A1B78814EDBB2137040F61802804B00251A8041F2512223F8022C33784FF4F07003F0010343EA450502F0A1F8013CE3 | ||||
| :400E400005F003052ED0032DF0D1764B4FF480721A8007221A70744A002548211570917002221D705D7103F8032C0422DA716F4A6F4C13786F4E43F00103137012F8013C9A | ||||
| :400E8000062743F0030302F8013C2378012243F0800323705D4B1A70674A137843F02003137000E0FEE707FB056300219A881868013502F0CDF8072DF5D16048604E0025F3 | ||||
| :400EC00050F8041F05F1105303F14A0221F0FF074B33C9B20B4452005B0002329A4206D012F802EC12F801CC0EF807C0F5E7B0420D44E5D1534A00231360936013619361FD | ||||
| :400F0000514B524F1A68524BDFF88C811A60514B1A6803F1784303F5D6431A604E4A137843F002031370137C43F0020313742378A2F5863243F040032370413A137843F047 | ||||
| :400F400010031370454A464B07CA03C31A80454A2833106843F8250C127903F8212C424A07CA03C31A80414AE83B07CA03C31A803F4A083307CA03C31A803E4A3E4BA2F5B0 | ||||
| :400F8000616203CBC2F8100EC2F8141E1378042043F008031370394B02F5AA521B783D78DBB298F80060EDB203F007010C321B091170F6B2537045F003033B7046F0030326 | ||||
| :400FC00088F800302E4B48221A702E4A402313702D49937013729372082382F81F3220220A7048710A72294A0A20137001F0BEFB274B88F8006044223D70264D1A7094E8E4 | ||||
| :401000000F0007C52B80BDE8F08100BF004800401C0B00480F010049A146004025420040224200400440004006400040A2430040A04300404D3B0000E8460040FCFFFF470A | ||||
| :401040009000004800760040240B0048F846004020760040280B004803500140DC0A0048C0510040E80A0048F00A0048FC0A0048080B004832510040140B0048CF01004921 | ||||
| :401080001D51004001590040235B0040585B004076580040B0430040F946004008B501F0ABFF03680C2B00D1FEE7FEE7084908B50B68084A1844821A802A01DC086005E043 | ||||
| :4010C00001F09AFF0C2303604FF0FF33184608BDCC80FF1F9093FF1F80B51148114B0025C0B1A3F1100192C922460439161BB74204D051F8046F42F8046BF7E7114653F88D | ||||
| :40110000046C8C1AA64202D041F8045BF9E701381033E5E701F076FFFFF7B0F9FEE700BF01000000E03C0000124A134B10B51A60124A134C1368134843F40073136000238F | ||||
| :40114000032B98BF54F823204FEA830188BF0E4A0133302B4250F3D10C4B1A780C4B1A700C4B084A1A60FFF739FEBDE8104001F0CFB900BF0004FA050CED00E014ED00E016 | ||||
| :40118000000000000080FF1F9D100000BC760040C080FF1F08ED00E0F8B501F0F9FE4B4A01271378022643F001031370137C484C43F001031374474B02F5E3521F700B3215 | ||||
| :4011C00003F8946C1378054603F07F031370002001F0CCFA2378404A03F0F90323701378384603F0DF03137023783B43237001F0BDFA282001F0BAFA384B30461A7802F089 | ||||
| :401200007F021A701A7802F0BF021A7023783343237001F0ABFA2378314A43F0040323700023137053702F4AFF2199540133092BFBD1284601F0B0FE0721172001F0DEFA5F | ||||
| :401240002949172001F0CCFA0721182001F0D6FA2649182001F0C4FA0721152001F0CEFA2349152001F0BCFA0721052001F0C6FA2049052001F0B4FA0721062001F0BEFA17 | ||||
| :401280001D49062001F0ACFA0721084601F0B6FA1A49072001F0A4FA0721082001F0AEFA1749082001F09CFA0021162001F0A6FA1449162001F094FA07210C2001F09EFA0C | ||||
| :4012C000BDE8F84010490C2001F08ABAA5430040944300409D60004012600040F851004084600040B592FF1F671B0000A1190000651B0000991A0000C51A0000F51A0000BA | ||||
| :401300002D1B00006D1B0000E11B0000214B224A10B5187000231370204A40201370204A0F2413701F4A13701F4A13701F4A13701F4A13701F4B4FF400021A604FF080729F | ||||
| :401340001A604FF400121A6020221A601860802018604FF480701860174804704FF480001860164B1A70933B19B91A7802F0FE0202E01A7842F001021A70114B03221A70D2 | ||||
| :40138000802203F8202C012001F0FAFD0D4B04221A7010BDD092FF1FD692FF1FD492FF1FD592FF1FD192FF1FC092FF1FD392FF1F4893FF1F00E100E09E6000409C600040AF | ||||
| :4013C000286000401260004070B5074C054623780E461BB9FFF7E0FE0123237031462846BDE87040FFF792BF8092FF1F0A4A002313700A4A13700A4A13700A4A13700A4ADE | ||||
| :4014000013700A4A13700A4A13700A4B03221A70802203F8202C7047D692FF1FD492FF1FD592FF1FD192FF1FC092FF1FD392FF1F4893FF1F28600040014B1878704700BFC1 | ||||
| :40144000D592FF1F044B1A7802F0FF001AB118780022C0B21A707047D492FF1F024A0C2303FB002040787047DC92FF1F431E072B0CD8074A064B00010344805C5B7800F0CD | ||||
| :401480000F0043EA0020023880B2704700207047FC5F00401A4A38B50C2303FB00231B79090C13F0800F00F1FF35044619BF8AB24FF480438BB24FF48042032D18D8DFE8AD | ||||
| :4014C00005F002070C110021084600F0FDFF0DE00021084600F0DCFF08E00021084600F0BBFF03E00021084600F09AFF054B1855EDB2072D03D801F0CFF8034B185538BDA0 | ||||
| :40150000DC92FF1FAC92FF1FB592FF1F431E072B2DE9F0470446894615465CD82F4F0C2202FB0072D388DFF8B8A09BB2C3F500739D424FF00C0303FB007388BFD588DB7824 | ||||
| :4015400084BFC5F50075ADB2254A43EA15230601B354B244EBB28AF80130224B1A5C9846FF2A01D1FFF796FF0C2303FB047200215170B9F1000F28D03DB31B4F385D00F016 | ||||
| :40158000F3FF11232946FE2218F8040001F0B8F806F5C04278321FFA89F118F8040001F0C1F8124D18F80410385D01F02DF80121385D00F0C3FF735D43F002037355735D92 | ||||
| :4015C00003F0FD037355BDE8F08703FB04746379DBB28AF80230BDE8F08700BFDC92FF1FFC5F0040B592FF1FAC92FF1F706000402DE9F047044615468846002940D0431E54 | ||||
| :40160000072B3FD8FFF732FFA84203D22046FFF72DFF05461D4E335DFF2B03D141462046FFF738FFDFF868A027011AF8040000F09BFF1223FE222946305D01F061F807F557 | ||||
| :40164000C0411FFA88F27831305D01F06BF8DFF84490315D1AF8040000F0D6FF01211AF8040000F06BFF17F8093043F0020307F8093017F8093003F0FD0307F8093002E099 | ||||
| :401680000D4600E000252846BDE8F087B592FF1FAC92FF1F70600040431E072B0AD8064A0C2303FB002300225A705A79034BD2B200011A54704700BFDC92FF1FFE5F0040C3 | ||||
| :4016C000431E072B9FBF024B000108221A547047FE5F004030B51A4A1A491B4D0878138803449BB21380194A00231488D8B2A4B27CB1082B0CD050680078C0B2E854506895 | ||||
| :401700000133013050601088013880B21080ECE718460B780E4C082B0E4A00D040B10E4D2B7883F080032B700F232370022301E0022323701370094B1870087030BD00BF12 | ||||
| :401740004C93FF1F4893FF1F00600040C492FF1FC192FF1FD692FF1FD292FF1F4993FF1F074B02221A70074B80221A70064B0F221A70064A00231370054A012013707047C2 | ||||
| :40178000D692FF1FD292FF1FC192FF1F4893FF1F4993FF1F30B5164B16491B780A8803F00F03023BDBB21A4492B20A80124C134A0020118889B279B173B15568215C013B85 | ||||
| :4017C000C9B229705168DBB20131516011880130013989B21180ECE7094A1370094A137883F080031370084B0B221A7030BD00BF296000404C93FF1F00600040C492FF1F4C | ||||
| :401800004993FF1FD292FF1FC192FF1F064A06231370064A01201370054B80221A70054B00221A70704700BFD692FF1FC192FF1FD292FF1F4993FF1F054B9A683AB19A682B | ||||
| :40184000044910709A680988518000229A607047C492FF1F4C93FF1F08B5124B1A78D2B21A701B78DBB21A0602D50F4A137008BD0220FFF7E1FF0D4B1B7803F06003202BFD | ||||
| :4018800005D0402B06D043B900F012FC04E001F087FB01E0FFF77AFA10B9034B03221A7008BD00BF28600040C192FF1F0060004008B5084A084B0120197813880B449BB208 | ||||
| :4018C0001380064B00221A70FFF7B6FF044B03221A7008BD4C93FF1F4893FF1FD692FF1FC192FF1F08B50C4B1B78DBB2042B07D0062B09D0022B0DD1BDE80840FFF7D8BF34 | ||||
| :40190000BDE80840FFF746BF0320FFF795FF034B03221A7008BD00BFD692FF1FC192FF1F08B5054B002201201A70FFF785FF034B03221A7008BD00BFD692FF1FC192FF1FCE | ||||
| :4019400008B50A4B1A7832B11A78094942F080020A7000221A70074B002201201A70FFF76BFF054B03221A7008BD00BFC092FF1F08600040D692FF1FC192FF1F074B1B782C | ||||
| :40198000DBB2042B05D0062B05D0022B05D1FFF7A1BEFFF7C5BFFFF7D3BF7047D692FF1F38B51D4C2378DBB2DD0634D518060AD503F00F03012B2ED1FFF74EFF174B1B782A | ||||
| :4019C000190609D538BD5A0602D5FFF7D7FF03E09D0620D5FFF786FF23781B061BD4104B1A78104B1B7813430F4A13701278934211D10A4A0849154613782078DBB200064D | ||||
| :401A000005D41378DBB20B700B7803F00F0328788342F1D138BD38BD28600040C192FF1FD292FF1F4993FF1F29600040054A00231380054A916819B191680B7092685380CB | ||||
| :401A4000704700BF4C93FF1FC492FF1F0E4808B503889BB213B9FFF783FE13E00B4B02221A700B4B00221A70FFF7E0FF094AD1799379028843EA012392B2934238BF03806C | ||||
| :401A8000FFF728FE012008BDC492FF1FD692FF1FD292FF1F00600040084B01221A700F3B9B7C074B1A7B02F00302012A1EBFDA7B82F08002DA7301225A7370470B600040D9 | ||||
| :401AC000DC92FF1F094B02221A700F3B93F82230074B1A7E02F00302012A1EBFDA7E82F08002DA7601225A76704700BF0B600040DC92FF1F0B4B04221A700F3B93F83230CF | ||||
| :401B0000094B93F8242002F00302012A1EBF93F8272082F0800283F82720012283F82520704700BF0B600040DC92FF1F0B4B08221A700F3B93F84230094B93F8302002F0F9 | ||||
| :401B40000302012A1EBF93F8332082F0800283F83320012283F83120704700BF0B600040DC92FF1F7047FFF741BC0000F0B5184B184E19780C27C9B201234FF0000C31B372 | ||||
| :401B8000CA0720D5144A4FEA031E7244947850782040C5070DD507FB03652C79240608D5147804F0FE0414706D790C4CEDB204F80E50840706D507FB036425792D0658BF05 | ||||
| :401BC00084F801C090700133DBB24908D7E7F0BD9F600040DC92FF1F70600040FE5F004000F08EBC70B50446184B88B003AA03F11006154618685968083303C5B3422A46B4 | ||||
| :401C0000F7D11B782B70FCB12223237001AD03232846637000F06CFE002220461146AB5C08AC04EB131414F8144C03F00F03847008AC234413F8143C0132082AC170037125 | ||||
| :401C4000417100F10400EAD108B070BD773B00002DE9F0431C4D01222E460C201F274FF0800E4FF0080C194B00FB02581401234418705F70164998F805902144B9F1000F62 | ||||
| :401C800007D098F8044024064CBF887081F802C001E081F802E000FB0261CC880132E4B29C71CC88092AC4F30724DC71CC88E4B21C71C988C1F307215971D4D1054BFF2213 | ||||
| :401CC0001A70BDE8F08300BFDC92FF1F70600040FC5F00400A600040064B074A1B7802EBC30253681A7C824286BF03EBC003586900207047D092FF1F9C3B00002DE9F84F64 | ||||
| :401D0000424B1A78002A7ED01878414D0138C0B2FFF7E2FFA8463F4AC3681478007ADFF800C1E4B203EBC0000C2600274FF0010E834268D01A78A24263D11CF80420597891 | ||||
| :401D400091425ED19A7893F8039002F07F0206FB02FA05EB0A01CF7093F802B009F0030981F804B093F803B005F80AB0B3F804A0A1F808A093F902A0BAF1000F0BDAB9F11C | ||||
| :401D8000010F0CBF4FF007094FF00D0981F8059081F801E009E0B9F1010F0CBF4FF005094FF0090981F805904F704FEA02191A4906FB0282494481F802E0B2F808A0CAF330 | ||||
| :401DC000072A81F800A0B2F808A05FFA8AFA81F801A0B2F806A011495FFA8AFA494481F806A0B2F80690C9F3072981F80790B2F806905FFA89F981F80490D288C2F3072281 | ||||
| :401E00004A71083394E7BDE8F88F00BFD592FF1FDC92FF1FD192FF1FFC5F004070600040C292FF1F08B5064B18780138C0B2FFF753FF20B143681B7900EBC300406908BDDA | ||||
| :401E4000D592FF1F00212DE9F84F0B464E4E0C2707FB01F401313219092933554FF000059370494CD3701381937253705371EFD118B1464B1D70464B1D70464B1A78002AC0 | ||||
| :401E80007FD0187801250138C0B2FFF725FFA8464368DFF8F8E0DB790C2713F0400F3E4B4FF0000C1A7814BF42F0010202F0FE021A70027AD20007FB0541C36803EB020993 | ||||
| :401EC0004B4531D093F802A00AF07F06AE4229D10E89B3F804B0B6B25E4538BFA1F808B01E7893F801B01EF80660B3451AD181F804A0DE780E7093F902A0DE78BAF1000F12 | ||||
| :401F000006F0030607DA012E0CBF07260D264E7181F8018006E0012E0CBF052609264E7181F801C00833CBE70135092DC3D1C1680A328B1C0A440C200833934209D013F814 | ||||
| :401F4000081C13F80A5C01F07F0100FB01418D72F2E7FFF767FF114B0121186000230C2000FB0142D3801289013113449BB203F00102134409299BB2F2D1BDE8F84FFFF732 | ||||
| :401F800067BEBDE8F88F00BFDC92FF1FC292FF1F4A93FF1FD592FF1FD392FF1FD892FF1F114B1B7903F07F035A1E072A19D80F490C2202FB031291781B0141F00101917098 | ||||
| :401FC0000021D170517841F002015170127912F0800F074A1A4414BF8D2389239370FFF715BC0020704700BF00600040DC92FF1FFC5F004030B4194B1A7902F07F02531EE1 | ||||
| :40200000072B27D8164B0C2404FB02339978154D01F0FE0199700021D97029461201505D114400F07F0050555A7802F0FD025A701A795B78120605D5012B01D18C7006E077 | ||||
| :402040000D2303E0012B0CBF082309238B7030BCFFF7DCBB002030BC704700BF00600040DC92FF1FFC5F004010B50D4B0D4C21791878C9B20138C0B2FFF72EFE43681B791B | ||||
| :402080008B4201D2012909D8074A0848535CDBB24354A3780120DBB2535410BD002010BDD592FF1F00600040C292FF1F4A93FF1F38B5874A874C13780021DBB221801806BC | ||||
| :4020C000517840F188800A2900F20081DFE811F05800FE00FE00FE00FE00FE000B00FE007900FE007D00D3787949012B09D17A4B1A787A4B03EBC2035B685B6863601223C5 | ||||
| :4021000010E0CB78022B12D18878FFF7E5FD002800F0DC80436863606368DA7863689B7843EA02232380BDE83840FFF78FBCCB78032B21D16A4B00228878D5B2854203D3F6 | ||||
| :40214000634A92783AB910E0187801320028F7D018780344F0E75E4A62499278097C914203D16148FFF73EFD5F4B1A78002A00F0AD801A78228018E0BDE8384000F010BF77 | ||||
| :4021800013F0030313D0022B40F0A0802380504B0C211B7903F07F02544B01FB02339A78534BD2B21A7000225A706360BBE702222280504A11784E4AC9B211705370626062 | ||||
| :4021C000B1E7012323804C4BEFE70123238013794A4A1344E9E701390A2977D8DFE801F037764F76067676760A7620009378444ADBB25AE0937803F0FF0153B93E4B1A7892 | ||||
| :4022000091425FD019703F4B01201870FFF71AFE58E0481EC0B2FFF75FFD0028EED155E0FFF722FF002851D0294A374913791279DBB2D2B20A70354A3049D25CCB5C9A4236 | ||||
| :4022400040D0304B01221A70FFF758FD3AE003F00303012B2BD009D3022B37D11C4B9B78002B33D1BDE83840FFF7C4BE184B9B78012B2BD11F4A137803F0FD0315E003F0E5 | ||||
| :402280000303012B13D008D3022B1FD1104B9B78E3B9BDE83840FFF783BE0D4B9B78012B14D1144A137843F0020313700AE0084B1A795AB998781B791549DBB2CA5C22EAEF | ||||
| :4022C0000002CA54BDE83840FFF7A0BA002038BD00600040C492FF1FD092FF1F9C3B0000003C0000733C00006893FF1FDC92FF1F8192FF1FD392FF1FD592FF1FC292FF1F96 | ||||
| :40230000C092FF1FD492FF1FD192FF1F4A93FF1FD792FF1F014B1870704700BF78650040014B1878704700BF6C640040014B1870704700BF78640040064A0123136002F698 | ||||
| :4023400088321268E0211064034A1170A2F540721360704780E100E000E400E0014B1870704700BF7A650040014B1870704700BF7F64004073B515461E460B4C0523002210 | ||||
| :40238000019200920A4601461846237000F064F932462946207800F01FF90221207800F009F9207802B070BDD080FF1F064A0423136002F688321268E0219064034A117031 | ||||
| :4023C000A2F202321360704780E100E002E400E0014B04221A60704700E100E0014B04221A60704780E100E0014B1870704700BF7E640040704738B505460078012428B1CB | ||||
| :4024000000F066FD285D0134E4B2F8E738BD08B50D2000F05DFDBDE808400A2000F058BDF7B516461F460B4C00230325019300930A4601462846257000F00EF93A46314617 | ||||
| :40244000207800F0C9F80221207800F0B3F8207803B0F0BDE080FF1FF7B516461F460B4C00230225019300930A4601462846257000F0F2F83A463146207800F0ADF829460B | ||||
| :40248000207800F097F8207803B0F0BDE180FF1FF7B516461F460B4C00230125019300930A4601462846257000F0D6F83A463146207800F091F80221207800F07BF8207844 | ||||
| :4024C00003B0F0BDE280FF1F73B515461E460B4C0023019300930A4601461846237000F0BBF832462946207800F076F80221207800F060F8207802B070BD00BFE380FF1FB2 | ||||
| :40250000024B1878C0F38010704700BF8F450040074A7F23802113705170064A013BDBB202F80839002BF9D1034A1370704700BFE480FF1FF87B00400078004017280FD877 | ||||
| :40254000084B0001C25C11B142F0200201E002F0DF02C254C25C42F00102C25400207047012070471070004017280BD8064B0001C25C02F0FE02C254C25C02F0DF02C25490 | ||||
| :4025800000207047012070471070004017280DD8074900010B4603441A7942F004021A71435C43F00103435400207047012070471070004017280BD8064A0001835C4900D2 | ||||
| :4025C00003F0F10301F00E011943815400207047012070471070004041F6FF73994208BF4FF400519A4208BF4FF4005217289FBFC00000F1804000F5EC4081809ABFC28072 | ||||
| :40260000002001207047000017289FBF034B00011954002088BF0120704700BF1970004017289FBF054B00011A5C01F007019DBF1143195400200120704700BF147000408D | ||||
| :4026400017289FBF034B0001185C00F0070088BFFF20704714700040172810B51AD8C00001F07F0100F1804441EAC21204F5EC44D2B222709DF8082003F00F0343EA021304 | ||||
| :40268000DBB263709DF80C30002003F00F03A370E07010BD012010BD10B500F079FC0A4A5378182B0AD91478013B5370E30003F1804303F5F0431B78137000E0FF2400F0DE | ||||
| :4026C0006BFC204610BD00BFE480FF1F030610B5044611D400F05CFC084AE300117803F1804303F5F04319705378147001335370BDE8104000F050BC10BD00BFE480FF1F4C | ||||
| :4027000030B504060CD411F4704509D1C40004F1804404F5F0442180A270E370284630BD012030BD03065FBFC00000F1804000F5F04081805ABFC28000200120704700000C | ||||
| :4027400038B50446084DB4F5004F05D9286800F017FCA4F50044F6E7034B58686043BDE8384000F00DBC00BFEC80FF1F024B1B7A584300F005BC00BFEC80FF1F0E4B00F01A | ||||
| :4027800003001A78490102F0FC02104318701A7801F0600142F080021A701A7802F07F021A701A7802F09F020A431A701A7842F010021A70704700BF83430040014B012277 | ||||
| :4027C0001A70704784430040044B00F00F021B6853F8220043F82210704700BF08ED00E0054A00F01F00126800F1100352F8230042F82310704700BF08ED00E000F01F0089 | ||||
| :4028000000F16040490100F56440C9B2017070470F4B10B50F4900240F205C609C60DC601C615C61FFF7D0FF0B4A136843F0040313600A4B4FF47A72DB68B3FBF2F3084A9B | ||||
| :402840001360084B4FF400421C60C3F8E82010BD8492FF1FBD28000010E000E0EC80FF1F14E000E018E000E0024A136843F002031360704710E000E008B5FFF7F5FF034AF5 | ||||
| :40288000136843F00103136008BD00BF10E000E010B5054CA3691BB9FFF7BAFF0123A361BDE81040FFF7E8BF8492FF1F024B1868C0F30040704700BF10E000E038B5FFF723 | ||||
| :4028C000F5FF012808D1054D002455F8243003B198470134052CF8D138BD00BF8892FF1F024B03EB80035868596070478492FF1F134B144A1B78DBB20360127843EA0223E0 | ||||
| :40290000114A0360127843EA0243104A0360127843EA026303600E4B0E4A1B78DBB24360127843EA02230C4A4360127843EA02430A4A4360127843EA02634360704700BF30 | ||||
| :402940000301004904010049EC460040020100490101004900010049050100490601004910B500F015FB204A044613780A2043F002031370137C43F00203137412F80A3C43 | ||||
| :4029800043F0010302F80A3C937943F00103937102F5AB52137843F003031370134B18221A7013F8012C42F0400203F8012C13F8012C02F0FC0203F8012CCE2203F8062CBB | ||||
| :4029C000A3F597530222183B1A70094A137843F008031370FFF7CAFE064B10222046BDE810401A6000F0D8BAAB4300400E5900402F5B004080E200E008B500F0C9FA0F4A73 | ||||
| :402A0000137803F0FE031370A2F5AA521D3A137803F0FD031370137C03F0FD03137412F80A3C03F0FE0302F80A3C937903F0FE039371BDE8084000F0AFBA00BF0859004072 | ||||
| :402A4000044A137803F03F0343EA8010C0B21070704700BF08590040082804D00A280CBF8223C22300E0422308380E4AC0B20428137098BF0C4B4FF0000298BF33F9101067 | ||||
| :402A80000A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B1A8070470A590040883B00005293FF1F5493FF1F5893FF1F08B5102000F0A6F9C9 | ||||
| :402AC00007210420FFF79AFE07490420FFF788FE064A0C20137843F006031370FFF7BCFF034B00221A8008BDB12B0000095900405093FF1F10B5054C23781BB9FFF7DCFFF1 | ||||
| :402B000001232370BDE81040FFF72ABFA092FF1F044B1A7802F0FB021A701A7842F001021A7070470859004010B5084B1C7814F0010403D10028F9D0002404E02046FFF7D9 | ||||
| :402B400015FE024B1B78204610BD00BF09590040034A044B1B881088181A00B2704700BF5893FF1FA25B00400E4A13881BB223B111880A2309B2594301E00B4B19680B4B98 | ||||
| :402B80001B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270475293FF1F5493FF1F5093FF1F7047000010B500F0EBF9214A0446137884 | ||||
| :402BC0000A2043F001031370137C43F00103137412F80A3C43F0020302F80A3C937943F00203937102F5AA521832137843F003031370144B18221A7013F8012C42F0400241 | ||||
| :402C000003F8012C13F8012C02F0FC0203F8012CCE2203F8062CA3F597530222123B1A70094A137843F008031370FFF79FFD074B08222046BDE810401A6000F0ADB900BFEB | ||||
| :402C4000AB43004006590040275B004080E200E008B500F09DF90F4A137803F0FE031370A2F5AA52153A137803F0FE031370137C03F0FE03137412F80A3C03F0FD0302F8BA | ||||
| :402C80000A3C937903F0FD039371BDE8084000F083B900BF00590040044A137803F03F0343EA8010C0B21070704700BF00590040082804D00A280CBF8223C22300E04223BE | ||||
| :402CC00008380E4AC0B20428137098BF0C4B4FF0000298BF33F910100A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B1A8070470259004094 | ||||
| :402D0000923B00005E93FF1F6493FF1F5C93FF1F08B5102000F084F807210320FFF76EFD07490320FFF75CFD064A0C20137843F006031370FFF7BCFF034B00221A8008BD88 | ||||
| :402D4000092E0000015900406093FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040FFF728BFA192FF1F044B1A7802F0FB021A701A7842F001021A7070470059004046 | ||||
| :402D800010B5084B1C7814F0010403D10028F9D0002404E02046FFF7E9FC024B1B78204610BD00BF01590040034A044B1B881088181A00B2704700BF5C93FF1FA05B00406B | ||||
| :402DC0000E4A13881BB223B111880A2309B2594301E00B4B19680B4B1B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270475E93FF1F0D | ||||
| :402E00006493FF1F6093FF1F70470000034A00F0F800137803431370704700BF02410040034A00F0F800137803431370704700BF06410040014B1870704700BF7C64004043 | ||||
| :402E4000014B1870704700BF7B64004073B515461E460B4C04230022019200920A46014618462370FFF7F8FB324629462078FFF7B3FB02212078FFF79DFB207802B070BDE9 | ||||
| :402E8000FC80FF1F074A0223136002F688321268E0215064044A11706FF440710A441360704700BF80E100E001E400E0014B1870704700BF74640040014B1870704700BFE2 | ||||
| :402EC00075640040014B1870704700BF7D640040FEB5494652465B460EB40746244909688A46244A12682448022100F071F8030020480068C018204900F06AF814388346CB | ||||
| :402F00000121C9430C460125002600F041F8814651460B7823400B705846013000F030F83800F04028400B78234003430B70584600F026F80136072EF2D900200130013812 | ||||
| :402F4000013001200B78234003430B705846043000F016F8484600F01FF800BF00BF00BF0EBC894692469B46FEBD00BFAFF30080D480FF1FF880FF1F00C2010000000000FD | ||||
| :402F80000230800803D000BF01380046FCD17047EFF3108072B6704780F31088704700BF094A137803F00303012B0AD0022B09D113790C2103F07F02044B01FB02339B7A4A | ||||
| :402FC00000E013790020704700600040DC92FF1F002902D0B0FBF1F0704708B14FF0FF3000F008B80029F8D00246B0FBF1F000FB11217047704700BF014B1868704700BFEC | ||||
| :403000006081FF1F0E4B70B51E460E4C0025E41AA410A54204D056F8253098470135F8E700F044FE084B094C1E46E41AA4100025A54204D056F8253098470135F8E770BD98 | ||||
| :40304000B83C0000B83C0000B83C0000C03C000003460244934202D003F8011BFAE7704730B5141E05469BB0184604DA8B232B604FF0FF301DE04FF40273ADF80C300CBFA2 | ||||
| :40308000234604F1FF33029305934FF6FF7300910491ADF80E3002461E9B6946284600F073F8431CBCBF8B232B6014B1009B00221A701BB030BD000007B5009313460A464B | ||||
| :4030C000014603480068FFF7CBFF03B05DF804FB6081FF1F2DE9F0478E6882469E420C46914698463ED88A8912F4906F3AD02568096902236F1A656905EB450595FBF3F5B9 | ||||
| :403100007B1C43449D4238BF1D4653050FD5294600F04AFB064698B13A46216900F0D2FAA38923F4906343F08003A38113E02A4600F098FB064670B92169504600F0E8FAA0 | ||||
| :403140000C23CAF80030A3894FF0FF3043F04003A381BDE8F08726613E44266046466561ED1BA560464528BF464649463246206800F0B3FAA36800209B1BA36023681E44F5 | ||||
| :403180002660BDE8F08700002DE9F04F9DB003938B8980461C060D4616460DD50B695BB9402100F001FB2860286118B90C23C8F80030CDE040236B610023099320238DF86F | ||||
| :4031C0002930DFF89CB130238DF82A3037463C4614F8013B1BB9B7EB060910D003E0252BF9D02746F3E74B46324629464046FFF771FF013000F0A780099B4B4409933B7803 | ||||
| :40320000002B00F0A08000234FF0FF3204930793059206938DF853301A930126052221784E4800F041FA671C049B38B14B4A3C46801A06FA00F018430490EFE7D90644BFAF | ||||
| :4032400020228DF853201A0744BF2B228DF8532022782A2A03D0079A00210A200BE0039A111D12680391002A10DA524243F00200079204900BE027463B780134303B092B51 | ||||
| :4032800003D800FB02320121F5E701B107923B782E2B1ED17B782A2B0AD1039B02371A1D1B680392002BB8BF4FF0FF33059310E0002319460593781C0A2407463A780130D0 | ||||
| :4032C000303A092A03D804FB01210123F5E703B1059103223978224800F0E6F940B14023CBEB000003FA00F0049B013718430490397806221B487E1C8DF8281000F0D4F9CF | ||||
| :4033000088B1194B33B9039B073323F007030833039314E003AB00932A46144B04A94046AFF3008007E003AB00932A460F4B04A9404600F093F8B0F1FF3F824603D0099B27 | ||||
| :403340005344099342E7AB895B0601D4099801E04FF0FF301DB0BDE8F08F00BF873C00008D3C0000913C000000000000D53000002DE9F04791461F460A698B680646934279 | ||||
| :40338000B8BF1346C9F8003091F843200C46DDF8208012B10133C9F800302368990642BFD9F800300233C9F80030256815F0060510D104F1190A07E0012352463946304631 | ||||
| :4033C000C04701301AD00135E368D9F800209B1A9D42F1DB94F843302268003318BF012392060FD5E118302081F843005A1C94F845102244023382F8431003E04FF0FF3091 | ||||
| :40340000BDE8F08704F1430239463046C0470130F4D02268D9F80050E36802F00602042A08BF5D1B2269A3680CBF25EAE57500259342C4BF9B1AED184FF000091A344D45BF | ||||
| :4034400009D00123224639463046C0470130D5D009F10109F3E70020BDE8F0872DE9F04317460A7E85B06E2A984606460C460C9B01F1430E00F0AE8011D8632A22D009D833 | ||||
| :40348000002A00F0BB80582A40F0CA8081F84520834955E0642A1ED0692A1CD0C0E0732A00F0B08009D86F2A2ED0702A40F0B8800A6842F020020A603EE0752A24D0782A87 | ||||
| :4034C0003AD0ADE01A6801F14205111D1960136884F84230A8E021681A6811F0800F02D0111D196008E011F0400F02F10401196002D0B2F9003000E01368002B3CDA2D228D | ||||
| :403500005B4284F8432037E021681A6811F0800F02D0111D196007E011F0400F02F10401196001D0138800E01368227E5C496F2A14BF0A2208221BE078225A4984F8452055 | ||||
| :403540002268186812F0800F00F104051D6003D1550601D5038800E00368D00744BF42F0200222601BB9226822F0200222601022002084F8430001E049490A226568002DF0 | ||||
| :40358000A56008DB206820F0040020602BB9002D7DD175460CE0002B79D07546B3FBF2F002FB1033CB5C05F8013D03460028F5D1082A0BD12368DA0708D5236962689A42E0 | ||||
| :4035C000DEBF302305F8013C05F1FF35C5EB0E0323612EE008681A6810F0800F496903D0101D1860136808E010F0400F02F104001860136801D0198000E019600023236173 | ||||
| :40360000754616E01A68111D1960156800216268284600F049F808B1401B6060636804E004F1420584F8422001232361002384F84330CDF800803B4603AA21463046FFF70C | ||||
| :4036400097FE013002D14FF0FF3026E023692A4639463046C0470130F5D023689B0710D5002504F1190907E001234A4639463046C0470130E7D00135E368039A9B1A9D42D0 | ||||
| :40368000F2DBE068039B9842B8BF184605E00B7804F1420584F842308AE705B0BDE8F083773B0000983C000010B5C9B202449042034605D01C7801308C42F8D1184610BD55 | ||||
| :4036C000002010BD10B5431E0A44914204D011F8014B03F8014FF8E710BD884210B501EB020301D8421E0BE09842FBD28118D21AD34204D013F8014D01F8014DF8E710BD71 | ||||
| :40370000994204D011F8014B02F8014FF8E710BD38B50546002944D051F8043C0C1F002BB8BFE41800F0D4F81E4A1368114613B96360146030E0A3420DD92268A0188342ED | ||||
| :4037400001BF18685B681218226063600C6023E0A24203D813465A68002AF9D118681918A1420BD12168014458188242196013D110685268014419605A600DE002D90C232A | ||||
| :403780002B6009E021686018824201BF106852680918216062605C602846BDE8384000F098B838BDA892FF1F70B5CD1C25F0030508350C2D38BF0C25002D064601DBA9429D | ||||
| :4037C00002D90C23336046E000F082F8234B1C681A462146A1B10B685B1B0ED40B2B03D90B60CC18CD501EE08C420BBF63684B681360636018BF0C4615E00C464968E9E70D | ||||
| :40380000174C23681BB9304600F052F820602946304600F04DF8431C18D0C41C24F00304A0420DD12560304600F053F804F10B00231D20F00700C31A0ED05A42E25070BD37 | ||||
| :40384000211A304600F034F80130EBD10C233360304600F03EF8002070BD00BFA892FF1FA492FF1FF8B5074615460E4621B91146BDE8F840FFF798BF1AB9FFF749FF2846F5 | ||||
| :40388000F8BD00F027F885420ED929463846FFF78BFF044650B131462A46FFF713FF31463846FFF735FF01E03046F8BD2046F8BD38B5064C0023054608462360FDF7F6FB46 | ||||
| :4038C000431C02D1236803B12B6038BD8C93FF1F7047704751F8040C0028BEBF091851F8043CC0180438704700000000050209020B020D020F021102130215022800000013 | ||||
| :40390000000104000100000000000000000157494E55534200003030303031000000000000000000E0000000000105000100D6000000070000002A00440065007600690041 | ||||
| :403940006300650049006E0074006500720066006100630065004700550049004400730000009E0000007B00330064003200370035006300660065002D003500340033000D | ||||
| :4039800035002D0034006400640035002D0061006300630061002D003900660062003900390035006500320066003600330038007D0000007B00330064003200370035001F | ||||
| :4039C0006300660065002D0035003400330035002D0034006400640035002D0061006300630061002D003900660062003900390035006500320066003600330038007D0098 | ||||
| :403A0000000000007265706C792030782530327800686F6D696E6700626567696E6E696E67207365656B2066726F6D20256420746F2025640066696E69736865642073652D | ||||
| :403A4000656B00796573006E6F00647269766520303A20257320647269766520313A2025730057616974696E6720666F72205553422E2E2E0055534220726561647900631F | ||||
| :403A80006F6D6D616E6420307825303278006661696C2025642B25642B2564203D3D2025642C206E6F74202564007061737365643D256400756E64657272756E2061667479 | ||||
| :403AC0006572202564207061636B65747300636F756E743D256420693D256420643D256400636D645F777269746500703D25642063723D25642063773D256420663D2564F8 | ||||
| :403B000020773D256420696E6465783D256420756E64657272756E3D256400756E64657272756E2100737563636573730073746172742065726173696E670073746F702027 | ||||
| :403B400065726173696E670069646C650000510040100040510040300000000140001000140140000800400140000A004C01400002005001402000303132333435363738CF | ||||
| :403B80003941424344454600000100000004000000100001000000040000001001000000A43B000001000000733C0000000000000000000001000000BC3B00000100000084 | ||||
| :403BC000453C000004000000DE3B0000000000000000000000000000DC3B0000FF00000001024000FF00000082024000FF00000003034000FF00000084034000FF000203FC | ||||
| :403C000004030904160346006C007500780045006E00670069006E0065002A0343006F0077006C00610072006B00200054006500630068006E006F006C006F006700690036 | ||||
| :403C4000650073000009022E0001010080320904000004FF00000107050102400000070582024000000705030340000A0705840340000A12010002FF0001080912006E016F | ||||
| :403C800000020180014300232D302B2000686C4C00656667454647003031323334353637383961626364656600000000F8B500BFF8BC08BC9E4670475900000029110000DA | ||||
| :403CC000F8B500BFF8BC08BC9E46704735000000E03C0000C880FF1FA000000028120000000000009093FF1FFF000000675000400C00000007000000FFFFFFFF7F8000006F | ||||
| :403D00003F0000000000007D00FA0000400000000090D003FF0000000000000000000000000000000000000000000000000000000000000000000000853C0000000000006A | ||||
| :403D400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081FF1F00000000A4 | ||||
| :403D80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003 | ||||
| :403DC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C3 | ||||
| :403E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082 | ||||
| :403E40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042 | ||||
| :403E80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 | ||||
| :403EC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C2 | ||||
| :403F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081 | ||||
| :403F40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041 | ||||
| @@ -4098,68 +4098,68 @@ | ||||
| :40FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041 | ||||
| :40FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 | ||||
| :0200000480007A | ||||
| :400000000145004008520040015B004001650040010101404D0201403D0301404C0401404D0501404D060140500701404B0801404B0901404B0A0140500B0140470C0140CB | ||||
| :40004000500D0140520E0140350F014046140140541501404B160140561701404718014044190140591A0140571B01400A400140104101400E4201400943014004440140BE | ||||
| :400080000D4501400A4601400F470140094801400F4901401B4C0140084D014008500140045101407E0208440905108011821801600C610A7C4027212A0A8C8000010109B1 | ||||
| :4000C0000202040805090808090F0B100C080D010F02100F1120140416011709180819101B0E1D011E01210422082301240829092A0E2C0D320F331F35203B083E043F1020 | ||||
| :400100005608580459045B045C905D905F01850287018C01900F9401960898249A089E07A008A101A222A302AA08AE10B01FB101B302B420B90ABE10BF05C202C70EC810AC | ||||
| :40014000C9FFCAFFCBFFCF83D804D904DA04DB04DC09DD09DF01030204A10620074008010A060B200C800D100E400F2010421110150416821720180419011E10202021010F | ||||
| :40018000262027202A012C042E023508376138083E583F0240045208588859215A025D4060026108621265806F0180068140874088408A088E209880C0F1C2FFC4FBCAA1EC | ||||
| :4001C000CCF0CEF2D004D61FD81FE20CE6C5EE82010D04020601070109080C010D080E0E100F130E150F161019081C201D082101220F2302240125042604270128012908CA | ||||
| :400200002A082C012F08301F3220330F3E043F045608580459045B045C095D905F01810182088302840885028A108B018C088D038F049102920194049701982099029A1FB5 | ||||
| :400240009C089D02A202A302A408A501A704A808A902AC1FAD03AE20B107B43FBF01D804D904DB04DC09DF0100400108048006A0070809880A400C810E080F20100511082C | ||||
| :40028000130115251740185019011B011E081F20210827402AA02B902C052D022F20308031213208350136803728388039243B013D083E4A3F2158405C105D806180851076 | ||||
| :4002C00087029102938094A195349644972099809B209C0C9D089EBAA480A602A713A908AC03B010B520B601C0F5C2FDC4FFCAFFCCFFCEFFD638D808E20AE648E880EA03A0 | ||||
| :40030000EE820003010D050506010801090C0B020C010D0D1001111012021602170D1801190D1C011D0D2201230D2401250D280129092C012D012E022F02310C3510360355 | ||||
| :4003400037033E403F51580459045B045F0180208102820F8404860A882F89028D028EA09204948095039640970C98049A099E10A020A102A20FA480A802AC01AD0AAF0550 | ||||
| :40038000B060B108B21FB306B480B501B61FBE10BF01D804D904DB04DC99DF01000902080302048A0708082209880C800D100F9011501305158016A01710180919041A08AD | ||||
| :4003C0001BD21D80210923042440254026102B422C042D012E402F20310836843721380239803A103D203E083F825D015F0169506AA06F0178017B807D027F8080048604BE | ||||
| :4004000089108A028F01938094A19525964497219B209C0D9D0A9EA89F08A321A480A520A68AA790AD01B040B210C0FFC2FFC4FFCAF9CCF2CEFDE242E401EA01000103027E | ||||
| :4004400004E0050108010A080B020CE00F02100F1280130814481602170218201B021E071F02200422482302261027022A082B042F10311F34E0361F382039023F015804DF | ||||
| :4004800059045B045C095F0180038109840387318A018B098C038F06900391129309940395099712980399409E02A003A309A603A709A803A909AC03AD49AF24B338B40349 | ||||
| :4004C000B540B707BB88BE10D804D904DB04DC90DF010080012002800320048A052008180A010B400C020D080E0610021325172918081E061F802002215423252480284155 | ||||
| :4005000029202B202C872D202F203108321233013448350137A0380239883B103C803E043F115A806E408340860287048A0690029289935094019704981A99019B889C84CD | ||||
| :400540009D209F20A0C2A108A280A328A401AB10B204C0FFC2FFC47FCAFFCCF7CEFFD608E080E620EA85EE2002800404050D064808200A400C0111011210144816021A07E2 | ||||
| :400580001B051C401E202608280129102A082C0F2D0A3020310C32C03303341F362037103A083E413F4056085804590B5B045C995D905F01822083018607870F88218A0825 | ||||
| :4005C0008B018C218F019210930E9428964297059AC89B039F01A02FA280A301A444A628A709A90FAA20AD0FB105B21FB4E0B503B709BA20BF51D804D904DC09DF010001EA | ||||
| :400600000184030805A4078009090A060D080E881006121015141701180219811A051B481D041E081F20210422412501264027082B052C822F2432113408350137A03908B7 | ||||
| :400640003C823D043F144410450858805B10630A64086610780284018601911092289358950896019704980A9B819D249F20A0C2A108A280A401A761A840AF11B040B504F1 | ||||
| :40068000B702C0FFC27FC477CAFCCCF5CEF2D60CD80CDE01E202E640E880EA10EE4002080349077F08010A280B090C2F0F091001117F1408160217091A071B091E401F2962 | ||||
| :4006C000221023722709280429782A282B042F19310732603348341F352837183F55580459045B045C095F01802081048440850186A088418A088C4F8E808F04920794041B | ||||
| :40070000966898689A029B019C41A208A610AA40AD02B01FB304B503B6E0BA80BF04D608D804D904DB04DC99DD90DF010128024003010521070109040A810B080D080E0633 | ||||
| :400740000F80128013181608170218821A801D081E041F14221423102601271A2B012D042E012F253210341036843721380239083A403C023D1A3E0A3F54584060026240FE | ||||
| :4007800068026B016F0A831886408B048C018D089342951496019714980899019B809C109D209E0A9F21A0C0A284A402A509A74AB308B504C0DFC2FFC45ECAF8CCF4CEFBE6 | ||||
| :4007C000D608D808E010E280E644EE820002012F020103800402060107070A060B200C020E010FC81002120114071528174218021A011B101C021E012121220523082544DD | ||||
| :400800002607272829212A012C0731E03207331F3B023E04580459045C905F0182698502861988198E198F119019924493049419962298229A199B089C19A20EA306A61923 | ||||
| :40084000A702A910AA19AB01AD01AE19AF10B070B208B301B407B510B607B70EB928BAA2BB80BE04BF14D804D904DB04DC99DF010082012402400521060207200810094941 | ||||
| :400880000B200C020D090E010F04104213141514164017801A201C821D011E281F012010210423C025442680270829202A082B402C802F1A30803108329034483614378162 | ||||
| :4008C000390A3B503D403F046D408C10C0FFC2FFC4FFCAF7CCA6CE5FE210010E04080508060409080C0D0E020F08110812091504180819081A021D081E04200423012702A7 | ||||
| :4009000029082D08300C320C330F34033A0A3F045608580459045B045C095D905F01801382048402871088028B1F8C088E018F1F901991019202951F96099A089B049C0273 | ||||
| :400940009D1FA001A20CA308A602A720A802AB02AC1BAD1FB210B40FB73FBB80BE14D804D904DC90DF010108021104020540060807200A040B810D110F2211021405161004 | ||||
| :400980001702190A1A041E201F20210425402680270229442A212C802E202F2130803120320433113545371039163A803B033D843F2058806002680D6A508101821084A1C0 | ||||
| :4009C000880289028B048E5090029134922893859508980599459AA99B219C229D0AA080A121A311A40CA690AA88AD80AF10B111B504B648C0F5C2FBC4F8CAFFCCFFCE7FAE | ||||
| :400A0000D608D808E248E401E602E809EE030001062008010A7E0D010E08107F167F1A041E1020022101247E26012A402C7F3501367F3B303E40580459045B045C905F0179 | ||||
| :400A4000804484118708881189078C078E088F109211941195A5974298119B429C119F21A011A307A433A5C6A644A721A878AA02AC20AD84AE02B3E0B51FB67FB71FB9A0BC | ||||
| :400A8000BE40C004C5E0C6C0C80AC9FFCAFFCBFFD004D601D804D904DA04DB04DC90DD09DF01E2C001160201030204020540071409A80B400C810D200F2010041141130440 | ||||
| :400AC00015A016A019801F80214023152510270428222B402F8030083250384039083B103D8041014B025210688069756B116C016E406F02705071E972A07348810A8204C4 | ||||
| :400B00008404850487048A108C509040910292A8938094A295A496409733980199049B209C269D0A9EB89F18A141A351A484A530A68CA808B210B540C0FFC2FFC4FFCA8B79 | ||||
| :400B4000CC0ECE1ED001E003E208E402EA40EE060601083109100D0C0E080F021040130116021702180319011A101E0420382304240325082608290A2B042C022E2130400E | ||||
| :400B8000310F3207351036383A803E013F10580459045B045C995F018001830C8401870188018A028B078C018F019001930194019701980199079E019F01A001A108A302BA | ||||
| :400BC000A601A701A801AB01AC01AE02AF01B507B603B708BE40BF50D804D904DF0100820201032A05480608081909800B400D080E461002128013241501174818011D4E2B | ||||
| :400C00001E01218022102408260228082BA22C082E022F103011328436063710380239A83D103F806D5080048280850186058C208D01900291A89248934494019620981A26 | ||||
| :400C40009A029B609C809D20A043A284A328AB80B604C0EFC2FFC4BFCAEFCCEFCE3FE080E451E8C0EE02000801010201050108040B010C010D010E081101130217011901F5 | ||||
| :400C80001A011D01210123022401250129012A022D01300332043303340836083A023E543F0440434502480149FF4AFF4BFF4D204EF05110580459045A045C095D095F017F | ||||
| :400CC0006108624063406480664067408004840885CC86018722881F8C048D01900493119401961E9722980499F19C019E10A004A344A588A604A824A9AAAA19AB44AC0134 | ||||
| :400D0000AE22B020B30FB50EB61FB7F0BE41BF10D804D90BDC90DF01002001020301058907080B040C200D090E011010120816801764181019221A0A1B801D021E0222083E | ||||
| :400D400025602711280929022B202C082E022F10301232843606371039A83A013D884010410248107C0283408520881089088B308C088D448F4091EA920193049602972033 | ||||
| :400D8000981B99819A839B0C9D209F10A022A108A286A320A408A601A7C0A904AB04AD01AE01B080B18AB608B708C0FBC2F2C4F6CAEFCCEFCE5FD003DE80E0A0E240E47094 | ||||
| :400DC000E602E890ECC01B011F0231203302368037083B40C630CCF0CE103088364037043A023C2088108F0893809F08A520AE80AF41B340CCF0CE60EE4053405640840897 | ||||
| :400E00008C8093809A409E029F04A488A520A6C0B2C0D460E2408E0292029E02A520A6C0AB04AE01EA80EE4015027B02C404DC015940670882108E4191029720AF10B7020E | ||||
| :400E4000D401D801E008E602EC021A4085408D049102966097289D40A201C608E60209440F4191029420962097299C409D40A201A544A810AB01B040C20FEA0126809202EF | ||||
| :400E8000A320A520A680AE40B720C820EE405280572079407E01828085208D409202A320A520D460DC80DE20E210E62004200A200C400F401F1050805B405E025F8083408D | ||||
| :400EC000894091029420962097209C409D40A201AF40B304C001C20DC601D405D605E001E801850188809102A480B3C0E401EA04EC04010109010B010D010F0111011B01BF | ||||
| :400F00001D0100FF01AB020211050000BF0000A09F001F000000000000000000100000004000000000000000C0000000FF0000B847004700000100008000000282008200D5 | ||||
| :400F400000000000000303000300000027001801270018010004000000050000000000000000000000000000000000000000000000000000000000000000000000000000DF | ||||
| :400000000145004008520040015B004001640040020101400B0301403E04014041050140130701405508014056090140510A0140540B01405B0C0140540D0140470E01400D | ||||
| :40004000380F01400A1501400B1701404B18014059190140521A01404E1B01400B40014012410140144201400C430140044401400D4501400946014011470140084801406A | ||||
| :4000800011490140154C0140034D014006500140045101407E0208020941118218021901600C61067C4027212D0A8C40E62082608580908091029840AD01B040E008E224DC | ||||
| :4000C000E680EE020008021003020405052006020B080F041110120117041A021B011C041F0420062107220123082610270428102A082B042F04300731203208330F361052 | ||||
| :40010000371038883A303B083E453F4156085808590A5B045C995D905F0189018B028D039601A002A102A301AC01B202B303B601BE04D608D804D904DB04DC99DD90DF0157 | ||||
| :40014000000A09900A400F10100811081302164119801AA01B221C101F802142231026082A252B012F80300231443220388039023B143F90584059105F80618063046640B5 | ||||
| :4001800068046B026D206E407A107B028110822088088A108E018F4090809102968098409A209D80A502B502C00CC22BC49ECA8FCC0FCE3FD61CD81CDE0AE204E60DEA04B2 | ||||
| :4001C000EE0181108D449010918092609D449E049F80A110A402A701A904AC01B208B720E202E60AEA05EE080004020804010602080409010AF90B140D010E020F2810030B | ||||
| :4002000012FC134114041580164017011A041B4E1C801E042202234124042620274128042A102B412CFF2DF12F02310F32FF330F35F03B0A3E045804590B5B045C905F0188 | ||||
| :40024000800481078378840485088730880489808C038DFF8E0490019101920294029502970498029C029DA09F48A002A102A304A404A53FA802A908AB10AC05AF80B13F30 | ||||
| :40028000B207B33FB7C0BB80BE04D804D904DC90DF01008801020308048405020708084009220A110C040D090F0911011202132814801568170119041C202104224A230182 | ||||
| :4002C00025052714288629042C022F6430083102324035013714394A3B203F60422043045C405D206D106E407C028D01914293689420952D96909785980A99039A089B0820 | ||||
| :400300009C709D109E069FD5A042A108A280A31CA494A502A65DA702AB02AD10B220B380B610C0FFC2FFC4FFCAFFCCEBCE3FD630DE80E212E410E60AE840EA01EC80000C29 | ||||
| :4003400002F1040C06100A040E021080120C140C164018011A021C031EFC22022608280C2A202CFF34FF3E10560858045B045D905F0180088121830284C085218601870427 | ||||
| :4003800088088B108D2F8E04900291019204941A96209740980899209B019C109E209F2FA046A121A238A30EA408A808A921AB08AD0FAE80B23FB360B480B51FB640B71FD4 | ||||
| :4003C000B908BE44C203C60EC804C9FFCAFFCBFFCF83D804D904DA04DB04DC99DD09DF01000801020309050A070909080A820B040D0A0F091141120813081402152A192051 | ||||
| :400400001D041F9024022508268027082A082B102C402D402E10351437813CA03D0540804240462057405A015B415EA6600263026540661668026A406D90835089408B01C6 | ||||
| :400440008E409142920693489422953D96B197809808994B9A109CF29D309F14A040A31CA480A54AA604A702A814AC08B780C0FFC2FFC4FFCAB0CCF0CEF0D040D6F8D8F8B5 | ||||
| :40048000E280E66CE802EC1000200250061008400A3010621208146216041A031C801D01207C2201261C2A102E10306031013280341F3E043F01580B59045B045C095F01FF | ||||
| :4004C000802381C8820C85C8860189C88A108C2F8D228FCC9130922F9302942395C8960899029A409C239F48A020A1C8A202A423A604A780A880A9D4AC0FAD80AF01B01FA9 | ||||
| :40050000B161B260B380B480B51FB808B902BE10BF14C062C702C810C9FFCAFFCBFFCD20CEF0D110D804D904DA04DB04DC99DD09DF01E108E240E340E480E640E7400040C6 | ||||
| :40054000012102200505070409220A110C800E040F6010481144148016221710180419021B0C1C201D011E0420C0212122092501281029022B052E202F04311A32603504B8 | ||||
| :4005800036443842392840044A0850085F80660267806B026E807C02810188108B028D018F40900891409348951096209780980899489A109CA29D019E029F14A351A54004 | ||||
| :4005C000A604A702AB80AF40B548C07FC2FFC4FFCA0FCC1FCE0FD004D204D610DE80E008E220E680EA81012002010340070308100A080B100F10100413101408161217100D | ||||
| :400600001B1C1C1B1D401F20217C2301250227042B102D022F083001316032023418351F36043E40580B590B5B045C995F01804082308610888089018A308B028D028F0133 | ||||
| :4006400090E2920894E296049A109E03A0FCA201A420A6D0AE1CAF01B2E0B301B502B61FB928BBC0BF14D608D80BD918DB04DC99DD90DF0100110501071408800A600C019B | ||||
| :400680000D100E0A0F60121013041480162218101A801B501D401E121F0C23442409250828812A202B182F02310132403314380139203B843D905C205F80640867026A40A1 | ||||
| :4006C0006D40780279407B017C027F0189088E10C07AC2FDC4B0CA1FCC0FCE3FD630D830DE91E63080028E409240A402AD40B301E204E640EC01EE0A878092409D409F8071 | ||||
| :40070000A402A701A810B614E202EA40EC010040021105C20724082009200A110BC00D020F4810F11202139014F11604179C18101AE11B901E0E1F0320F1220823902480D4 | ||||
| :40074000261127902B902DFC2F0134F035E0360F371F3A803B20580B590B5B045C995F018001821A8411850186068C059C01A703AC05AD03B101B20CB302B410B501B603BE | ||||
| :40078000BE10BF11C006C6ECC80CC9FFCAFFCBFFD004D601D804D904DA04DB04DC99DD09DF01E2C00080010803800410050109800C420E080F201140166019681B801C02B3 | ||||
| :4007C0001E081F6020042106220223842510264029482C422F6435013640371439083A403B403D203E083F4045104604492050105180680869056A106B236F027040713001 | ||||
| :40080000728173087C127F04842091529280934894A4952596119784980299039A289B149C309D109E069FE1A042A10CA288A314A40CA522A655A722A920B4C8B640B7042C | ||||
| :40084000C05DC2F1C431CAFACCF0CE72D204DE80E202E608EE10000101120324040706080760088009800A100C0F0D700EF00F01104011421280131014801620187019069A | ||||
| :400880001A801C011D0420082104220424012708280829042A022E0F2F10318032FF3370350F39203E043F01580459045B045C905F018210838487848A108B848D168E10FE | ||||
| :4008C0008F41901C920193E49402960497849A1C9B189E03A002A101A208A306A510A610A722AA10AB84ADE7AF08B5F8B61FB707BB80D80BD90BDC99DF01008001050208F7 | ||||
| :400900000410058109080A810B040C020E0A0F2010081202130A166819081E02200821142211232425802610290A2A802B042C022E222F20329235013614395A3C123D0820 | ||||
| :400940003E083F40458046024801498058105B206A407B307C028240860190109157928193409520980299039AE09B0A9C109E02A04BA10CA28EA314A404A611AB40AF2038 | ||||
| :40098000B001C0DFC2FFC47FCAFFCCEDCEFFDE80E402EA80EE021B011F0232203302350836803B408908C630CCF0CE1030013180344037043A013F80822088028B1097407A | ||||
| :4009C0009D08A108A620AE80AF01CCF0CE60E6805108560883408508932097409A089C419D089F04A002A108A580A740AA09D460E220E610EA20EE808108844185809320A9 | ||||
| :400A000097409C41A002A580AB04E2C0E650EA8014407002C404DC015840601084028C108D20A40AA808B040D401D802E008E402EA011B01811087019A109C40A120A4082A | ||||
| :400A4000AE10C6080A040B200E200F01861487108E0297019A109D10A120A408AB01B040C20FE408E8012620932097409902A002A108B502C82052015310550870027502C3 | ||||
| :400A80008E0193209902A002A108AA20AF40D4E0DC80DE20EC80EE40051008080C080F041F105120561059206202840887049A109D10A120A202A408C001C20DC601D407CD | ||||
| :400AC000D80285209D20AF1001010B010D010F0111011D0100FF01AB02021105BF0000A09F001F000000000000000000100000004000000000000000C0000000FF0000B8F6 | ||||
| :400B00004700470000010000800000028200820000000000000707000700000027001801270018010004000000050000000000000000000000000000000000000000000002 | ||||
| :400B40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000075 | ||||
| :400B80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035 | ||||
| :400BC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F5 | ||||
| :400C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B4 | ||||
| :400C40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000074 | ||||
| :400C80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034 | ||||
| :400CC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F4 | ||||
| :400D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B3 | ||||
| :400D40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000073 | ||||
| :400D80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033 | ||||
| :400DC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F3 | ||||
| :400E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B2 | ||||
| :400E40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000072 | ||||
| :400E80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000032 | ||||
| :400EC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F2 | ||||
| :400F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1 | ||||
| :400F40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071 | ||||
| :400F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031 | ||||
| :400FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F1 | ||||
| :4010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B0 | ||||
| @@ -4615,12 +4615,12 @@ | ||||
| :0200000490105A | ||||
| :04000000BC90ACAF55 | ||||
| :0200000490303A | ||||
| :0200000005AB4E | ||||
| :0200000090CF9F | ||||
| :0200000490402A | ||||
| :4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C0 | ||||
| :400040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 | ||||
| :400080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040 | ||||
| :4000C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | ||||
| :0200000490501A | ||||
| :0C00000000012E16106900002E321614AC | ||||
| :0C00000000012E16106900002E30A138FF | ||||
| :00000001FF | ||||
| @@ -814,9 +814,9 @@ | ||||
|   </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" /> | ||||
|       <Data key="LIN_Dynamic" value="LIN_Dynamic_v6_0" /> | ||||
|     </Group> | ||||
|   </Group> | ||||
|   <Data key="DataVersionKey" value="2" /> | ||||
| @@ -848,6 +848,7 @@ | ||||
|       <Data key="efd5f185-0c32-4824-ba72-3ceb5356f5a7" value="Clock_1" /> | ||||
|     </Group> | ||||
|     <Group key="Pin"> | ||||
|       <Data key="3e1862bb-be82-47b0-9549-7ebfe76b6f7b" value="Pin_2" /> | ||||
|       <Data key="4a398466-709f-4228-9500-96178658e13e" value="RDATA" /> | ||||
|       <Data key="5a3407c1-b434-4438-a7b4-b9dfd2280495" value="MOTEA" /> | ||||
|       <Data key="8d318d8b-cf7b-4b6b-b02c-ab1c5c49d0ba" value="SW1" /> | ||||
| @@ -858,6 +859,7 @@ | ||||
|       <Data key="472f8fdb-f772-44fb-8897-cc690694237b" value="WDATA" /> | ||||
|       <Data key="736cb12b-c863-43d4-a8f0-42f06023f8b5" value="SIDE1" /> | ||||
|       <Data key="4249c923-fcff-453b-8629-bec6fddd00c1" value="STEP" /> | ||||
|       <Data key="27315b0e-6a8c-4b7f-be77-73ab434fa803" value="Pin_1" /> | ||||
|       <Data key="1425177d-0d0e-4468-8bcc-e638e5509a9b" value="UartRx" /> | ||||
|       <Data key="a5d987c6-e45b-45b9-ad93-656fab06d720" value="TRK00" /> | ||||
|       <Data key="a93ef5b3-00f4-42c0-8fad-0e275a7e2537" value="MOTEB" /> | ||||
| @@ -869,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" /> | ||||
| @@ -3963,6 +3966,11 @@ | ||||
|     </Group> | ||||
|   </Group> | ||||
|   <Group key="Pin2"> | ||||
|     <Group key="3e1862bb-be82-47b0-9549-7ebfe76b6f7b"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="0,6" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="4a398466-709f-4228-9500-96178658e13e"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="1,5" /> | ||||
| @@ -4064,6 +4072,11 @@ | ||||
|         <Data key="Port Format" value="1,0" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="27315b0e-6a8c-4b7f-be77-73ab434fa803"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="0,7" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="1425177d-0d0e-4468-8bcc-e638e5509a9b"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="12,6" /> | ||||
| @@ -4149,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" /> | ||||
|   | ||||
| @@ -26,33 +26,12 @@ | ||||
| <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="patcher.vbs" persistent="patcher.vbs"> | ||||
| <Hidden v="False" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="OTHER;;;;" /> | ||||
| <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="protocol.h" persistent="..\protocol.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="crunch.c" persistent="..\lib\common\crunch.c"> | ||||
| <Hidden v="False" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="SOURCE_C;;;;" /> | ||||
| <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="crunch.h" persistent="..\lib\common\crunch.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> | ||||
| @@ -2795,6 +2774,138 @@ | ||||
| </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="Pin_2" persistent=""> | ||||
| <Hidden v="True" /> | ||||
| </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="Pin_2_aliases.h" persistent="Generated_Source\PSoC5\Pin_2_aliases.h"> | ||||
| <Hidden v="True" /> | ||||
| </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="Pin_2.c" persistent="Generated_Source\PSoC5\Pin_2.c"> | ||||
| <Hidden v="True" /> | ||||
| </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="Pin_2.h" persistent="Generated_Source\PSoC5\Pin_2.h"> | ||||
| <Hidden v="True" /> | ||||
| </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> | ||||
| <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="Pin_1" persistent=""> | ||||
| <Hidden v="True" /> | ||||
| </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="Pin_1_aliases.h" persistent="Generated_Source\PSoC5\Pin_1_aliases.h"> | ||||
| <Hidden v="True" /> | ||||
| </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="Pin_1.c" persistent="Generated_Source\PSoC5\Pin_1.c"> | ||||
| <Hidden v="True" /> | ||||
| </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="Pin_1.h" persistent="Generated_Source\PSoC5\Pin_1.h"> | ||||
| <Hidden v="True" /> | ||||
| </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> | ||||
| <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> | ||||
| @@ -3183,7 +3294,7 @@ | ||||
| <name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Optimization@SHARED Optimization Level" v="" /> | ||||
| <name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Optimization@SHARED Link Time Optimization" v="" /> | ||||
| <name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Optimization@SHARED Fat LTO objects" v="" /> | ||||
| <name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@User Commands@General@Pre Build Commands" v="cscript patcher.vbs" /> | ||||
| <name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@User Commands@General@Pre Build Commands" v="" /> | ||||
| <name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@User Commands@General@Post Build Commands" v="" /> | ||||
| </name> | ||||
| </platform> | ||||
| @@ -3362,8 +3473,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> | ||||
| @@ -3375,11 +3486,9 @@ | ||||
| <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="138" /> | ||||
| <current_generation v="150" /> | ||||
| </CyGuid_fec8f9e8-2365-4bdb-96d3-a4380222e01b> | ||||
| </CyXmlSerializer> | ||||
| @@ -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,90 +18,76 @@ module Sampler ( | ||||
|  | ||||
| //`#start body` -- edit after this line, do not edit this line | ||||
|  | ||||
| localparam STATE_RESET = 0; | ||||
| localparam STATE_WAITING = 1; | ||||
| localparam STATE_OPCODE = 2; | ||||
| // NOTE: Reset pulse is used in both clock domains, and must be long enough | ||||
| // to be detected in both. | ||||
|  | ||||
| reg [1:0] state; | ||||
| reg [6:0] counter; | ||||
| reg [5:0] counter; | ||||
|  | ||||
| reg oldsampleclock; | ||||
| wire sampleclocked; | ||||
| assign sampleclocked = !oldsampleclock && sampleclock; | ||||
| reg index_edge; | ||||
| reg rdata_edge; | ||||
|  | ||||
| reg oldindex; | ||||
| wire indexed; | ||||
| assign indexed = !oldindex && index; | ||||
| reg req_toggle; | ||||
|  | ||||
| wire rdataed; | ||||
| reg oldrdata; | ||||
| assign rdataed = !oldrdata && rdata; | ||||
| reg rdata_toggle; | ||||
| reg old_rdata_toggle; | ||||
|  | ||||
| assign req = (state == STATE_OPCODE); | ||||
| reg index_toggle; | ||||
| reg old_index_toggle; | ||||
|  | ||||
| always @(posedge clock) | ||||
| always @(posedge rdata) | ||||
| begin | ||||
|     rdata_toggle <= ~rdata_toggle; | ||||
| end | ||||
|  | ||||
| always @(posedge index) | ||||
| begin | ||||
|     index_toggle <= ~index_toggle; | ||||
| end | ||||
|  | ||||
| always @(posedge sampleclock) | ||||
| begin | ||||
|     if (reset) | ||||
|     begin | ||||
|         state <= STATE_RESET; | ||||
|         opcode <= 0; | ||||
|         oldsampleclock <= 0; | ||||
|         oldindex <= 0; | ||||
|         oldrdata <= 0; | ||||
|         old_rdata_toggle <= 0; | ||||
|         old_index_toggle <= 0; | ||||
|          | ||||
|         index_edge <= 0; | ||||
|         rdata_edge <= 0; | ||||
|         counter <= 0; | ||||
|         req_toggle <= 0; | ||||
|     end | ||||
|     else | ||||
|         case (state) | ||||
|             STATE_RESET: | ||||
|                 state <= STATE_WAITING; | ||||
|              | ||||
|             STATE_WAITING: | ||||
|             begin | ||||
|                 /* If something has happened, emit any necessary interval byte. */ | ||||
|                 if ((rdataed || indexed) && (counter != 0)) | ||||
|                 begin | ||||
|                     opcode <= {0, counter}; | ||||
|                     state <= STATE_OPCODE; | ||||
|                 end | ||||
|                 else if (indexed) | ||||
|                 begin | ||||
|                     oldindex <= 1; | ||||
|                     opcode <= 8'h81; | ||||
|                     state <= STATE_OPCODE; | ||||
|                 end | ||||
|                 else if (rdataed) | ||||
|                 begin | ||||
|                     oldrdata <= 1; | ||||
|                     opcode <= 8'h80; | ||||
|                     state <= STATE_OPCODE; | ||||
|                 end | ||||
|                 else if (sampleclocked) | ||||
|                 begin | ||||
|                     oldsampleclock <= 1; | ||||
|                     if (counter == 7'h7f) | ||||
|                     begin | ||||
|                         opcode <= {0, counter}; | ||||
|                         state <= STATE_OPCODE; | ||||
|                     end | ||||
|                     counter <= counter + 1; | ||||
|                 end | ||||
|                  | ||||
|                 /* Reset state once we've done the thing. */ | ||||
|                  | ||||
|                 if (oldrdata && !rdata) | ||||
|                     oldrdata <= 0; | ||||
|                 if (oldindex && !index) | ||||
|                     oldindex <= 0; | ||||
|                 if (oldsampleclock && !sampleclock) | ||||
|                     oldsampleclock <= 0; | ||||
|             end | ||||
|              | ||||
|             STATE_OPCODE: /* opcode or interval byte sent here */ | ||||
|             begin | ||||
|                 state <= STATE_WAITING; | ||||
|                 counter <= 0; | ||||
|             end | ||||
|         endcase | ||||
|     begin | ||||
|         /* If data_toggle or index_toggle have changed state, this means that they've | ||||
|          * gone high since the last sampleclock. */ | ||||
|           | ||||
|         index_edge <= index_toggle != old_index_toggle; | ||||
|         old_index_toggle <= index_toggle; | ||||
|          | ||||
|         rdata_edge <= rdata_toggle != old_rdata_toggle; | ||||
|         old_rdata_toggle <= rdata_toggle; | ||||
|          | ||||
|         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 | ||||
|  | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
|   | ||||
| @@ -19,19 +19,15 @@ module Sequencer ( | ||||
| //`#start body` -- edit after this line, do not edit this line | ||||
|  | ||||
| localparam STATE_LOAD = 0; | ||||
| localparam STATE_WAITING = 1; | ||||
| localparam STATE_PULSING = 2; | ||||
| localparam STATE_INDEXING = 3; | ||||
| localparam STATE_WRITING = 1; | ||||
|  | ||||
| localparam OPCODE_PULSE = 8'h80; | ||||
| localparam OPCODE_INDEX = 8'h81; | ||||
|  | ||||
| reg [1:0] state; | ||||
| reg [6:0] countdown; | ||||
| reg state; | ||||
| reg [5:0] countdown; | ||||
| reg pulsepending; | ||||
|  | ||||
| assign req = (!reset && (state == STATE_LOAD)); | ||||
| assign wdata = (state == STATE_PULSING); | ||||
| assign debug_state = state; | ||||
| assign wdata = (!reset && (state == STATE_WRITING) && (countdown == 0) && pulsepending); | ||||
| assign debug_state = 0; | ||||
|  | ||||
| reg olddataclock; | ||||
| wire dataclocked; | ||||
| @@ -52,49 +48,43 @@ begin | ||||
|     begin | ||||
|         state <= STATE_LOAD; | ||||
|         countdown <= 0; | ||||
|         pulsepending <= 0; | ||||
|         oldsampleclock <= 0; | ||||
|     end | ||||
|     else | ||||
|     begin | ||||
|         if (!oldsampleclock && sampleclock) | ||||
|             sampleclocked <= 1; | ||||
|         oldsampleclock <= sampleclock; | ||||
|          | ||||
|              | ||||
|         case (state) | ||||
|             STATE_LOAD: | ||||
|                 /* Wait for a posedge on dataclocked, indicating an opcode has | ||||
|             begin | ||||
|                 /* A posedge on dataclocked indicates that another opcode has | ||||
|                  * arrived. */ | ||||
|                 if (dataclocked) | ||||
|                     case (opcode) | ||||
|                         OPCODE_PULSE: | ||||
|                             state <= STATE_PULSING; | ||||
|                          | ||||
|                         OPCODE_INDEX: | ||||
|                             state <= STATE_INDEXING; | ||||
|                          | ||||
|                         default: | ||||
|                         begin | ||||
|                             countdown <= opcode[6:0]; | ||||
|                             state <= STATE_WAITING; | ||||
|                         end | ||||
|                     endcase | ||||
|                 begin | ||||
|                     pulsepending <= opcode[7]; | ||||
|                     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 | ||||
|              | ||||
|             STATE_WAITING: | ||||
|             STATE_WRITING: | ||||
|             begin | ||||
|                 if (sampleclocked) | ||||
|                 begin | ||||
|                     sampleclocked <= 0; | ||||
|                     countdown <= countdown - 1; | ||||
|                     /* Nasty fudge factor here to account for one to two | ||||
|                      * sample ticks lost per pulse. */ | ||||
|                     if (countdown <= 2) | ||||
|                     if (countdown == 0) | ||||
|                         state <= STATE_LOAD; | ||||
|                     else | ||||
|                         countdown <= countdown - 1; | ||||
|                     sampleclocked <= 0; | ||||
|                 end | ||||
|              | ||||
|             STATE_PULSING: | ||||
|                 state <= STATE_LOAD; | ||||
|              | ||||
|             STATE_INDEXING: | ||||
|                 if (indexed) | ||||
|                     state <= STATE_LOAD; | ||||
|             end | ||||
|         endcase | ||||
|     end | ||||
| end | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| @@ -5,7 +5,6 @@ | ||||
| #include <setjmp.h> | ||||
| #include "project.h" | ||||
| #include "../protocol.h" | ||||
| #include "../lib/common/crunch.h" | ||||
|  | ||||
| #define MOTOR_ON_TIME 5000 /* milliseconds */ | ||||
| #define STEP_INTERVAL_TIME 6 /* ms */ | ||||
| @@ -14,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; | ||||
| @@ -34,7 +37,6 @@ static struct set_drive_frame current_drive_flags; | ||||
| static uint8_t td[BUFFER_COUNT]; | ||||
| static uint8_t dma_buffer[BUFFER_COUNT][BUFFER_SIZE] __attribute__((aligned())); | ||||
| static uint8_t usb_buffer[BUFFER_SIZE] __attribute__((aligned())); | ||||
| static uint8_t xfer_buffer[BUFFER_SIZE] __attribute__((aligned())); | ||||
| static uint8_t dma_channel; | ||||
| #define NEXT_BUFFER(b) (((b)+1) % BUFFER_COUNT) | ||||
|  | ||||
| @@ -71,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) | ||||
| @@ -116,7 +147,7 @@ static void set_drive_flags(struct set_drive_frame* flags) | ||||
|      | ||||
|     current_drive_flags = *flags; | ||||
|     DRIVESELECT_REG_Write(flags->drive ? 2 : 1); /* select drive 1 or 0 */ | ||||
|     DENSITY_REG_Write(flags->high_density); /* density bit */ | ||||
|     DENSITY_REG_Write(!flags->high_density); /* double density bit */ | ||||
|     INDEX_REG_Write(flags->index_mode); | ||||
| } | ||||
|  | ||||
| @@ -151,6 +182,12 @@ static void wait_until_writeable(int ep) | ||||
|         ; | ||||
| } | ||||
|  | ||||
| static void wait_until_readable(int ep) | ||||
| { | ||||
|     while (USBFS_GetEPState(ep) != USBFS_OUT_BUFFER_FULL) | ||||
|         ; | ||||
| } | ||||
|  | ||||
| static void send_reply(struct any_frame* f) | ||||
| { | ||||
|     print("reply 0x%02x", f->f.type); | ||||
| @@ -168,9 +205,15 @@ static void send_error(int code) | ||||
| /* buffer must be big enough for a frame */ | ||||
| static int usb_read(int ep, uint8_t buffer[FRAME_SIZE]) | ||||
| { | ||||
|     if (USBFS_GetEPState(ep) != USBFS_OUT_BUFFER_FULL) | ||||
|     { | ||||
|         USBFS_EnableOutEP(ep); | ||||
|         wait_until_readable(ep); | ||||
|     } | ||||
|  | ||||
|     int length = USBFS_GetEPCount(ep); | ||||
|     USBFS_ReadOutEP(ep, buffer, length); | ||||
|     while (USBFS_GetEPState(ep) == USBFS_OUT_BUFFER_FULL) | ||||
|     while (USBFS_GetEPState(ep) != USBFS_OUT_BUFFER_EMPTY) | ||||
|         ; | ||||
|     return length; | ||||
| } | ||||
| @@ -239,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"); | ||||
| } | ||||
|  | ||||
| @@ -257,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(); | ||||
|      | ||||
| @@ -267,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; | ||||
| @@ -276,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); | ||||
| @@ -319,13 +367,7 @@ static void cmd_bulk_read_test(struct any_frame* f) | ||||
|         CyWdtClear(); | ||||
|         for (int y=0; y<256; y++) | ||||
|         { | ||||
|             USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM); | ||||
|             while (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) != USBFS_OUT_BUFFER_FULL) | ||||
|                 ; | ||||
|             USBFS_ReadOutEP(FLUXENGINE_DATA_OUT_EP_NUM, buffer, sizeof(buffer)); | ||||
|             while (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) != USBFS_OUT_BUFFER_EMPTY) | ||||
|                 ; | ||||
|              | ||||
|             usb_read(FLUXENGINE_DATA_OUT_EP_NUM, buffer); | ||||
|             for (unsigned z=0; z<sizeof(buffer); z++) | ||||
|             { | ||||
|                 if (buffer[z] != (uint8)(x+y+z)) | ||||
| @@ -356,7 +398,7 @@ static void deinit_dma(void) | ||||
| static void init_capture_dma(void) | ||||
| { | ||||
|     dma_channel = SAMPLER_DMA_DmaInitialize( | ||||
|         2 /* bytes */, | ||||
|         1 /* bytes */, | ||||
|         true /* request per burst */,  | ||||
|         HI16(CYDEV_PERIPH_BASE), | ||||
|         HI16(CYDEV_SRAM_BASE)); | ||||
| @@ -377,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. */ | ||||
|      | ||||
|     { | ||||
| @@ -397,16 +439,14 @@ 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; | ||||
|     } | ||||
|      | ||||
|     crunch_state_t cs = {}; | ||||
|     cs.outputptr = xfer_buffer; | ||||
|     cs.outputlen = BUFFER_SIZE; | ||||
|      | ||||
|     dma_writing_to_td = 0; | ||||
|     dma_reading_from_td = -1; | ||||
|     dma_underrun = false; | ||||
| @@ -463,54 +503,22 @@ static void cmd_read(struct read_frame* f) | ||||
|         { | ||||
|             /* Otherwise, there's a block waiting, so attempt to send it. */ | ||||
|              | ||||
|             uint8_t dma_buffer_usage = 0; | ||||
|             while (dma_buffer_usage < BUFFER_SIZE) | ||||
|             { | ||||
|                 cs.inputptr = dma_buffer[dma_reading_from_td] + dma_buffer_usage; | ||||
|                 cs.inputlen = BUFFER_SIZE - dma_buffer_usage; | ||||
|                 crunch(&cs); | ||||
|                 dma_buffer_usage += BUFFER_SIZE - cs.inputlen; | ||||
|                 count++; | ||||
|                  | ||||
|                 /* If there is no available space in the output buffer, flush the buffer via | ||||
|                  * USB and go again. */ | ||||
|                 if (cs.outputlen == 0) | ||||
|                 { | ||||
|                     wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM); | ||||
|                     memcpy(usb_buffer, xfer_buffer, FRAME_SIZE); | ||||
|                     USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE); | ||||
|                      | ||||
|                     cs.outputptr = xfer_buffer; | ||||
|                     cs.outputlen = BUFFER_SIZE; | ||||
|                 } | ||||
|             } | ||||
|             wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM); | ||||
|             USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, dma_buffer[dma_reading_from_td], BUFFER_SIZE); | ||||
|             count++; | ||||
|             dma_reading_from_td = NEXT_BUFFER(dma_reading_from_td); | ||||
|         } | ||||
|     } | ||||
| abort:; | ||||
|     bool saved_dma_underrun = dma_underrun; | ||||
|  | ||||
|     donecrunch(&cs); | ||||
|     /* Terminate the transfer (all transfers are an exact number of fragments). */ | ||||
|     wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM); | ||||
|     /* If there's a complete packet waiting, send it. */ | ||||
|     if (cs.outputlen != BUFFER_SIZE) | ||||
|     { | ||||
|         USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE); | ||||
|         wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM); | ||||
|     } | ||||
|     if ((cs.outputlen != 0) && (cs.outputlen != BUFFER_SIZE)) | ||||
|     { | ||||
|         /* If there's a partial packet waiting, send it; this will also terminate the transfer. */ | ||||
|         USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE-cs.outputlen); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         /* Otherwise just terminate the transfer. */ | ||||
|         USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, NULL, 0); | ||||
|     } | ||||
|     USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, NULL, 0); | ||||
|     wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM); | ||||
|     deinit_dma(); | ||||
|  | ||||
|     STEP_REG_Write(0); | ||||
|     if (saved_dma_underrun) | ||||
|     { | ||||
|         print("underrun after %d packets"); | ||||
| @@ -556,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; | ||||
| @@ -566,41 +575,21 @@ 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 */ | ||||
|     bool finished = false; | ||||
|     int packets = f->bytes_to_write / FRAME_SIZE; | ||||
|     bool finished = (packets == 0); | ||||
|     int count_written = 0; | ||||
|     int count_read = 0; | ||||
|     int packetwaiting = 0; | ||||
|     dma_writing_to_td = 0; | ||||
|     dma_reading_from_td = -1; | ||||
|     dma_underrun = false; | ||||
|  | ||||
|     crunch_state_t cs = {}; | ||||
|     cs.outputlen = BUFFER_SIZE; | ||||
|     USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM); | ||||
|      | ||||
|     int old_reading_from_td = -1; | ||||
|     for (;;) | ||||
|     { | ||||
|         CyWdtClear(); | ||||
|  | ||||
|         /* Make sure that we always have a USB read in progress whenever possible. */ | ||||
|          | ||||
|         if (!finished && !packetwaiting) | ||||
|         { | ||||
|             /* There is no read in progress; has data arrived in the external USB buffer? */ | ||||
|              | ||||
|             if (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) == USBFS_OUT_BUFFER_FULL) | ||||
|             { | ||||
|                 /* Yes, data has arrived, so initiate the copy. */ | ||||
|                  | ||||
|                 packetwaiting = USBFS_ReadOutEP(FLUXENGINE_DATA_OUT_EP_NUM, usb_buffer, FRAME_SIZE); | ||||
|             } | ||||
|         } | ||||
|         //CyWdtClear(); | ||||
|  | ||||
|         /* Read data from USB into the buffers. */ | ||||
|          | ||||
| @@ -609,59 +598,22 @@ static void cmd_write(struct write_frame* f) | ||||
|             if (writing && (dma_underrun || index_irq)) | ||||
|                 goto abort; | ||||
|              | ||||
|             /* Read crunched data, if necessary. */ | ||||
|              | ||||
|             if (cs.inputlen == 0) | ||||
|             uint8_t* buffer = dma_buffer[dma_writing_to_td]; | ||||
|             if (finished) | ||||
|             { | ||||
|                 if (finished) | ||||
|                 { | ||||
|                     /* There's no more data to read, so fake some. */ | ||||
|                      | ||||
|                     for (int i=0; i<BUFFER_SIZE; i++) | ||||
|                         xfer_buffer[i+0] = 0x7f; | ||||
|                     cs.inputptr = xfer_buffer; | ||||
|                     cs.inputlen = BUFFER_SIZE; | ||||
|                 } | ||||
|                 else if (packetwaiting) | ||||
|                 { | ||||
|                     /* There's a USB read into usb_buffer in progress, so check if it's finished. */ | ||||
|                      | ||||
|                     if (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) == USBFS_OUT_BUFFER_EMPTY) | ||||
|                     { | ||||
|                         /* It's done, so copy out the data. */ | ||||
|                          | ||||
|                         memcpy(xfer_buffer, usb_buffer, FRAME_SIZE); | ||||
|                         cs.inputptr = xfer_buffer; | ||||
|                         cs.inputlen = packetwaiting; | ||||
|  | ||||
|                         count_read++; | ||||
|                         if ((packetwaiting < FRAME_SIZE) || (count_read == packets)) | ||||
|                             finished = true; | ||||
|                         else | ||||
|                         { | ||||
|                             /* Wait for more USB data to show up. */ | ||||
|                              | ||||
|                             packetwaiting = 0; | ||||
|                             USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 /* There's no more data to read, so fake some. */ | ||||
|                  | ||||
|                 memset(buffer, 0x3f, BUFFER_SIZE); | ||||
|             } | ||||
|              | ||||
|             /* If there *is* data waiting in the buffer, uncrunch it. */ | ||||
|              | ||||
|             if (cs.inputlen != 0) | ||||
|             else | ||||
|             { | ||||
|                 cs.outputptr = dma_buffer[dma_writing_to_td] + BUFFER_SIZE - cs.outputlen; | ||||
|                 uncrunch(&cs); | ||||
|                 if (cs.outputlen == 0) | ||||
|                 { | ||||
|                     /* Completed a DMA buffer; queue it for writing. */ | ||||
|                      | ||||
|                     dma_writing_to_td = NEXT_BUFFER(dma_writing_to_td); | ||||
|                     cs.outputlen = BUFFER_SIZE; | ||||
|                 } | ||||
|                 (void) usb_read(FLUXENGINE_DATA_OUT_EP_NUM, buffer); | ||||
|                 count_read++; | ||||
|                  | ||||
|                 if (count_read == packets) | ||||
|                     finished = true; | ||||
|             } | ||||
|             dma_writing_to_td = NEXT_BUFFER(dma_writing_to_td); | ||||
|              | ||||
|             /* Once all the buffers are full, start writing. */ | ||||
|              | ||||
| @@ -679,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) | ||||
|                     ; | ||||
| @@ -701,7 +653,6 @@ static void cmd_write(struct write_frame* f) | ||||
|         } | ||||
|     } | ||||
| abort: | ||||
|     print("done %d %d", dma_reading_from_td, dma_writing_to_td); | ||||
|     SEQUENCER_DMA_FINISHED_IRQ_Disable(); | ||||
|  | ||||
|     SEQUENCER_CONTROL_Write(1); /* reset */ | ||||
| @@ -715,33 +666,29 @@ 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 --- | ||||
|          * easier than trying to terminate the connection. */ | ||||
|         while (count_read != packets) | ||||
|         { | ||||
|             if (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) == USBFS_OUT_BUFFER_FULL) | ||||
|             { | ||||
|                 int length = usb_read(FLUXENGINE_DATA_OUT_EP_NUM, usb_buffer); | ||||
|                 if (length < FRAME_SIZE) | ||||
|                     break; | ||||
|                 USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM); | ||||
|                 count_read++; | ||||
|             } | ||||
|             (void) usb_read(FLUXENGINE_DATA_OUT_EP_NUM, usb_buffer); | ||||
|             count_read++; | ||||
|         } | ||||
|         USBFS_DisableOutEP(FLUXENGINE_DATA_OUT_EP_NUM); | ||||
|     } | ||||
|      | ||||
|     deinit_dma(); | ||||
|     print("write finished"); | ||||
|      | ||||
|     STEP_REG_Write(0); | ||||
|     if (dma_underrun) | ||||
|     { | ||||
|         print("underrun!"); | ||||
|         send_error(F_ERROR_UNDERRUN); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     print("success"); | ||||
|     DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_WRITE_REPLY); | ||||
|     send_reply((struct any_frame*) &r); | ||||
| } | ||||
| @@ -749,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) | ||||
|         ; | ||||
| @@ -761,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); | ||||
| @@ -886,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: | ||||
| @@ -926,6 +875,21 @@ static void handle_command(void) | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void detect_drives(void) | ||||
| { | ||||
|     current_drive_flags.drive = 0; | ||||
|     start_motor(); | ||||
|     drive0_present = home(); | ||||
|     stop_motor(); | ||||
|      | ||||
|     current_drive_flags.drive = 1; | ||||
|     start_motor(); | ||||
|     drive1_present = home(); | ||||
|     stop_motor(); | ||||
|      | ||||
|     print("drive 0: %s drive 1: %s", drive0_present ? "yes" : "no", drive1_present ? "yes" : "no"); | ||||
| } | ||||
|  | ||||
| int main(void) | ||||
| { | ||||
|     CyGlobalIntEnable; | ||||
| @@ -939,23 +903,11 @@ int main(void) | ||||
|     DRIVESELECT_REG_Write(0); | ||||
|     UART_Start(); | ||||
|     USBFS_Start(0, USBFS_DWR_VDDD_OPERATION); | ||||
|     USBFS_DisableOutEP(FLUXENGINE_DATA_OUT_EP_NUM); | ||||
|      | ||||
|     detect_drives(); | ||||
|     CyWdtStart(CYWDT_1024_TICKS, CYWDT_LPMODE_DISABLED); | ||||
|      | ||||
|     current_drive_flags.drive = 0; | ||||
|     start_motor(); | ||||
|     drive0_present = home(); | ||||
|     stop_motor(); | ||||
|      | ||||
|     current_drive_flags.drive = 1; | ||||
|     start_motor(); | ||||
|     drive1_present = home(); | ||||
|     stop_motor(); | ||||
|      | ||||
|     print("drive 0: %s drive 1: %s", drive0_present ? "yes" : "no", drive1_present ? "yes" : "no"); | ||||
|      | ||||
|     /* UART_PutString("GO\r"); */ | ||||
|  | ||||
|     for (;;) | ||||
|     { | ||||
|         CyWdtClear(); | ||||
| @@ -971,7 +923,7 @@ int main(void) | ||||
|         { | ||||
|             print("Waiting for USB..."); | ||||
|             while (!USBFS_GetConfiguration()) | ||||
|                 ; | ||||
|                 CyWdtClear(); | ||||
|             print("USB ready"); | ||||
|             USBFS_EnableOutEP(FLUXENGINE_CMD_OUT_EP_NUM); | ||||
|         } | ||||
| @@ -985,3 +937,75 @@ int main(void) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| const uint8_t USBFS_MSOS_CONFIGURATION_DESCR[USBFS_MSOS_CONF_DESCR_LENGTH] = { | ||||
| /*  Length of the descriptor 4 bytes       */   0x28u, 0x00u, 0x00u, 0x00u, | ||||
| /*  Version of the descriptor 2 bytes      */   0x00u, 0x01u, | ||||
| /*  wIndex - Fixed:INDEX_CONFIG_DESCRIPTOR */   0x04u, 0x00u, | ||||
| /*  bCount - Count of device functions.    */   0x01u, | ||||
| /*  Reserved : 7 bytes                     */   0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, | ||||
| /*  bFirstInterfaceNumber                  */   0x00u, | ||||
| /*  Reserved                               */   0x01u, | ||||
| /*  compatibleId - "WINUSB\0\0"            */   'W', 'I', 'N', 'U', 'S', 'B', 0, 0, | ||||
| /*  subcompatibleID - "00001\0\0"          */   '0', '0', '0', '0', '1', | ||||
|                                                 0x00u, 0x00u, 0x00u, | ||||
| /*  Reserved : 6 bytes                     */   0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u | ||||
| }; | ||||
|  | ||||
| const uint8_t USBFS_MSOS_EXTENDED_PROPERTIES_DESCR[224] = { | ||||
|     /* Length; 4 bytes       */   224, 0, 0, 0, | ||||
|     /* Version; 2 bytes      */   0x00, 0x01, /* 1.0 */ | ||||
|     /* wIndex                */   0x05, 0x00, | ||||
|     /* Number of sections    */   0x01, 0x00, | ||||
|     /* Property section size */   214, 0, 0, 0, | ||||
|     /* Property data type    */   0x07, 0x00, 0x00, 0x00, /* 7 = REG_MULTI_SZ Unicode */ | ||||
|     /* Property name length  */   42, 0, | ||||
|     /* Property name         */   'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, | ||||
|                                   'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, | ||||
|                                   'a', 0, 'c', 0, 'e', 0, 'G', 0, 'U', 0, 'I', 0, | ||||
|                                   'D', 0, 's', 0, 0,   0, | ||||
|     /* Property data length  */   158, 0, 0, 0, | ||||
|     /* GUID #1 data          */   '{', 0, '3', 0, 'd', 0, '2', 0, '7', 0, '5', 0, | ||||
|                                   'c', 0, 'f', 0, 'e', 0, '-', 0, '5', 0, '4', 0, | ||||
|                                   '3', 0, '5', 0, '-', 0, '4', 0, 'd', 0, 'd', 0, | ||||
|                                   '5', 0, '-', 0, 'a', 0, 'c', 0, 'c', 0, 'a', 0, | ||||
|                                   '-', 0, '9', 0, 'f', 0, 'b', 0, '9', 0, '9', 0, | ||||
|                                   '5', 0, 'e', 0, '2', 0, 'f', 0, '6', 0, '3', 0, | ||||
|                                   '8', 0, '}', 0, '\0', 0, | ||||
|     /* GUID #2 data          */   '{', 0, '3', 0, 'd', 0, '2', 0, '7', 0, '5', 0, | ||||
|                                   'c', 0, 'f', 0, 'e', 0, '-', 0, '5', 0, '4', 0, | ||||
|                                   '3', 0, '5', 0, '-', 0, '4', 0, 'd', 0, 'd', 0, | ||||
|                                   '5', 0, '-', 0, 'a', 0, 'c', 0, 'c', 0, 'a', 0, | ||||
|                                   '-', 0, '9', 0, 'f', 0, 'b', 0, '9', 0, '9', 0, | ||||
|                                   '5', 0, 'e', 0, '2', 0, 'f', 0, '6', 0, '3', 0, | ||||
|                                   '8', 0, '}', 0, '\0', 0, '\0', 0 | ||||
| }; | ||||
|  | ||||
| uint8 USBFS_HandleVendorRqst(void) | ||||
| { | ||||
|     if (!(USBFS_bmRequestTypeReg & USBFS_RQST_DIR_D2H)) | ||||
|         return false; | ||||
|  | ||||
|     switch (USBFS_bRequestReg) | ||||
|     { | ||||
|         case USBFS_GET_EXTENDED_CONFIG_DESCRIPTOR: | ||||
|             switch (USBFS_wIndexLoReg) | ||||
|             { | ||||
|                 case 4: | ||||
|                     USBFS_currentTD.pData = (volatile uint8 *) &USBFS_MSOS_CONFIGURATION_DESCR[0u]; | ||||
|                     USBFS_currentTD.count = USBFS_MSOS_CONFIGURATION_DESCR[0u]; | ||||
|                     return USBFS_InitControlRead(); | ||||
|                      | ||||
|                 case 5: | ||||
|                     USBFS_currentTD.pData = (volatile uint8 *) &USBFS_MSOS_EXTENDED_PROPERTIES_DESCR[0u]; | ||||
|                     USBFS_currentTD.count = USBFS_MSOS_EXTENDED_PROPERTIES_DESCR[0u]; | ||||
|                     return USBFS_InitControlRead(); | ||||
|             } | ||||
|  | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,18 +0,0 @@ | ||||
| const READ = 1 | ||||
| const WRITE = 2 | ||||
|  | ||||
| filename = "Generated_Source\PSoC5\USBFS_descr.c" | ||||
| set fso = CreateObject("Scripting.FileSystemObject") | ||||
|  | ||||
| set file = fso.OpenTextFile(filename, READ) | ||||
| text = file.ReadAll | ||||
| file.Close | ||||
|  | ||||
| set r = New RegExp | ||||
| r.MultiLine = True | ||||
| r.Pattern = "/\* +compatibleID.*\n.*" | ||||
| text = r.replace(text, "'W', 'I', 'N', 'U', 'S', 'B', 0, 0,") | ||||
|  | ||||
| set file = fso.CreateTextFile(filename, True) | ||||
| file.Write text | ||||
| file.Close | ||||
							
								
								
									
										64
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,21 +1,45 @@ | ||||
| PACKAGES = zlib sqlite3 libusb-1.0 | ||||
| PACKAGES = zlib sqlite3 protobuf | ||||
| ifeq ($(shell uname),Linux) | ||||
| PACKAGES += gtk+-3.0 | ||||
| endif | ||||
|  | ||||
| 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 | ||||
|  | ||||
| export CDBGFLAGS = -O0 -g | ||||
| export LDDBGFLAGS = -O0 -g | ||||
|  | ||||
| ifeq ($(OS), Windows_NT) | ||||
| else | ||||
| ifeq ($(shell uname),Darwin) | ||||
| else | ||||
| 	PACKAGES += libudev | ||||
| endif | ||||
| endif | ||||
|  | ||||
| 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 WINDRES = /mingw32/bin/windres | ||||
| 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 \ | ||||
| 	-lsetupapi -lwinusb -lole32 -lprotobuf -luuid | ||||
| export GUILIBS += -luser32 -lkernel32 -lgdi32 -lcomctl32 -luxtheme -lmsimg32 \ | ||||
| 	-lcomdlg32 -ld2d1 -ldwrite -lole32 -loleaut32 -loleacc -luuid \ | ||||
| 	-lwindowscodecs | ||||
| export EXTENSION = .exe | ||||
| else | ||||
|  | ||||
| @@ -25,21 +49,41 @@ $(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 COBJC = clang | ||||
| 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)) -ldl | ||||
| export EXTENSION = | ||||
|  | ||||
| ifeq ($(shell uname),Darwin) | ||||
| AR = ar rcS | ||||
| RANLIB += -c -no_warning_for_no_symbols | ||||
| export CC = clang | ||||
| export CXX = clang++ | ||||
| export COBJC = clang | ||||
| export LDFLAGS += \ | ||||
| 	-framework Foundation \ | ||||
| 	-framework AppKit \ | ||||
| 	-framework IOKit \ | ||||
| 	-framework CoreFoundation | ||||
| endif | ||||
|  | ||||
| endif | ||||
| export XXD = xxd | ||||
|  | ||||
| CFLAGS += -Ilib -Idep/fmt -Iarch | ||||
|  | ||||
| export OBJDIR = .obj | ||||
|  | ||||
| all: .obj/build.ninja | ||||
| 	@ninja -f .obj/build.ninja -v | ||||
| 	@ninja -f .obj/build.ninja -k 0 | ||||
| 	@if command -v cscope > /dev/null; then cscope -bRq; fi | ||||
|  | ||||
| clean: | ||||
| 	@echo CLEAN | ||||
|   | ||||
							
								
								
									
										98
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								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,17 +29,18 @@ 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> | ||||
|  | ||||
| **Important note.** On 2019-02-09 I did a hardware redesign and moved the pins on | ||||
| the board. Sorry for the inconvenience, but it means you don't have to modify | ||||
| the board any more to make it work. If you built the hardware prior to then, | ||||
| you'll need to adjust it. | ||||
| **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. | ||||
|  | ||||
| **Another important note.** On 2019-07-03 I've revamped the build process and | ||||
| the (command line) user interface. It should be much nicer now, not least in | ||||
| that there's a single client binary with all the functionality in it. The | ||||
| interface is a little different, but not much. The build process is now | ||||
| better (simpler). See [the building](doc/building.md) and | ||||
| [using](doc/using.md) pages for more details. | ||||
| **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 | ||||
| inconvenience. | ||||
|  | ||||
| Where? | ||||
| ------ | ||||
| @@ -59,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? | ||||
| ------ | ||||
| @@ -77,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 | ||||
| @@ -110,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 | ||||
| @@ -195,6 +212,29 @@ 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/libusbp` contains the libusbp library, taken from | ||||
| https://github.com/pololu/libusbp. It is MIT 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,29 +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(); | ||||
| }; | ||||
|  | ||||
| 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,38 +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; | ||||
| 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)); | ||||
| } | ||||
|  | ||||
| void AmigaDecoder::decodeSectorRecord() | ||||
| { | ||||
|     const auto& rawbits = readRawBits(AMIGA_RECORD_SIZE*16); | ||||
|     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; | ||||
| } | ||||
|   | ||||
| @@ -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); | ||||
| } | ||||
|   | ||||
| @@ -9,31 +9,11 @@ | ||||
| #define BROTHER_DATA_RECORD_CHECKSUM     3 | ||||
| #define BROTHER_DATA_RECORD_ENCODED_SIZE 415 | ||||
|  | ||||
| #define BROTHER_TRACKS_PER_DISK          78 | ||||
| #define BROTHER_TRACKS_PER_240KB_DISK    78 | ||||
| #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: | ||||
| 	virtual ~BrotherEncoder() {} | ||||
|  | ||||
| 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,42 +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 | ||||
| { | ||||
| 	if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_DISK) | ||||
|         || (physicalSide != 0)) | ||||
| 		return std::unique_ptr<Fluxmap>(); | ||||
| public: | ||||
| 	BrotherEncoder(const EncoderProto& config): | ||||
| 		AbstractEncoder(config), | ||||
| 		_config(config.brother()) | ||||
| 	{} | ||||
|  | ||||
| 	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++) | ||||
| public: | ||||
| 	std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, 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; | ||||
| 		std::vector<std::shared_ptr<Sector>> sectors; | ||||
|  | ||||
| 		const auto& sectorData = allSectors.get(physicalTrack, 0, sectorId); | ||||
| 		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; | ||||
|  | ||||
| 		fillBitmapTo(bits, cursor, headerCursor, { true, false }); | ||||
| 		write_sector_header(bits, cursor, physicalTrack, sectorId); | ||||
| 		fillBitmapTo(bits, cursor, dataCursor, { true, false }); | ||||
| 		write_sector_data(bits, cursor, sectorData->data); | ||||
| 			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; | ||||
| 	} | ||||
|  | ||||
| 	if (cursor >= bits.size()) | ||||
| 		Error() << "track data overrun"; | ||||
| 	fillBitmapTo(bits, cursor, bits.size(), { true, false }); | ||||
|     std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, | ||||
| 			const std::vector<std::shared_ptr<Sector>>& sectors, const Image& image) override | ||||
| 	{ | ||||
| 		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; | ||||
|  | ||||
| 	// 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; | ||||
| 			case BROTHER240: | ||||
| 				if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_240KB_DISK)) | ||||
| 					return std::unique_ptr<Fluxmap>(); | ||||
| 				logicalTrack = physicalTrack; | ||||
| 				break; | ||||
| 		} | ||||
|  | ||||
| 		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; | ||||
| 	} | ||||
|  | ||||
| private: | ||||
| 	const BrotherEncoderProto& _config; | ||||
|  | ||||
| }; | ||||
|  | ||||
| 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, | ||||
| @@ -57,11 +58,11 @@ const FluxPattern FM_TRS80DAM1_PATTERN(16, 0xf56b); | ||||
|  | ||||
| /*  | ||||
|  * TRS80DAM2 record: | ||||
|  * flux:   XXXX-X-X-XX-XXX- = 0xf56c | ||||
|  * flux:   XXXX-X-X-XX-XXX- = 0xf56e | ||||
|  * clock:  X X - - - X X X  = 0xc7 | ||||
|  * data:    X X X X X - X - = 0xfa | ||||
|  */ | ||||
| const FluxPattern FM_TRS80DAM2_PATTERN(16, 0xf56c); | ||||
| const FluxPattern FM_TRS80DAM2_PATTERN(16, 0xf56e); | ||||
|  | ||||
| /* MFM record separator: | ||||
|  * 0xA1 is: | ||||
| @@ -89,71 +90,139 @@ 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]; | ||||
| 		if (eof()) | ||||
| 			return RecordType::UNKNOWN_RECORD; | ||||
| 		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); | ||||
|  | ||||
| 		IbmDecoderProto::TrackdataProto trackdata; | ||||
| 		getTrackFormat(trackdata, _sector->physicalCylinder, _sector->physicalHead); | ||||
|  | ||||
| 		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 (trackdata.swap_sides()) | ||||
| 			_sector->logicalSide ^= 1; | ||||
| 		if (trackdata.ignore_side_byte()) | ||||
| 			_sector->logicalSide = _sector->physicalHead; | ||||
| 		if (trackdata.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 | ||||
| 	{ | ||||
| 		IbmDecoderProto::TrackdataProto trackdata; | ||||
| 		getTrackFormat(trackdata, cylinder, head); | ||||
|  | ||||
| 		std::set<unsigned> s; | ||||
| 		if (trackdata.has_sectors()) | ||||
| 		{ | ||||
| 			for (int sectorId : trackdata.sectors().sector()) | ||||
| 				s.insert(sectorId); | ||||
| 		} | ||||
| 		else if (trackdata.has_sector_range()) | ||||
| 		{ | ||||
| 			int sectorId = trackdata.sector_range().min_sector(); | ||||
| 			while (sectorId <= trackdata.sector_range().max_sector()) | ||||
| 			{ | ||||
| 				s.insert(sectorId); | ||||
| 				sectorId++; | ||||
| 			} | ||||
| 		} | ||||
| 		return s; | ||||
| 	} | ||||
|  | ||||
| private: | ||||
| 	void getTrackFormat(IbmDecoderProto::TrackdataProto& trackdata, unsigned cylinder, unsigned head) const | ||||
| 	{ | ||||
| 		trackdata.Clear(); | ||||
| 		for (const auto& f : _config.trackdata()) | ||||
| 		{ | ||||
| 			if (f.has_cylinder() && (f.cylinder() != cylinder)) | ||||
| 				continue; | ||||
| 			if (f.has_head() && (f.head() != head)) | ||||
| 				continue; | ||||
|  | ||||
| 			trackdata.MergeFrom(f); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 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,137 +65,249 @@ 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) | ||||
| private: | ||||
| 	static std::set<unsigned> getSectorIds(const IbmEncoderProto::TrackdataProto& trackdata) | ||||
| 	{ | ||||
| 		int sectorId = charToInt(sectorChar); | ||||
| 		if (!first) | ||||
| 			writeBytes(_parameters.gap3, gapFill); | ||||
| 		first = false; | ||||
|  | ||||
| 		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); | ||||
|  | ||||
| 		/* 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. */ | ||||
|  | ||||
| 		std::set<unsigned> s; | ||||
| 		if (trackdata.has_sectors()) | ||||
| 		{ | ||||
| 			Bytes header; | ||||
| 			ByteWriter bw(header); | ||||
|  | ||||
| 			writeBytes(_parameters.useFm ? 6 : 12, 0x00); | ||||
| 			if (!_parameters.useFm) | ||||
| 			for (int sectorId : trackdata.sectors().sector()) | ||||
| 				s.insert(sectorId); | ||||
| 		} | ||||
| 		else if (trackdata.has_sector_range()) | ||||
| 		{ | ||||
| 			int sectorId = trackdata.sector_range().min_sector(); | ||||
| 			while (sectorId <= trackdata.sector_range().max_sector()) | ||||
| 			{ | ||||
| 				for (int i=0; i<3; i++) | ||||
| 					bw.write_8(MFM_RECORD_SEPARATOR_BYTE); | ||||
| 				s.insert(sectorId); | ||||
| 				sectorId++; | ||||
| 			} | ||||
| 			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); | ||||
| 		} | ||||
| 		return s; | ||||
| 	} | ||||
|  | ||||
| 			int conventionalHeaderStart = 0; | ||||
| 			if (!_parameters.useFm) | ||||
| public: | ||||
| 	std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override | ||||
| 	{ | ||||
| 		std::vector<std::shared_ptr<Sector>> sectors; | ||||
| 		IbmEncoderProto::TrackdataProto trackdata; | ||||
| 		getTrackFormat(trackdata, physicalTrack, physicalSide); | ||||
|  | ||||
| 		int logicalSide = physicalSide ^ trackdata.swap_sides(); | ||||
| 		for (int sectorId : getSectorIds(trackdata)) | ||||
|         { | ||||
| 			const auto& sector = image.get(physicalTrack, logicalSide, 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 | ||||
| 	{ | ||||
| 		IbmEncoderProto::TrackdataProto trackdata; | ||||
| 		getTrackFormat(trackdata, physicalTrack, physicalSide); | ||||
|  | ||||
| 		auto writeBytes = [&](const Bytes& bytes) | ||||
| 		{ | ||||
| 			if (trackdata.use_fm()) | ||||
| 				encodeFm(_bits, _cursor, bytes); | ||||
| 			else | ||||
| 				encodeMfm(_bits, _cursor, bytes, _lastBit); | ||||
| 		}; | ||||
|  | ||||
| 		auto writeFillerRawBytes = [&](int count, uint16_t byte) | ||||
| 		{ | ||||
| 			for (int i=0; i<count; i++) | ||||
| 				writeRawBits(byte, 16); | ||||
| 		}; | ||||
|  | ||||
| 		auto writeFillerBytes = [&](int count, uint8_t byte) | ||||
| 		{ | ||||
| 			Bytes b { byte }; | ||||
| 			for (int i=0; i<count; i++) | ||||
| 				writeBytes(b); | ||||
| 		}; | ||||
|  | ||||
| 		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++) | ||||
| 					writeRawBits(MFM_RECORD_SEPARATOR, 16); | ||||
| 				conventionalHeaderStart += 3; | ||||
|  | ||||
| 				s >>= 1; | ||||
| 				sectorSize += 1; | ||||
| 			} | ||||
| 			writeRawBits(_parameters.idamByte, 16); | ||||
| 			conventionalHeaderStart += 1; | ||||
|  | ||||
| 			writeBytes(header.slice(conventionalHeaderStart)); | ||||
| 		} | ||||
|  | ||||
| 		writeBytes(_parameters.gap2, gapFill); | ||||
| 		uint16_t gapFill = trackdata.gap_fill_byte(); | ||||
|  | ||||
| 		writeFillerRawBytes(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; | ||||
| 			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); | ||||
| 			writeFillerRawBytes(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) | ||||
| 				writeFillerRawBytes(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)); | ||||
| 			} | ||||
|  | ||||
| 			writeFillerRawBytes(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()) | ||||
| 			writeFillerRawBytes(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 | ||||
|   | ||||
							
								
								
									
										68
									
								
								arch/ibm/ibm.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								arch/ibm/ibm.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| import "lib/common.proto"; | ||||
|  | ||||
| message IbmDecoderProto { | ||||
| 	// Next: 10 | ||||
| 	message TrackdataProto { | ||||
| 		message SectorsProto { | ||||
| 			repeated int32 sector = 1            [(help) = "require these sectors to exist for a good read"]; | ||||
| 		} | ||||
| 		message SectorRangeProto { | ||||
| 			optional int32 min_sector = 1        [(help) = "require these sectors to exist for a good read"]; | ||||
| 			optional int32 max_sector = 2        [(help) = "require these sectors to exist for a good read"]; | ||||
| 		} | ||||
|  | ||||
| 		optional int32 cylinder = 7              [(help) = "if set, the format applies only to this track"]; | ||||
| 		optional int32 head = 8                  [(help) = "if set, the format applies only to this head"]; | ||||
|  | ||||
| 		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"]; | ||||
|  | ||||
| 		oneof required_sectors { | ||||
| 			SectorsProto sectors = 5             [(help) = "require these sectors to exist for a good read"]; | ||||
| 			SectorRangeProto sector_range = 9    [(help) = "require these sectors to exist for a good read"]; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	repeated TrackdataProto trackdata = 1; | ||||
| } | ||||
|  | ||||
| message IbmEncoderProto { | ||||
| 	// Next: 20 | ||||
| 	message TrackdataProto { | ||||
| 		message SectorsProto { | ||||
| 			repeated int32 sector = 1		[(help) = "write these sectors (in order) on each track"]; | ||||
| 		} | ||||
| 		message SectorRangeProto { | ||||
| 			optional int32 min_sector = 1   [(help) = "write these sectors (in order) on each track"]; | ||||
| 			optional int32 max_sector = 2   [(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 int32 gap_fill_byte = 18   [default=0x9254, (help) = "16-bit raw bit pattern of gap fill byte"]; | ||||
|  | ||||
| 		oneof required_sectors { | ||||
| 			SectorsProto sectors = 17            [(help) = "require these sectors to exist for a good read"]; | ||||
| 			SectorRangeProto sector_range = 19   [(help) = "require these sectors to exist for a good read"]; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	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,92 +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; | ||||
| 	do | ||||
| 		sectors.insert(count); | ||||
| 	while (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) { | ||||
| 			return SECTOR_RECORD; | ||||
| 		} | ||||
| 		return UNKNOWN_RECORD; | ||||
| 	} | ||||
|  | ||||
| 	void decodeSectorRecord() | ||||
| 	{ | ||||
| 		readRawBits(16); | ||||
| 		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; | ||||
| 			return SECTOR_RECORD; | ||||
| 		} | ||||
|  | ||||
| 		if (matcher == &FM_PATTERN) { | ||||
| 			_sectorType = SECTOR_TYPE_FM; | ||||
| 			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; | ||||
| 		} | ||||
|  | ||||
| 		readRawBits(48); | ||||
|  | ||||
| 		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 | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user