mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	Compare commits
	
		
			680 Commits
		
	
	
		
			FluxEngine
			...
			kaypro2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | b9623a09d3 | ||
|  | 7be5623952 | ||
|  | 7186b25a69 | ||
|  | 42cacb18bd | ||
|  | d09c03f4d2 | ||
|  | 7884813973 | ||
|  | 10464f3c43 | ||
|  | 1c64df9482 | ||
|  | ad240b150e | ||
|  | 1177ef6f8d | ||
|  | 145b1065c5 | ||
|  | 0783f701f6 | ||
|  | 2ff50c0c56 | ||
|  | 4f4ed1307f | ||
|  | 6d5b7cb64e | ||
|  | 00fc4e3890 | ||
|  | 7344ee4402 | ||
|  | 740eacc7ac | ||
|  | 8b1bcf21ee | ||
|  | b0a5174c0a | ||
|  | b7cca1b95b | ||
|  | 44c51f1246 | ||
|  | 516d43d7a8 | ||
|  | 86d49d563e | ||
|  | a2911a9585 | ||
|  | 9a12b651f9 | ||
|  | 9fa631acca | ||
|  | 8df7998a83 | ||
|  | c81c1926c0 | ||
|  | 7ab1288424 | ||
|  | 3ee88adfa9 | ||
|  | 29e8c99b4f | ||
|  | 8b115f8156 | ||
|  | 11c546f113 | ||
|  | c087539eb7 | ||
|  | 7f13c1cbfb | ||
|  | 5a4f989236 | ||
|  | 2a06adcabb | ||
|  | 8cec3354ea | ||
|  | f9df728f45 | ||
|  | 46eead34c4 | ||
|  | 786b35fee2 | ||
|  | 9dae587ca8 | ||
|  | 5c6c609991 | ||
|  | 0be8fedf26 | ||
|  | 1f9aaf1ac0 | ||
|  | 7f3e9f2544 | ||
|  | 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 | ||
|  | 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 | ||
|  | adbcb2cd31 | ||
|  | c47a563790 | ||
|  | 04c09d1a5b | ||
|  | 323da8272a | ||
|  | 38700c79fc | ||
|  | d504d1890a | ||
|  | d53e757cfb | ||
|  | 4983239458 | ||
|  | 376985828a | ||
|  | dce0a26820 | ||
|  | 14e0a67e7d | ||
|  | 1656947764 | ||
|  | 647862cdbd | ||
|  | 4a8d83838c | ||
|  | 8acf8e181d | ||
|  | 2df9920209 | ||
|  | 1a6c6b5420 | ||
|  | edc56d44d6 | ||
|  | ef4eff0195 | ||
|  | df8d45bf66 | ||
|  | 89a27619ff | ||
|  | 387a86969a | ||
|  | acb5059d17 | ||
|  | a4002d2617 | ||
|  | a63a90bbd0 | ||
|  | d25f96dd24 | ||
|  | e8febe6508 | ||
|  | ad3a930c6a | ||
|  | be41c1de76 | ||
|  | d528978667 | ||
|  | 827fcf69d2 | ||
|  | 711ff545e0 | ||
|  | 5befa31050 | ||
|  | 8e5c2d0ebb | ||
|  | f95fceeb3d | ||
|  | 003b20dbf0 | ||
|  | cd9bbaa4b6 | ||
|  | 71e622bf72 | ||
|  | 2a065a08df | ||
|  | 6087228378 | ||
|  | efd74e0d7b | ||
|  | b68a9dcc4f | ||
|  | 008855daa9 | ||
|  | 7a9d36de2a | ||
|  | c56e982c9a | ||
|  | 002cc171a2 | ||
|  | 32e721b47a | ||
|  | 1e82f697a9 | ||
|  | fa09631e32 | ||
|  | e06436ce1e | ||
|  | b2f443e1ad | ||
|  | 2e07be0cf7 | ||
|  | bf0b14d094 | ||
|  | c9f5803194 | ||
|  | 5293560c02 | ||
|  | c49823aa9d | ||
|  | c4ef4882ae | ||
|  | a8eca06cf0 | ||
|  | 065257b5aa | ||
|  | 29bdfc043a | ||
|  | 933ffe7ab4 | ||
|  | e517f28563 | ||
|  | 91ffcf59c3 | ||
|  | 51c618f325 | ||
|  | 9dc1067032 | ||
|  | 9e75dc3af1 | ||
|  | efa4c933b3 | ||
|  | 6af80d1e5e | ||
|  | 0c48897814 | ||
|  | 60e5e35947 | ||
|  | 86c4e959ca | ||
|  | b0c675c589 | ||
|  | d77841c3b7 | ||
|  | 4ed1fb6bac | ||
|  | bcc9e9d9a5 | ||
|  | ec327e25a4 | ||
|  | d0ed5b32f7 | ||
|  | 7c66e1b0d4 | ||
|  | 4475e9f085 | ||
|  | 5c9639ec5a | ||
|  | 792cc88192 | ||
|  | 21fe586724 | ||
|  | 5a0fb2761a | ||
|  | ef4581ed39 | ||
|  | 73419704c2 | ||
|  | a8b92d4780 | ||
|  | 98140b0646 | ||
|  | 4429ce1f84 | ||
|  | 1f50941a2c | ||
|  | a7de04848c | ||
|  | c264fec6e9 | ||
|  | 4488b2542f | ||
|  | 2f1a5189d6 | ||
|  | effaeff51e | ||
|  | 1210549f59 | ||
|  | 7200de9702 | ||
|  | 5dd5c8516a | ||
|  | f7fb2a844b | ||
|  | 20b1b2a4a8 | ||
|  | f8b8bc2295 | ||
|  | 2d4d56d09f | ||
|  | 39599b76c8 | ||
|  | c2c40ccfbb | ||
|  | ab42eb23f4 | ||
|  | 05eff0e528 | ||
|  | 23311b4b68 | ||
|  | 5e97df8d15 | ||
|  | 898e8c551c | ||
|  | ad69c6bd27 | ||
|  | 661399cc83 | ||
|  | edbb4b1daa | ||
|  | 6389e8a756 | ||
|  | c187b79d80 | ||
|  | edbe624c5a | ||
|  | 44e2334815 | ||
|  | b448ab7917 | ||
|  | 072a097003 | ||
|  | a66e704bab | ||
|  | ed0d578b18 | ||
|  | 32bb956710 | ||
|  | f436d6b582 | ||
|  | d2f8c27cb6 | ||
|  | eaa3c57425 | ||
|  | 549f12a2ab | ||
|  | aea254fbe7 | ||
|  | 8ee6eed4dc | ||
|  | 3094c5c919 | ||
|  | 1e012699af | ||
|  | 91d6e9aeb9 | ||
|  | a40b26ff46 | ||
|  | ebcb9c4bb0 | ||
|  | 2520834b18 | ||
|  | a1f3087046 | ||
|  | e9670e205e | ||
|  | 658e2b7295 | ||
|  | 7b4a8d6de2 | ||
|  | e8f7b51aef | ||
|  | 9d6bc57a5f | ||
|  | 73766f92b4 | ||
|  | 80badf3b54 | ||
|  | 116529f85a | ||
|  | 5a2b2bc07a | ||
|  | 41070395c0 | ||
|  | 4304d1eede | 
| @@ -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 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 | ||||
|  | ||||
							
								
								
									
										54
									
								
								.github/workflows/ccpp.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								.github/workflows/ccpp.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| name: C/C++ CI | ||||
|  | ||||
| on: [push] | ||||
|  | ||||
| jobs: | ||||
|   build-linux: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - uses: actions/checkout@v1 | ||||
|       with: | ||||
|         fetch-depth: 1 | ||||
|     - name: apt | ||||
|       run: sudo apt update && sudo apt install libusb-1.0-0-dev libsqlite3-dev ninja-build protobuf-compiler | ||||
|     - name: make | ||||
|       run: make | ||||
|  | ||||
|   build-macos: | ||||
|     runs-on: macos-latest | ||||
|     steps: | ||||
|     - uses: actions/checkout@v2 | ||||
|       with: | ||||
|         fetch-depth: 1 | ||||
|     - name: brew | ||||
|       run: brew install sqlite pkg-config libusb ninja protobuf | ||||
|     - name: make | ||||
|       run: make | ||||
|  | ||||
|   build-windows: | ||||
|     runs-on: windows-latest | ||||
|     defaults: | ||||
|       run: | ||||
|         shell: msys2 {0} | ||||
|     steps: | ||||
|     - uses: msys2/setup-msys2@v2 | ||||
|       with: | ||||
|         update: true | ||||
|         msystem: MINGW32 | ||||
|         install: >- | ||||
|           make | ||||
|           ninja | ||||
|           mingw-w64-i686-libusb | ||||
|           mingw-w64-i686-sqlite3 | ||||
|           mingw-w64-i686-zlib | ||||
|           mingw-w64-i686-gcc | ||||
|           zip | ||||
|           mingw-w64-i686-protobuf | ||||
|           vim | ||||
|     - uses: actions/checkout@v1 | ||||
|       with: | ||||
|         fetch-depth: 1 | ||||
|     - name: build | ||||
|       run: | | ||||
|         make | ||||
|  | ||||
							
								
								
									
										63
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| name: Autorelease | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - "master" | ||||
|  | ||||
| jobs: | ||||
|   dev-release: | ||||
|     runs-on: windows-latest | ||||
|     defaults: | ||||
|       run: | ||||
|         shell: msys2 {0} | ||||
|     steps: | ||||
|     - uses: msys2/setup-msys2@v2 | ||||
|       with: | ||||
|         update: true | ||||
|         msystem: MINGW32 | ||||
|         install: >- | ||||
|           make | ||||
|           ninja | ||||
|           mingw-w64-i686-libusb | ||||
|           mingw-w64-i686-sqlite3 | ||||
|           mingw-w64-i686-zlib | ||||
|           mingw-w64-i686-gcc | ||||
|           zip | ||||
|           mingw-w64-i686-protobuf | ||||
|           vim | ||||
|     - uses: actions/checkout@v2 | ||||
|       with: | ||||
|         fetch-depth: 1 | ||||
|     - name: build | ||||
|       run: | | ||||
|         make | ||||
|     - name: zip | ||||
|       run: | | ||||
|         zip -9 fluxengine.zip fluxengine.exe brother120tool.exe brother240tool.exe FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex | ||||
|     - name: date | ||||
|       run: | | ||||
|         echo "RELEASE_DATE=$(date --rfc-3339=date)" >> ${GITHUB_ENV} | ||||
|     - name: tag | ||||
|       uses: EndBug/latest-tag@latest | ||||
|       with: | ||||
|         tag-name: dev | ||||
|       env: | ||||
|         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||
|     - name: delete-old-assets | ||||
|       uses: mknejp/delete-release-assets@v1 | ||||
|       with: | ||||
|         token: ${{ github.token }} | ||||
|         tag: dev | ||||
|         assets: |  | ||||
|           fluxengine.zip | ||||
|         fail-if-no-assets: false | ||||
|     - name: release | ||||
|       uses: softprops/action-gh-release@v1 | ||||
|       with: | ||||
|         name: Development build ${{ env.RELEASE_DATE }} | ||||
|         files: | | ||||
|           fluxengine.zip | ||||
|         tag_name: dev | ||||
|       env: | ||||
|         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||
							
								
								
									
										39
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -1,39 +0,0 @@ | ||||
| language: shell | ||||
| git: | ||||
|     depth: 1 | ||||
|  | ||||
| matrix: | ||||
|     include: | ||||
|         - | ||||
|             os: linux | ||||
|             sudo: false | ||||
|             dist: xenial | ||||
|             compiler: gcc | ||||
|             env: CXX=g++-8 | ||||
|             script: | ||||
|             - make | ||||
|         - | ||||
|             os: osx | ||||
|             osx_image: xcode10.2 | ||||
|             compiler: clang | ||||
|             env: | ||||
|             - HOMEBREW_NO_INSTALL_CLEANUP=1 | ||||
|  | ||||
| addons: | ||||
|     apt: | ||||
|         sources: | ||||
|         - llvm-toolchain-precise-3.8 | ||||
|         - ubuntu-toolchain-r-test | ||||
|         packages: | ||||
|         - ninja-build | ||||
|         - libusb-1.0-0-dev | ||||
|         - libsqlite3-dev | ||||
|         - g++-8 | ||||
|     homebrew: | ||||
|         packages: | ||||
|         - ninja | ||||
|  | ||||
| script: | ||||
| - make | ||||
|  | ||||
|  | ||||
| @@ -1,246 +1,246 @@ | ||||
| :4000000000800020110000005D0D00005D0D0000064A08B5136843F020031360044B1A6803F53F5302331A6000F0B6FEE8460040FA46004010B5054C237833B9044B13B19E | ||||
| :400040000448AFF300800123237010BD6081FF1F00000000242E0000084B10B51BB108490848AFF300800848036803B910BD074B002BFBD0BDE81040184700BF00000000F7 | ||||
| :400080006481FF1F242E0000C880FF1F0000000072B6034A13680133136062B6704700BF8081FF1F0A4A0B4B516801310B40002BBEBF03F1FF3363F00F030133536051688E | ||||
| :4000C0009368994202BF024B01221A73704700BF8081FF1F0F0000800A4A0B4B916801310B40002BBEBF03F1FF3363F00F030133936091685368994202BF024B01221A7381 | ||||
| :40010000704700BF8081FF1F0F000080024B012200205A7302F024B98081FF1F10B5C4B2204601F007FA0128FAD110BD70B5C4B220460E4601F006FA314605460246204646 | ||||
| :4001400001F066FA204601F0F5F90128FAD0284670BD000038B5094CA57B3DB9012002F0A5F84FF47A7000F08FFFE573236823610123A373BDE8384000F0C4BF8081FF1F58 | ||||
| :4001800038B50446C5B2284602F09CF8012000F091FF44F00200C0B202F094F8012000F089FF284602F08EF8BDE83840062000F06BBF000038B5044D0024285D013400F0EE | ||||
| :4001C00029FF102CF9D138BD9481FF1F0FB400B593B014AB53F8042B402102A8019302F013FA02A802F04DF802F057F813B05DF804EB04B07047000010B5044601780648AD | ||||
| :40020000FFF7E4FF0420FFF789FF62782146BDE81040042001F0AAB9362E000007B50023ADF804308DF80600032301A88DF80530FFF7E2FF03B05DF804FB0000F8B5234C6B | ||||
| :400240000646FFF787FFE37B93B92148FFF7BEFF02F032F818B90120FFF792FFF8E70120FFF78EFF01200023E073636200F022FF3246616A1748FFF7A9FF144D0027636AD6 | ||||
| :400280009E421BD002F018F828B16B6A13B11248FFF79CFF6762636A9E4205DD0020FFF76FFF6B6A013305E005DA0120FFF768FF6B6A013B6B6200F025FFE0E7322000F0F2 | ||||
| :4002C000E3FEBDE8F8400548FFF780BF8081FF1F432E00004A2E0000672E0000852E00002DE9F04F97B062B600F076FFBE49042000F09AFFBD4801F0EBFFBD4802F018F8BA | ||||
| :40030000BC4802F061F8002002F030F801F0B8FF0221002001F0C4F8B74D0321084600F0D1FE2E462C4600F0EDFEAB7B5BB12A692B689B1A41F28832934204D9002001F0E9 | ||||
| :40034000B5FF0023AB7301F0E3F818B9AB48FFF73DFF04E001F0E2F80028F7D109E001F0D7F80028FBD0A648FFF730FF032001F03BF9032001F0DEF80128D4D1A14903206B | ||||
| :40038000FFF7D4FE94F828109F48FFF71FFF94F82830023B102B00F24B83DFE813F0110049031A00490320004903380049035C004903A4014903100349032F0349033B0369 | ||||
| :4003C00003238DF818308DF8193008238DF81A301CE394F82A00FFF731FF8C4B13E3FFF7B9FE00236373637B002BFCD0002373733268637B002BFCD0336807218DF8181037 | ||||
| :400400009B1A04218DF81910ADF81A30FEE20220FFF784FE4FF000090DF1180A4FF480780027C8EB0903DA1907F80A200137402FF9D10220FFF772FE3A465146022001F003 | ||||
| :4004400095F8B8F10108EBD109F10109B9F1400FE4D16F4BAEE294F82A0001F07BFF606AFFF7ECFE012001F087FF01F0D9FF694BDFF8A8811A78002742F004021A701A7898 | ||||
| :4004800042F001021A701A7802F0FE021A701A7802F0FE021A7001F0C7FF0220FFF73EFE41F6FF734FF480420121022001F024FF84F8680000F094FD08F807000137102F6D | ||||
| :4004C000F8D1DFF85CA100270AF15D081FFA88F90137102F14BF3A4600221AF8010F22440623127D402100F0AFFD4A4646F24B419AF8000000F0BAFD09F14009102F1FFAED | ||||
| :4005000089F9E5D14448FFF761FE00237373637B002BFCD000271422394606A87773DFF8049102F03EF84023099338464FF0FF337760CDF82090B360377301F01DFF012097 | ||||
| :4005400001F060FF736896F868003344197D00F0FFFC96F8680000F0BDFC012196F8680000F090FC636813B96B7B002BFAD0002794F82BA0A76094F80CB0BBF1000F6CD1F8 | ||||
| :4005800000F0C0FD6B7B43B1BAF1010A85F80DB003D162E02B7B002B5FD1A26863689A42F8D04FF0000BA36806A808EB83135B440693CBF14003079300F054FA079B0137BF | ||||
| :4005C000C3F140039B44099B5FFA8BFB002B34D1022000F0AFFF012826D0637B002B3CD12B7B002BF4D038E0910000000D010000A5000000D90000008081FF1F932E0000D3 | ||||
| :40060000A62E0000A881FF1FB02E0000282E00002A2E00009B640040BF2E00009481FF1F9381FF1FF085FF1F4022BE49022000F09DFF4023CDF820900993BBF13F0FB2D9DF | ||||
| :40064000A268B94B01321340002BBEBF03F1FF3363F00F030133A3608DE7002001F0D2FE042194F8680000F07FFC94F8680000F08BFC0028F9D106A800F028FA0220FFF76E | ||||
| :400680004DFDDDF82480B8F1400F06D0C8F1400292B2A449022000F069FF099A32F0400203D11146022000F061FF0220FFF736FDFFF780FD237B33B19C48FFF787FD02209F | ||||
| :4006C000FFF7ACFD06E09A4B05A81B88ADF81430FFF792FD627B3946237B9648CDF80080FFF774FDA7E1E76A17F03F0701D003209FE195F82A0001F02DFE012001F042FE8F | ||||
| :4007000001F08EFE8C4BDFF834821A7802F0FB021A701A7842F001021A701A7802F0FE021A701A7802F0FE021A7001F07DFE686AFFF784FD01214FF4804341F6FF7208468D | ||||
| :4007400001F026FE85F8680000F04AFC08F807000137102FF8D1DFF8E891002709F15D031FFA83F803930137102F14BF3A46002219F8010F22440523127D402100F064FC2C | ||||
| :40078000414646F24E4299F8000000F06FFC08F14008102F1FFA88F8E5D1F36A00279B09142239464FF0FF3806A877600293C6F80880377301F0F5FE402301200993B946CF | ||||
| :4007C00000F012FFBA466268574B01321340002BBCBF03F1FF3363F00F03A168B8BF01338B4200F08F80BAF1000F07D0237B002B40F0A8806B7B002B40F0A480079B002B71 | ||||
| :4008000034D1B9F1000F0BD07F2246495A540133402BFAD10691079328E0BAF1000F06D1012000F087FE01288346F6D107E0237B002B40F087806B7B002BF1D082E0394921 | ||||
| :40084000FFF774FC8146374B07905846069300F0CBFEB9F13F0F07F1010706DD029BDB1BD3F1000949EB030900E0D946079BDBB16368039A06A802EB8312099BC3F1400367 | ||||
| :400880001344089300F031F9099B6BB96A68264B01321340002BBEBF03F1FF3363F00F030133636040230993A36801332AD16B680F2B27D14FF00008C5F8088001F096FD23 | ||||
| :4008C00085F80C80AB6895F868002B44197D00F03FFB95F8680000F0FDFA012195F8680000F0D0FA85F80D80637B002BFCD04FF00008012086F80D8001F032FD404601F022 | ||||
| :4009000041FD02E0BAF1000F05D0237BD3B96B7BC3B94FF0010AA36843453FF454AFD5F8088050E7F085FF1F0F000080C42E00002C2E0000DE2E00009E6400409481FF1FEE | ||||
| :400940009381FF1F01F058FD012001F01BFD002001F006FD042194F8680000F005FB94F8680000F011FB0028F9D196F8680000F09FFAB9F1000F16D1029BBB420ADD012015 | ||||
| :4009800000F0D8FD01288046F6D12E49FFF7CEFB3F2803DC012000F061FE04E0404600F023FE0137E8E7FFF705FC237B0BB102203FE0254B1B8805A8ADF8143027E094F880 | ||||
| :4009C0002A0001F0C7FC606AFFF738FC1F48FFF7FDFB00236373637B002BFCD0012001F0BFFC00237373637B002BFCD0002001F0B7FC1748FFF7EAFB164B04E00020E073A1 | ||||
| :400A0000FFF71CFC144B1B88ADF8183006A8FFF7F3FB10E094F82A0094F8B034834205D085F8B00401F0A2FC0023EB730B4BEAE70120FFF7F3FB032000F0D6FD0848FFF7DE | ||||
| :400A4000C5FB70E4F085FF1F2E2E0000F72E0000052F0000302E0000322E0000342E0000122F000010B54268002A2ED0C368002B2BD00368048A591C01601B78013A13F031 | ||||
| :400A8000800F817C42601DBF03F0010242EA84030231083114BF43F0020343EA0423817414BF03820382837C072BDCD9028A083B42FA03F38268511C81601370C368013BDD | ||||
| :400AC000C360837C083B8374CDE710BD07B5827C42B102AA002102F8011D026001224260FFF7C0FF03B05DF804FB30B543686BB3C2685AB3827C072A0CD8046890F9105057 | ||||
| :400B0000611C01602178013B41EA05210832018243608274827C018AA2F108042141CBB2090608D5C3F3801363F07F03023A03F08103827402E08474002BD7D08268511C9E | ||||
| :400B400081601370C368013BC360CFE730BD0000F8B572B6634B61221A70A3F5F06301221A80192406229C7083F88022522203F5C0731A705C4B5D4A1B785D4EDBB2137059 | ||||
| :400B800040F618025B4B00251A8041F2512223F8022C33784FF4F07003F0010343EA450501F036FC013C05F0030521D0032DF0D1514B4FF480721A8007221A704F4A0024BB | ||||
| :400BC00048211470917002221C705C7103F8032C4B4A4C4D1378062643F001031370414B01221A70484A137843F02003137000E0FEE706FB045300219A881868013401F08C | ||||
| :400C0000D0FC082CF5D180224049414801F0BEFC404D4148002450F8041F04F1105303F1420221F0FF064333C9B20B4452005B0002329A4206D012F8027C12F801EC07F8F3 | ||||
| :400C400006E0F5E7A8420C44E5D1344B00221A60334B34491A68344B344C1A60344A137843F002031370137C43F002031374314B1A7842F040021A700A7842F010020A7053 | ||||
| :400C80002D4A07CA03C42D49228008682C4A28341060097911712B4A07CA03C422802A4AE83C07CA03C42280284A083407CA03C4274922800A78A4F6785442F008020A70E0 | ||||
| :400CC000244A01F5AA5112780C31D2B202F00700120908704A70204A442111700FCB07C42380F8BD004800400F010049A1460040254200402242004004400040064000405A | ||||
| :400D0000A2430040172F0000E8460040A4050048800A014080000048FCFFFF47007600405C060048C243004008760040C051004003500140A04300402406004830060048BA | ||||
| :400D4000CB51004038060048440600485006004822430040CF0100497658004008B501F0E9FB03680C2B00D1FEE7FEE7084908B50B68084A1844821A802A01DC086005E027 | ||||
| :400D800001F0D8FB0C2303604FF0FF33184608BDCC80FF1F1087FF1F80B51148114B0025C0B1A3F1100192C922460439161BB74204D051F8046F42F8046BF7E7114653F822 | ||||
| :400DC000046C8C1AA64202D041F8045BF9E701381033E5E701F0B4FBFFF782FAFEE700BF01000000D8300000124A134B10B51A60124A134C1368134843F4007313600023DA | ||||
| :400E0000032B98BF54F823204FEA830188BF0E4A0133302B4250F3D10C4B1A780C4B1A700C4B084A1A60FFF793FEBDE8104000F013B800BF0004FA050CED00E014ED00E0BD | ||||
| :400E4000000000000080FF1F5D0D0000BC760040C080FF1F08ED00E0074A7F23802113705170064A013BDBB202F80839002BF9D1034A1370704700BFD080FF1FF87B00403D | ||||
| :400E80000078004017280FD8084B0001C25C11B142F0200201E002F0DF02C254C25C42F00102C25400207047012070471070004017280BD8064B0001C25C02F0FE02C25490 | ||||
| :400EC000C25C02F0DF02C25400207047012070471070004017280DD8074900010B4603441A7942F004021A71435C43F00103435400207047012070471070004017280BD81B | ||||
| :400F0000064A0001835C490003F0F10301F00E011943815400207047012070471070004041F6FF73994208BF4FF400519A4208BF4FF4005217289FBFC00000F1804000F597 | ||||
| :400F4000EC4081809ABFC280002001207047000017289FBF034B00011954002088BF0120704700BF1970004017289FBF054B00011A5C01F007019DBF1143195400200120D6 | ||||
| :400F8000704700BF1470004017289FBF034B0001185C00F0070088BFFF20704714700040172810B51AD8C00001F07F0100F1804441EAC21204F5EC44D2B222709DF80820E8 | ||||
| :400FC00003F00F0343EA0213DBB263709DF80C30002003F00F03A370E07010BD012010BD10B501F01DFA0A4A5378182B0AD91478013B5370E30003F1804303F5F0431B7841 | ||||
| :40100000137000E0FF2401F00FFA204610BD00BFD080FF1F030610B5044611D401F000FA084AE300117803F1804303F5F04319705378147001335370BDE8104001F0F4B9E6 | ||||
| :4010400010BD00BFD080FF1F30B504060CD411F4704509D1C40004F1804404F5F0442180A270E370284630BD012030BD03065FBFC00000F1804000F5F04081805ABFC280E1 | ||||
| :40108000002001207047000038B50446084DB4F5004F05D9286801F0BBF9A4F50044F6E7034B58686043BDE8384001F0B1B900BFD880FF1F024B1B7A584301F0A9B900BFFA | ||||
| :4010C000D880FF1F0E4B00F003001A78490102F0FC02104318701A7801F0600142F080021A701A7802F07F021A701A7802F09F020A431A701A7842F010021A70704700BF04 | ||||
| :4011000083430040014B01221A70704784430040044B00F00F021B6853F8220043F82210704700BF08ED00E0054A00F01F00126800F1100352F8230042F82310704700BFCE | ||||
| :4011400008ED00E000F01F0000F16040490100F56440C9B2017070470F4B10B50F4900240F205C609C60DC601C615C61FFF7D0FF0B4A136843F0040313600A4B4FF47A72B6 | ||||
| :40118000DB68B3FBF2F3084A1360084B4FF400421C60C3F8E82010BD3486FF1F0512000010E000E0D880FF1F14E000E018E000E0024A136843F002031360704710E000E0D6 | ||||
| :4011C00008B5FFF7F5FF034A136843F00103136008BD00BF10E000E010B5054CA3691BB9FFF7BAFF0123A361BDE81040FFF7E8BF3486FF1F024B1868C0F30040704700BF15 | ||||
| :4012000010E000E038B5FFF7F5FF012808D1054D002455F8243003B198470134052CF8D138BD00BF3886FF1F024B03EB80035868596070473486FF1F134B144A1B78DBB2FA | ||||
| :401240000360127843EA0223114A0360127843EA0243104A0360127843EA026303600E4B0E4A1B78DBB24360127843EA02230C4A4360127843EA02430A4A4360127843EA46 | ||||
| :4012800002634360704700BF0301004904010049EC4600400201004901010049000100490501004906010049F8B501F0B9F8444A01271378022643F001031370137C414C95 | ||||
| :4012C00043F001031374404B02F5E3521F700B3203F8946C1378054603F07F0313700020FFF7E8FE2378394A03F0F90323701378384603F0DF03137023783B432370FFF745 | ||||
| :40130000D9FE2820FFF7D6FE314B30461A7802F07F021A701A7802F0BF021A70237833432370FFF7C7FE23782A4A43F004032370002313702846537001F076F807211720A4 | ||||
| :40134000FFF700FF24491720FFF7EEFE07211820FFF7F8FE21491820FFF7E6FE07211520FFF7F0FE1E491520FFF7DEFE07210320FFF7E8FE1B490320FFF7D6FE07210420B7 | ||||
| :40138000FFF7E0FE18490420FFF7CEFE07210520FFF7D8FE15490520FFF7C6FE07210620FFF7D0FE12490620FFF7BEFE07210C20FFF7C8FEBDE8F8400E490C20FFF7B4BE9F | ||||
| :4013C000A5430040944300409D60004012600040F851004084600040031B00003D190000011B0000351A0000611A0000911A0000C91A0000071B000008B51D4B1D4A1870F4 | ||||
| :40140000002313701C4A13701C4A13701C4A13701C4A13701C4A13701C4A13701C4B4FF400021A604FF080721A604FF400121A6008221A6010221A6020221A6040221A6008 | ||||
| :40144000144B19B91A7802F0FE0202E01A7842F001021A70104B03221A70802203F8202C012000F0D5FF0D4B04221A7008BD00BF6C86FF1F7286FF1F7086FF1F7186FF1FD1 | ||||
| :401480006D86FF1F5C86FF1F6F86FF1FE486FF1F00E100E009600040286000401260004070B5074C054623780E461BB9FFF7FCFE0123237031462846BDE87040FFF79CBFE4 | ||||
| :4014C0005086FF1F0A4A002313700A4A13700A4A13700A4A13700A4A13700A4A13700A4A13700A4B03221A70802203F8202C70477286FF1F7086FF1F7186FF1F6D86FF1F00 | ||||
| :401500005C86FF1F6F86FF1FE486FF1F28600040014B1878704700BF7186FF1F044B1A7802F0FF001AB118780022C0B21A7070477086FF1F024A0C2303FB002040787047C3 | ||||
| :401540007886FF1F431E072B0CD8074A064B00010344805C5B7800F00F0043EA0020023880B2704700207047FC5F0040431E072BF0B531D8194B0C2505FB0035EC88184F78 | ||||
| :40158000A4B2C4F50074A2424FF00C0404FB003488BFEA88E67884BFC2F5007292B2104C46EA12260501EE552C44D6B2667041B90C2202FB0030002343704379DBB2A37019 | ||||
| :4015C000F0BD0E46074F2F44751AADB2AA42EFD916F8015B3D72F7E7F0BD00BF7886FF1FFC5F004070600040431E072B0AD8064A0C2303FB002300225A705A79034BD2B2AF | ||||
| :4016000000011A54704700BF7886FF1FFE5F004038B505461446D1B1431E072B19D8FFF791FFA04203D22846FFF78CFF04460A4609482B011844531A9BB29C4203D9037AE4 | ||||
| :4016400002F8013BF7E72846FFF7CEFF02E00C4600E00024204638BD70600040431E072B9FBF024B000108221A547047FE5F004030B51A4A1A491B4D0878138803449BB294 | ||||
| :401680001380194A00231488D8B2A4B27CB1082B0CD050680078C0B2E85450680133013050601088013880B21080ECE718460B780E4C082B0E4A00D040B10E4D2B7883F050 | ||||
| :4016C00080032B700F232370022301E0022323701370094B1870087030BD00BFE886FF1FE486FF1F006000406086FF1F5D86FF1F7286FF1F6E86FF1FE586FF1F074B0222E6 | ||||
| :401700001A70074B80221A70064B0F221A70064A00231370054A0120137070477286FF1F6E86FF1F5D86FF1FE486FF1FE586FF1F30B5164B16491B780A8803F00F03023BAF | ||||
| :40174000DBB21A4492B20A80124C134A0020118889B279B173B15568215C013BC9B229705168DBB20131516011880130013989B21180ECE7094A1370094A137883F08003B3 | ||||
| :401780001370084B0B221A7030BD00BF29600040E886FF1F006000406086FF1FE586FF1F6E86FF1F5D86FF1F064A06231370064A01201370054B80221A70054B00221A70F3 | ||||
| :4017C000704700BF7286FF1F5D86FF1F6E86FF1FE586FF1F054B9A683AB19A68044910709A680988518000229A6070476086FF1FE886FF1F08B5124B1A78D2B21A701B78A1 | ||||
| :40180000DBB21A0602D50F4A137008BD0220FFF7E1FF0D4B1B7803F06003202B05D0402B06D043B900F0D4FB04E000F057FE01E000F008FD10B9034B03221A7008BD00BFE5 | ||||
| :40184000286000405D86FF1F0060004008B5084A084B0120197813880B449BB21380064B00221A70FFF7B6FF044B03221A7008BDE886FF1FE486FF1F7286FF1F5D86FF1F8B | ||||
| :4018800008B50C4B1B78DBB2042B07D0062B09D0022B0DD1BDE80840FFF7D8BFBDE80840FFF746BF0320FFF795FF034B03221A7008BD00BF7286FF1F5D86FF1F08B5054B25 | ||||
| :4018C000002201201A70FFF785FF034B03221A7008BD00BF7286FF1F5D86FF1F08B50A4B1A7832B11A78094942F080020A7000221A70074B002201201A70FFF76BFF054BF5 | ||||
| :4019000003221A7008BD00BF5C86FF1F086000407286FF1F5D86FF1F074B1B78DBB2042B05D0062B05D0022B05D1FFF7A1BEFFF7C5BFFFF7D3BF70477286FF1F38B51D4CBC | ||||
| :401940002378DBB2DD0634D518060AD503F00F03012B2ED1FFF74EFF174B1B78190609D538BD5A0602D5FFF7D7FF03E09D0620D5FFF786FF23781B061BD4104B1A78104B10 | ||||
| :401980001B7813430F4A13701278934211D10A4A0849154613782078DBB2000605D41378DBB20B700B7803F00F0328788342F1D138BD38BD286000405D86FF1F6E86FF1F8B | ||||
| :4019C000E586FF1F29600040054A00231380054A916819B191680B7092685380704700BFE886FF1F6086FF1F0E4808B503889BB213B9FFF783FE13E00B4B02221A700B4BBC | ||||
| :401A000000221A70FFF7E0FF094AD1799379028843EA012392B2934238BF0380FFF728FE012008BD6086FF1F7286FF1F6E86FF1F00600040084B01221A700F3B9B7C074B8D | ||||
| :401A40001A7B02F00302012A1EBFDA7B82F08002DA7301225A7370470B6000407886FF1F094B02221A700F3B93F82230074B1A7E02F00302012A1EBFDA7E82F08002DA7620 | ||||
| :401A800001225A76704700BF0B6000407886FF1F0B4B04221A700F3B93F83230094B93F8242002F00302012A1EBF93F8272082F0800283F82720012283F82520704700BFB6 | ||||
| :401AC0000B6000407886FF1F0B4B08221A700F3B93F84230094B93F8302002F00302012A1EBF93F8332082F0800283F83320012283F83120704700BF0B6000407886FF1FD4 | ||||
| :401B00007047FFF7DFBC00F0B3BB000070B50446184B88B003AA03F11006154618685968083303C5B3422A46F7D11B782B70FCB12223237001AD032328466370FFF77CFB3D | ||||
| :401B4000002220461146AB5C08AC04EB131414F8144C03F00F03847008AC234413F8143C0132082AC1700371417100F10400EAD108B070BD472F00002DE9F0411A4D012242 | ||||
| :401B80002E460C2080274FF0080E184B00FB025C14012344187016499CF805802144B8F1000F07D09CF8044024064CBF887081F802E000E08F7000FB0261CC880132E4B2A3 | ||||
| :401BC0009C71CC88092AC4F30724DC71CC88E4B21C71C988C1F307215971D6D1054BFF221A70BDE8F08100BF7886FF1F70600040FC5F00400A600040064B074A1B7802EBAA | ||||
| :401C0000C30253681A7C824286BF03EBC0035869002070476C86FF1F942F00002DE9F84F424B1A78002A7ED01878414D0138C0B2FFF7E2FFA8463F4AC3681478007ADFF856 | ||||
| :401C400000C1E4B203EBC0000C2600274FF0010E834268D01A78A24263D11CF80420597891425ED19A7893F8039002F07F0206FB02FA05EB0A01CF7093F802B009F00309EA | ||||
| :401C800081F804B093F803B005F80AB0B3F804A0A1F808A093F902A0BAF1000F0BDAB9F1010F0CBF4FF007094FF00D0981F8059081F801E009E0B9F1010F0CBF4FF0050959 | ||||
| :401CC0004FF0090981F805904F704FEA02191A4906FB0282494481F802E0B2F808A0CAF3072A81F800A0B2F808A05FFA8AFA81F801A0B2F806A011495FFA8AFA494481F873 | ||||
| :401D000006A0B2F80690C9F3072981F80790B2F806905FFA89F981F80490D288C2F307224A71083394E7BDE8F88F00BF7186FF1F7886FF1F6D86FF1FFC5F00407060004018 | ||||
| :401D40005E86FF1F08B5064B18780138C0B2FFF753FF20B143681B7900EBC300406908BD7186FF1F00212DE9F84F0B464E4E0C2707FB01F401313219092933554FF000057F | ||||
| :401D80009370494CD3701381937253705371EFD118B1464B1D70464B1D70464B1A78002A7FD0187801250138C0B2FFF725FFA8464368DFF8F8E0DB790C2713F0400F3E4BA2 | ||||
| :401DC0004FF0000C1A7814BF42F0010202F0FE021A70027AD20007FB0541C36803EB02094B4531D093F802A00AF07F06AE4229D10E89B3F804B0B6B25E4538BFA1F808B058 | ||||
| :401E00001E7893F801B01EF80660B3451AD181F804A0DE780E7093F902A0DE78BAF1000F06F0030607DA012E0CBF07260D264E7181F8018006E0012E0CBF052609264E7156 | ||||
| :401E400081F801C00833CBE70135092DC3D1C1680A328B1C0A440C200833934209D013F8081C13F80A5C01F07F0100FB01418D72F2E7FFF767FF114B0121186000230C2005 | ||||
| :401E800000FB0142D3801289013113449BB203F00102134409299BB2F2D1BDE8F84FFFF76BBEBDE8F88F00BF7886FF1F5E86FF1FE686FF1F7186FF1F6F86FF1F7486FF1FB3 | ||||
| :401EC000114B1B7903F07F035A1E072A19D80F490C2202FB031291781B0141F0010191700021D170517841F002015170127912F0800F074A1A4414BF8D2389239370FFF7DF | ||||
| :401F000053BC0020704700BF006000407886FF1FFC5F004030B4194B1A7902F07F02531E072B27D8164B0C2404FB02339978154D01F0FE0199700021D97029461201505DEB | ||||
| :401F4000114400F07F0050555A7802F0FD025A701A795B78120605D5012B01D18C7006E00D2303E0012B0CBF082309238B7030BCFFF71ABC002030BC704700BF00600040FD | ||||
| :401F80007886FF1FFC5F004010B50D4B0D4C21791878C9B20138C0B2FFF72EFE43681B798B4201D2012909D8074A0848535CDBB24354A3780120DBB2535410BD002010BDFA | ||||
| :401FC0007186FF1F006000405E86FF1FE686FF1F38B58A4A8A4C13780021DBB221801806517840F18D800A2900F20581DFE811F05D00030103010301030103010B00030117 | ||||
| :402000007E0003018200D3787C49012B09D17D4B1A787D4B03EBC2035B685B686360122310E0CB78022B12D18878FFF7E5FD002800F0E180436863606368DA7863689B7836 | ||||
| :4020400043EA02232380BDE83840FFF7CDBCCB78032B26D16D4B00228878D5B2854209D3664A91786A4AEE2908BF1346634A917881B106E0187801320028F1D0187803446E | ||||
| :40208000EAE764499278097C914203D16248FFF73DFD614B1A78002A00F0AD801A78228018E0BDE8384000F019BA13F0030313D0022B40F0A0802380504B0C211B7903F0A6 | ||||
| :4020C0007F02564B01FB02339A78554BD2B21A7000225A706360B6E702222280514A11784F4AC9B2117053706260ACE7012323804D4BEFE70123238013794C4A1344E9E7A5 | ||||
| :4021000001390A2977D8DFE801F037764F76067676760A7620009378454ADBB25AE0937803F0FF0153B9404B1A7891425FD01970404B01201870FFF715FE58E0481EC0B251 | ||||
| :40214000FFF75AFD0028EED155E0FFF71DFF002851D02A4A384913791279DBB2D2B20A70364A3249D25CCB5C9A4240D0314B01221A70FFF753FD3AE003F00303012B2BD01F | ||||
| :4021800009D3022B37D11D4B9B78002B33D1BDE83840FFF7BFBE194B9B78012B2BD1214A137803F0FD0315E003F00303012B13D008D3022B1FD1114B9B78E3B9BDE838402F | ||||
| :4021C000FFF77EBE0D4B9B78012B14D1154A137843F0020313700AE0084B1A795AB998781B791749DBB2CA5C22EA0002CA54BDE83840FFF7D9BA002038BD00BF00600040AC | ||||
| :402200006086FF1F6C86FF1F942F0000F82F0000802F00006B300000EA86FF1F7886FF1F5186FF1F6F86FF1F7186FF1F5E86FF1F5C86FF1F7086FF1F6D86FF1FE686FF1FDE | ||||
| :402240007386FF1F074B1A78120609D55B78012B06D1054B054A5A6012781A80FFF7C4BB00207047006000406086FF1F582F0000024B1878C0F38010704700BF8F450040F9 | ||||
| :40228000704738B505460078012428B100F0D0F8285D0134E4B2F8E738BD08B50D2000F0C7F8BDE808400A2000F0C2B8014B1870704700BF7C640040014B1878704700BF07 | ||||
| :4022C0006A640040014B1870704700BF78650040074A0223136002F688321268E0215064044A11706FF440710A441360704700BF80E100E001E400E073B515461E460B4C41 | ||||
| :402300000023019300930A46014618462370FEF747FE324629462078FEF702FE02212078FEF7ECFD207802B070BD00BFF480FF1F064A0123136002F688321268E021106434 | ||||
| :40234000034A1170A2F540721360704780E100E000E400E0014B1870704700BF79650040014B1870704700BF7A640040014B1870704700BF7B640040014B1870704700BF94 | ||||
| :402380007F640040014B1870704700BF7E64004073B515461E460B4C01230022019200920A46014618462370FEF7FAFD324629462078FEF7B5FD02212078FEF79FFD207867 | ||||
| :4023C00002B070BDF580FF1F064A0423136002F688321268E0219064034A1170A2F202321360704780E100E002E400E0014B04221A60704700E100E0014B04221A60704792 | ||||
| :4024000080E100E0014B1870704700BF7D6400400230800803D000BF01380046FCD17047EFF3108072B6704780F31088704700BFFEB5494652465B460EB407462449096867 | ||||
| :402440008A46244A12682448022100F05FF8030020480068C018204900F058F8143883460121C9430C4601250026FFF7D9FF814651460B7823400B7058460130FFF7C8FF80 | ||||
| :402480003800F04028400B78234003430B705846FFF7BEFF0136072EF2D9002001300138013001200B78234003430B7058460430FFF7AEFF4846FFF7B7FF00BF00BF00BFAE | ||||
| :4024C0000EBC894692469B46FEBD00BFAFF30080E880FF1FE480FF1F00C20100094A137803F00303012B0AD0022B09D113790C2103F07F02044B01FB02339B7A00E0137911 | ||||
| :4025000000207047006000407886FF1F002902D0B0FBF1F0704708B14FF0FF3000F008B80029F8D00246B0FBF1F000FB11217047704700BF014B1868704700BF5881FF1F9B | ||||
| :402540000E4B70B51E460E4C0025E41AA410A54204D056F8253098470135F8E700F0A2FD084B094C1E46E41AA4100025A54204D056F8253098470135F8E770BDB030000025 | ||||
| :40258000B0300000B0300000B830000010B5431E0A44914204D011F8014B03F8014FF8E710BD03460244934202D003F8011BFAE7704730B5141E05469BB0184604DA8B2390 | ||||
| :4025C0002B604FF0FF301DE04FF40273ADF80C300CBF234604F1FF33029305934FF6FF7300910491ADF80E3002461E9B6946284600F072F8431CBCBF8B232B6014B1009B19 | ||||
| :4026000000221A701BB030BD07B5009313460A46014603480068FFF7CCFF03B05DF804FB5881FF1F2DE9F0478E6882469E420C46914698463ED88A8912F4906F3AD02568CE | ||||
| :40264000096902236F1A656905EB450595FBF3F57B1C43449D4238BF1D4653050FD5294600F040FB064698B13A462169FFF78EFFA38923F4906343F08003A38113E02A46F8 | ||||
| :4026800000F08EFB064670B92169504600F0DEFA0C23CAF80030A3894FF0FF3043F04003A381BDE8F08726613E44266046466561ED1BA560464528BF464649463246206858 | ||||
| :4026C00000F0A8FAA36800209B1BA36023681E442660BDE8F08700002DE9F04F9DB003938B8980461C060D4616460DD50B695BB9402100F0F7FA2860286118B90C23C8F875 | ||||
| :402700000030CDE040236B610023099320238DF82930DFF89CB130238DF82A3037463C4614F8013B1BB9B7EB060910D003E0252BF9D02746F3E74B46324629464046FFF774 | ||||
| :4027400071FF013000F0A780099B4B4409933B78002B00F0A08000234FF0FF3204930793059206938DF853301A930126052221784E4800F041FA671C049B38B14B4A3C4671 | ||||
| :40278000801A06FA00F018430490EFE7D90644BF20228DF853201A0744BF2B228DF8532022782A2A03D0079A00210A200BE0039A111D12680391002A10DA524243F00200F7 | ||||
| :4027C000079204900BE027463B780134303B092B03D800FB02320121F5E701B107923B782E2B1ED17B782A2B0AD1039B02371A1D1B680392002BB8BF4FF0FF33059310E09B | ||||
| :40280000002319460593781C0A2407463A780130303A092A03D804FB01210123F5E703B1059103223978224800F0E6F940B14023CBEB000003FA00F0049B013718430490DD | ||||
| :40284000397806221B487E1C8DF8281000F0D4F988B1194B33B9039B073323F007030833039314E003AB00932A46144B04A94046AFF3008007E003AB00932A460F4B04A9C1 | ||||
| :40288000404600F093F8B0F1FF3F824603D0099B5344099342E7AB895B0601D4099801E04FF0FF301DB0BDE8F08F00BF7F300000853000008930000000000000252600002B | ||||
| :4028C0002DE9F04791461F460A698B6806469342B8BF1346C9F8003091F843200C46DDF8208012B10133C9F800302368990642BFD9F800300233C9F80030256815F006057D | ||||
| :4029000010D104F1190A07E00123524639463046C04701301AD00135E368D9F800209B1A9D42F1DB94F843302268003318BF012392060FD5E118302081F843005A1C94F8D8 | ||||
| :4029400045102244023382F8431003E04FF0FF30BDE8F08704F1430239463046C0470130F4D02268D9F80050E36802F00602042A08BF5D1B2269A3680CBF25EAE5750025B6 | ||||
| :402980009342C4BF9B1AED184FF000091A344D4509D00123224639463046C0470130D5D009F10109F3E70020BDE8F0872DE9F04317460A7E85B06E2A984606460C460C9B6E | ||||
| :4029C00001F1430E00F0AE8011D8632A22D009D8002A00F0BB80582A40F0CA8081F84520834955E0642A1ED0692A1CD0C0E0732A00F0B08009D86F2A2ED0702A40F0B8802B | ||||
| :402A00000A6842F020020A603EE0752A24D0782A3AD0ADE01A6801F14205111D1960136884F84230A8E021681A6811F0800F02D0111D196008E011F0400F02F1040119606C | ||||
| :402A400002D0B2F9003000E01368002B3CDA2D225B4284F8432037E021681A6811F0800F02D0111D196007E011F0400F02F10401196001D0138800E01368227E5C496F2ACA | ||||
| :402A800014BF0A2208221BE078225A4984F845202268186812F0800F00F104051D6003D1550601D5038800E00368D00744BF42F0200222601BB9226822F0200222601022F1 | ||||
| :402AC000002084F8430001E049490A226568002DA56008DB206820F0040020602BB9002D7DD175460CE0002B79D07546B3FBF2F002FB1033CB5C05F8013D03460028F5D1BC | ||||
| :402B0000082A0BD12368DA0708D5236962689A42DEBF302305F8013C05F1FF35C5EB0E0323612EE008681A6810F0800F496903D0101D1860136808E010F0400F02F1040011 | ||||
| :402B40001860136801D0198000E0196000232361754616E01A68111D1960156800216268284600F049F808B1401B6060636804E004F1420584F8422001232361002384F833 | ||||
| :402B80004330CDF800803B4603AA21463046FFF797FE013002D14FF0FF3026E023692A4639463046C0470130F5D023689B0710D5002504F1190907E001234A463946304683 | ||||
| :402BC000C0470130E7D00135E368039A9B1A9D42F2DBE068039B9842B8BF184605E00B7804F1420584F842308AE705B0BDE8F083472F00009030000010B5C9B20244904274 | ||||
| :402C0000034605D01C7801308C42F8D1184610BD002010BD884210B501EB020301D8421E0BE09842FBD28118D21AD34204D013F8014D01F8014DF8E710BD994204D011F845 | ||||
| :402C4000014B02F8014FF8E710BD000038B50546002944D051F8043C0C1F002BB8BFE41800F0D4F81E4A1368114613B96360146030E0A3420DD92268A018834201BF186830 | ||||
| :402C80005B681218226063600C6023E0A24203D813465A68002AF9D118681918A1420BD12168014458188242196013D110685268014419605A600DE002D90C232B6009E0C1 | ||||
| :402CC00021686018824201BF106852680918216062605C602846BDE8384000F098B838BD5886FF1F70B5CD1C25F0030508350C2D38BF0C25002D064601DBA94202D90C232E | ||||
| :402D0000336046E000F082F8234B1C681A462146A1B10B685B1B0ED40B2B03D90B60CC18CD501EE08C420BBF63684B681360636018BF0C4615E00C464968E9E7174C2368F3 | ||||
| :402D40001BB9304600F052F820602946304600F04DF8431C18D0C41C24F00304A0420DD12560304600F053F804F10B00231D20F00700C31A0ED05A42E25070BD211A30463F | ||||
| :402D800000F034F80130EBD10C233360304600F03EF8002070BD00BF5886FF1F5486FF1FF8B5074615460E4621B91146BDE8F840FFF798BF1AB9FFF749FF2846F8BD00F084 | ||||
| :402DC00027F885420ED929463846FFF78BFF044650B131462A46FFF7D9FB31463846FFF735FF01E03046F8BD2046F8BD38B5064C0023054608462360FDF7B8FF431C02D1FC | ||||
| :402E0000236803B12B6038BD0C87FF1F7047704751F8040C0028BEBF091851F8043CC0180438704700000000050209020B020D020F02110213027265706C79203078253091 | ||||
| :402E4000327800686F6D696E6700626567696E6E696E67207365656B2066726F6D20256420746F20256400756E65787065637465646C7920646574656374656420747261A1 | ||||
| :402E8000636B20300066696E6973686564207365656B0057616974696E6720666F72205553422E2E2E0055534220726561647900636F6D6D616E64203078253032780077D8 | ||||
| :402EC00061697400756E64657272756E206166746572202564207061636B65747300636F756E743D256420693D256420643D2564207A7A3D25640073746172742065726153 | ||||
| :402F000073696E670073746F702065726173696E670069646C650000510040100030510040400000000140800A000B0140000500140140000800400140000A004C01400040 | ||||
| :402F400002005001402000303132333435363738394142434445460028000000000104000100000000000000000157494E5553420000303030303100000000000000000004 | ||||
| :402F800012034D0053004600540031003000300001000000010000009C2F0000010000006B300000000000000000000001000000B42F0000010000003D3000000400000072 | ||||
| :402FC000D62F0000000000000000000000000000D42F0000FF00000001024000FF00000082024000FF00000003034000FF00000084034000FF000203040309041603460042 | ||||
| :403000006C007500780045006E00670069006E0065002A0343006F0077006C00610072006B00200054006500630068006E006F006C006F0067006900650073000009022EA4 | ||||
| :403040000001010080320904000004FF00000007050102400000070582024000000705030340000A0705840340000A12010002FF0001080912006E010002018001430023A3 | ||||
| :403080002D302B2000686C4C00656667454647003031323334353637383961626364656600000000F8B500BFF8BC08BC9E46704759000000E90D0000F8B500BFF8BC08BC30 | ||||
| :4030C0009E46704735000000D8300000C880FF1F98000000B0050000000000001087FF1F7F800000030000000000007D00FA0000400000000090D0031550004002000000CD | ||||
| :4031000005000000FFFF000000000000000000000000000000000000000000000000000000000000000000007D3000000000000000000000000000000000000000000000DF | ||||
| :4031400000000000000000000000000000000000000000000000000000000000000000000000000000000000F880FF1F0000000000000000000000000000000000000000B9 | ||||
| :40318000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F | ||||
| :4031C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CF | ||||
| :40320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008E | ||||
| :40324000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004E | ||||
| :40328000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E | ||||
| :4032C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CE | ||||
| :40330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008D | ||||
| :40334000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004D | ||||
| :40338000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D | ||||
| :4033C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CD | ||||
| :40340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008C | ||||
| :40344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004C | ||||
| :40348000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C | ||||
| :4034C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CC | ||||
| :40350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008B | ||||
| :40354000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004B | ||||
| :40358000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B | ||||
| :4035C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CB | ||||
| :40360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008A | ||||
| :40364000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004A | ||||
| :40368000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A | ||||
| :4036C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CA | ||||
| :403700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000089 | ||||
| :403740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000049 | ||||
| :403780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009 | ||||
| :4037C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C9 | ||||
| :403800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000088 | ||||
| :403840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000048 | ||||
| :403880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008 | ||||
| :4038C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C8 | ||||
| :403900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000087 | ||||
| :403940000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000047 | ||||
| :403980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 | ||||
| :4039C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C7 | ||||
| :403A00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086 | ||||
| :403A40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046 | ||||
| :403A80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006 | ||||
| :403AC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C6 | ||||
| :403B00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000085 | ||||
| :403B40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045 | ||||
| :403B80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005 | ||||
| :403BC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C5 | ||||
| :403C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084 | ||||
| :403C40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044 | ||||
| :403C80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 | ||||
| :4000000000800020110000004110000041100000064A08B5136843F020031360044B1A6803F53F5302331A6001F028F8E8460040FA46004010B5054C237833B9044B13B163 | ||||
| :400040000448AFF300800123237010BD6881FF1F00000000C8380000084B10B51BB108490848AFF300800848036803B910BD074B002BFBD0BDE81040184700BF0000000041 | ||||
| :400080006C81FF1FC8380000C880FF1F000000000A4A0B4B116801310B40002BBEBF03F1FF3363F03F030133136011685368994202BF024B01221A72704700BF8881FF1FBC | ||||
| :4000C0003F0000800A4A0B4B516801310B40002BBEBF03F1FF3363F03F030133536051681368994202BF024B01221A72704700BF8881FF1F3F000080114BDA68196919B9FD | ||||
| :4001000001221A75597514E09969521A19698A4294BF587D00201875187D094908B1002204E0086982428CBF002201224A75DA689A611B7D13B1002002F046B9704700BF70 | ||||
| :400140008881FF1F10B5C4B2204601F059F90128FAD110BD08B572B60F4B0F49DA680132DA60DA690132C82A08BF0022DA611A6AD8690132A72A08BF00220A621B6A002B13 | ||||
| :400180000CBF02230023002814BF184643F0010002F082FE62B608BD8881FF1F38B50446C5B2284602F0B2F8062002F0CFFA44F00200C0B202F0AAF8062002F0C7FA28460D | ||||
| :4001C00002F0A4F8BDE83840062002F0A9BA10B5642402F095F828B9FFF7E0FF013CF8D1204610BD012010BD70B5C4B2054620460E4601F005F9012805D0204601F01EFA34 | ||||
| :400200002846FFF79FFF204601F002F9314605460246204601F0BEF9204601F0F1F80028FAD1284670BD000038B5044D0024285D013402F03BFA402CF9D138BDAC81FF1FCB | ||||
| :4002400008B502F055FC002002F05EFC02F070FC02F07AFC80B208BD10B50446012002F06DF8642002F05CFAFFF7EAFF2080002002F064F8642002F053FAFFF7E1FF60809C | ||||
| :4002800010BD08B502F060FD002002F069FD02F07BFD02F085FD80B208BD10B50446FFF796FF322002F03CFAFFF7EBFF20800120FFF774FF322002F033FAFFF7E2FF6080D2 | ||||
| :4002C00010BD0FB400B593B014AB53F8042B402102A8019302F0E0FE02A802F07CF802F086F813B05DF804EB04B0704710B5044601780648FFF7E5FF0420FFF723FF627816 | ||||
| :400300002146BDE81040042001F0D2B8DC38000007B50023ADF804308DF80600032301A88DF80530FFF7E2FF03B05DF804FB000010B5074C94F8643043B1002001F0DAFFEE | ||||
| :40034000002002F06DFD002384F8643010BD00BF8881FF1F38B5104D837895F8672004469A4204D0FFF7E4FF002385F86A302368C5F865302279094B1A71A378002B14BF45 | ||||
| :400380000220012002F04CFDE07802F043FD2079BDE8384002F07ABD8881FF1FED81FF1F38B50D4C94F8645065B904F16500FFF7D1FF012001F09EFF4FF47A7002F0B0F968 | ||||
| :4003C00084F86A50E368E366012384F86430BDE8384002F0E3B900BF8881FF1FF8B5214C0546FFF7DDFF94F86A3003B15DB91E48FFF767FFFFF7EBFE0120002384F86A007C | ||||
| :40040000236702F0A3F92A46216F1848FFF759FF144E0027236F9D4216D001F071FF00B13767236F9D4205DD0120FFF7B7FE336F013305E005DA0020FFF7B0FE336F013B0B | ||||
| :40044000336702F0ABF9E5E7322002F069F92A2DCCBF0020012002F025FDBDE8F8400448FFF72FBF8881FF1FE9380000F03800000D3900002DE9F04F99B062B602F0F8F947 | ||||
| :400480009E49042002F01CFA9D4801F045FF9D4802F0E8FC9C4801F079FF02F0C9FB02F09BFA002002F0BCFC01F094FF0221002000F05CFF954C012001F0D4F8002384F890 | ||||
| :4004C0006730FFF76DFFFFF782FE84F87400FFF72FFF012384F86730FFF762FFFFF777FE84F87500FFF724FF894B94F87400894994F875202546002A14BF0A461A4600286F | ||||
| :4005000008BF19468448FFF7DCFE0321084602F025F9264602F042F994F8643043B1EA6EEB689B1A41F28832934201D9FFF700FF00F054FF18B97948FFF7C3FE04E000F079 | ||||
| :4005400053FF0028F7D10BE000F048FF10B902F025F9F9E77248FFF7B4FE032001F06EF8032000F04DFF0128D4D16E48FFF7F2FE6D490320FFF738FE94F876106B48FFF7F9 | ||||
| :40058000A0FE94F87630023B142B00F2D683DFE813F01500D4031E00D4032400D4035000D4037600D403D900D403C101D4030803D4032C03D4033303D4034D0303238DF851 | ||||
| :4005C00020308DF821300F238DF822302AE394F87800FFF703FF564B21E340F2DC57FFF7DFFE00232375E068227D02F0FF012AB9EB681B1ABB42F7DD0B4611E083B100227E | ||||
| :40060000174696F87810F068277594F814E0BEF1000F02D1EB681B1AF7E701329142F3DA07228DF8202004228DF82120ADF82230F8E20220FFF786FD4FF000080DF1200A54 | ||||
| :4006400002F0ACF84FF480790027C9EB0803DA1907F80A200137402FF9D10220FFF772FD3A465146022000F023FFB9F10109EBD108F10108B8F1400FE2D12E4B38E04FF076 | ||||
| :40068000010A4FF000080DF1200B02F087F84FF0000959460120FFF7A7FD08EB090300270493049B1BF807203B44DBB29A4209D08DE80C0041463B464A461F48FFF701FEE0 | ||||
| :4006C0004FF0000A0137402FEBD109F10109B9F5807FDED108F10108B8F1400FD5D151461648FFF7EEFDBAF1000F00F01B81144B1B8807A8ADF81C3095E200BF5501000004 | ||||
| :40070000F900000091000000C50000008881FF1F1F3900001B390000223900003A3900004D390000ED81FF1FFE81FF1F57390000CC380000CE380000663900008239000026 | ||||
| :40074000D0380000206FFFF749FE94F8780001F0F5FD94F8780001F0D9FD02F009FCB94BDFF8FC821A78002702F0FB021A701A7842F001021A701A7802F0FE021A701A7880 | ||||
| :4007800002F0FE021A7002F0F7FB0220FFF7DAFC012141F6FF734FF48042084602F046FB84F8B60001F068FF08F807000137402FF8D1DFF8B0A200270AF195091FFA89F816 | ||||
| :4007C0000137402F14BF3A4600221AF8010F2244062392F82420402101F082FF424646F240419AF8000001F08DFF08F14008402F1FFA88F8E4D196F8793053B196F87C30C8 | ||||
| :40080000336100233375237D002BFCD000233375336100234FF0FF32236062602372236894F8B600234493F8241001F0DDFE94F8B60001F09BFE012194F8B60001F06EFEAA | ||||
| :400840002368002BFCD0002398467360D6F80CA0012701F0A3FFE368B4F87A20CAEB030393420DD367B1042195F8B60001F0C8FE94F8B60001F0D4FE0028F9D107463072CF | ||||
| :40088000237AFBB96A682B689A4202D1002FE0D118E00220FFF756FC6968402209EB8111022000F005FE6A68674B01321340002BBEBF03F1FF3363F03F03013308F1010820 | ||||
| :4008C0006360C6E70220277AFFF73CFC00221146022000F0EDFD0220FFF734FCFFB2FFF7A3FC002001F012FD37B15848FFF7E9FC0220FFF70DFD06E0554B08A81B88ADF871 | ||||
| :400900002030FFF7F3FC227D4146237A5148FFF7D8FC15E25048FFF7D4FCD4F87A7017F03F0701D0032009E2286FFFF757FD95F8780001F003FD95F8780001F0E7FC012054 | ||||
| :4009400001F002FD02F014FB444BDFF814811A7842F004021A701A7842F001021A701A7802F0FE021A701A7802F0FE021A7002F003FB01214FF4804341F6FF72084601F0CB | ||||
| :40098000E9FC85F8B60001F077FE08F807000137402FF8D1DFF8CC90002709F195031FFA83F804930137402F14BF3A46002219F8010F2244052392F82420402101F090FEB2 | ||||
| :4009C000414646F2475299F8000001F09BFE08F14008402F1FFA88F8E4D100274FF0FF33376098467360BB463B46D6F87A9037725FEA99190CBF4FF0010A4FF0000A2168C1 | ||||
| :400A0000114A01310A40002ABCBF02F1FF3262F03F026068B8BF013282426FD02BB1227A002A7AD12A7D002A77D12068049A059302EB8010BAF1000F16D040223F2102F079 | ||||
| :400A4000F7FA1CE0906400403F0000808C390000D2380000A6390000B939000097650040AC81FF1FAB81FF1F014601370120FFF7BBFBC7EB0903D3F1000A4AEB030A216882 | ||||
| :400A8000B34A01310A40002ABEBF02F1FF3262F03F02013222606268059B01322ED12A683F2A2BD14FF00008C5F8048001F080FC85F808806B6895F8B6002B4493F82410D9 | ||||
| :400AC00001F092FD95F8B60001F050FD012195F8B60001F023FD95F87E302B6185F81480237D002BFCD04FF00008012086F8148001F06AFC404601F027FC00E023B1237A54 | ||||
| :400B00005BB92B7D4BB90123626842453FF477AF0BF1010BD5F8048071E701F04FFC012001F012FC002001F04FFC042194F8B60001F066FD94F8B60001F072FD8046002873 | ||||
| :400B4000F8D196F8B60001F0FFFC337D327A0293012303920193CDF800A05B463A4649467C48FFF7AEFBC6F81080BAF1000F0BD0FFF75AFB002001F0C9FB237A63B1764854 | ||||
| :400B8000FFF79FFB0220D9E0B945F1D073490120FFF72AFB0137F7E77148FFF792FB714B3DE094F8780001F0C9FB206FFFF716FC6D48FFF786FB94F87930236100232375F8 | ||||
| :400BC000237D002BFCD0012001F0FEFB00233375237D002BFCD0002001F0F6FB002363483361FFF76EFB624B19E0002084F86A00FFF7F4FB5F4B12E094F8743023B195F870 | ||||
| :400C000075200AB985F8782094F875201AB113B9012385F878305848FFF79CFB574B1B88ADF8203008A8FFF761FB89E0FFF780FB02F07CF8002002F01FF82A2701F04AFFE9 | ||||
| :400C4000002001F0EDFE3A46002108A802F0F0F917238DF820308DF8217001F09FFD002001F048FB002002F0DBF8C82001F058FD0DF12200FFF7F0FA0DF13600FFF70DFB01 | ||||
| :400C800001F08CFD012002F0CBF8322001F048FD0DF12600FFF7E0FA0DF13A00FFF7FDFA012001F027FB4FF4967001F039FD01F075FD0DF12E00FFF7CFFA0DF14200FFF71B | ||||
| :400CC000ECFA002001F016FB4FF4967001F028FD01F064FD022002F0A3F8322001F020FD0DEB0700FFF7B8FA0DF13E00FFF7D5FA012001F0FFFA4FF4967001F011FD01F040 | ||||
| :400D00004DFD0DF13200FFF7A7FA0DF14600FFF7C4FA002001F0EEFA4FF4967001F000FD01F03CFD002002F07BF8002384F86A3001F07EFF01F050FE74E70120FFF7E8FA91 | ||||
| :400D4000032000F07BFC0E48FFF7BBFAFFF7E2BB3F000080C3390000F33900004092FF1FFD390000D4380000053A0000133A0000D6380000D8380000FE81FF1FDA380000E3 | ||||
| :400D8000203A00002DE9F04172B6884B61221A70A3F5F06301221A801924854A9C7092E803008033062283F8002283E80300522203F580731A707F4B7F4A1B787F4EDBB2FE | ||||
| :400DC000137040F618027E4B00251A8041F2512223F8022C33784FF4F07003F0010343EA450502F0BDF8013C05F003052ED0032DF0D1744B4FF480721A8007221A70724A20 | ||||
| :400E0000002548211570917002221D705D7103F8032C0422DA716D4A6D4C13786D4E43F00103137012F8013C062743F0030302F8013C2378012243F0800323705B4B1A70F9 | ||||
| :400E4000654A137843F02003137000E0FEE707FB056300219A881868013502F0E9F8072DF5D15E485E4E002550F8041F05F1105303F1480221F0FF074933C9B20B44520042 | ||||
| :400E80005B0002329A4206D012F802EC12F801CC0EF807C0F5E7B0420D44E5D1514A002313609360136193614F4B504F1A68504BDFF888811A604F4B1A684F4B1A604F4A7B | ||||
| :400EC000137843F002031370137C43F0020313742378A2F5863243F040032370413A137843F010031370464A464B07CA03C31A80454A2833106843F8250C127903F8212CA9 | ||||
| :400F0000424A07CA03C31A80414AE83B07CA03C31A80404A083307CA03C31A803E4A3F4BA2F5616203CBC2F8100EC2F8141E1378042043F008031370394B02F5AA521B78A7 | ||||
| :400F40003D78DBB298F80060EDB203F007010C321B091170F6B2537045F003033B7046F0030388F800302F4B48221A702E4A402313702E49937013729372082382F81F32BF | ||||
| :400F800020220A7048710A72294A0A20137001F0DDFB284B88F8006044223D70264D1A7094E80F0007C52B80BDE8F081004800404C0A00480F010049A1460040254200408F | ||||
| :400FC000224200400440004006400040A2430040A0430040253A0000E8460040FCFFFF478C00004800760040540A0048F846004020760040580A004828760040035001404D | ||||
| :401000000C0A0048C0510040180A0048200A00482C0A0048380A004832510040440A0048CF0100491D51004001590040235B0040585B004076580040B0430040F9460040F2 | ||||
| :4010400008B501F0C9FF03680C2B00D1FEE7FEE7084908B50B68084A1844821A802A01DC086005E001F0B8FF0C2303604FF0FF33184608BDCC80FF1F9093FF1F80B5114817 | ||||
| :40108000114B0025C0B1A3F1100192C922460439161BB74204D051F8046F42F8046BF7E7114653F8046C8C1AA64202D041F8045BF9E701381033E5E701F094FFFFF7DAF9D9 | ||||
| :4010C000FEE700BF01000000F43B0000124A134B10B51A60124A134C1368134843F4007313600023032B98BF54F823204FEA830188BF0E4A0133302B4250F3D10C4B1A7814 | ||||
| :401100000C4B1A700C4B084A1A60FFF73BFEBDE8104001F0EDB900BF0004FA050CED00E014ED00E0000000000080FF1F41100000BC760040C080FF1F08ED00E0F8B501F042 | ||||
| :4011400017FF4B4A01271378022643F001031370137C484C43F001031374474B02F5E3521F700B3203F8946C1378054603F07F031370002001F0EAFA2378404A03F0F903F2 | ||||
| :4011800023701378384603F0DF03137023783B43237001F0DBFA282001F0D8FA384B30461A7802F07F021A701A7802F0BF021A7023783343237001F0C9FA2378314A43F0C6 | ||||
| :4011C000040323700023137053702F4AFF2199540133092BFBD1284601F0CEFE0721172001F0FCFA2949172001F0EAFA0721182001F0F4FA2649182001F0E2FA0721152033 | ||||
| :4012000001F0ECFA2349152001F0DAFA0721052001F0E4FA2049052001F0D2FA0721062001F0DCFA1D49062001F0CAFA0721084601F0D4FA1A49072001F0C2FA07210820F8 | ||||
| :4012400001F0CCFA1749082001F0BAFA0021162001F0C4FA1449162001F0B2FA07210C2001F0BCFABDE8F84010490C2001F0A8BAA5430040944300409D6000401260004076 | ||||
| :40128000F851004084600040B592FF1F0B1B000045190000091B00003D1A0000691A0000991A0000D11A0000111B0000851B0000214B224A10B5187000231370204A40209B | ||||
| :4012C0001370204A0F2413701F4A13701F4A13701F4A13701F4A13701F4B4FF400021A604FF080721A604FF400121A6020221A601860802018604FF480701860174804702E | ||||
| :401300004FF480001860164B1A70933B19B91A7802F0FE0202E01A7842F001021A70114B03221A70802203F8202C012001F018FE0D4B04221A7010BDD092FF1FD692FF1F39 | ||||
| :40134000D492FF1FD592FF1FD192FF1FC092FF1FD392FF1F4893FF1F00E100E09E6000409C600040286000401260004070B5074C054623780E461BB9FFF7E0FE0123237031 | ||||
| :4013800031462846BDE87040FFF792BF8092FF1F0A4A002313700A4A13700A4A13700A4A13700A4A13700A4A13700A4A13700A4B03221A70802203F8202C7047D692FF1F4E | ||||
| :4013C000D492FF1FD592FF1FD192FF1FC092FF1FD392FF1F4893FF1F28600040014B1878704700BFD592FF1F044B1A7802F0FF001AB118780022C0B21A707047D492FF1F52 | ||||
| :40140000024A0C2303FB002040787047DC92FF1F431E072B0CD8074A064B00010344805C5B7800F00F0043EA0020023880B2704700207047FC5F00401A4A38B50C2303FBA9 | ||||
| :4014400000231B79090C13F0800F00F1FF35044619BF8AB24FF480438BB24FF48042032D18D8DFE805F002070C110021084601F01BF80DE00021084600F0FAFF08E0002180 | ||||
| :40148000084600F0D9FF03E00021084600F0B8FF054B1855EDB2072D03D801F0EDF8034B185538BDDC92FF1FAC92FF1FB592FF1F431E072B2DE9F0470446894615465CD857 | ||||
| :4014C0002F4F0C2202FB0072D388DFF8B8A09BB2C3F500739D424FF00C0303FB007388BFD588DB7884BFC5F50075ADB2254A43EA15230601B354B244EBB28AF80130224BD4 | ||||
| :401500001A5C9846FF2A01D1FFF796FF0C2303FB047200215170B9F1000F28D03DB31B4F385D01F011F811232946FE2218F8040001F0D6F806F5C04278321FFA89F118F8D2 | ||||
| :40154000040001F0DFF8124D18F80410385D01F04BF80121385D00F0E1FF735D43F002037355735D03F0FD037355BDE8F08703FB04746379DBB28AF80230BDE8F08700BFE7 | ||||
| :40158000DC92FF1FFC5F0040B592FF1FAC92FF1F706000402DE9F047044615468846002940D0431E072B3FD8FFF732FFA84203D22046FFF72DFF05461D4E335DFF2B03D1DE | ||||
| :4015C00041462046FFF738FFDFF868A027011AF8040000F0B9FF1223FE222946305D01F07FF807F5C0411FFA88F27831305D01F089F8DFF84490315D1AF8040000F0F4FFE9 | ||||
| :4016000001211AF8040000F089FF17F8093043F0020307F8093017F8093003F0FD0307F8093002E00D4600E000252846BDE8F087B592FF1FAC92FF1F70600040431E072BA7 | ||||
| :401640000AD8064A0C2303FB002300225A705A79034BD2B200011A54704700BFDC92FF1FFE5F0040431E072B9FBF024B000108221A547047FE5F004030B51A4A1A491B4D0A | ||||
| :401680000878138803449BB21380194A00231488D8B2A4B27CB1082B0CD050680078C0B2E85450680133013050601088013880B21080ECE718460B780E4C082B0E4A00D003 | ||||
| :4016C00040B10E4D2B7883F080032B700F232370022301E0022323701370094B1870087030BD00BF4C93FF1F4893FF1F00600040C492FF1FC192FF1FD692FF1FD292FF1FE1 | ||||
| :401700004993FF1F074B02221A70074B80221A70064B0F221A70064A00231370054A012013707047D692FF1FD292FF1FC192FF1F4893FF1F4993FF1F30B5164B16491B78E1 | ||||
| :401740000A8803F00F03023BDBB21A4492B20A80124C134A0020118889B279B173B15568215C013BC9B229705168DBB20131516011880130013989B21180ECE7094A1370B3 | ||||
| :40178000094A137883F080031370084B0B221A7030BD00BF296000404C93FF1F00600040C492FF1F4993FF1FD292FF1FC192FF1F064A06231370064A01201370054B802273 | ||||
| :4017C0001A70054B00221A70704700BFD692FF1FC192FF1FD292FF1F4993FF1F054B9A683AB19A68044910709A680988518000229A607047C492FF1F4C93FF1F08B5124BAC | ||||
| :401800001A78D2B21A701B78DBB21A0602D50F4A137008BD0220FFF7E1FF0D4B1B7803F06003202B05D0402B06D043B900F012FC04E001F0A5FB01E000F046FD10B9034B1C | ||||
| :4018400003221A7008BD00BF28600040C192FF1F0060004008B5084A084B0120197813880B449BB21380064B00221A70FFF7B6FF044B03221A7008BD4C93FF1F4893FF1F1D | ||||
| :40188000D692FF1FC192FF1F08B50C4B1B78DBB2042B07D0062B09D0022B0DD1BDE80840FFF7D8BFBDE80840FFF746BF0320FFF795FF034B03221A7008BD00BFD692FF1FCC | ||||
| :4018C000C192FF1F08B5054B002201201A70FFF785FF034B03221A7008BD00BFD692FF1FC192FF1F08B50A4B1A7832B11A78094942F080020A7000221A70074B00220120D1 | ||||
| :401900001A70FFF76BFF054B03221A7008BD00BFC092FF1F08600040D692FF1FC192FF1F074B1B78DBB2042B05D0062B05D0022B05D1FFF7A1BEFFF7C5BFFFF7D3BF70479E | ||||
| :40194000D692FF1F38B51D4C2378DBB2DD0634D518060AD503F00F03012B2ED1FFF74EFF174B1B78190609D538BD5A0602D5FFF7D7FF03E09D0620D5FFF786FF23781B066B | ||||
| :401980001BD4104B1A78104B1B7813430F4A13701278934211D10A4A0849154613782078DBB2000605D41378DBB20B700B7803F00F0328788342F1D138BD38BD2860004067 | ||||
| :4019C000C192FF1FD292FF1F4993FF1F29600040054A00231380054A916819B191680B7092685380704700BF4C93FF1FC492FF1F0E4808B503889BB213B9FFF783FE13E0D1 | ||||
| :401A00000B4B02221A700B4B00221A70FFF7E0FF094AD1799379028843EA012392B2934238BF0380FFF728FE012008BDC492FF1FD692FF1FD292FF1F00600040084B012220 | ||||
| :401A40001A700F3B9B7C074B1A7B02F00302012A1EBFDA7B82F08002DA7301225A7370470B600040DC92FF1F094B02221A700F3B93F82230074B1A7E02F00302012A1EBF0F | ||||
| :401A8000DA7E82F08002DA7601225A76704700BF0B600040DC92FF1F0B4B04221A700F3B93F83230094B93F8242002F00302012A1EBF93F8272082F0800283F827200122E0 | ||||
| :401AC00083F82520704700BF0B600040DC92FF1F0B4B08221A700F3B93F84230094B93F8302002F00302012A1EBF93F8332082F0800283F83320012283F83120704700BFF5 | ||||
| :401B00000B600040DC92FF1F7047FFF741BC0000F0B5184B184E19780C27C9B201234FF0000C31B3CA0720D5144A4FEA031E7244947850782040C5070DD507FB03652C799F | ||||
| :401B4000240608D5147804F0FE0414706D790C4CEDB204F80E50840706D507FB036425792D0658BF84F801C090700133DBB24908D7E7F0BD9F600040DC92FF1F70600040D5 | ||||
| :401B8000FE5F004000F0ACBC70B50446184B88B003AA03F11006154618685968083303C5B3422A46F7D11B782B70FCB12223237001AD03232846637000F08AFE00222046DB | ||||
| :401BC0001146AB5C08AC04EB131414F8144C03F00F03847008AC234413F8143C0132082AC1700371417100F10400EAD108B070BD4F3A00002DE9F0431C4D01222E460C2093 | ||||
| :401C00001F274FF0800E4FF0080C194B00FB02581401234418705F70164998F805902144B9F1000F07D098F8044024064CBF887081F802C001E081F802E000FB0261CC880F | ||||
| :401C40000132E4B29C71CC88092AC4F30724DC71CC88E4B21C71C988C1F307215971D4D1054BFF221A70BDE8F08300BFDC92FF1F70600040FC5F00400A600040064B074A70 | ||||
| :401C80001B7802EBC30253681A7C824286BF03EBC003586900207047D092FF1FB03A00002DE9F84F424B1A78002A7ED01878414D0138C0B2FFF7E2FFA8463F4AC368147810 | ||||
| :401CC000007ADFF800C1E4B203EBC0000C2600274FF0010E834268D01A78A24263D11CF80420597891425ED19A7893F8039002F07F0206FB02FA05EB0A01CF7093F802B01E | ||||
| :401D000009F0030981F804B093F803B005F80AB0B3F804A0A1F808A093F902A0BAF1000F0BDAB9F1010F0CBF4FF007094FF00D0981F8059081F801E009E0B9F1010F0CBF20 | ||||
| :401D40004FF005094FF0090981F805904F704FEA02191A4906FB0282494481F802E0B2F808A0CAF3072A81F800A0B2F808A05FFA8AFA81F801A0B2F806A011495FFA8AFAAB | ||||
| :401D8000494481F806A0B2F80690C9F3072981F80790B2F806905FFA89F981F80490D288C2F307224A71083394E7BDE8F88F00BFD592FF1FDC92FF1FD192FF1FFC5F004052 | ||||
| :401DC00070600040C292FF1F08B5064B18780138C0B2FFF753FF20B143681B7900EBC300406908BDD592FF1F00212DE9F84F0B464E4E0C2707FB01F4013132190929335553 | ||||
| :401E00004FF000059370494CD3701381937253705371EFD118B1464B1D70464B1D70464B1A78002A7FD0187801250138C0B2FFF725FFA8464368DFF8F8E0DB790C2713F0B5 | ||||
| :401E4000400F3E4B4FF0000C1A7814BF42F0010202F0FE021A70027AD20007FB0541C36803EB02094B4531D093F802A00AF07F06AE4229D10E89B3F804B0B6B25E4538BF50 | ||||
| :401E8000A1F808B01E7893F801B01EF80660B3451AD181F804A0DE780E7093F902A0DE78BAF1000F06F0030607DA012E0CBF07260D264E7181F8018006E0012E0CBF052673 | ||||
| :401EC00009264E7181F801C00833CBE70135092DC3D1C1680A328B1C0A440C200833934209D013F8081C13F80A5C01F07F0100FB01418D72F2E7FFF767FF114B01211860E6 | ||||
| :401F000000230C2000FB0142D3801289013113449BB203F00102134409299BB2F2D1BDE8F84FFFF767BEBDE8F88F00BFDC92FF1FC292FF1F4A93FF1FD592FF1FD392FF1FCE | ||||
| :401F4000D892FF1F114B1B7903F07F035A1E072A19D80F490C2202FB031291781B0141F0010191700021D170517841F002015170127912F0800F074A1A4414BF8D238923CF | ||||
| :401F80009370FFF715BC0020704700BF00600040DC92FF1FFC5F004030B4194B1A7902F07F02531E072B27D8164B0C2404FB02339978154D01F0FE0199700021D970294600 | ||||
| :401FC0001201505D114400F07F0050555A7802F0FD025A701A795B78120605D5012B01D18C7006E00D2303E0012B0CBF082309238B7030BCFFF7DCBB002030BC704700BF9C | ||||
| :4020000000600040DC92FF1FFC5F004010B50D4B0D4C21791878C9B20138C0B2FFF72EFE43681B798B4201D2012909D8074A0848535CDBB24354A3780120DBB2535410BD56 | ||||
| :40204000002010BDD592FF1F00600040C292FF1F4A93FF1F38B58A4A8A4C13780021DBB221801806517840F18D800A2900F20581DFE811F05D000301030103010301030167 | ||||
| :402080000B0003017E0003018200D3787C49012B09D17D4B1A787D4B03EBC2035B685B686360122310E0CB78022B12D18878FFF7E5FD002800F0E180436863606368DA7885 | ||||
| :4020C00063689B7843EA02232380BDE83840FFF78FBCCB78032B26D16D4B00228878D5B2854209D3664A91786A4AEE2908BF1346634A917881B106E0187801320028F1D025 | ||||
| :4021000018780344EAE764499278097C914203D16248FFF739FD614B1A78002A00F0AD801A78228018E0BDE8384000F029BF13F0030313D0022B40F0A0802380504B0C21C4 | ||||
| :402140001B7903F07F02564B01FB02339A78554BD2B21A7000225A706360B6E702222280514A11784F4AC9B2117053706260ACE7012323804D4BEFE70123238013794C4AC4 | ||||
| :402180001344E9E701390A2977D8DFE801F037764F76067676760A7620009378454ADBB25AE0937803F0FF0153B9404B1A7891425FD01970404B01201870FFF715FE58E082 | ||||
| :4021C000481EC0B2FFF75AFD0028EED155E0FFF71DFF002851D02A4A384913791279DBB2D2B20A70364A3249D25CCB5C9A4240D0314B01221A70FFF753FD3AE003F00303EE | ||||
| :40220000012B2BD009D3022B37D11D4B9B78002B33D1BDE83840FFF7BFBE194B9B78012B2BD1214A137803F0FD0315E003F00303012B13D008D3022B1FD1114B9B78E3B9A4 | ||||
| :40224000BDE83840FFF77EBE0D4B9B78012B14D1154A137843F0020313700AE0084B1A795AB998781B791749DBB2CA5C22EA0002CA54BDE83840FFF79BBA002038BD00BFEC | ||||
| :4022800000600040C492FF1FD092FF1FB03A0000143B00009C3A0000873B00006893FF1FDC92FF1F8192FF1FD392FF1FD592FF1FC292FF1FC092FF1FD492FF1FD192FF1FF4 | ||||
| :4022C0004A93FF1FD792FF1F074B1A78120609D55B78012B06D1054B054A5A6012781A80FFF786BB0020704700600040C492FF1F743A0000014B1870704700BF76650040FA | ||||
| :40230000014B1878704700BF67640040014B1870704700BF77640040064A0123136002F688321268E0211064034A1170A2F540721360704780E100E000E400E0014B187039 | ||||
| :40234000704700BF74640040014B1870704700BF7565004073B515461E460B4C05230022019200920A4601461846237000F064F932462946207800F01FF90221207800F0B7 | ||||
| :4023800009F9207802B070BDD080FF1F064A0423136002F688321268E0219064034A1170A2F202321360704780E100E002E400E0014B04221A60704700E100E0014B04228E | ||||
| :4023C0001A60704780E100E0014B1870704700BF74650040704738B505460078012428B100F066FD285D0134E4B2F8E738BD08B50D2000F05DFDBDE808400A2000F058BDDC | ||||
| :40240000F7B516461F460B4C00230325019300930A4601462846257000F00EF93A463146207800F0C9F80221207800F0B3F8207803B0F0BDE080FF1FF7B516461F460B4C05 | ||||
| :4024400000230225019300930A4601462846257000F0F2F83A463146207800F0ADF82946207800F097F8207803B0F0BDE180FF1FF7B516461F460B4C002301250193009322 | ||||
| :402480000A4601462846257000F0D6F83A463146207800F091F80221207800F07BF8207803B0F0BDE280FF1F73B515461E460B4C0023019300930A4601461846237000F026 | ||||
| :4024C000BBF832462946207800F076F80221207800F060F8207802B070BD00BFE380FF1F024B1878C0F38010704700BF8F450040074A7F23802113705170064A013BDBB2F7 | ||||
| :4025000002F80839002BF9D1034A1370704700BFE480FF1FF87B00400078004017280FD8084B0001C25C11B142F0200201E002F0DF02C254C25C42F00102C2540020704780 | ||||
| :40254000012070471070004017280BD8064B0001C25C02F0FE02C254C25C02F0DF02C25400207047012070471070004017280DD8074900010B4603441A7942F004021A7150 | ||||
| :40258000435C43F00103435400207047012070471070004017280BD8064A0001835C490003F0F10301F00E011943815400207047012070471070004041F6FF73994208BFD2 | ||||
| :4025C0004FF400519A4208BF4FF4005217289FBFC00000F1804000F5EC4081809ABFC280002001207047000017289FBF034B00011954002088BF0120704700BF197000402C | ||||
| :4026000017289FBF054B00011A5C01F007019DBF1143195400200120704700BF1470004017289FBF034B0001185C00F0070088BFFF20704714700040172810B51AD8C000B7 | ||||
| :4026400001F07F0100F1804441EAC21204F5EC44D2B222709DF8082003F00F0343EA0213DBB263709DF80C30002003F00F03A370E07010BD012010BD10B500F079FC0A4A00 | ||||
| :402680005378182B0AD91478013B5370E30003F1804303F5F0431B78137000E0FF2400F06BFC204610BD00BFE480FF1F030610B5044611D400F05CFC084AE300117803F1FE | ||||
| :4026C000804303F5F04319705378147001335370BDE8104000F050BC10BD00BFE480FF1F30B504060CD411F4704509D1C40004F1804404F5F0442180A270E370284630BDB0 | ||||
| :40270000012030BD03065FBFC00000F1804000F5F04081805ABFC280002001207047000038B50446084DB4F5004F05D9286800F017FCA4F50044F6E7034B58686043BDE875 | ||||
| :40274000384000F00DBC00BFEC80FF1F024B1B7A584300F005BC00BFEC80FF1F0E4B00F003001A78490102F0FC02104318701A7801F0600142F080021A701A7802F07F024E | ||||
| :402780001A701A7802F09F020A431A701A7842F010021A70704700BF83430040014B01221A70704784430040044B00F00F021B6853F8220043F82210704700BF08ED00E008 | ||||
| :4027C000054A00F01F00126800F1100352F8230042F82310704700BF08ED00E000F01F0000F16040490100F56440C9B2017070470F4B10B50F4900240F205C609C60DC60F4 | ||||
| :402800001C615C61FFF7D0FF0B4A136843F0040313600A4B4FF47A72DB68B3FBF2F3084A1360084B4FF400421C60C3F8E82010BD8492FF1F9D28000010E000E0EC80FF1FC6 | ||||
| :4028400014E000E018E000E0024A136843F002031360704710E000E008B5FFF7F5FF034A136843F00103136008BD00BF10E000E010B5054CA3691BB9FFF7BAFF0123A36179 | ||||
| :40288000BDE81040FFF7E8BF8492FF1F024B1868C0F30040704700BF10E000E038B5FFF7F5FF012808D1054D002455F8243003B198470134052CF8D138BD00BF8892FF1FAE | ||||
| :4028C000024B03EB80035868596070478492FF1F134B144A1B78DBB20360127843EA0223114A0360127843EA0243104A0360127843EA026303600E4B0E4A1B78DBB2436031 | ||||
| :40290000127843EA02230C4A4360127843EA02430A4A4360127843EA02634360704700BF0301004904010049EC46004002010049010100490001004905010049060100490D | ||||
| :4029400010B500F015FB204A044613780A2043F002031370137C43F00203137412F80A3C43F0010302F80A3C937943F00103937102F5AB52137843F003031370134B18223F | ||||
| :402980001A7013F8012C42F0400203F8012C13F8012C02F0FC0203F8012CCE2203F8062CA3F597530222183B1A70094A137843F008031370FFF7CAFE064B10222046BDE8DE | ||||
| :4029C00010401A6000F0D8BAAB4300400E5900402F5B004080E200E008B500F0C9FA0F4A137803F0FE031370A2F5AA521D3A137803F0FD031370137C03F0FD03137412F8E1 | ||||
| :402A00000A3C03F0FE0302F80A3C937903F0FE039371BDE8084000F0AFBA00BF08590040044A137803F03F0343EA8010C0B21070704700BF08590040082804D00A280CBF9D | ||||
| :402A40008223C22300E0422308380E4AC0B20428137098BF0C4B4FF0000298BF33F910100A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B33 | ||||
| :402A80001A8070470A590040603A00005293FF1F5493FF1F5893FF1F08B5102000F0A6F907210420FFF79AFE07490420FFF788FE064A0C20137843F006031370FFF7BCFFBA | ||||
| :402AC000034B00221A8008BD912B0000095900405093FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040FFF72ABFA092FF1F044B1A7802F0FB021A701A7842F0010256 | ||||
| :402B00001A7070470859004010B5084B1C7814F0010403D10028F9D0002404E02046FFF715FE024B1B78204610BD00BF09590040034A044B1B881088181A00B2704700BF1D | ||||
| :402B40005893FF1FA25B00400E4A13881BB223B111880A2309B2594301E00B4B19680B4B1B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F0C1 | ||||
| :402B800000B270475293FF1F5493FF1F5093FF1F7047000010B500F0EBF9214A044613780A2043F001031370137C43F00103137412F80A3C43F0020302F80A3C937943F0DB | ||||
| :402BC0000203937102F5AA521832137843F003031370144B18221A7013F8012C42F0400203F8012C13F8012C02F0FC0203F8012CCE2203F8062CA3F597530222123B1A7067 | ||||
| :402C0000094A137843F008031370FFF79FFD074B08222046BDE810401A6000F0ADB900BFAB43004006590040275B004080E200E008B500F09DF90F4A137803F0FE0313708E | ||||
| :402C4000A2F5AA52153A137803F0FE031370137C03F0FE03137412F80A3C03F0FD0302F80A3C937903F0FD039371BDE8084000F083B900BF00590040044A137803F03F0361 | ||||
| :402C800043EA8010C0B21070704700BF00590040082804D00A280CBF8223C22300E0422308380E4AC0B20428137098BF0C4B4FF0000298BF33F910100A4B88BF11461A80AE | ||||
| :402CC00042F210734B4341F2883103F6C41393FBF1F305490B60054B1A807047025900406A3A00005E93FF1F6493FF1F5C93FF1F08B5102000F084F807210320FFF76EFD92 | ||||
| :402D000007490320FFF75CFD064A0C20137843F006031370FFF7BCFF034B00221A8008BDE92D0000015900406093FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040C8 | ||||
| :402D4000FFF728BFA192FF1F044B1A7802F0FB021A701A7842F001021A7070470059004010B5084B1C7814F0010403D10028F9D0002404E02046FFF7E9FC024B1B78204621 | ||||
| :402D800010BD00BF01590040034A044B1B881088181A00B2704700BF5C93FF1FA05B00400E4A13881BB223B111880A2309B2594301E00B4B19680B4B1B88C01A42F2107381 | ||||
| :402DC00000B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270475E93FF1F6493FF1F6093FF1F70470000034A00F0F800137803431370704700BF02410040A1 | ||||
| :402E0000034A00F0F800137803431370704700BF06410040014B1870704700BF72640040014B1870704700BF7864004073B515461E460B4C04230022019200920A46014603 | ||||
| :402E400018462370FFF7F8FB324629462078FFF7B3FB02212078FFF79DFB207802B070BDFC80FF1F074A0223136002F688321268E0215064044A11706FF440710A4413608D | ||||
| :402E8000704700BF80E100E001E400E0014B1870704700BF75640040014B1870704700BF76640040014B1870704700BF79640040FEB5494652465B460EB407462449096800 | ||||
| :402EC0008A46244A12682448022100F071F8030020480068C018204900F06AF8143883460121C9430C460125002600F041F8814651460B7823400B705846013000F030F81C | ||||
| :402F00003800F04028400B78234003430B70584600F026F80136072EF2D9002001300138013001200B78234003430B705846043000F016F8484600F01FF800BF00BF00BF12 | ||||
| :402F40000EBC894692469B46FEBD00BFAFF30080D480FF1FF880FF1F00C20100000000000230800803D000BF01380046FCD17047EFF3108072B6704780F31088704700BF77 | ||||
| :402F8000094A137803F00303012B0AD0022B09D113790C2103F07F02044B01FB02339B7A00E013790020704700600040DC92FF1F002902D0B0FBF1F0704708B14FF0FF3097 | ||||
| :402FC00000F008B80029F8D00246B0FBF1F000FB11217047704700BF014B1868704700BF6081FF1F0E4B70B51E460E4C0025E41AA410A54204D056F8253098470135F8E75C | ||||
| :4030000000F0DEFD084B094C1E46E41AA4100025A54204D056F8253098470135F8E770BDCC3B0000CC3B0000CC3B0000D43B000003460244934202D003F8011BFAE770475A | ||||
| :4030400030B5141E05469BB0184604DA8B232B604FF0FF301DE04FF40273ADF80C300CBF234604F1FF33029305934FF6FF7300910491ADF80E3002461E9B6946284600F0D4 | ||||
| :4030800073F8431CBCBF8B232B6014B1009B00221A701BB030BD000007B5009313460A46014603480068FFF7CBFF03B05DF804FB6081FF1F2DE9F0478E6882469E420C46D9 | ||||
| :4030C000914698463ED88A8912F4906F3AD02568096902236F1A656905EB450595FBF3F57B1C43449D4238BF1D4653050FD5294600F04AFB064698B13A46216900F0D2FA24 | ||||
| :40310000A38923F4906343F08003A38113E02A4600F098FB064670B92169504600F0E8FA0C23CAF80030A3894FF0FF3043F04003A381BDE8F08726613E44266046466561E0 | ||||
| :40314000ED1BA560464528BF464649463246206800F0B3FAA36800209B1BA36023681E442660BDE8F08700002DE9F04F9DB003938B8980461C060D4616460DD50B695BB958 | ||||
| :40318000402100F001FB2860286118B90C23C8F80030CDE040236B610023099320238DF82930DFF89CB130238DF82A3037463C4614F8013B1BB9B7EB060910D003E0252BD0 | ||||
| :4031C000F9D02746F3E74B46324629464046FFF771FF013000F0A780099B4B4409933B78002B00F0A08000234FF0FF3204930793059206938DF853301A93012605222178C6 | ||||
| :403200004E4800F041FA671C049B38B14B4A3C46801A06FA00F018430490EFE7D90644BF20228DF853201A0744BF2B228DF8532022782A2A03D0079A00210A200BE0039AA2 | ||||
| :40324000111D12680391002A10DA524243F00200079204900BE027463B780134303B092B03D800FB02320121F5E701B107923B782E2B1ED17B782A2B0AD1039B02371A1DAA | ||||
| :403280001B680392002BB8BF4FF0FF33059310E0002319460593781C0A2407463A780130303A092A03D804FB01210123F5E703B1059103223978224800F0E6F940B1402309 | ||||
| :4032C000CBEB000003FA00F0049B013718430490397806221B487E1C8DF8281000F0D4F988B1194B33B9039B073323F007030833039314E003AB00932A46144B04A940468F | ||||
| :40330000AFF3008007E003AB00932A460F4B04A9404600F093F8B0F1FF3F824603D0099B5344099342E7AB895B0601D4099801E04FF0FF301DB0BDE8F08F00BF9B3B000071 | ||||
| :40334000A13B0000A53B000000000000B53000002DE9F04791461F460A698B6806469342B8BF1346C9F8003091F843200C46DDF8208012B10133C9F800302368990642BF15 | ||||
| :40338000D9F800300233C9F80030256815F0060510D104F1190A07E00123524639463046C04701301AD00135E368D9F800209B1A9D42F1DB94F843302268003318BF01230D | ||||
| :4033C00092060FD5E118302081F843005A1C94F845102244023382F8431003E04FF0FF30BDE8F08704F1430239463046C0470130F4D02268D9F80050E36802F00602042AD7 | ||||
| :4034000008BF5D1B2269A3680CBF25EAE57500259342C4BF9B1AED184FF000091A344D4509D00123224639463046C0470130D5D009F10109F3E70020BDE8F0872DE9F0438A | ||||
| :4034400017460A7E85B06E2A984606460C460C9B01F1430E00F0AE8011D8632A22D009D8002A00F0BB80582A40F0CA8081F84520834955E0642A1ED0692A1CD0C0E0732A65 | ||||
| :4034800000F0B08009D86F2A2ED0702A40F0B8800A6842F020020A603EE0752A24D0782A3AD0ADE01A6801F14205111D1960136884F84230A8E021681A6811F0800F02D098 | ||||
| :4034C000111D196008E011F0400F02F10401196002D0B2F9003000E01368002B3CDA2D225B4284F8432037E021681A6811F0800F02D0111D196007E011F0400F02F104010E | ||||
| :40350000196001D0138800E01368227E5C496F2A14BF0A2208221BE078225A4984F845202268186812F0800F00F104051D6003D1550601D5038800E00368D00744BF42F032 | ||||
| :40354000200222601BB9226822F0200222601022002084F8430001E049490A226568002DA56008DB206820F0040020602BB9002D7DD175460CE0002B79D07546B3FBF2F020 | ||||
| :4035800002FB1033CB5C05F8013D03460028F5D1082A0BD12368DA0708D5236962689A42DEBF302305F8013C05F1FF35C5EB0E0323612EE008681A6810F0800F496903D0FC | ||||
| :4035C000101D1860136808E010F0400F02F104001860136801D0198000E0196000232361754616E01A68111D1960156800216268284600F049F808B1401B6060636804E0BC | ||||
| :4036000004F1420584F8422001232361002384F84330CDF800803B4603AA21463046FFF797FE013002D14FF0FF3026E023692A4639463046C0470130F5D023689B0710D563 | ||||
| :40364000002504F1190907E001234A4639463046C0470130E7D00135E368039A9B1A9D42F2DBE068039B9842B8BF184605E00B7804F1420584F842308AE705B0BDE8F083AB | ||||
| :403680004F3A0000AC3B000010B5C9B202449042034605D01C7801308C42F8D1184610BD002010BD10B5431E0A44914204D011F8014B03F8014FF8E710BD884210B501EBCE | ||||
| :4036C000020301D8421E0BE09842FBD28118D21AD34204D013F8014D01F8014DF8E710BD994204D011F8014B02F8014FF8E710BD38B50546002944D051F8043C0C1F002BF2 | ||||
| :40370000B8BFE41800F0D4F81E4A1368114613B96360146030E0A3420DD92268A018834201BF18685B681218226063600C6023E0A24203D813465A68002AF9D118681918DB | ||||
| :40374000A1420BD12168014458188242196013D110685268014419605A600DE002D90C232B6009E021686018824201BF106852680918216062605C602846BDE8384000F0C4 | ||||
| :4037800098B838BDA892FF1F70B5CD1C25F0030508350C2D38BF0C25002D064601DBA94202D90C23336046E000F082F8234B1C681A462146A1B10B685B1B0ED40B2B03D94E | ||||
| :4037C0000B60CC18CD501EE08C420BBF63684B681360636018BF0C4615E00C464968E9E7174C23681BB9304600F052F820602946304600F04DF8431C18D0C41C24F00304D4 | ||||
| :40380000A0420DD12560304600F053F804F10B00231D20F00700C31A0ED05A42E25070BD211A304600F034F80130EBD10C233360304600F03EF8002070BD00BFA892FF1F09 | ||||
| :40384000A492FF1FF8B5074615460E4621B91146BDE8F840FFF798BF1AB9FFF749FF2846F8BD00F027F885420ED929463846FFF78BFF044650B131462A46FFF713FF3146E1 | ||||
| :403880003846FFF735FF01E03046F8BD2046F8BD38B5064C0023054608462360FDF7D8FB431C02D1236803B12B6038BD8C93FF1F7047704751F8040C0028BEBF091851F8F0 | ||||
| :4038C000043CC0180438704700000000050209020B020D020F021102130215027265706C792030782530327800686F6D696E6700626567696E6E696E67207365656B2066CB | ||||
| :40390000726F6D20256420746F2025640066696E6973686564207365656B00796573006E6F00647269766520303A20257320647269766520313A2025730057616974696E5F | ||||
| :403940006720666F72205553422E2E2E0055534220726561647900636F6D6D616E6420307825303278006661696C2025642B25642B2564203D3D2025642C206E6F7420254E | ||||
| :4039800064007061737365643D256400756E64657272756E206166746572202564207061636B65747300636F756E743D256420693D256420643D256400636D645F77726997 | ||||
| :4039C000746500703D25642063723D25642063773D256420663D256420773D256420696E6465783D256420756E64657272756E3D256400756E64657272756E21007375635E | ||||
| :403A0000636573730073746172742065726173696E670073746F702065726173696E670069646C6500005100401000405100403000000001400010001401400008004001A3 | ||||
| :403A400040000A004C0140000200500140200030313233343536373839414243444546000001000000040000001000010000000400000010280000000001040001000000C2 | ||||
| :403A800000000000000157494E5553420000303030303100000000000000000012034D005300460054003100300030000100000001000000B83A000001000000873B0000A5 | ||||
| :403AC000000000000000000001000000D03A000001000000593B000004000000F23A0000000000000000000000000000F03A0000FF00000001024000FF00000082024000C7 | ||||
| :403B0000FF00000003034000FF00000084034000FF00020304030904160346006C007500780045006E00670069006E0065002A0343006F0077006C00610072006B00200034 | ||||
| :403B400054006500630068006E006F006C006F0067006900650073000009022E0001010080320904000004FF00000107050102400000070582024000000705030340000AE8 | ||||
| :403B80000705840340000A12010002FF0001080912006E0100020180014300232D302B2000686C4C0065666745464700303132333435363738396162636465660000000069 | ||||
| :403BC000F8B500BFF8BC08BC9E46704759000000CD100000F8B500BFF8BC08BC9E46704735000000F83B0000C880FF1FA00000002812000000000000000000009093FF1FA8 | ||||
| :403C0000FF000000675000400C00000007000000FFFFFFFF7F8000003F0000000000007D00FA0000400000000090D003FF0000000000000000000000000000000000000028 | ||||
| :403C400000000000000000000000000000000000993B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070 | ||||
| :403C8000000000000000000000000000000000000081FF1F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065 | ||||
| :403CC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C4 | ||||
| :403D00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083 | ||||
| :403D40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043 | ||||
| @@ -4098,48 +4098,48 @@ | ||||
| :40FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041 | ||||
| :40FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 | ||||
| :0200000480007A | ||||
| :40000000014500400752004005640040010101400303014001050140010701400D090140100A0140460B01405C0C0140490D0140590E0140360F014001150140031701407A | ||||
| :400040002418014035190140061B01400C4001400D4101400742014005430140054401401445014008460140094701400948014008490140174C0140044D014005500140AF | ||||
| :40008000035101407E020803094610831196601561047C402B802D0A3B7E3E807E01E208E224E602EE02E020EA0188849140980199809C809D209E409F20A140A280A4408A | ||||
| :4000C000AF10EA09050408030E01110120022D0231043302360337013F45580B59045B045C095F0100800120058507040E601240171819801C201D2D1F0A21052301251099 | ||||
| :40010000260C27182A402F2A3002361838083D223E403F04452A4E88560858805F506409668068026C046D40780179407B01830185058B408C489240930494409B049C01D3 | ||||
| :400140009D859E889F28A143A210A320A410A604A701AD80C0F3C230C468CA78CC61CEF2D0E0D220D638D830DE01E029E402E808001002400403060C080209010B021201CF | ||||
| :4001800014031674170118191A621B061E80228024102628281029012B042F01307F327F34803507382A3E10580459045B045C995F018018820184078502863889488A047E | ||||
| :4001C0008B908D088F349028945095FD97029B029C209D02A006A102A3FDA402A503A7F8A838AA07AC80ADA0AF48B040B23FB307B401B5C0B680B738BBA0BE51C021C720DA | ||||
| :40020000C820C9FFCAFFCBFFCD20CEF0D110D804D904DA04DB04DC99DD09DF01E108E240E340E480E640E740010A02040515080809800A800E680F0210A212081608170980 | ||||
| :40024000180519081B0A1D021E201F1421D0220826202704290A2A802D802F0430A03208362439A03A043C20400550025C405F2068016D806F018302870288018B108C0233 | ||||
| :4002800092C09304980899129A049C019D0C9E80A0A0A101A320A410A580A61CA708AC02B0A0B310C07EC2FDC47FCA3BCC6ECE2ED00CD630E008E220E6020447050A063891 | ||||
| :4002C00008040C310E4A0F0510081201150D162019011C082004240428492A16303F33033440350C3A033E10406441034302452446E04705481B49FF4AFF4BFF4D204EF0B5 | ||||
| :40030000511056085804590B5A045B045C995D995F0161086280630C64406540664067A8684069A86B086D088001820A8306840F86108701880289018A058B02900292340E | ||||
| :40034000940F9620970199019A0F9B049E40A480A840B038B107B407B6C0BA20D201D610D804D904DB04DC99DD90DF0100400108020405140680080809800A800D020E2AAA | ||||
| :4003800010A0120816101720184019021A041D121E021F602128232425013128361438043B803C203D023F0440404204430848A04A085204531058A0600E62106A806E4015 | ||||
| :4003C0007801C077C2FDC46ECC66CEEAD007D204D60CD80CDE01E208EA01E201E680EA0205010F022D023301350239203F14560859045B045D905F01800288018C018F0427 | ||||
| :400400009D01A502A804A904AD08AE01B004B10CB301B403B502BE01BF14D608D80BD904DB04DC99DD90DF0101A00240100812021880192020C821082202272429202A4043 | ||||
| :400440002B102D4032403680378038403D803F0859145A405F806240632867016A806C086F02780183018B028D108E409140980199809D209E409F20A140A280A444C00BA7 | ||||
| :40048000C403CA1ECC08CE58D61ED81EDE01E680EA02A904AB04AD08B440E802EE01170433043402371039043A203E808620C420CCE0CE70E21030203720831084028A08BE | ||||
| :4004C0009C029E809F10AD04CC30E220E640EE40560889809A089E809F20A420D4409E809F20A580A820EA8014407E018710C404DE045104564058405D8062086740858012 | ||||
| :40050000871088408A018E4096029710B040D407D604D803E005E402EA01820286088740924095089770A608AE400B210F149240950897B1A202AB01AF40C20F25808280E6 | ||||
| :400540008B029E80A580AF20C820E280EA4073807F029B80A302AB80DC80DE20EA8005200B800C020D040F08520254205E4061028C028F04924095089780A202AF04C001D7 | ||||
| :40058000C20DD403D604D802E202E602A920AD02B420EC0801010D010F0111011D0100BD012A10050820324039804620082010C42000080280000000FE1001ED00E3001C2E | ||||
| :4005C00000000000000000000000040182EF3D10000000083800C11F07E0000000080220000010004603020000E0000412FFFFFF0020F00120100000000008000404040460 | ||||
| :4006000099990001000800004020800840200008000040A8000000000000000000000000000000003F00003F1F001F0000000000000000001000000040000000000000003B | ||||
| :40064000C0000000FF0020FF4700470000010000A00000BFBF009F00000000000001000000000000000000000000000000000000000000000000000000000000000000004F | ||||
| :40068000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003A | ||||
| :4006C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FA | ||||
| :4007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B9 | ||||
| :400740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000079 | ||||
| :400780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000039 | ||||
| :4007C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F9 | ||||
| :4008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B8 | ||||
| :400840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078 | ||||
| :400880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038 | ||||
| :4008C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F8 | ||||
| :4009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B7 | ||||
| :400940000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077 | ||||
| :400980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037 | ||||
| :4009C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F7 | ||||
| :400A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B6 | ||||
| :400A40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076 | ||||
| :400000000145004009520040015B00400165004047000140380101404E0201404703014046040140440501404C060140490701402C08014031090140040B0140030D014075 | ||||
| :400040006C14014057150140591601404B17014011190140071B01400B400140104101400C4201400F43014002440140054501400A4601400B4701400C480140104901404C | ||||
| :40008000174C01400C4D014006500140045101407E02080409021082110218021904601561137C402721240A02E40303040E0520064107C00A840B900E840F901001120693 | ||||
| :4000C00013901684179019011A841B481C081DFC1E221F0221C122182324268427902B9C2CE72E10300733E0351F36F83A023B084204460E480449FF4AFF4BFF4F83580B46 | ||||
| :40010000590B5A045B045C995D095F01868088028A8190E7921094019686980F9A409C0F9E20A2E0A618A804AA81AE80B207B4F8D80BDC09DF010022022003010524084089 | ||||
| :4001400009080A080B400C420D200E2010021108130215801610172119011A011C241E201F0C210422082308284029042B88312032643301382039883A013B804240528017 | ||||
| :400180005A215B4A600461016218634278027C028280C06FC2FFC4FDCA07CC0FCE0FD001D60FD80FDE8103140404050806110710081F0A800C010E1E0FE4101F124015102D | ||||
| :4001C00016E0178218021A111B141C1F1E20211023212408261127142B142D1F2F4032F0330F360F37F03A083B80580B590B5B045C995F018203830884618608873088204C | ||||
| :4002000089108A508B828DC78E108F2892109304961C97C49A109B04A061A110A204A341A440A630A704AB04AC7CAE02AF04B01FB30FB460B5F4BB08D80BD90BDB04DC99FF | ||||
| :40024000DF01012A02200301040805400708081009080B8C0C420E200F04104211081504180819221A0C1B011C221D4C1E211F4820042218242025442731285029402B8839 | ||||
| :400280002C022E042F883204331134103508380439813A103D8C3E016230680269806A806D4078027C029308942096E897809C029D249F61A403A50CA620A781AA01AB0889 | ||||
| :4002C000C0EFC2FEC42DCAFFCC67CEDFDE81E208021004400620080C0C010E0210081101140818051A081C04200828202AC02CE02F0130603280341E3501360138203E40ED | ||||
| :400300005608580459045B045C995D905F0181608209842487108A128B108F10903F93039407950197089B1C9D40A036A209A310A710A82DA901AA12AB04AC40AD7CAF0220 | ||||
| :40034000B11FB238B440B540B607B720BE10D608D80BD90BDB04DC99DD90DF01000201280302040A070409980B800C020E20104212081550170119281A401B401E201FA0A5 | ||||
| :4003800022102662274828022C022E052F043302364237283C203D803F0558805D80600267016B026D106F017C0287208B848F4091409205930496409B209C029F48A0124A | ||||
| :4003C000A140A208A620A780AD01AE08C07FC23FC4DBCAF8CCF1CEF0D618D818DE80E208E408EA040104020F0440068008700A800C800E200F0110011106130114081602E9 | ||||
| :40040000170218011C0F1EF0200124072608288029052A102B022C082E04310736FF3E403F01580459045B045F018001811C820283E18402852087C0880489828B218C0248 | ||||
| :400440008D088F10900491FF940495089710980599029C049D04A002A1FCA402A520A740A802AC03AE04AF02B007B3FCB503BB20BE01D804D904DB04DC90DF010081012440 | ||||
| :4004800004450520084009080A080B810C080D010E020F041008120113861544172219011C0220042114222C23282740280229012B202D1030083180321033023705396892 | ||||
| :4004C0003A013D82588068066C016D806F048004810184048F0191109220940A9780980299209B019C409F04A401A598A702A880A980AF02C0FFC2FFC4FFCA2BCCCFCE9F8E | ||||
| :40050000D608E24CE402E605EA04EC02EE0C06010B0410041304160119021C022101240829042C013001310232043304340236083701380239083E553F45560858045904A9 | ||||
| :400540005B045D905F0183018A029501A401AC02B401B501B602B880B920BE50BF10D804D904DB04DF01030804080D800F50100212101410154019101A021E2A1F022210BD | ||||
| :40058000250226882C802F083308372138023F10584059105DA45E01645266106A406C076D406F09800282C085808608890293409980AF40C022C2B0C4A5CAA0CCA2CE2157 | ||||
| :4005C000D6FCD8F0EA04EE0C9980E208E448EA049980B180E208018002200608070108280B100C020D210E2C1028110F1434152117081828192F1C101E021F2F202821210D | ||||
| :40060000230224022740282829212B042C202D212E012F0E321F336035803620371F39083E443F1040524720482049FF4AFF4BFF4D204EF05110580459045A045B045C9038 | ||||
| :400640005D095F01610862406340648066406740800F810183028503861087FC88208A018B048C208DFF8E0290039302942395809608970499049A409B209D049E2F9FF9AF | ||||
| :40068000A023A104A20CA308A423A504A604A740A82FA904AB10AF02B060B3FFB460B61FB822BF04D804D904DB04DC09DF01012202200301040205040608070209880A04D5 | ||||
| :4006C0000B800C080D800E48118012081305144015051610171019881C401D401E041F602118228023112410284129082A102D202E402F6030083240331234013680372A63 | ||||
| :40070000381039423A083C063D803F1041104980510159025A0269806C016D806F0285018D409004914592C2930494429604979199249A089B3B9D40A009A180A22CA548B8 | ||||
| :40074000A722AC02B704C0FFC2FFC47FCAFFCCFFCEFFD004D208E402E808EE1200FF01880403054606FC07B8080C09880A100C0C0EF10F0112081510160417A0180C198849 | ||||
| :400780001A401C011D421E021F04218822022480259A260C2720280C29882A202E022F0431C132FF333F35C137C139A23E043F04580459045B045C905F01800282058521EF | ||||
| :4007C000870288028C0291279403950896049B389D049F01A118A340A706AC02AF01B006B107B310B401B560B708BE10BF40C006C5ECC803C9FFCAFFCBFFD004D601D8046C | ||||
| :40080000D904DA04DB04DC99DD09DF01E2C00020010203020406056007100A200C010D800E040F1013801542172819131D042003218022D5240425102605278128102901DB | ||||
| :400840002A802D202E402F603180321433023680372838043C043D803F11481049104B0264016701684869476A406C02728873068410860194419546978799209B2C9F827A | ||||
| :40088000A228A448A598A601A722AB40B002B481C0FBC2F4C4F1CAFBCC7FCEF2D204E220E604EA4082108A018E048F029222960197109D209F20A214A302B080B104B6017C | ||||
| :4008C000E220EA10EC808F209F20AF10B211B520E412EE021B011F083240330836843B408140C630CCF0CE10E62030803204358037083A023D408480914096809740A6046A | ||||
| :40090000AE80AF01CCF0CE60E210508057208580968897409D809E02A604AB08D460E210EA20832284808E02968097409E02A480A620A720AA24AE04E230E620EC80EE30D9 | ||||
| :400940001501C4045D828740B101D605EE011B04850287108D8097809D82A480A880C608E4020B880C800F108A109798A480A740AB44AF04C20FE404262080018A01974061 | ||||
| :40098000A280A302A620AA40B680C820E620EE8052805302551070017E0190029202A110A280A302AF40B510D4E0DC80DE20EE40052008040E020F801F1053805610588014 | ||||
| :4009C00063028E208F809A109D20A740B120C001C20DC601D407D602E002E402EA04762084809A209C80AF10B004B301B601DE04E801EA08EE01010109010B010D011101C4 | ||||
| :400A00001B0100FF01AB020211050000BF0000A09F001F000000000000000000100000004000000000000000C0000000FF0000B847004700000100008000000282008200DC | ||||
| :400A400000000000000707000700000027001801270018010004000000050000000000000000000000000000000000000000000000000000000000000000000000000000D8 | ||||
| :400A80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036 | ||||
| :400AC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F6 | ||||
| :400B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B5 | ||||
| @@ -4615,12 +4615,12 @@ | ||||
| :0200000490105A | ||||
| :04000000BC90ACAF55 | ||||
| :0200000490303A | ||||
| :020000004C1A98 | ||||
| :02000000FEBF41 | ||||
| :0200000490402A | ||||
| :4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C0 | ||||
| :400040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 | ||||
| :400080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040 | ||||
| :4000C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | ||||
| :0200000490501A | ||||
| :0C00000000012E16106900002E2A5C83FF | ||||
| :0C00000000012E16106900002E300F28A1 | ||||
| :00000001FF | ||||
							
								
								
									
										27
									
								
								FluxEngine.cydsn/FIFOin/API/c.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								FluxEngine.cydsn/FIFOin/API/c.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| #include "cyfitter_cfg.h" | ||||
| #include "cydevice_trm.h" | ||||
| #include "cyfitter.h" | ||||
| #include "`$INSTANCE_NAME`_h.h" | ||||
|  | ||||
| void `$INSTANCE_NAME`_Start() | ||||
| { | ||||
|    `$INSTANCE_NAME`_Init(); | ||||
| }     | ||||
|  | ||||
| void `$INSTANCE_NAME`_Stop() | ||||
| { | ||||
|     `$INSTANCE_NAME`_Disable(); | ||||
| } | ||||
|  | ||||
| void `$INSTANCE_NAME`_Init() | ||||
| {     | ||||
|     `$INSTANCE_NAME`_Enable(); | ||||
|      | ||||
| } | ||||
| void `$INSTANCE_NAME`_Enable() | ||||
| { | ||||
| } | ||||
|  | ||||
| void `$INSTANCE_NAME`_Disable() | ||||
| { | ||||
| } | ||||
							
								
								
									
										50
									
								
								FluxEngine.cydsn/FIFOin/API/h.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								FluxEngine.cydsn/FIFOin/API/h.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| #if !defined(`$INSTANCE_NAME`_H) | ||||
| #define `$INSTANCE_NAME`_H | ||||
|  | ||||
| #include "cytypes.h" | ||||
| #include "cyfitter.h" | ||||
| #include "CyLib.h"  | ||||
|  | ||||
| #define `$INSTANCE_NAME`_FIFO_PTR	         ((reg8 *) `$INSTANCE_NAME`_dp__F0_REG) | ||||
|  | ||||
|     /* Macros to clear DP FIFOs.*/ | ||||
| #define `$INSTANCE_NAME`_CLEAR do { \ | ||||
|     CY_SET_XTND_REG8(\ | ||||
|         ((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0x01u | \ | ||||
|         CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)));\ | ||||
|     CY_SET_XTND_REG8(\ | ||||
|         ((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0xfeu & \ | ||||
|         CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)));\ | ||||
|     } while(0) | ||||
|  | ||||
| /* Macros to set FIFO level mode. See the TRM for details */ | ||||
| #define `$INSTANCE_NAME`_SET_LEVEL_NORMAL \ | ||||
|     CY_SET_XTND_REG8(\ | ||||
|         ((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0xfbu & \ | ||||
|         CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG))) | ||||
| #define `$INSTANCE_NAME`_SET_LEVEL_MID \ | ||||
|     CY_SET_XTND_REG8(\ | ||||
|         ((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0x04u | \ | ||||
|         CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG))) | ||||
|  | ||||
| /* Macros to set FIFO to single-buffer mode. */ | ||||
| #define `$INSTANCE_NAME`_SINGLE_BUFFER_SET \ | ||||
|     CY_SET_XTND_REG8(\ | ||||
|         ((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0x01u | \ | ||||
|         CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG))) | ||||
|  | ||||
| /* Macros to return the FIFO to normal mode. */ | ||||
| #define `$INSTANCE_NAME`_SINGLE_BUFFER_UNSET \ | ||||
|     CY_SET_XTND_REG8(\ | ||||
|         ((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0xfeu & \ | ||||
|         CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG))) | ||||
|      | ||||
| void `$INSTANCE_NAME`_Enable(); | ||||
| void `$INSTANCE_NAME`_Disable(); | ||||
| void `$INSTANCE_NAME`_Start(); | ||||
| void `$INSTANCE_NAME`_Stop(); | ||||
| void `$INSTANCE_NAME`_Init(); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| /* [] END OF FILE */ | ||||
							
								
								
									
										
											BIN
										
									
								
								FluxEngine.cydsn/FIFOin/FIFOin.cysym
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								FluxEngine.cydsn/FIFOin/FIFOin.cysym
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										128
									
								
								FluxEngine.cydsn/FIFOin/FIFOin.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								FluxEngine.cydsn/FIFOin/FIFOin.v
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
|  | ||||
| //`#start header` -- edit after this line, do not edit this line | ||||
| `include "cypress.v" | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
|  | ||||
| /* Ultra-simple FIFO in component: a byte is shifted in every clock when req | ||||
|  * is high. */ | ||||
|   | ||||
| module FIFOin (drq, clk, d, req); | ||||
| 	output  drq; | ||||
| 	input   clk; | ||||
| 	input  [7:0] d; | ||||
| 	input  req; | ||||
|  | ||||
| //`#start body` -- edit after this line, do not edit this line | ||||
|  | ||||
| wire [7:0] pi; | ||||
| assign pi = d; | ||||
|  | ||||
| wire load; | ||||
| assign load = req; | ||||
|  | ||||
| cy_psoc3_dp #(.cy_dpconfig( | ||||
| { | ||||
| 	`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
| 	`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
| 	`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
| 	`CS_CMP_SEL_CFGA, /*CFGRAM0:    */ | ||||
| 	`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
| 	`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
| 	`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
| 	`CS_CMP_SEL_CFGA, /*CFGRAM1:     */ | ||||
| 	`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
| 	`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
| 	`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
| 	`CS_CMP_SEL_CFGA, /*CFGRAM2:     */ | ||||
| 	`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
| 	`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
| 	`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
| 	`CS_CMP_SEL_CFGA, /*CFGRAM3:     */ | ||||
| 	`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
| 	`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
| 	`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
| 	`CS_CMP_SEL_CFGA, /*CFGRAM4:     */ | ||||
| 	`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
| 	`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
| 	`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
| 	`CS_CMP_SEL_CFGA, /*CFGRAM5:     */ | ||||
| 	`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
| 	`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
| 	`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
| 	`CS_CMP_SEL_CFGA, /*CFGRAM6:     */ | ||||
| 	`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
| 	`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
| 	`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
| 	`CS_CMP_SEL_CFGA, /*CFGRAM7:     */ | ||||
| 	8'hFF, 8'h00,	/*CFG9:     */ | ||||
| 	8'hFF, 8'hFF,	/*CFG11-10:     */ | ||||
| 	`SC_CMPB_A1_D1, `SC_CMPA_A1_D1, `SC_CI_B_ARITH, | ||||
| 	`SC_CI_A_ARITH, `SC_C1_MASK_DSBL, `SC_C0_MASK_DSBL, | ||||
| 	`SC_A_MASK_DSBL, `SC_DEF_SI_0, `SC_SI_B_DEFSI, | ||||
| 	`SC_SI_A_DEFSI, /*CFG13-12:     */ | ||||
| 	`SC_A0_SRC_PIN, `SC_SHIFT_SL, 1'h0, | ||||
| 	1'h0, `SC_FIFO1_BUS, `SC_FIFO0_ALU, | ||||
| 	`SC_MSB_DSBL, `SC_MSB_BIT0, `SC_MSB_NOCHN, | ||||
| 	`SC_FB_NOCHN, `SC_CMP1_NOCHN, | ||||
| 	`SC_CMP0_NOCHN, /*CFG15-14:     */ | ||||
| 	10'h00, `SC_FIFO_CLK__DP,`SC_FIFO_CAP_AX, | ||||
| 	`SC_FIFO_LEVEL,`SC_FIFO__SYNC,`SC_EXTCRC_DSBL, | ||||
| 	`SC_WRK16CAT_DSBL /*CFG17-16:     */ | ||||
| } | ||||
| )) dp( | ||||
| 	/* input          */ .clk(clk), | ||||
| 	/* input [02:00]  */ .cs_addr(3'b0),    // Program counter | ||||
| 	/* input          */ .route_si(1'b0),   // Shift in | ||||
| 	/* input          */ .route_ci(1'b0),   // Carry in | ||||
| 	/* input          */ .f0_load(load),    // Load FIFO 0 | ||||
| 	/* input          */ .f1_load(1'b0), 	// Load FIFO 1 | ||||
| 	/* input          */ .d0_load(1'b0), 	// Load Data Register 0 | ||||
| 	/* input          */ .d1_load(1'b0), 	// Load Data Register 1 | ||||
| 	/* output         */ .ce0(), 			// Accumulator 0 = Data register 0 | ||||
| 	/* output         */ .cl0(), 			// Accumulator 0 < Data register 0 | ||||
| 	/* output         */ .z0(), 			// Accumulator 0 = 0 | ||||
| 	/* output         */ .ff0(), 			// Accumulator 0 = FF | ||||
| 	/* output         */ .ce1(), 			// Accumulator [0|1] = Data register 1 | ||||
| 	/* output         */ .cl1(), 			// Accumulator [0|1] < Data register 1 | ||||
| 	/* output         */ .z1(), 			// Accumulator 1 = 0 | ||||
| 	/* output         */ .ff1(), 			// Accumulator 1 = FF | ||||
| 	/* output         */ .ov_msb(), 		// Operation over flow | ||||
| 	/* output         */ .co_msb(), 		// Carry out | ||||
| 	/* output         */ .cmsb(), 			// Carry out | ||||
| 	/* output         */ .so(), 			// Shift out | ||||
|     /* output         */ .f0_bus_stat(drq), // not empty | ||||
| 	/* output         */ .f0_blk_stat(full),// full | ||||
| 	/* output         */ .f1_bus_stat(), 	// FIFO 1 status to uP | ||||
| 	/* output         */ .f1_blk_stat(), 	// FIFO 1 status to DP | ||||
| 	/* input          */ .ci(1'b0), 		// Carry in from previous stage | ||||
| 	/* output         */ .co(), 			// Carry out to next stage | ||||
| 	/* input          */ .sir(1'b0), 		// Shift in from right side | ||||
| 	/* output         */ .sor(), 			// Shift out to right side | ||||
| 	/* input          */ .sil(1'b0), 		// Shift in from left side | ||||
| 	/* output         */ .sol(), 			// Shift out to left side | ||||
| 	/* input          */ .msbi(1'b0), 		// MSB chain in | ||||
| 	/* output         */ .msbo(), 			// MSB chain out | ||||
| 	/* input [01:00]  */ .cei(2'b0),        // Compare equal in from prev stage | ||||
| 	/* output [01:00] */ .ceo(),            // Compare equal out to next stage | ||||
| 	/* input [01:00]  */ .cli(2'b0), 	    // Compare less than in from prv stage | ||||
| 	/* output [01:00] */ .clo(),            // Compare less than out to next stage | ||||
| 	/* input [01:00]  */ .zi(2'b0),         // Zero detect in from previous stage | ||||
| 	/* output [01:00] */ .zo(),             // Zero detect out to next stage | ||||
| 	/* input [01:00]  */ .fi(2'b0), 		// 0xFF detect in from previous stage | ||||
| 	/* output [01:00] */ .fo(), 	        // 0xFF detect out to next stage | ||||
| 	/* input [01:00]  */ .capi(2'b0),	    // Capture in from previous stage | ||||
| 	/* output [01:00] */ .capo(),		    // Capture out to next stage | ||||
| 	/* input          */ .cfbi(1'b0), 		// CRC Feedback in from previous stage | ||||
| 	/* output         */ .cfbo(), 			// CRC Feedback out to next stage | ||||
| 	/* input [07:00]  */ .pi(pi), 		    // Parallel data port | ||||
| 	/* output [07:00] */ .po()              // Parallel data port | ||||
| ); | ||||
|  | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
| endmodule | ||||
| //`#start footer` -- edit after this line, do not edit this line | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										27
									
								
								FluxEngine.cydsn/FIFOout/API/c.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								FluxEngine.cydsn/FIFOout/API/c.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| #include "cyfitter_cfg.h" | ||||
| #include "cydevice_trm.h" | ||||
| #include "cyfitter.h" | ||||
| #include "`$INSTANCE_NAME`_h.h" | ||||
|  | ||||
| void `$INSTANCE_NAME`_Start() | ||||
| { | ||||
|    `$INSTANCE_NAME`_Init(); | ||||
| }     | ||||
|  | ||||
| void `$INSTANCE_NAME`_Stop() | ||||
| { | ||||
|     `$INSTANCE_NAME`_Disable(); | ||||
| } | ||||
|  | ||||
| void `$INSTANCE_NAME`_Init() | ||||
| {     | ||||
|     `$INSTANCE_NAME`_Enable(); | ||||
|      | ||||
| } | ||||
| void `$INSTANCE_NAME`_Enable() | ||||
| { | ||||
| } | ||||
|  | ||||
| void `$INSTANCE_NAME`_Disable() | ||||
| { | ||||
| } | ||||
							
								
								
									
										50
									
								
								FluxEngine.cydsn/FIFOout/API/h.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								FluxEngine.cydsn/FIFOout/API/h.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| #if !defined(`$INSTANCE_NAME`_H) | ||||
| #define `$INSTANCE_NAME`_H | ||||
|  | ||||
| #include "cytypes.h" | ||||
| #include "cyfitter.h" | ||||
| #include "CyLib.h"  | ||||
|  | ||||
| #define `$INSTANCE_NAME`_FIFO_PTR	         ((reg8 *) `$INSTANCE_NAME`_dp__F0_REG) | ||||
|  | ||||
|     /* Macros to clear DP FIFOs.*/ | ||||
| #define `$INSTANCE_NAME`_CLEAR do { \ | ||||
|     CY_SET_XTND_REG8(\ | ||||
|         ((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0x01u | \ | ||||
|         CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)));\ | ||||
|     CY_SET_XTND_REG8(\ | ||||
|         ((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0xfeu & \ | ||||
|         CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)));\ | ||||
|     } while(0) | ||||
|  | ||||
| /* Macros to set FIFO level mode. See the TRM for details */ | ||||
| #define `$INSTANCE_NAME`_SET_LEVEL_NORMAL \ | ||||
|     CY_SET_XTND_REG8(\ | ||||
|         ((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0xfbu & \ | ||||
|         CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG))) | ||||
| #define `$INSTANCE_NAME`_SET_LEVEL_MID \ | ||||
|     CY_SET_XTND_REG8(\ | ||||
|         ((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0x04u | \ | ||||
|         CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG))) | ||||
|  | ||||
| /* Macros to set FIFO to single-buffer mode. */ | ||||
| #define `$INSTANCE_NAME`_SINGLE_BUFFER_SET \ | ||||
|     CY_SET_XTND_REG8(\ | ||||
|         ((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0x01u | \ | ||||
|         CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG))) | ||||
|  | ||||
| /* Macros to return the FIFO to normal mode. */ | ||||
| #define `$INSTANCE_NAME`_SINGLE_BUFFER_UNSET \ | ||||
|     CY_SET_XTND_REG8(\ | ||||
|         ((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0xfeu & \ | ||||
|         CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG))) | ||||
|      | ||||
| void `$INSTANCE_NAME`_Enable(); | ||||
| void `$INSTANCE_NAME`_Disable(); | ||||
| void `$INSTANCE_NAME`_Start(); | ||||
| void `$INSTANCE_NAME`_Stop(); | ||||
| void `$INSTANCE_NAME`_Init(); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| /* [] END OF FILE */ | ||||
							
								
								
									
										
											BIN
										
									
								
								FluxEngine.cydsn/FIFOout/FIFOout.cysym
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								FluxEngine.cydsn/FIFOout/FIFOout.cysym
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										169
									
								
								FluxEngine.cydsn/FIFOout/FIFOout.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								FluxEngine.cydsn/FIFOout/FIFOout.v
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,169 @@ | ||||
|  | ||||
| //`#start header` -- edit after this line, do not edit this line | ||||
| `include "cypress.v" | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
| // Generated on 11/16/2017 at 15:44 | ||||
| // Component: FIFOout | ||||
| module FIFOout ( | ||||
|     input req, | ||||
| 	input clk, | ||||
|     output [7:0] d, | ||||
| 	output drq, | ||||
| 	output empty, | ||||
|     output ack | ||||
| ); | ||||
|  | ||||
| //`#start body` -- edit after this line, do not edit this line | ||||
|  | ||||
| /* Reads from the FIFO are done based on the FIFO being not empty. */ | ||||
|   | ||||
| wire [7:0] po; | ||||
| assign d = po; | ||||
|  | ||||
| localparam STATE_WAITFORREQ = 0; | ||||
| localparam STATE_READFROMFIFO = 1; | ||||
| localparam STATE_WAITFORNREQ = 2; | ||||
|  | ||||
| reg [1:0] state; | ||||
| wire readfromfifo; | ||||
|  | ||||
| assign ack = (state == STATE_WAITFORNREQ); | ||||
| assign readfromfifo = (state == STATE_READFROMFIFO); | ||||
|  | ||||
| always @(posedge clk) | ||||
| begin | ||||
|     case (state) | ||||
|         /* opcode is not valid; req is low; wait for req to go high. */ | ||||
|         STATE_WAITFORREQ: | ||||
|         begin | ||||
|             if (!empty && req) | ||||
|                 state <= STATE_READFROMFIFO; | ||||
|         end | ||||
|          | ||||
|         /* Fetch a single value from the FIFO. */ | ||||
|         STATE_READFROMFIFO: | ||||
|             state <= STATE_WAITFORNREQ; | ||||
|              | ||||
|         /* opcode is valid; ack is high. Wait for req to go low. */ | ||||
|         STATE_WAITFORNREQ: | ||||
|             if (!req) | ||||
|                 state <= STATE_WAITFORREQ; | ||||
|     endcase | ||||
| end | ||||
|              | ||||
| cy_psoc3_dp #(.cy_dpconfig( | ||||
| { | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM0: idle */ | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC___F0, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM1: read from fifo */ | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM2:           */ | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM3:           */ | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM4:           */ | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM5:           */ | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM6:           */ | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM7:           */ | ||||
|     8'hFF, 8'h00,  /*CFG9:           */ | ||||
|     8'hFF, 8'hFF,  /*CFG11-10:           */ | ||||
|     `SC_CMPB_A1_D1, `SC_CMPA_A1_D1, `SC_CI_B_ARITH, | ||||
|     `SC_CI_A_ARITH, `SC_C1_MASK_DSBL, `SC_C0_MASK_DSBL, | ||||
|     `SC_A_MASK_DSBL, `SC_DEF_SI_0, `SC_SI_B_DEFSI, | ||||
|     `SC_SI_A_DEFSI, /*CFG13-12:           */ | ||||
|     `SC_A0_SRC_ACC, `SC_SHIFT_SL, 1'h0, | ||||
|     1'h0, `SC_FIFO1_BUS, `SC_FIFO0_BUS, | ||||
|     `SC_MSB_DSBL, `SC_MSB_BIT0, `SC_MSB_NOCHN, | ||||
|     `SC_FB_NOCHN, `SC_CMP1_NOCHN, | ||||
|     `SC_CMP0_NOCHN, /*CFG15-14:           */ | ||||
|     10'h00, `SC_FIFO_CLK__DP,`SC_FIFO_CAP_AX, | ||||
|     `SC_FIFO_LEVEL,`SC_FIFO_ASYNC,`SC_EXTCRC_DSBL, | ||||
|     `SC_WRK16CAT_DSBL /*CFG17-16:           */ | ||||
| } | ||||
| )) dp( | ||||
|         /*  input                   */  .reset(1'b0), | ||||
|         /*  input                   */  .clk(clk), | ||||
|         /*  input   [02:00]         */  .cs_addr({2'b0, readfromfifo}), | ||||
|         /*  input                   */  .route_si(1'b0), | ||||
|         /*  input                   */  .route_ci(1'b0), | ||||
|         /*  input                   */  .f0_load(1'b0), | ||||
|         /*  input                   */  .f1_load(1'b0), | ||||
|         /*  input                   */  .d0_load(1'b0), | ||||
|         /*  input                   */  .d1_load(1'b0), | ||||
|         /*  output                  */  .ce0(), | ||||
|         /*  output                  */  .cl0(), | ||||
|         /*  output                  */  .z0(), | ||||
|         /*  output                  */  .ff0(), | ||||
|         /*  output                  */  .ce1(), | ||||
|         /*  output                  */  .cl1(), | ||||
|         /*  output                  */  .z1(), | ||||
|         /*  output                  */  .ff1(), | ||||
|         /*  output                  */  .ov_msb(), | ||||
|         /*  output                  */  .co_msb(), | ||||
|         /*  output                  */  .cmsb(), | ||||
|         /*  output                  */  .so(), | ||||
|         /*  output                  */  .f0_bus_stat(drq), // not full | ||||
|         /*  output                  */  .f0_blk_stat(empty), // empty | ||||
|         /*  output                  */  .f1_bus_stat(), | ||||
|         /*  output                  */  .f1_blk_stat(), | ||||
|          | ||||
|         /* input                    */  .ci(1'b0),     // Carry in from previous stage | ||||
|         /* output                   */  .co(),// Carry out to next stage | ||||
|         /* input                    */  .sir(1'b0),    // Shift in from right side | ||||
|         /* output                   */  .sor(),        // Shift out to right side | ||||
|         /* input                    */  .sil(1'b0),    // Shift in from left side | ||||
|         /* output                   */  .sol(),        // Shift out to left side | ||||
|         /* input                    */  .msbi(1'b0),   // MSB chain in | ||||
|         /* output                   */  .msbo(),       // MSB chain out | ||||
|         /* input [01:00]            */  .cei(2'b0),    // Compare equal in from prev stage | ||||
|         /* output [01:00]           */  .ceo(),        // Compare equal out to next stage | ||||
|         /* input [01:00]            */  .cli(2'b0),    // Compare less than in from prv stage | ||||
|         /* output [01:00]           */  .clo(),        // Compare less than out to next stage | ||||
|         /* input [01:00]            */  .zi(2'b0),     // Zero detect in from previous stage | ||||
|         /* output [01:00]           */  .zo(),         // Zero detect out to next stage | ||||
|         /* input [01:00]            */  .fi(2'b0),     // 0xFF detect in from previous stage | ||||
|         /* output [01:00]           */  .fo(),         // 0xFF detect out to next stage | ||||
|         /* input [01:00]            */  .capi(2'b0),   // Software capture from previous stage | ||||
|         /* output [01:00]           */  .capo(),       // Software capture to next stage | ||||
|         /* input                    */  .cfbi(1'b0),   // CRC Feedback in from previous stage | ||||
|         /* output                   */  .cfbo(),       // CRC Feedback out to next stage | ||||
|         /* input [07:00]            */  .pi(8'b0),     // Parallel data port | ||||
|         /* output [07:00]           */  .po(po)       // Parallel data port | ||||
| ); | ||||
|  | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
| endmodule | ||||
| //`#start footer` -- edit after this line, do not edit this line | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -28,6 +28,54 @@ | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="1a7e8637-3b6b-4e84-839c-0dfc18fdaf5b"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="NAMED_DIVIDER" /> | ||||
|         <Data key="desired_freq" value="0" /> | ||||
|         <Data key="desired_unit" value="15" /> | ||||
|         <Data key="divider" value="0" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
|         <Data key="minus_tolerance" value="5" /> | ||||
|         <Data key="name" value="Clock_5" /> | ||||
|         <Data key="named_src_direct_connect" value="True" /> | ||||
|         <Data key="netlist_name" value="Clock_5" /> | ||||
|         <Data key="placement" value="AUTO" /> | ||||
|         <Data key="plus_accuracy" value="0.25" /> | ||||
|         <Data key="plus_tolerance" value="5" /> | ||||
|         <Data key="scope" value="LOCAL" /> | ||||
|         <Data key="src_clk_id" value="75C2148C-3656-4d8a-846D-0CAE99AB6FF7" /> | ||||
|         <Data key="src_clk_name" value="BUS_CLK" /> | ||||
|         <Data key="start_on_reset" value="True" /> | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="3f3708ae-fb62-4012-919b-9a3b9a1dfbc2"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="NAMED_DIVIDER" /> | ||||
|         <Data key="desired_freq" value="0" /> | ||||
|         <Data key="desired_unit" value="15" /> | ||||
|         <Data key="divider" value="0" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
|         <Data key="minus_tolerance" value="5" /> | ||||
|         <Data key="name" value="Clock_8" /> | ||||
|         <Data key="named_src_direct_connect" value="True" /> | ||||
|         <Data key="netlist_name" value="Clock_8" /> | ||||
|         <Data key="placement" value="AUTO" /> | ||||
|         <Data key="plus_accuracy" value="0.25" /> | ||||
|         <Data key="plus_tolerance" value="5" /> | ||||
|         <Data key="scope" value="LOCAL" /> | ||||
|         <Data key="src_clk_id" value="75C2148C-3656-4d8a-846D-0CAE99AB6FF7" /> | ||||
|         <Data key="src_clk_name" value="BUS_CLK" /> | ||||
|         <Data key="start_on_reset" value="True" /> | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="4eef02b9-8ad1-43c4-85f1-b3335faa5fc4"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
| @@ -147,6 +195,54 @@ | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="71bc291d-84a7-40a8-b7b2-1c8a34326a31"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="NAMED_FREQ" /> | ||||
|         <Data key="desired_freq" value="300" /> | ||||
|         <Data key="desired_unit" value="0" /> | ||||
|         <Data key="divider" value="65536" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
|         <Data key="minus_tolerance" value="5" /> | ||||
|         <Data key="name" value="CLOCK300" /> | ||||
|         <Data key="named_src_direct_connect" value="False" /> | ||||
|         <Data key="netlist_name" value="CLOCK300" /> | ||||
|         <Data key="placement" value="AUTO" /> | ||||
|         <Data key="plus_accuracy" value="0.25" /> | ||||
|         <Data key="plus_tolerance" value="5" /> | ||||
|         <Data key="scope" value="LOCAL" /> | ||||
|         <Data key="src_clk_id" value="CEF43CFB-0213-49b9-B980-2FFAB81C5B47" /> | ||||
|         <Data key="src_clk_name" value="IMO" /> | ||||
|         <Data key="start_on_reset" value="True" /> | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="90ce0c72-9f10-44ef-a049-f0f525d59bea"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="NAMED_FREQ" /> | ||||
|         <Data key="desired_freq" value="128" /> | ||||
|         <Data key="desired_unit" value="0" /> | ||||
|         <Data key="divider" value="65536" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
|         <Data key="minus_tolerance" value="5" /> | ||||
|         <Data key="name" value="CLOCK8" /> | ||||
|         <Data key="named_src_direct_connect" value="False" /> | ||||
|         <Data key="netlist_name" value="CLOCK8" /> | ||||
|         <Data key="placement" value="AUTO" /> | ||||
|         <Data key="plus_accuracy" value="0.25" /> | ||||
|         <Data key="plus_tolerance" value="5" /> | ||||
|         <Data key="scope" value="LOCAL" /> | ||||
|         <Data key="src_clk_id" value="CEF43CFB-0213-49b9-B980-2FFAB81C5B47" /> | ||||
|         <Data key="src_clk_name" value="IMO" /> | ||||
|         <Data key="start_on_reset" value="True" /> | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="349ffa20-8576-4ac3-9a6f-34ef606de6cf"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
| @@ -170,6 +266,29 @@ | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="4033c29d-f4bc-4e94-ac95-aa587e869f88/696a0979-21fc-4185-bf38-6c79febcde7a"> | ||||
|         <Data key="check_tolerance" value="False" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="AUTO" /> | ||||
|         <Data key="desired_freq" value="1600000" /> | ||||
|         <Data key="desired_unit" value="0" /> | ||||
|         <Data key="divider" value="40" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
|         <Data key="minus_tolerance" value="5" /> | ||||
|         <Data key="name" value="OUTPUT_VOLTAGE_ADC_theACLK" /> | ||||
|         <Data key="netlist_name" value="\OUTPUT_VOLTAGE_ADC:theACLK\" /> | ||||
|         <Data key="placement" value="AUTO" /> | ||||
|         <Data key="plus_accuracy" value="0.25" /> | ||||
|         <Data key="plus_tolerance" value="5" /> | ||||
|         <Data key="scope" value="LOCAL" /> | ||||
|         <Data key="src_clk_id" value="61737EF6-3B74-48f9-8B91-F7473A442AE7" /> | ||||
|         <Data key="src_clk_name" value="MASTER_CLK" /> | ||||
|         <Data key="start_on_reset" value="True" /> | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="6616e828-6611-4893-a674-66c861d79d6c"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
| @@ -241,6 +360,53 @@ | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="09974428-e912-491f-8d2f-361ba50e7599"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="NAMED_DIVIDER" /> | ||||
|         <Data key="desired_freq" value="0" /> | ||||
|         <Data key="desired_unit" value="15" /> | ||||
|         <Data key="divider" value="0" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
|         <Data key="minus_tolerance" value="5" /> | ||||
|         <Data key="name" value="Clock_6" /> | ||||
|         <Data key="named_src_direct_connect" value="True" /> | ||||
|         <Data key="netlist_name" value="Clock_6" /> | ||||
|         <Data key="placement" value="AUTO" /> | ||||
|         <Data key="plus_accuracy" value="0.25" /> | ||||
|         <Data key="plus_tolerance" value="5" /> | ||||
|         <Data key="scope" value="LOCAL" /> | ||||
|         <Data key="src_clk_id" value="75C2148C-3656-4d8a-846D-0CAE99AB6FF7" /> | ||||
|         <Data key="src_clk_name" value="BUS_CLK" /> | ||||
|         <Data key="start_on_reset" value="True" /> | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="a5825a94-fa18-4e4f-a843-bc687cacbd56/696a0979-21fc-4185-bf38-6c79febcde7a"> | ||||
|         <Data key="check_tolerance" value="False" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="AUTO" /> | ||||
|         <Data key="desired_freq" value="1600000" /> | ||||
|         <Data key="desired_unit" value="0" /> | ||||
|         <Data key="divider" value="40" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
|         <Data key="minus_tolerance" value="5" /> | ||||
|         <Data key="name" value="INPUT_VOLTAGE_ADC_theACLK" /> | ||||
|         <Data key="netlist_name" value="\INPUT_VOLTAGE_ADC:theACLK\" /> | ||||
|         <Data key="placement" value="AUTO" /> | ||||
|         <Data key="plus_accuracy" value="0.25" /> | ||||
|         <Data key="plus_tolerance" value="5" /> | ||||
|         <Data key="scope" value="LOCAL" /> | ||||
|         <Data key="src_clk_id" value="61737EF6-3B74-48f9-8B91-F7473A442AE7" /> | ||||
|         <Data key="src_clk_name" value="MASTER_CLK" /> | ||||
|         <Data key="start_on_reset" value="True" /> | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="b762c287-7f87-4b21-982e-84be01dc5115"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
| @@ -288,6 +454,30 @@ | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="b722443b-8f81-46dc-bf9b-c95eb62bc181"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="NAMED_DIVIDER" /> | ||||
|         <Data key="desired_freq" value="0" /> | ||||
|         <Data key="desired_unit" value="15" /> | ||||
|         <Data key="divider" value="0" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
|         <Data key="minus_tolerance" value="5" /> | ||||
|         <Data key="name" value="Clock_1" /> | ||||
|         <Data key="named_src_direct_connect" value="True" /> | ||||
|         <Data key="netlist_name" value="Clock_1" /> | ||||
|         <Data key="placement" value="AUTO" /> | ||||
|         <Data key="plus_accuracy" value="0.25" /> | ||||
|         <Data key="plus_tolerance" value="5" /> | ||||
|         <Data key="scope" value="LOCAL" /> | ||||
|         <Data key="src_clk_id" value="75C2148C-3656-4d8a-846D-0CAE99AB6FF7" /> | ||||
|         <Data key="src_clk_name" value="BUS_CLK" /> | ||||
|         <Data key="start_on_reset" value="True" /> | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="cb7e877c-9fb4-4fc1-a708-f1e48eb5a68c"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
| @@ -312,6 +502,30 @@ | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="d3075dc6-05c8-4dc9-9959-cf7014c0e66f"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="NAMED_DIVIDER" /> | ||||
|         <Data key="desired_freq" value="0" /> | ||||
|         <Data key="desired_unit" value="15" /> | ||||
|         <Data key="divider" value="0" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
|         <Data key="minus_tolerance" value="5" /> | ||||
|         <Data key="name" value="Clock_7" /> | ||||
|         <Data key="named_src_direct_connect" value="True" /> | ||||
|         <Data key="netlist_name" value="Clock_7" /> | ||||
|         <Data key="placement" value="AUTO" /> | ||||
|         <Data key="plus_accuracy" value="0.25" /> | ||||
|         <Data key="plus_tolerance" value="5" /> | ||||
|         <Data key="scope" value="LOCAL" /> | ||||
|         <Data key="src_clk_id" value="75C2148C-3656-4d8a-846D-0CAE99AB6FF7" /> | ||||
|         <Data key="src_clk_name" value="BUS_CLK" /> | ||||
|         <Data key="start_on_reset" value="True" /> | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="e4a53a4c-40e1-4747-a72a-10193ffdf31c"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
| @@ -600,7 +814,7 @@ | ||||
|   </Group> | ||||
|   <Group key="Component"> | ||||
|     <Group key="v1"> | ||||
|       <Data key="cy_boot" value="cy_boot_v5_80" /> | ||||
|       <Data key="cy_boot" value="cy_boot_v6_10" /> | ||||
|       <Data key="Em_EEPROM_Dynamic" value="Em_EEPROM_Dynamic_v2_20" /> | ||||
|       <Data key="LIN_Dynamic" value="LIN_Dynamic_v5_0" /> | ||||
|     </Group> | ||||
| @@ -609,45 +823,60 @@ | ||||
|   <Group key="DWRInstGuidMapping"> | ||||
|     <Group key="Clock"> | ||||
|       <Data key="0b2f9bbb-00ce-4115-a788-ffb9d046a9e5" value="Clock_4" /> | ||||
|       <Data key="1a7e8637-3b6b-4e84-839c-0dfc18fdaf5b" value="Clock_5" /> | ||||
|       <Data key="3f3708ae-fb62-4012-919b-9a3b9a1dfbc2" value="Clock_8" /> | ||||
|       <Data key="4eef02b9-8ad1-43c4-85f1-b3335faa5fc4" value="Clock_3" /> | ||||
|       <Data key="06c4d5d4-f15f-4b29-a1d0-c24b2e38b1ec" value="CounterClock" /> | ||||
|       <Data key="24cd38f7-f472-4403-837f-86807c8f5333" value="PULSE_CLOCK" /> | ||||
|       <Data key="63ed4137-0b09-4256-8a27-35c9a2653f1a" value="Clock_2" /> | ||||
|       <Data key="66f14071-bddd-4b4d-a9aa-a129cceaa7b6" value="Clock_3" /> | ||||
|       <Data key="71bc291d-84a7-40a8-b7b2-1c8a34326a31" value="CLOCK300" /> | ||||
|       <Data key="90ce0c72-9f10-44ef-a049-f0f525d59bea" value="CLOCK8" /> | ||||
|       <Data key="349ffa20-8576-4ac3-9a6f-34ef606de6cf" value="Clock_1" /> | ||||
|       <Data key="4033c29d-f4bc-4e94-ac95-aa587e869f88/696a0979-21fc-4185-bf38-6c79febcde7a" value="OUTPUT_VOLTAGE_ADC_theACLK" /> | ||||
|       <Data key="6616e828-6611-4893-a674-66c861d79d6c" value="SignalSamplingClock" /> | ||||
|       <Data key="12664fc6-9d70-44b1-8a49-887a292e1b7f" value="Clock_3" /> | ||||
|       <Data key="75187c05-9501-4450-b306-6ccdd3bb77db" value="Clock_5" /> | ||||
|       <Data key="09974428-e912-491f-8d2f-361ba50e7599" value="Clock_6" /> | ||||
|       <Data key="a5825a94-fa18-4e4f-a843-bc687cacbd56/696a0979-21fc-4185-bf38-6c79febcde7a" value="INPUT_VOLTAGE_ADC_theACLK" /> | ||||
|       <Data key="b762c287-7f87-4b21-982e-84be01dc5115" value="Clock_2" /> | ||||
|       <Data key="b0162966-0060-4af5-82d1-fcb491ad7619/be0a0e37-ad17-42ca-b5a1-1a654d736358" value="UART_IntClock" /> | ||||
|       <Data key="b722443b-8f81-46dc-bf9b-c95eb62bc181" value="Clock_1" /> | ||||
|       <Data key="cb7e877c-9fb4-4fc1-a708-f1e48eb5a68c" value="CounterClock" /> | ||||
|       <Data key="d3075dc6-05c8-4dc9-9959-cf7014c0e66f" value="Clock_7" /> | ||||
|       <Data key="e4a53a4c-40e1-4747-a72a-10193ffdf31c" value="Clock_1" /> | ||||
|       <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" /> | ||||
|       <Data key="8fc20a4f-e4d1-44b3-a5d4-546e8628d61e" value="LED" /> | ||||
|       <Data key="12e00eac-69b5-4717-85c8-25ef6b224d4c" value="DEBUG_PINS" /> | ||||
|       <Data key="41e2d8ed-5494-4d8c-8ff7-f4f789cece51" value="REDWC" /> | ||||
|       <Data key="264be2d3-9481-494b-8d9c-c1905a45e9cc" value="FDD" /> | ||||
|       <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" /> | ||||
|       <Data key="b8380fb7-fdb8-449f-bd8d-c4ca96cdf55a" value="DEBUG_PINS" /> | ||||
|       <Data key="bc2e8987-db82-469c-bf6f-22fd3464cc70" value="DEBUG_PINS" /> | ||||
|       <Data key="bc5d52a1-1b25-4aa0-9ba9-3f81d122772f" value="DEBUG_PINS" /> | ||||
|       <Data key="beca5e2d-f70f-4900-a4db-7eca1ed3126e/8b77a6c4-10a0-4390-971c-672353e2a49c" value="USBFS_Dm" /> | ||||
|       <Data key="beca5e2d-f70f-4900-a4db-7eca1ed3126e/618a72fc-5ddd-4df5-958f-a3d55102db42" value="USBFS_Dp" /> | ||||
|       <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="e851a3b9-efb8-48be-bbb8-b303b216c393" value="LED" /> | ||||
|       <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" /> | ||||
|       <Data key="ed092b9b-d398-4703-be89-cebf998501f6" value="UartTx" /> | ||||
|       <Data key="f9a7371a-8a7d-4144-8b08-69e3d2a3a663" value="INDEX360" /> | ||||
|       <Data key="fbd1f839-40f9-498e-a48b-5f3048ea5c3d/52f31aa9-2f0a-497d-9a1f-1424095e13e6" value="UART_tx" /> | ||||
|       <Data key="fede1767-f3fd-4021-b3d7-8f9d88f36f9b" value="DRVSA" /> | ||||
|       <Data key="fff78075-035e-43d7-8577-bc5be4d21926" value="WGATE" /> | ||||
| @@ -3737,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" /> | ||||
| @@ -3752,6 +3986,11 @@ | ||||
|         <Data key="Port Format" value="2,2" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="8fc20a4f-e4d1-44b3-a5d4-546e8628d61e"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="2,1" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="12e00eac-69b5-4717-85c8-25ef6b224d4c"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="2,2" /> | ||||
| @@ -3833,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" /> | ||||
| @@ -3859,6 +4103,32 @@ | ||||
|         <Data key="Port Format" value="2,3" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="bc2e8987-db82-469c-bf6f-22fd3464cc70"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="0,0" /> | ||||
|       </Group> | ||||
|       <Group key="1"> | ||||
|         <Data key="Port Format" value="0,1" /> | ||||
|       </Group> | ||||
|       <Group key="2"> | ||||
|         <Data key="Port Format" value="0,2" /> | ||||
|       </Group> | ||||
|       <Group key="3"> | ||||
|         <Data key="Port Format" value="0,3" /> | ||||
|       </Group> | ||||
|       <Group key="4"> | ||||
|         <Data key="Port Format" value="0,4" /> | ||||
|       </Group> | ||||
|       <Group key="5"> | ||||
|         <Data key="Port Format" value="0,5" /> | ||||
|       </Group> | ||||
|       <Group key="6"> | ||||
|         <Data key="Port Format" value="0,6" /> | ||||
|       </Group> | ||||
|       <Group key="7"> | ||||
|         <Data key="Port Format" value="0,7" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="bc5d52a1-1b25-4aa0-9ba9-3f81d122772f"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="0,5" /> | ||||
| @@ -3892,9 +4162,14 @@ | ||||
|         <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="2,1" /> | ||||
|         <Data key="Port Format" value="3,0" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="e51063a9-4fad-40c7-a06b-7cc4b137dc18"> | ||||
| @@ -3912,9 +4187,14 @@ | ||||
|         <Data key="Port Format" value="12,7" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="f9a7371a-8a7d-4144-8b08-69e3d2a3a663"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="3,1" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="fbd1f839-40f9-498e-a48b-5f3048ea5c3d/52f31aa9-2f0a-497d-9a1f-1424095e13e6"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="2,5" /> | ||||
|         <Data key="Port Format" value="12,7" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="fede1767-f3fd-4021-b3d7-8f9d88f36f9b"> | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										83
									
								
								FluxEngine.cydsn/Sampler/Sampler.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								FluxEngine.cydsn/Sampler/Sampler.v
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
|  | ||||
| //`#start header` -- edit after this line, do not edit this line | ||||
| `include "cypress.v" | ||||
|  | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
| // Generated on 12/11/2019 at 21:18 | ||||
| // Component: Sampler | ||||
| module Sampler ( | ||||
| 	output [2:0] debug_state, | ||||
| 	output reg [7:0] opcode, | ||||
| 	output  reg       req, | ||||
| 	input   clock, | ||||
| 	input   index, | ||||
| 	input   rdata, | ||||
| 	input   reset, | ||||
| 	input   sampleclock | ||||
| ); | ||||
|  | ||||
| //`#start body` -- edit after this line, do not edit this line | ||||
|  | ||||
| // NOTE: Reset pulse is used in both clock domains, and must be long enough | ||||
| // to be detected in both. | ||||
|  | ||||
| reg [5:0] counter; | ||||
|  | ||||
| reg index_q; | ||||
| reg rdata_q; | ||||
|  | ||||
| reg index_edge; | ||||
| reg rdata_edge; | ||||
|  | ||||
| reg req_toggle; | ||||
|  | ||||
| always @(posedge sampleclock) | ||||
| begin | ||||
|     if (reset) | ||||
|     begin | ||||
|         index_edge <= 0; | ||||
|         rdata_edge <= 0; | ||||
|         index_q <= 0; | ||||
|         rdata_q <= 0; | ||||
|         counter <= 0; | ||||
|         req_toggle <= 0; | ||||
|     end | ||||
|     else | ||||
|     begin | ||||
|         /* Both index and rdata are active high -- positive-going edges | ||||
|          * indicate the start of an index pulse and read pulse, respectively. | ||||
|          */ | ||||
|           | ||||
|         index_edge <= index && !index_q; | ||||
|         index_q <= index; | ||||
|          | ||||
|         rdata_edge <= rdata && !rdata_q; | ||||
|         rdata_q <= rdata; | ||||
|          | ||||
|         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 | ||||
| endmodule | ||||
| //`#start footer` -- edit after this line, do not edit this line | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										95
									
								
								FluxEngine.cydsn/Sequencer/Sequencer.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								FluxEngine.cydsn/Sequencer/Sequencer.v
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
|  | ||||
| //`#start header` -- edit after this line, do not edit this line | ||||
| `include "cypress.v" | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
| // Generated on 11/24/2019 at 17:25 | ||||
| // Component: Sequencer | ||||
| module Sequencer ( | ||||
| 	output req, /* request new data on leading edge */ | ||||
| 	output wdata, | ||||
|     output [2:0] debug_state, | ||||
| 	input clock, | ||||
| 	input dataclock, /* incoming data on leading edge */ | ||||
| 	input [7:0] opcode, | ||||
|     input index, | ||||
|     input sampleclock, | ||||
|     input reset | ||||
| ); | ||||
|  | ||||
| //`#start body` -- edit after this line, do not edit this line | ||||
|  | ||||
| localparam STATE_LOAD = 0; | ||||
| localparam STATE_WRITING = 1; | ||||
|  | ||||
| reg state; | ||||
| reg [5:0] countdown; | ||||
| reg pulsepending; | ||||
|  | ||||
| assign req = (!reset && (state == STATE_LOAD)); | ||||
| assign wdata = (!reset && (state == STATE_WRITING) && (countdown == 0) && pulsepending); | ||||
| assign debug_state = 0; | ||||
|  | ||||
| reg olddataclock; | ||||
| wire dataclocked; | ||||
| always @(posedge clock) olddataclock <= dataclock; | ||||
| assign dataclocked = !olddataclock && dataclock; | ||||
|  | ||||
| reg oldsampleclock; | ||||
| reg sampleclocked; | ||||
|  | ||||
| reg oldindex; | ||||
| wire indexed; | ||||
| always @(posedge clock) oldindex <= index; | ||||
| assign indexed = !oldindex && index; | ||||
|  | ||||
| always @(posedge clock) | ||||
| begin | ||||
|     if (reset) | ||||
|     begin | ||||
|         state <= STATE_LOAD; | ||||
|         countdown <= 0; | ||||
|         pulsepending <= 0; | ||||
|         oldsampleclock <= 0; | ||||
|     end | ||||
|     else | ||||
|     begin | ||||
|         if (!oldsampleclock && sampleclock) | ||||
|             sampleclocked <= 1; | ||||
|         oldsampleclock <= sampleclock; | ||||
|              | ||||
|         case (state) | ||||
|             STATE_LOAD: | ||||
|             begin | ||||
|                 /* A posedge on dataclocked indicates that another opcode has | ||||
|                  * arrived. */ | ||||
|                 if (dataclocked) | ||||
|                 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_WRITING: | ||||
|             begin | ||||
|                 if (sampleclocked) | ||||
|                 begin | ||||
|                     if (countdown == 0) | ||||
|                         state <= STATE_LOAD; | ||||
|                     else | ||||
|                         countdown <= countdown - 1; | ||||
|                     sampleclocked <= 0; | ||||
|                 end | ||||
|             end | ||||
|         endcase | ||||
|     end | ||||
| end | ||||
|  | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
| endmodule | ||||
| //`#start footer` -- edit after this line, do not edit this line | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
							
								
								
									
										
											BIN
										
									
								
								FluxEngine.cydsn/SuperCounter/SuperCounter.cysym
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								FluxEngine.cydsn/SuperCounter/SuperCounter.cysym
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										156
									
								
								FluxEngine.cydsn/SuperCounter/SuperCounter.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								FluxEngine.cydsn/SuperCounter/SuperCounter.v
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | ||||
|  | ||||
| //`#start header` -- edit after this line, do not edit this line | ||||
| `include "cypress.v" | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
| // Generated on 11/16/2017 at 15:44 | ||||
| // Component: FIFOout | ||||
| module SuperCounter ( | ||||
| 	input clk, | ||||
|     input reset, | ||||
|     input count, | ||||
|     output [7:0] d, | ||||
| 	output drq, | ||||
| 	output empty, | ||||
|     output ack | ||||
| ); | ||||
|  | ||||
| //`#start body` -- edit after this line, do not edit this line | ||||
|  | ||||
| parameter ResetValue = 0; | ||||
| parameter Delta = 1; | ||||
|      | ||||
| wire [7:0] po; | ||||
| assign d = po; | ||||
|  | ||||
| localparam STATE_RESET = 0; | ||||
| localparam STATE_WAIT = 1; | ||||
| localparam STATE_ADD = 2; | ||||
|  | ||||
| reg oldcount; | ||||
| wire counted; | ||||
| assign counted = count && !oldcount; | ||||
|  | ||||
| always @(posedge clk) oldcount <= count; | ||||
|  | ||||
| wire [2:0] cs; | ||||
| assign cs = reset ? STATE_RESET : (counted ? STATE_ADD : STATE_WAIT); | ||||
|              | ||||
| cy_psoc3_dp #(.d0_init(ResetValue), .d1_init(Delta),  | ||||
| .cy_dpconfig( | ||||
| { | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC___D0, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM0:  STATE_RESET*/ | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC__ALU, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM1:  STATE_WAIT*/ | ||||
|     `CS_ALU_OP__ADD, `CS_SRCA_A0, `CS_SRCB_D1, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC__ALU, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM2:  STATE_ADD*/ | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM3:             */ | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM4:             */ | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM5:             */ | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM6:             */ | ||||
|     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, | ||||
|     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, | ||||
|     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, | ||||
|     `CS_CMP_SEL_CFGA, /*CFGRAM7:             */ | ||||
|     8'hFF, 8'h00,  /*CFG9:             */ | ||||
|     8'hFF, 8'hFF,  /*CFG11-10:             */ | ||||
|     `SC_CMPB_A1_D1, `SC_CMPA_A1_D1, `SC_CI_B_ARITH, | ||||
|     `SC_CI_A_ARITH, `SC_C1_MASK_DSBL, `SC_C0_MASK_DSBL, | ||||
|     `SC_A_MASK_DSBL, `SC_DEF_SI_0, `SC_SI_B_DEFSI, | ||||
|     `SC_SI_A_DEFSI, /*CFG13-12:             */ | ||||
|     `SC_A0_SRC_ACC, `SC_SHIFT_SL, 1'h0, | ||||
|     1'h0, `SC_FIFO1_BUS, `SC_FIFO0_BUS, | ||||
|     `SC_MSB_DSBL, `SC_MSB_BIT0, `SC_MSB_NOCHN, | ||||
|     `SC_FB_NOCHN, `SC_CMP1_NOCHN, | ||||
|     `SC_CMP0_NOCHN, /*CFG15-14:             */ | ||||
|     10'h00, `SC_FIFO_CLK__DP,`SC_FIFO_CAP_AX, | ||||
|     `SC_FIFO_LEVEL,`SC_FIFO_ASYNC,`SC_EXTCRC_DSBL, | ||||
|     `SC_WRK16CAT_DSBL /*CFG17-16:             */ | ||||
| } | ||||
| )) dp( | ||||
|         /*  input                   */  .reset(1'b0), | ||||
|         /*  input                   */  .clk(clk), | ||||
|         /*  input   [02:00]         */  .cs_addr(cs), | ||||
|         /*  input                   */  .route_si(1'b0), | ||||
|         /*  input                   */  .route_ci(1'b0), | ||||
|         /*  input                   */  .f0_load(1'b0), | ||||
|         /*  input                   */  .f1_load(1'b0), | ||||
|         /*  input                   */  .d0_load(1'b0), | ||||
|         /*  input                   */  .d1_load(1'b0), | ||||
|         /*  output                  */  .ce0(), | ||||
|         /*  output                  */  .cl0(), | ||||
|         /*  output                  */  .z0(), | ||||
|         /*  output                  */  .ff0(), | ||||
|         /*  output                  */  .ce1(), | ||||
|         /*  output                  */  .cl1(), | ||||
|         /*  output                  */  .z1(), | ||||
|         /*  output                  */  .ff1(), | ||||
|         /*  output                  */  .ov_msb(), | ||||
|         /*  output                  */  .co_msb(), | ||||
|         /*  output                  */  .cmsb(), | ||||
|         /*  output                  */  .so(), | ||||
|         /*  output                  */  .f0_bus_stat(), | ||||
|         /*  output                  */  .f0_blk_stat(), | ||||
|         /*  output                  */  .f1_bus_stat(), | ||||
|         /*  output                  */  .f1_blk_stat(), | ||||
|          | ||||
|         /* input                    */  .ci(1'b0),     // Carry in from previous stage | ||||
|         /* output                   */  .co(),// Carry out to next stage | ||||
|         /* input                    */  .sir(1'b0),    // Shift in from right side | ||||
|         /* output                   */  .sor(),        // Shift out to right side | ||||
|         /* input                    */  .sil(1'b0),    // Shift in from left side | ||||
|         /* output                   */  .sol(),        // Shift out to left side | ||||
|         /* input                    */  .msbi(1'b0),   // MSB chain in | ||||
|         /* output                   */  .msbo(),       // MSB chain out | ||||
|         /* input [01:00]            */  .cei(2'b0),    // Compare equal in from prev stage | ||||
|         /* output [01:00]           */  .ceo(),        // Compare equal out to next stage | ||||
|         /* input [01:00]            */  .cli(2'b0),    // Compare less than in from prv stage | ||||
|         /* output [01:00]           */  .clo(),        // Compare less than out to next stage | ||||
|         /* input [01:00]            */  .zi(2'b0),     // Zero detect in from previous stage | ||||
|         /* output [01:00]           */  .zo(),         // Zero detect out to next stage | ||||
|         /* input [01:00]            */  .fi(2'b0),     // 0xFF detect in from previous stage | ||||
|         /* output [01:00]           */  .fo(),         // 0xFF detect out to next stage | ||||
|         /* input [01:00]            */  .capi(2'b0),   // Software capture from previous stage | ||||
|         /* output [01:00]           */  .capo(),       // Software capture to next stage | ||||
|         /* input                    */  .cfbi(1'b0),   // CRC Feedback in from previous stage | ||||
|         /* output                   */  .cfbo(),       // CRC Feedback out to next stage | ||||
|         /* input [07:00]            */  .pi(8'b0),     // Parallel data port | ||||
|         /* output [07:00]           */  .po(po)       // Parallel data port | ||||
| ); | ||||
|  | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
| endmodule | ||||
| //`#start footer` -- edit after this line, do not edit this line | ||||
| //`#end` -- edit above this line, do not edit this line | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											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,19 +13,26 @@ | ||||
| #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 volatile uint32_t clock = 0; | ||||
| 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; | ||||
| static bool homed = false; | ||||
| static int current_track = 0; | ||||
| static uint8_t current_drive_flags = 0; | ||||
| static struct set_drive_frame current_drive_flags; | ||||
|  | ||||
| #define BUFFER_COUNT 16 | ||||
| #define BUFFER_COUNT 64 /* the maximum */ | ||||
| #define BUFFER_SIZE 64 | ||||
| static uint8_t td[BUFFER_COUNT]; | ||||
| static uint8_t dma_buffer[BUFFER_COUNT][BUFFER_SIZE] __attribute__((aligned())); | ||||
| @@ -41,21 +47,67 @@ static volatile bool dma_underrun = false; | ||||
| #define DECLARE_REPLY_FRAME(STRUCT, TYPE) \ | ||||
|     STRUCT r = {.f = { .type = TYPE, .size = sizeof(STRUCT) }} | ||||
|  | ||||
| static void stop_motor(void); | ||||
|  | ||||
| static void system_timer_cb(void) | ||||
| { | ||||
|     CyGlobalIntDisable; | ||||
|     clock++; | ||||
|      | ||||
|     static int counter300rpm = 0; | ||||
|     counter300rpm++; | ||||
|     if (counter300rpm == 200) | ||||
|         counter300rpm = 0; | ||||
|      | ||||
|     static int counter360rpm = 0; | ||||
|     counter360rpm++; | ||||
|     if (counter360rpm == 167) | ||||
|         counter360rpm = 0; | ||||
|      | ||||
|     FAKE_INDEX_GENERATOR_REG_Write( | ||||
|         ((counter300rpm == 0) ? 1 : 0) | ||||
|         | ((counter360rpm == 0) ? 2 : 0)); | ||||
|      | ||||
|     CyGlobalIntEnable; | ||||
| } | ||||
|  | ||||
| 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) | ||||
| @@ -85,10 +137,25 @@ static void print(const char* msg, ...) | ||||
|     UART_PutCRLF(); | ||||
| } | ||||
|  | ||||
| static void set_drive_flags(struct set_drive_frame* flags) | ||||
| { | ||||
|     if (current_drive_flags.drive != flags->drive) | ||||
|     { | ||||
|         stop_motor(); | ||||
|         homed = false; | ||||
|     } | ||||
|      | ||||
|     current_drive_flags = *flags; | ||||
|     DRIVESELECT_REG_Write(flags->drive ? 2 : 1); /* select drive 1 or 0 */ | ||||
|     DENSITY_REG_Write(flags->high_density); /* density bit */ | ||||
|     INDEX_REG_Write(flags->index_mode); | ||||
| } | ||||
|  | ||||
| static void start_motor(void) | ||||
| { | ||||
|     if (!motor_on) | ||||
|     { | ||||
|         set_drive_flags(¤t_drive_flags); | ||||
|         MOTOR_REG_Write(1); | ||||
|         CyDelay(1000); | ||||
|         homed = false; | ||||
| @@ -99,12 +166,28 @@ static void start_motor(void) | ||||
|     CyWdtClear(); | ||||
| } | ||||
|  | ||||
| static void stop_motor(void) | ||||
| { | ||||
|     if (motor_on) | ||||
|     { | ||||
|         MOTOR_REG_Write(0); | ||||
|         DRIVESELECT_REG_Write(0); /* deselect all drives */ | ||||
|         motor_on = false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void wait_until_writeable(int ep) | ||||
| { | ||||
|     while (USBFS_GetEPState(ep) != USBFS_IN_BUFFER_EMPTY) | ||||
|         ; | ||||
| } | ||||
|  | ||||
| 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); | ||||
| @@ -122,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; | ||||
| } | ||||
| @@ -138,25 +227,36 @@ static void cmd_get_version(struct any_frame* f) | ||||
|  | ||||
| static void step(int dir) | ||||
| { | ||||
|     STEP_REG_Write(dir); | ||||
|     CyDelayUs(1); | ||||
|     STEP_REG_Write(dir | 2); | ||||
|     CyDelayUs(1); | ||||
|     STEP_REG_Write(dir); | ||||
|     STEP_REG_Write(dir); /* step high */ | ||||
|     CyDelayUs(6); | ||||
|     STEP_REG_Write(dir | 2); /* step low */ | ||||
|     CyDelayUs(6); | ||||
|     STEP_REG_Write(dir); /* step high again, drive moves now */ | ||||
|     CyDelay(STEP_INTERVAL_TIME); | ||||
| } | ||||
|  | ||||
| /* returns true if it looks like a drive is attached */ | ||||
| static bool home(void) | ||||
| { | ||||
|     for (int i=0; i<100; i++) | ||||
|     { | ||||
|         /* Don't keep stepping forever, because if a drive's | ||||
|          * not connected bad things happen. */ | ||||
|         if (TRACK0_REG_Read()) | ||||
|             return true; | ||||
|         step(STEP_TOWARDS0); | ||||
|     } | ||||
|      | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| static void seek_to(int track) | ||||
| { | ||||
|     start_motor(); | ||||
|     if (!homed) | ||||
|     if (!homed || (track == 0)) | ||||
|     { | ||||
|         print("homing"); | ||||
|         while (!TRACK0_REG_Read()) | ||||
|             step(STEP_TOWARDS0); | ||||
|              | ||||
|         /* Step to -1, which should be a nop, to reset the disk on disk change. */ | ||||
|         step(STEP_TOWARDS0); | ||||
|         home(); | ||||
|          | ||||
|         homed = true; | ||||
|         current_track = 0; | ||||
| @@ -167,11 +267,7 @@ static void seek_to(int track) | ||||
|     while (track != current_track) | ||||
|     { | ||||
|         if (TRACK0_REG_Read()) | ||||
|         { | ||||
|             if (current_track != 0) | ||||
|                 print("unexpectedly detected track 0"); | ||||
|             current_track = 0; | ||||
|         } | ||||
|          | ||||
|         if (track > current_track) | ||||
|         { | ||||
| @@ -186,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"); | ||||
| } | ||||
|  | ||||
| @@ -204,30 +301,48 @@ 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(); | ||||
|      | ||||
|     index_irq = false; | ||||
|     while (!index_irq) | ||||
|         ; | ||||
|     index_irq = false; | ||||
|     int start_clock = clock; | ||||
|     int elapsed = 0; | ||||
|     while (!index_irq) | ||||
|         ; | ||||
|     int end_clock = clock; | ||||
|     { | ||||
|         elapsed = clock - start_clock; | ||||
|         if (elapsed > 1500) | ||||
|         { | ||||
|             elapsed = 0; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (elapsed != 0) | ||||
|     { | ||||
|         int target_pulse_count = f->hard_sector_count + 1; | ||||
|         start_clock = 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); | ||||
|     r.period_ms = end_clock - start_clock; | ||||
|     r.period_ms = elapsed; | ||||
|     send_reply((struct any_frame*) &r);     | ||||
| } | ||||
|  | ||||
| static void cmd_bulk_test(struct any_frame* f) | ||||
| static void cmd_bulk_write_test(struct any_frame* f) | ||||
| { | ||||
|     uint8_t buffer[64]; | ||||
|      | ||||
|     wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM); | ||||
|     for (int x=0; x<64; x++) | ||||
|     { | ||||
|         CyWdtClear(); | ||||
|         for (int y=0; y<256; y++) | ||||
|         { | ||||
|             for (unsigned z=0; z<sizeof(buffer); z++) | ||||
| @@ -236,11 +351,44 @@ static void cmd_bulk_test(struct any_frame* f) | ||||
|             wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM); | ||||
|             USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, buffer, sizeof(buffer)); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_BULK_TEST_REPLY); | ||||
|     DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_BULK_WRITE_TEST_REPLY); | ||||
|     send_reply(&r); | ||||
| } | ||||
|  | ||||
| static void cmd_bulk_read_test(struct any_frame* f) | ||||
| { | ||||
|     uint8_t buffer[64]; | ||||
|      | ||||
|     bool passed = true; | ||||
|     for (int x=0; x<64; x++) | ||||
|     { | ||||
|         CyWdtClear(); | ||||
|         for (int y=0; y<256; y++) | ||||
|         { | ||||
|             usb_read(FLUXENGINE_DATA_OUT_EP_NUM, buffer); | ||||
|             for (unsigned z=0; z<sizeof(buffer); z++) | ||||
|             { | ||||
|                 if (buffer[z] != (uint8)(x+y+z)) | ||||
|                 { | ||||
|                     print("fail %d+%d+%d == %d, not %d", x, y, z, buffer[z], (uint8)(x+y+z)); | ||||
|                     passed = false; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     print("passed=%d", passed); | ||||
|     if (passed) | ||||
|     { | ||||
|         DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_BULK_READ_TEST_REPLY); | ||||
|         send_reply(&r); | ||||
|     } | ||||
|     else | ||||
|         send_error(F_ERROR_INVALID_VALUE); | ||||
| } | ||||
|  | ||||
| static void deinit_dma(void) | ||||
| { | ||||
|     for (int i=0; i<BUFFER_COUNT; i++) | ||||
| @@ -249,8 +397,8 @@ static void deinit_dma(void) | ||||
|  | ||||
| static void init_capture_dma(void) | ||||
| { | ||||
|     dma_channel = CAPTURE_DMA_DmaInitialize( | ||||
|         2 /* bytes */, | ||||
|     dma_channel = SAMPLER_DMA_DmaInitialize( | ||||
|         1 /* bytes */, | ||||
|         true /* request per burst */,  | ||||
|         HI16(CYDEV_PERIPH_BASE), | ||||
|         HI16(CYDEV_SRAM_BASE)); | ||||
| @@ -264,49 +412,45 @@ static void init_capture_dma(void) | ||||
|             nexti = 0; | ||||
|  | ||||
|         CyDmaTdSetConfiguration(td[i], BUFFER_SIZE, td[nexti],    | ||||
|             CY_DMA_TD_INC_DST_ADR | CAPTURE_DMA__TD_TERMOUT_EN); | ||||
|         CyDmaTdSetAddress(td[i], LO16((uint32)&SAMPLER_DATAPATH_F0_REG), LO16((uint32)&dma_buffer[i])); | ||||
|             CY_DMA_TD_INC_DST_ADR | SAMPLER_DMA__TD_TERMOUT_EN); | ||||
|         CyDmaTdSetAddress(td[i], LO16((uint32)SAMPLER_FIFO_FIFO_PTR), LO16((uint32)&dma_buffer[i])); | ||||
|     }     | ||||
| } | ||||
|  | ||||
| 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. */ | ||||
|      | ||||
|     SAMPLER_CONTROL_Write(1); /* reset */ | ||||
|      | ||||
|     { | ||||
|         uint8_t i = CyEnterCriticalSection(); | ||||
|         SAMPLER_DATAPATH_F0_SET_LEVEL_MID; | ||||
|         SAMPLER_DATAPATH_F0_CLEAR; | ||||
|         SAMPLER_DATAPATH_F0_SINGLE_BUFFER_UNSET; | ||||
|         SAMPLER_FIFO_SET_LEVEL_NORMAL; | ||||
|         SAMPLER_FIFO_CLEAR; | ||||
|         SAMPLER_FIFO_SINGLE_BUFFER_UNSET; | ||||
|         CyExitCriticalSection(i); | ||||
|     } | ||||
|      | ||||
|     wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM); | ||||
|     init_capture_dma(); | ||||
|  | ||||
|     /* Wait for the beginning of a rotation. */ | ||||
|     /* Wait for the beginning of a rotation, if requested. */ | ||||
|          | ||||
|     print("wait"); | ||||
|     index_irq = false; | ||||
|     while (!index_irq) | ||||
|         ; | ||||
|     index_irq = false; | ||||
|      | ||||
|     crunch_state_t cs = {}; | ||||
|     cs.outputptr = usb_buffer; | ||||
|     cs.outputlen = BUFFER_SIZE; | ||||
|     if (f->synced) | ||||
|     { | ||||
|         hardsec_index_threshold = f->hardsec_threshold_ms; | ||||
|         index_irq = false; | ||||
|         while (!index_irq) | ||||
|             ; | ||||
|         index_irq = false; | ||||
|         hardsec_index_threshold = 0; | ||||
|     } | ||||
|      | ||||
|     dma_writing_to_td = 0; | ||||
|     dma_reading_from_td = -1; | ||||
|     dma_underrun = false; | ||||
|     int count = 0; | ||||
|     SAMPLER_CONTROL_Write(0); /* !reset */ | ||||
|     CAPTURE_CONTROL_Write(1); | ||||
|     CyDmaChSetInitialTd(dma_channel, td[dma_writing_to_td]); | ||||
|     CyDmaClearPendingDrq(dma_channel); | ||||
|     CyDmaChEnable(dma_channel, 1); | ||||
| @@ -314,74 +458,68 @@ static void cmd_read(struct read_frame* f) | ||||
|     /* Wait for the first DMA transfer to complete, after which we can start the | ||||
|      * USB transfer. */ | ||||
|  | ||||
|     while ((dma_writing_to_td == 0) && !index_irq) | ||||
|     while (dma_writing_to_td == 0) | ||||
|         ; | ||||
|     dma_reading_from_td = 0; | ||||
|     bool dma_running = true; | ||||
|      | ||||
|     /* Start transferring. */ | ||||
|  | ||||
|     int revolutions = f->revolutions; | ||||
|     while (!dma_underrun) | ||||
|     uint32_t start_time = clock; | ||||
|     for (;;) | ||||
|     { | ||||
|         CyWdtClear(); | ||||
|  | ||||
|         /* Have we reached the index pulse? */ | ||||
|         if (index_irq) | ||||
|         { | ||||
|             index_irq = false; | ||||
|             revolutions--; | ||||
|             if (revolutions == 0) | ||||
|                 break; | ||||
|         } | ||||
|         /* If the sample session is over, stop reading but continue processing until | ||||
|          * the DMA chain is empty. */ | ||||
|          | ||||
|         /* Wait for the next block to be read. */ | ||||
|         while (dma_reading_from_td == dma_writing_to_td) | ||||
|         if ((clock - start_time) >= f->milliseconds) | ||||
|         { | ||||
|             /* On an underrun, give up immediately. */ | ||||
|             if (dma_underrun) | ||||
|                 goto abort; | ||||
|         } | ||||
|  | ||||
|         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 (cs.outputlen == 0) | ||||
|             if (dma_running) | ||||
|             { | ||||
|                 while (USBFS_GetEPState(FLUXENGINE_DATA_IN_EP_NUM) != USBFS_IN_BUFFER_EMPTY) | ||||
|                 { | ||||
|                     if (index_irq || dma_underrun) | ||||
|                         goto abort; | ||||
|                 } | ||||
|  | ||||
|                 USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE); | ||||
|                 cs.outputptr = usb_buffer; | ||||
|                 cs.outputlen = BUFFER_SIZE; | ||||
|                 CyDmaChSetRequest(dma_channel, CY_DMA_CPU_TERM_CHAIN); | ||||
|                 while (CyDmaChGetRequest(dma_channel)) | ||||
|                     ; | ||||
|                 dma_running = false; | ||||
|                 dma_underrun = false; | ||||
|             } | ||||
|         } | ||||
|         dma_reading_from_td = NEXT_BUFFER(dma_reading_from_td); | ||||
|          | ||||
|         /* If there's an underrun event, stop immediately. */ | ||||
|          | ||||
|         if (dma_underrun) | ||||
|             goto abort; | ||||
|          | ||||
|         /* If there are no more blocks to be read, check to see if we've finished. */ | ||||
|          | ||||
|         if (dma_reading_from_td == dma_writing_to_td) | ||||
|         { | ||||
|             /* Also if we've run out of blocks to send. */ | ||||
|              | ||||
|             if (!dma_running) | ||||
|                 goto abort; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             /* Otherwise, there's a block waiting, so attempt to send it. */ | ||||
|              | ||||
|             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:; | ||||
|     CAPTURE_CONTROL_Write(0); | ||||
|     CyDmaChSetRequest(dma_channel, CY_DMA_CPU_TERM_CHAIN); | ||||
|     while (CyDmaChGetRequest(dma_channel)) | ||||
|         ; | ||||
|     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); | ||||
|     unsigned zz = cs.outputlen; | ||||
|     if (cs.outputlen != BUFFER_SIZE) | ||||
|         USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE-cs.outputlen); | ||||
|     if ((cs.outputlen == BUFFER_SIZE) || (cs.outputlen == 0)) | ||||
|         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(); | ||||
|  | ||||
|     if (dma_underrun) | ||||
|     STEP_REG_Write(0); | ||||
|     if (saved_dma_underrun) | ||||
|     { | ||||
|         print("underrun after %d packets"); | ||||
|         send_error(F_ERROR_UNDERRUN); | ||||
| @@ -391,7 +529,7 @@ abort:; | ||||
|         DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_READ_REPLY); | ||||
|         send_reply(&r); | ||||
|     } | ||||
|     print("count=%d i=%d d=%d zz=%d", count, index_irq, dma_underrun, zz); | ||||
|     print("count=%d i=%d d=%d", count, index_irq, dma_underrun); | ||||
| } | ||||
|  | ||||
| static void init_replay_dma(void) | ||||
| @@ -412,46 +550,47 @@ static void init_replay_dma(void) | ||||
|  | ||||
|         CyDmaTdSetConfiguration(td[i], BUFFER_SIZE, td[nexti], | ||||
|             CY_DMA_TD_INC_SRC_ADR | SEQUENCER_DMA__TD_TERMOUT_EN); | ||||
|         CyDmaTdSetAddress(td[i], LO16((uint32)&dma_buffer[i]), LO16((uint32)&SEQUENCER_DATAPATH_F0_REG)); | ||||
|         CyDmaTdSetAddress(td[i], LO16((uint32)&dma_buffer[i]), LO16((uint32)REPLAY_FIFO_FIFO_PTR)); | ||||
|     }     | ||||
| } | ||||
|  | ||||
| static void cmd_write(struct write_frame* f) | ||||
| { | ||||
|     print("cmd_write"); | ||||
|      | ||||
|     if (f->bytes_to_write % FRAME_SIZE) | ||||
|     { | ||||
|         send_error(F_ERROR_INVALID_VALUE); | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     seek_to(current_track);     | ||||
|     SIDE_REG_Write(f->side); | ||||
|     SEQUENCER_CONTROL_Write(1); /* reset */ | ||||
|     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(); | ||||
|         SEQUENCER_DATAPATH_F0_SET_LEVEL_NORMAL; | ||||
|         SEQUENCER_DATAPATH_F0_CLEAR; | ||||
|         SEQUENCER_DATAPATH_F0_SINGLE_BUFFER_UNSET; | ||||
|         uint8_t i = CyEnterCriticalSection();         | ||||
|         REPLAY_FIFO_SET_LEVEL_MID; | ||||
|         REPLAY_FIFO_CLEAR; | ||||
|         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; | ||||
|     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(); | ||||
|  | ||||
|         /* Read data from USB into the buffers. */ | ||||
|          | ||||
|         if (NEXT_BUFFER(dma_writing_to_td) != dma_reading_from_td) | ||||
| @@ -459,54 +598,25 @@ 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++) | ||||
|                         usb_buffer[i+0] = 0x7f; | ||||
|                     cs.inputptr = usb_buffer; | ||||
|                     cs.inputlen = BUFFER_SIZE; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     while (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) != USBFS_OUT_BUFFER_FULL) | ||||
|                     { | ||||
|                         if (writing && (dma_underrun || index_irq)) | ||||
|                             goto abort; | ||||
|                     } | ||||
|  | ||||
|                     int length = usb_read(FLUXENGINE_DATA_OUT_EP_NUM, usb_buffer); | ||||
|                     cs.inputptr = usb_buffer; | ||||
|                     cs.inputlen = length; | ||||
|                     USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM); | ||||
|  | ||||
|                     count_read++; | ||||
|                     if ((length < FRAME_SIZE) || (count_read == packets)) | ||||
|                         finished = true; | ||||
|                 } | ||||
|                 /* 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. */ | ||||
|              | ||||
|             /* If we have a full buffer, start writing. */ | ||||
|             if ((dma_reading_from_td == -1) && (dma_writing_to_td == BUFFER_COUNT-1)) | ||||
|             { | ||||
|                 dma_reading_from_td = old_reading_from_td = 0; | ||||
| @@ -521,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) | ||||
|                     ; | ||||
| @@ -532,7 +642,7 @@ static void cmd_write(struct write_frame* f) | ||||
|                 SEQUENCER_CONTROL_Write(0); /* start writing! */ | ||||
|             } | ||||
|         } | ||||
|          | ||||
|  | ||||
|         if (writing && (dma_underrun || index_irq)) | ||||
|             goto abort; | ||||
|  | ||||
| @@ -555,31 +665,30 @@ abort: | ||||
|         CyDmaChDisable(dma_channel); | ||||
|     } | ||||
|      | ||||
|     //debug("p=%d cr=%d cw=%d f=%d l=%d w=%d index=%d underrun=%d", packets, count_read, count_written, finished, listening, writing, index_irq, dma_underrun); | ||||
|     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) | ||||
|     { | ||||
|         while (count_read < packets) | ||||
|         /* 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(); | ||||
|      | ||||
|     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); | ||||
| } | ||||
| @@ -587,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) | ||||
|         ; | ||||
| @@ -599,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); | ||||
| @@ -607,17 +718,105 @@ static void cmd_erase(struct erase_frame* f) | ||||
|  | ||||
| static void cmd_set_drive(struct set_drive_frame* f) | ||||
| { | ||||
|     if (current_drive_flags != f->drive_flags) | ||||
|     { | ||||
|         current_drive_flags = f->drive_flags; | ||||
|         DRIVE_REG_Write(current_drive_flags); | ||||
|         homed = false; | ||||
|     } | ||||
|     if (drive0_present && !drive1_present) | ||||
|         f->drive = 0; | ||||
|     if (drive1_present && !drive0_present) | ||||
|         f->drive = 1; | ||||
|     set_drive_flags(f); | ||||
|      | ||||
|     DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_SET_DRIVE_REPLY); | ||||
|     send_reply((struct any_frame*) &r); | ||||
| } | ||||
|     | ||||
|  | ||||
| static uint16_t read_output_voltage_mv(void) | ||||
| { | ||||
|     OUTPUT_VOLTAGE_ADC_StartConvert(); | ||||
|     OUTPUT_VOLTAGE_ADC_IsEndConversion(OUTPUT_VOLTAGE_ADC_WAIT_FOR_RESULT); | ||||
|     uint16_t samples = OUTPUT_VOLTAGE_ADC_GetResult16(); | ||||
|     return OUTPUT_VOLTAGE_ADC_CountsTo_mVolts(samples); | ||||
| } | ||||
|  | ||||
| static void read_output_voltages(struct voltages* v) | ||||
| { | ||||
|     SIDE_REG_Write(1); /* set DIR to low (remember this is inverted) */ | ||||
|     CyDelay(100); | ||||
|     v->logic0_mv = read_output_voltage_mv(); | ||||
|  | ||||
|     SIDE_REG_Write(0); | ||||
|     CyDelay(100); | ||||
|     v->logic1_mv = read_output_voltage_mv(); | ||||
| } | ||||
|  | ||||
| static uint16_t read_input_voltage_mv(void) | ||||
| { | ||||
|     INPUT_VOLTAGE_ADC_StartConvert(); | ||||
|     INPUT_VOLTAGE_ADC_IsEndConversion(INPUT_VOLTAGE_ADC_WAIT_FOR_RESULT); | ||||
|     uint16_t samples = INPUT_VOLTAGE_ADC_GetResult16(); | ||||
|     return INPUT_VOLTAGE_ADC_CountsTo_mVolts(samples); | ||||
| } | ||||
|  | ||||
| static void read_input_voltages(struct voltages* v) | ||||
| { | ||||
|     home(); | ||||
|     CyDelay(50); | ||||
|     v->logic0_mv = read_input_voltage_mv(); | ||||
|      | ||||
|     step(STEP_AWAYFROM0); | ||||
|     CyDelay(50); | ||||
|     v->logic1_mv = read_input_voltage_mv(); | ||||
| } | ||||
|  | ||||
| static void cmd_measure_voltages(void) | ||||
| { | ||||
|     stop_motor(); | ||||
|     INPUT_VOLTAGE_ADC_Start(); | ||||
|     INPUT_VOLTAGE_ADC_SetPower(INPUT_VOLTAGE_ADC__HIGHPOWER); | ||||
|     OUTPUT_VOLTAGE_ADC_Start(); | ||||
|     OUTPUT_VOLTAGE_ADC_SetPower(OUTPUT_VOLTAGE_ADC__HIGHPOWER); | ||||
|      | ||||
|     DECLARE_REPLY_FRAME(struct voltages_frame, F_FRAME_MEASURE_VOLTAGES_REPLY); | ||||
|      | ||||
|     CyWdtClear(); | ||||
|     MOTOR_REG_Write(0); /* should be ignored anyway */ | ||||
|     DRIVESELECT_REG_Write(0); /* deselect both drives */ | ||||
|     CyDelay(200); /* wait for things to settle */ | ||||
|     read_output_voltages(&r.output_both_off); | ||||
|     read_input_voltages(&r.input_both_off); | ||||
|  | ||||
|     CyWdtClear(); | ||||
|     DRIVESELECT_REG_Write(1); /* select drive 0 */ | ||||
|     CyDelay(50); | ||||
|     read_output_voltages(&r.output_drive_0_selected); | ||||
|     read_input_voltages(&r.input_drive_0_selected); | ||||
|     MOTOR_REG_Write(1); | ||||
|     CyDelay(300); | ||||
|     CyWdtClear(); | ||||
|     read_output_voltages(&r.output_drive_0_running); | ||||
|     read_input_voltages(&r.input_drive_0_running); | ||||
|     MOTOR_REG_Write(0); | ||||
|     CyDelay(300); | ||||
|      | ||||
|     CyWdtClear(); | ||||
|     DRIVESELECT_REG_Write(2); /* select drive 1 */ | ||||
|     CyDelay(50); | ||||
|     read_output_voltages(&r.output_drive_1_selected); | ||||
|     read_input_voltages(&r.input_drive_1_selected); | ||||
|     MOTOR_REG_Write(1); | ||||
|     CyDelay(300); | ||||
|     CyWdtClear(); | ||||
|     read_output_voltages(&r.output_drive_1_running); | ||||
|     read_input_voltages(&r.input_drive_1_running); | ||||
|     MOTOR_REG_Write(0); | ||||
|     CyDelay(300); | ||||
|  | ||||
|     CyWdtClear(); | ||||
|     DRIVESELECT_REG_Write(0); | ||||
|     homed = false; | ||||
|     INPUT_VOLTAGE_ADC_Stop(); | ||||
|     OUTPUT_VOLTAGE_ADC_Stop(); | ||||
|     send_reply((struct any_frame*) &r); | ||||
| } | ||||
|  | ||||
| static void handle_command(void) | ||||
| { | ||||
|     static uint8_t input_buffer[FRAME_SIZE]; | ||||
| @@ -636,11 +835,15 @@ 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_TEST_CMD: | ||||
|             cmd_bulk_test(f); | ||||
|         case F_FRAME_BULK_WRITE_TEST_CMD: | ||||
|             cmd_bulk_write_test(f); | ||||
|             break; | ||||
|              | ||||
|         case F_FRAME_BULK_READ_TEST_CMD: | ||||
|             cmd_bulk_read_test(f); | ||||
|             break; | ||||
|              | ||||
|         case F_FRAME_READ_CMD: | ||||
| @@ -662,28 +865,49 @@ static void handle_command(void) | ||||
|         case F_FRAME_SET_DRIVE_CMD: | ||||
|             cmd_set_drive((struct set_drive_frame*) f); | ||||
|             break; | ||||
|          | ||||
|         case F_FRAME_MEASURE_VOLTAGES_CMD: | ||||
|             cmd_measure_voltages(); | ||||
|             break; | ||||
|              | ||||
|         default: | ||||
|             send_error(F_ERROR_BAD_COMMAND); | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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; | ||||
|     CySysTickStart(); | ||||
|     CySysTickSetCallback(4, system_timer_cb); | ||||
|     INDEX_IRQ_StartEx(&index_irq_cb); | ||||
|     CAPTURE_DMA_FINISHED_IRQ_StartEx(&capture_dma_finished_irq_cb); | ||||
|     SAMPLER_DMA_FINISHED_IRQ_StartEx(&capture_dma_finished_irq_cb); | ||||
|     SEQUENCER_DMA_FINISHED_IRQ_StartEx(&replay_dma_finished_irq_cb); | ||||
|     DRIVE_REG_Write(0); | ||||
|     INPUT_VOLTAGE_ADC_Stop(); | ||||
|     OUTPUT_VOLTAGE_ADC_Stop(); | ||||
|     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); | ||||
|      | ||||
|     /* UART_PutString("GO\r"); */ | ||||
|  | ||||
|     for (;;) | ||||
|     { | ||||
|         CyWdtClear(); | ||||
| @@ -692,23 +916,21 @@ int main(void) | ||||
|         { | ||||
|             uint32_t time_on = clock - motor_on_time; | ||||
|             if (time_on > MOTOR_ON_TIME) | ||||
|             { | ||||
|                 MOTOR_REG_Write(0); | ||||
|                 motor_on = false; | ||||
|             } | ||||
|                 stop_motor(); | ||||
|         } | ||||
|          | ||||
|         if (!USBFS_GetConfiguration() || USBFS_IsConfigurationChanged()) | ||||
|         { | ||||
|             print("Waiting for USB..."); | ||||
|             while (!USBFS_GetConfiguration()) | ||||
|                 ; | ||||
|                 CyWdtClear(); | ||||
|             print("USB ready"); | ||||
|             USBFS_EnableOutEP(FLUXENGINE_CMD_OUT_EP_NUM); | ||||
|         } | ||||
|          | ||||
|         if (USBFS_GetEPState(FLUXENGINE_CMD_OUT_EP_NUM) == USBFS_OUT_BUFFER_FULL) | ||||
|         { | ||||
|             set_drive_flags(¤t_drive_flags); | ||||
|             handle_command(); | ||||
|             USBFS_EnableOutEP(FLUXENGINE_CMD_OUT_EP_NUM); | ||||
|             print("idle"); | ||||
|   | ||||
							
								
								
									
										44
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,33 +1,57 @@ | ||||
| PACKAGES = zlib sqlite3 libusb-1.0 | ||||
| PACKAGES = zlib sqlite3 libusb-1.0 protobuf | ||||
|  | ||||
| export CFLAGS = -O3 -g --std=c++14 \ | ||||
| 	-ffunction-sections -fdata-sections | ||||
| export LDFLAGS = -O3 | ||||
| export CFLAGS = -x c++ --std=c++14 -ffunction-sections -fdata-sections | ||||
| export LDFLAGS = -pthread | ||||
|  | ||||
| export COPTFLAGS = -Os | ||||
| export LDOPTFLAGS = -Os | ||||
|  | ||||
| export CDBGFLAGS = -O0 -g | ||||
| export LDDBGFLAGS = -O0 -g | ||||
|  | ||||
| ifeq ($(OS), Windows_NT) | ||||
| export PROTOC = /mingw32/bin/protoc | ||||
| export CXX = /mingw32/bin/g++ | ||||
| export AR = /mingw32/bin/ar rcs | ||||
| export AR = /mingw32/bin/ar rc | ||||
| export RANLIB = /mingw32/bin/ranlib | ||||
| export STRIP = /mingw32/bin/strip | ||||
| export CFLAGS += -I/mingw32/include/libusb-1.0 | ||||
| export CFLAGS += -I/mingw32/include/libusb-1.0 -I/mingw32/include | ||||
| export LDFLAGS += | ||||
| export LIBS = -static -lz -lsqlite3 -lusb-1.0 | ||||
| export LIBS += -L/mingw32/lib -static -lz -lsqlite3 -lusb-1.0 -lprotobuf | ||||
| export EXTENSION = .exe | ||||
| else | ||||
|  | ||||
| packages-exist = $(shell pkg-config --exists $(PACKAGES) && echo yes) | ||||
| ifneq ($(packages-exist),yes) | ||||
| $(warning These pkg-config packages are installed: $(shell pkg-config --list-all | sort | awk '{print $$1}')) | ||||
| $(error You must have these pkg-config packages installed: $(PACKAGES)) | ||||
| endif | ||||
|  | ||||
| export PROTOC = protoc | ||||
| export CXX = g++ | ||||
| export AR = ar rcs | ||||
| export AR = ar rc | ||||
| export RANLIB = ranlib | ||||
| export STRIP = strip | ||||
| export CFLAGS += $(shell pkg-config --cflags $(PACKAGES)) | ||||
| export LDFLAGS += | ||||
| export LIBS = $(shell pkg-config --libs $(PACKAGES)) | ||||
| export LIBS += $(shell pkg-config --libs $(PACKAGES)) | ||||
| export EXTENSION = | ||||
|  | ||||
| ifeq ($(shell uname),Darwin) | ||||
| AR = ar rcS | ||||
| RANLIB += -c -no_warning_for_no_symbols | ||||
| endif | ||||
|  | ||||
| endif | ||||
| export XXD = xxd | ||||
|  | ||||
| CFLAGS += -Ilib -Idep/fmt -Iarch | ||||
|  | ||||
| export OBJDIR = .obj | ||||
|  | ||||
| all: .obj/build.ninja | ||||
| 	@ninja -f .obj/build.ninja -v | ||||
| 	@ninja -f .obj/build.ninja | ||||
| 	@if command -v cscope > /dev/null; then cscope -bRq; fi | ||||
|  | ||||
| clean: | ||||
| 	@echo CLEAN | ||||
|   | ||||
							
								
								
									
										95
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										95
									
								
								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,22 +90,27 @@ people who've had it work). | ||||
|  | ||||
| ### Old disk formats | ||||
|  | ||||
| | Format                                   | Read? | Write? | Notes | | ||||
| |:-----------------------------------------|:-----:|:------:|-------| | ||||
| | IBM PC compatible                        |  🦄   |        | 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 | | ||||
| | [Kaypro II](doc/disk-ibm.md)              |  🦄   |   🦄   |                                     | | ||||
| | [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 | ||||
| IBM writer is completely generic, it should be configurable for these | ||||
| formats... theoretically. I don't have the hardware to try it. | ||||
|  | ||||
| ### Even older disk formats | ||||
|  | ||||
| These formats are for particularly old, weird architectures, even by the | ||||
| @@ -106,8 +124,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 | ||||
| @@ -191,6 +213,21 @@ 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. | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
							
								
								
									
										100
									
								
								arch/amiga/amiga.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								arch/amiga/amiga.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| #include "globals.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "amiga.h" | ||||
| #include "bytes.h" | ||||
| #include "fmt/format.h" | ||||
|  | ||||
| uint32_t amigaChecksum(const Bytes& bytes) | ||||
| { | ||||
|     ByteReader br(bytes); | ||||
|     uint32_t checksum = 0; | ||||
|  | ||||
|     assert((bytes.size() & 3) == 0); | ||||
|     while (!br.eof()) | ||||
|         checksum ^= br.read_be32(); | ||||
|  | ||||
|     return checksum & 0x55555555; | ||||
| } | ||||
|  | ||||
| static uint8_t everyother(uint16_t x) | ||||
| { | ||||
| 	                  /* aabb ccdd eeff gghh */ | ||||
| 	x &= 0x6666;      /* 0ab0 0cd0 0ef0 0gh0 */ | ||||
| 	x >>= 1;          /* 00ab 00cd 00ef 00gh */ | ||||
| 	x |= x << 2;      /* abab cdcd efef ghgh */ | ||||
| 	x &= 0x3c3c;      /* 00ab cd00 00ef gh00 */ | ||||
| 	x >>= 2;          /* 0000 abcd 0000 efgh */ | ||||
| 	x |= x >> 4;      /* 0000 abcd abcd efgh */ | ||||
| 	return x; | ||||
| } | ||||
|  | ||||
| Bytes amigaInterleave(const Bytes& input) | ||||
| { | ||||
| 	Bytes output; | ||||
| 	ByteWriter bw(output); | ||||
|  | ||||
| 	/* Write all odd bits. (Numbering starts at 0...) */ | ||||
|  | ||||
| 	{ | ||||
| 		ByteReader br(input); | ||||
| 		while (!br.eof()) | ||||
| 		{ | ||||
| 			uint16_t x = br.read_be16(); | ||||
| 			x &= 0xaaaa;       /* a0b0 c0d0 e0f0 g0h0 */ | ||||
| 			x |= x >> 1;       /* aabb ccdd eeff gghh */ | ||||
| 			x = everyother(x); /* 0000 0000 abcd efgh */ | ||||
| 			bw.write_8(x); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* Write all even bits. */ | ||||
|  | ||||
| 	{ | ||||
| 		ByteReader br(input); | ||||
| 		while (!br.eof()) | ||||
| 		{ | ||||
| 			uint16_t x = br.read_be16(); | ||||
| 			x &= 0x5555;       /* 0a0b 0c0d 0e0f 0g0h */ | ||||
| 			x |= x << 1;       /* aabb ccdd eeff gghh */ | ||||
| 			x = everyother(x); /* 0000 0000 abcd efgh */ | ||||
| 			bw.write_8(x); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return output; | ||||
| } | ||||
|  | ||||
| Bytes amigaDeinterleave(const uint8_t*& input, size_t len) | ||||
| { | ||||
|     assert(!(len & 1)); | ||||
|     const uint8_t* odds = &input[0]; | ||||
|     const uint8_t* evens = &input[len/2]; | ||||
|     Bytes output; | ||||
|     ByteWriter bw(output); | ||||
|  | ||||
|     for (size_t i=0; i<len/2; i++) | ||||
|     { | ||||
|         uint8_t o = *odds++; | ||||
|         uint8_t e = *evens++; | ||||
|  | ||||
|         /* This is the 'Interleave bits with 64-bit multiply' technique from | ||||
|          * http://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN | ||||
|          */ | ||||
|         uint16_t result = | ||||
|             (((e * 0x0101010101010101ULL & 0x8040201008040201ULL) | ||||
|                 * 0x0102040810204081ULL >> 49) & 0x5555) | | ||||
|             (((o * 0x0101010101010101ULL & 0x8040201008040201ULL) | ||||
|                 * 0x0102040810204081ULL >> 48) & 0xAAAA); | ||||
|          | ||||
|         bw.write_be16(result); | ||||
|     } | ||||
|  | ||||
|     input += len; | ||||
|     return output; | ||||
| } | ||||
|  | ||||
| Bytes amigaDeinterleave(const Bytes& input) | ||||
| { | ||||
| 	const uint8_t* ptr = input.cbegin(); | ||||
| 	return amigaDeinterleave(ptr, input.size()); | ||||
| } | ||||
| @@ -1,20 +1,20 @@ | ||||
| #ifndef AMIGA_H | ||||
| #define AMIGA_H | ||||
|  | ||||
| #include "encoders/encoders.h" | ||||
|  | ||||
| #define AMIGA_SECTOR_RECORD 0xaaaa44894489LL | ||||
|  | ||||
| #define AMIGA_TRACKS_PER_DISK 80 | ||||
| #define AMIGA_SECTORS_PER_TRACK 11 | ||||
| #define AMIGA_RECORD_SIZE 0x21f | ||||
|  | ||||
| class Sector; | ||||
| class Fluxmap; | ||||
| extern std::unique_ptr<AbstractDecoder> createAmigaDecoder(const DecoderProto& config); | ||||
| extern std::unique_ptr<AbstractEncoder> createAmigaEncoder(const EncoderProto& config); | ||||
|  | ||||
| class AmigaDecoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
|     virtual ~AmigaDecoder() {} | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
|     void decodeSectorRecord(); | ||||
| }; | ||||
| extern uint32_t amigaChecksum(const Bytes& bytes); | ||||
| extern Bytes amigaInterleave(const Bytes& input); | ||||
| extern Bytes amigaDeinterleave(const uint8_t*& input, size_t len); | ||||
| extern Bytes amigaDeinterleave(const Bytes& input); | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										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,13 @@ | ||||
| #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 "lib/data.pb.h" | ||||
| #include <string.h> | ||||
| #include <algorithm> | ||||
|  | ||||
| @@ -21,79 +22,65 @@ | ||||
|           | ||||
| static const FluxPattern SECTOR_PATTERN(48, AMIGA_SECTOR_RECORD); | ||||
|  | ||||
| static Bytes deinterleave(const uint8_t*& input, size_t len) | ||||
| class AmigaDecoder : public AbstractDecoder | ||||
| { | ||||
|     assert(!(len & 1)); | ||||
|     const uint8_t* odds = &input[0]; | ||||
|     const uint8_t* evens = &input[len/2]; | ||||
|     Bytes output; | ||||
|     ByteWriter bw(output); | ||||
| public: | ||||
| 	AmigaDecoder(const DecoderProto& config): | ||||
| 		AbstractDecoder(config), | ||||
| 		_config(config.amiga()) | ||||
| 	{} | ||||
|  | ||||
|     for (size_t i=0; i<len/2; i++) | ||||
|     { | ||||
|         uint8_t o = *odds++; | ||||
|         uint8_t e = *evens++; | ||||
|     RecordType advanceToNextRecord() | ||||
| 	{ | ||||
| 		_sector->clock = _fmr->seekToPattern(SECTOR_PATTERN); | ||||
| 		if (_fmr->eof() || !_sector->clock) | ||||
| 			return UNKNOWN_RECORD; | ||||
| 		return SECTOR_RECORD; | ||||
| 	} | ||||
|  | ||||
|         /* This is the 'Interleave bits with 64-bit multiply' technique from | ||||
|          * http://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN | ||||
|          */ | ||||
|         uint16_t result = | ||||
|             (((e * 0x0101010101010101ULL & 0x8040201008040201ULL) | ||||
|                 * 0x0102040810204081ULL >> 49) & 0x5555) | | ||||
|             (((o * 0x0101010101010101ULL & 0x8040201008040201ULL) | ||||
|                 * 0x0102040810204081ULL >> 48) & 0xAAAA); | ||||
|          | ||||
|         bw.write_be16(result); | ||||
|     } | ||||
|     void decodeSectorRecord() | ||||
| 	{ | ||||
| 		const auto& rawbits = readRawBits(AMIGA_RECORD_SIZE*16); | ||||
| 		if (rawbits.size() < (AMIGA_RECORD_SIZE*16)) | ||||
| 			return; | ||||
| 		const auto& rawbytes = toBytes(rawbits).slice(0, AMIGA_RECORD_SIZE*2); | ||||
| 		const auto& bytes = decodeFmMfm(rawbits).slice(0, AMIGA_RECORD_SIZE); | ||||
|  | ||||
|     input += len; | ||||
|     return output; | ||||
| 		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)); | ||||
| } | ||||
|  | ||||
| static uint32_t checksum(const Bytes& bytes) | ||||
| { | ||||
|     ByteReader br(bytes); | ||||
|     uint32_t checksum = 0; | ||||
|  | ||||
|     assert((bytes.size() & 3) == 0); | ||||
|     while (!br.eof()) | ||||
|         checksum ^= br.read_be32(); | ||||
|  | ||||
|     return checksum & 0x55555555; | ||||
| } | ||||
|  | ||||
| AbstractDecoder::RecordType AmigaDecoder::advanceToNextRecord() | ||||
| { | ||||
|     _sector->clock = _fmr->seekToPattern(SECTOR_PATTERN); | ||||
|     if (_fmr->eof() || !_sector->clock) | ||||
|         return UNKNOWN_RECORD; | ||||
|     return SECTOR_RECORD; | ||||
| } | ||||
|  | ||||
| void AmigaDecoder::decodeSectorRecord() | ||||
| { | ||||
|     const auto& rawbits = readRawBits(AMIGA_RECORD_SIZE*16); | ||||
|     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 = deinterleave(ptr, 4); | ||||
|     Bytes recoveryinfo = deinterleave(ptr, 16); | ||||
|  | ||||
|     _sector->logicalTrack = header[1] >> 1; | ||||
|     _sector->logicalSide = header[1] & 1; | ||||
|     _sector->logicalSector = header[2]; | ||||
|  | ||||
|     uint32_t wantedheaderchecksum = deinterleave(ptr, 4).reader().read_be32(); | ||||
|     uint32_t gotheaderchecksum = checksum(rawbytes.slice(6, 40)); | ||||
|     if (gotheaderchecksum != wantedheaderchecksum) | ||||
|         return; | ||||
|  | ||||
|     uint32_t wanteddatachecksum = deinterleave(ptr, 4).reader().read_be32(); | ||||
|     uint32_t gotdatachecksum = checksum(rawbytes.slice(62, 1024)); | ||||
|  | ||||
|     _sector->data.clear(); | ||||
|     _sector->data.writer().append(deinterleave(ptr, 512)).append(recoveryinfo); | ||||
|     _sector->status = (gotdatachecksum == wanteddatachecksum) ? Sector::OK : Sector::BAD_CHECKSUM; | ||||
| } | ||||
|   | ||||
							
								
								
									
										162
									
								
								arch/amiga/encoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								arch/amiga/encoder.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | ||||
| #include "globals.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
| #include "amiga.h" | ||||
| #include "crc.h" | ||||
| #include "writer.h" | ||||
| #include "image.h" | ||||
| #include "arch/amiga/amiga.pb.h" | ||||
| #include "lib/encoders/encoders.pb.h" | ||||
|  | ||||
| static bool lastBit; | ||||
|  | ||||
| static int charToInt(char c) | ||||
| { | ||||
| 	if (isdigit(c)) | ||||
| 		return c - '0'; | ||||
| 	return 10 + tolower(c) - 'a'; | ||||
| } | ||||
|  | ||||
| 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 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); | ||||
|  | ||||
| 	checksum = 0; | ||||
| 	Bytes header =  | ||||
| 		{ | ||||
| 			0xff, /* Amiga 1.0 format byte */ | ||||
| 			(uint8_t) ((sector->logicalTrack<<1) | sector->logicalSide), | ||||
| 			(uint8_t) sector->logicalSector, | ||||
| 			(uint8_t) (AMIGA_SECTORS_PER_TRACK - sector->logicalSector) | ||||
| 		}; | ||||
| 	write_interleaved_bytes(header); | ||||
| 	Bytes recoveryInfo(16); | ||||
| 	if (sector->data.size() == 528) | ||||
| 		recoveryInfo = sector->data.slice(512, 16); | ||||
| 	write_interleaved_bytes(recoveryInfo); | ||||
| 	write_interleaved_word(checksum); | ||||
|  | ||||
| 	Bytes data = sector->data.slice(0, 512); | ||||
| 	write_interleaved_word(amigaChecksum(encodeMfm(amigaInterleave(data), lastBit))); | ||||
| 	write_interleaved_bytes(data); | ||||
| } | ||||
|  | ||||
| class AmigaEncoder : public AbstractEncoder | ||||
| { | ||||
| public: | ||||
| 	AmigaEncoder(const EncoderProto& config): | ||||
| 		AbstractEncoder(config), | ||||
| 		_config(config.amiga()) {} | ||||
|  | ||||
| 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 < 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); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		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) | ||||
| 	{ | ||||
| 		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) | ||||
|     { | ||||
|         /* 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: | ||||
| @@ -73,8 +74,10 @@ const FluxPattern FM_TRS80DAM2_PATTERN(16, 0xf56c); | ||||
|  * encoding (you can't do 10 00). So this can't be spoofed by user data. | ||||
|  *  | ||||
|  * shifted: 10 00 10 01 00 01 00 1 | ||||
|  *  | ||||
|  * It's repeated three times. | ||||
|  */ | ||||
| const FluxPattern MFM_PATTERN(16, 0x4489); | ||||
| const FluxPattern MFM_PATTERN(48, 0x448944894489LL); | ||||
|  | ||||
| const FluxMatchers ANY_RECORD_PATTERN( | ||||
|     { | ||||
| @@ -87,70 +90,101 @@ 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() | ||||
| 	{ | ||||
| 		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); | ||||
|     uint8_t id = decodeFmMfm(idbits).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(); | ||||
| 		if (_currentHeaderLength > 0) | ||||
| 			readRawBits(_currentHeaderLength*16); | ||||
| 		auto idbits = readRawBits(16); | ||||
| 		const Bytes idbytes = decodeFmMfm(idbits); | ||||
| 		uint8_t id = idbytes.slice(0, 1)[0]; | ||||
| 		seek(here); | ||||
| 		 | ||||
| 		switch (id) | ||||
| 		{ | ||||
| 			case IBM_IDAM: | ||||
| 				return RecordType::SECTOR_RECORD; | ||||
|  | ||||
| 			case IBM_DAM1: | ||||
| 			case IBM_DAM2: | ||||
| 			case IBM_TRS80DAM1: | ||||
| 			case IBM_TRS80DAM2: | ||||
| 				return RecordType::DATA_RECORD; | ||||
| 		} | ||||
| 		return RecordType::UNKNOWN_RECORD; | ||||
| 	} | ||||
|  | ||||
|     void decodeSectorRecord() | ||||
| 	{ | ||||
| 		unsigned recordSize = _currentHeaderLength + IBM_IDAM_LEN; | ||||
| 		auto bits = readRawBits(recordSize*16); | ||||
| 		auto bytes = decodeFmMfm(bits).slice(0, recordSize); | ||||
|  | ||||
| 		ByteReader br(bytes); | ||||
| 		br.seek(_currentHeaderLength); | ||||
| 		br.read_8(); /* skip ID byte */ | ||||
| 		_sector->logicalTrack = br.read_8(); | ||||
| 		_sector->logicalSide = br.read_8(); | ||||
| 		_sector->logicalSector = br.read_8(); | ||||
| 		_currentSectorSize = 1 << (br.read_8() + 7); | ||||
| 		uint16_t wantCrc = br.read_be16(); | ||||
| 		uint16_t gotCrc = crc16(CCITT_POLY, bytes.slice(0, _currentHeaderLength + 5)); | ||||
| 		if (wantCrc == gotCrc) | ||||
| 			_sector->status = Sector::DATA_MISSING; /* correct but unintuitive */ | ||||
|  | ||||
| 		if (_config.swap_sides()) | ||||
| 			_sector->logicalSide ^= 1; | ||||
| 		if (_config.ignore_side_byte()) | ||||
| 			_sector->logicalSide = _sector->physicalHead; | ||||
| 	} | ||||
|  | ||||
|     void 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; | ||||
| 	} | ||||
|  | ||||
| 	std::set<unsigned> requiredSectors(unsigned cylinder, unsigned head) const override | ||||
| 	{ | ||||
| 		std::set<unsigned> s; | ||||
| 		for (int sectorId : _config.sectors().sector()) | ||||
| 			s.insert(sectorId); | ||||
| 		return s; | ||||
| 	} | ||||
|  | ||||
| private: | ||||
| 	const IbmDecoderProto& _config; | ||||
|     unsigned _currentSectorSize; | ||||
|     unsigned _currentHeaderLength; | ||||
| }; | ||||
|  | ||||
| std::unique_ptr<AbstractDecoder> createIbmDecoder(const DecoderProto& config) | ||||
| { | ||||
| 	return std::unique_ptr<AbstractDecoder>(new IbmDecoder(config)); | ||||
| } | ||||
|  | ||||
| void IbmDecoder::decodeSectorRecord() | ||||
| { | ||||
|     unsigned recordSize = _currentHeaderLength + IBM_IDAM_LEN; | ||||
|     auto bits = readRawBits(recordSize*16); | ||||
|     auto bytes = decodeFmMfm(bits).slice(0, recordSize); | ||||
|  | ||||
|     ByteReader br(bytes); | ||||
|     br.seek(_currentHeaderLength); | ||||
|     br.read_8(); /* skip ID byte */ | ||||
|     _sector->logicalTrack = br.read_8(); | ||||
|     _sector->logicalSide = br.read_8(); | ||||
|     _sector->logicalSector = br.read_8() - _sectorBase; | ||||
|     _currentSectorSize = 1 << (br.read_8() + 7); | ||||
|     uint16_t wantCrc = br.read_be16(); | ||||
|     uint16_t gotCrc = crc16(CCITT_POLY, bytes.slice(0, _currentHeaderLength + 5)); | ||||
|     if (wantCrc == gotCrc) | ||||
|         _sector->status = Sector::DATA_MISSING; /* correct but unintuitive */ | ||||
|  | ||||
|     if (_ignoreSideByte) | ||||
|         _sector->logicalSide = _sector->physicalSide; | ||||
| } | ||||
|  | ||||
| void IbmDecoder::decodeDataRecord() | ||||
| { | ||||
|     unsigned recordLength = _currentHeaderLength + _currentSectorSize + 3; | ||||
|     auto bits = readRawBits(recordLength*16); | ||||
|     auto bytes = decodeFmMfm(bits).slice(0, recordLength); | ||||
|  | ||||
|     ByteReader br(bytes); | ||||
|     br.seek(_currentHeaderLength); | ||||
|     br.read_8(); /* skip ID byte */ | ||||
|  | ||||
|     _sector->data = br.read(_currentSectorSize); | ||||
|     uint16_t wantCrc = br.read_be16(); | ||||
|     uint16_t gotCrc = crc16(CCITT_POLY, bytes.slice(0, recordLength-2)); | ||||
|     _sector->status = (wantCrc == gotCrc) ? Sector::OK : Sector::BAD_CHECKSUM; | ||||
| } | ||||
|   | ||||
							
								
								
									
										289
									
								
								arch/ibm/encoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								arch/ibm/encoder.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,289 @@ | ||||
| #include "globals.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
| #include "ibm.h" | ||||
| #include "crc.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> | ||||
|  | ||||
| /* IAM record separator: | ||||
|  * 0xC2 is: | ||||
|  * data:    1  1  0  0  0  0  1  0  = 0xc2 | ||||
|  * mfm:     01 01 00 10 10 10 01 00 = 0x5254 | ||||
|  * special: 01 01 00 10 00 10 01 00 = 0x5224 | ||||
|  */ | ||||
| #define MFM_IAM_SEPARATOR 0x5224 | ||||
|  | ||||
| /* FM IAM record: | ||||
|  * flux:   XXXX-XXX-XXXX-X- = 0xf77a | ||||
|  * clock:  X X - X - X X X  = 0xd7 | ||||
|  * data:    X X X X X X - - = 0xfc | ||||
|  */ | ||||
| #define FM_IAM_RECORD 0xf77a | ||||
|  | ||||
| /* MFM IAM record: | ||||
|  * data:   1  1  1  1  1  1  0  0  = 0xfc | ||||
|  * flux:   01 01 01 01 01 01 00 10 = 0x5552 | ||||
|  */ | ||||
| #define MFM_IAM_RECORD 0x5552 | ||||
|  | ||||
| /* MFM record separator: | ||||
|  * 0xA1 is: | ||||
|  * data:    1  0  1  0  0  0  0  1  = 0xa1 | ||||
|  * mfm:     01 00 01 00 10 10 10 01 = 0x44a9 | ||||
|  * special: 01 00 01 00 10 00 10 01 = 0x4489 | ||||
|  *                       ^^^^^ | ||||
|  * 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. | ||||
|  *  | ||||
|  * shifted: 10 00 10 01 00 01 00 1 | ||||
|  *  | ||||
|  * It's repeated three times. | ||||
|  */ | ||||
| #define MFM_RECORD_SEPARATOR 0x4489 | ||||
| #define MFM_RECORD_SEPARATOR_BYTE 0xa1 | ||||
|  | ||||
| /* MFM IDAM byte: | ||||
|  * data:    1  1  1  1  1  1  1  0  = 0xfe | ||||
|  * mfm:     01 01 01 01 01 01 01 00 = 0x5554 | ||||
|  */ | ||||
|  | ||||
| /* MFM DAM byte: | ||||
|  * data:    1  1  1  1  1  0  1  1  = 0xfb | ||||
|  * mfm:     01 01 01 01 01 00 01 01 = 0x5545 | ||||
|  */ | ||||
|  | ||||
| static uint8_t decodeUint16(uint16_t raw) | ||||
| { | ||||
| 	Bytes b; | ||||
| 	ByteWriter bw(b); | ||||
| 	bw.write_be16(raw); | ||||
| 	return decodeFmMfm(b.toBits())[0]; | ||||
| } | ||||
|  | ||||
| class IbmEncoder : public AbstractEncoder | ||||
| { | ||||
| public: | ||||
| 	IbmEncoder(const EncoderProto& config): | ||||
| 		AbstractEncoder(config), | ||||
| 		_config(config.ibm()) | ||||
| 	{} | ||||
|  | ||||
| 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 getTrackFormat(IbmEncoderProto::TrackdataProto& trackdata, unsigned cylinder, unsigned head) | ||||
| 	{ | ||||
| 		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); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 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 : trackdata.sectors().sector()) | ||||
|         { | ||||
| 			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 writeFillerBytes = [&](int count, uint8_t byte) | ||||
| 		{ | ||||
| 			Bytes bytes = { byte }; | ||||
| 			for (int i=0; i<count; i++) | ||||
| 				writeBytes(bytes); | ||||
| 		}; | ||||
|  | ||||
| 		double clockRateUs = 1e3 / trackdata.clock_rate_khz(); | ||||
| 		if (!trackdata.use_fm()) | ||||
| 			clockRateUs /= 2.0; | ||||
| 		int bitsPerRevolution = (trackdata.track_length_ms() * 1000.0) / clockRateUs; | ||||
| 		_bits.resize(bitsPerRevolution*2); | ||||
| 		_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) | ||||
| 			{ | ||||
| 				s >>= 1; | ||||
| 				sectorSize += 1; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		uint8_t gapFill = trackdata.use_fm() ? 0x00 : 0x4e; | ||||
|  | ||||
| 		writeFillerBytes(trackdata.gap0(), gapFill); | ||||
| 		if (trackdata.emit_iam()) | ||||
| 		{ | ||||
| 			writeFillerBytes(trackdata.use_fm() ? 6 : 12, 0x00); | ||||
| 			if (!trackdata.use_fm()) | ||||
| 			{ | ||||
| 				for (int i=0; i<3; i++) | ||||
| 					writeRawBits(MFM_IAM_SEPARATOR, 16); | ||||
| 			} | ||||
| 			writeRawBits(trackdata.use_fm() ? FM_IAM_RECORD : MFM_IAM_RECORD, 16); | ||||
| 			writeFillerBytes(trackdata.gap1(), gapFill); | ||||
| 		} | ||||
|  | ||||
| 		int logicalSide = physicalSide ^ trackdata.swap_sides(); | ||||
| 		bool first = true; | ||||
| 		for (int sectorId : trackdata.sectors().sector()) | ||||
| 		{ | ||||
| 			if (!first) | ||||
| 				writeFillerBytes(trackdata.gap3(), gapFill); | ||||
| 			first = false; | ||||
|  | ||||
| 			const auto& sectorData = image.get(physicalTrack, logicalSide, sectorId); | ||||
| 			if (!sectorData) | ||||
| 				continue; | ||||
|  | ||||
| 			/* Writing the sector and data records are fantastically annoying. | ||||
| 			 * The CRC is calculated from the *very start* of the record, and | ||||
| 			 * include the malformed marker bytes. Our encoder doesn't know | ||||
| 			 * about this, of course, with the result that we have to construct | ||||
| 			 * the unencoded header, calculate the checksum, and then use the | ||||
| 			 * same logic to emit the bytes which require special encoding | ||||
| 			 * before encoding the rest of the header normally. */ | ||||
|  | ||||
| 			{ | ||||
| 				Bytes header; | ||||
| 				ByteWriter bw(header); | ||||
|  | ||||
| 				writeFillerBytes(trackdata.use_fm() ? 6 : 12, 0x00); | ||||
| 				if (!trackdata.use_fm()) | ||||
| 				{ | ||||
| 					for (int i=0; i<3; i++) | ||||
| 						bw.write_8(MFM_RECORD_SEPARATOR_BYTE); | ||||
| 				} | ||||
| 				bw.write_8(idamUnencoded); | ||||
| 				bw.write_8(sectorData->logicalTrack); | ||||
| 				bw.write_8(sectorData->logicalSide); | ||||
| 				bw.write_8(sectorData->logicalSector); | ||||
| 				bw.write_8(sectorSize); | ||||
| 				uint16_t crc = crc16(CCITT_POLY, header); | ||||
| 				bw.write_be16(crc); | ||||
|  | ||||
| 				int conventionalHeaderStart = 0; | ||||
| 				if (!trackdata.use_fm()) | ||||
| 				{ | ||||
| 					for (int i=0; i<3; i++) | ||||
| 						writeRawBits(MFM_RECORD_SEPARATOR, 16); | ||||
| 					conventionalHeaderStart += 3; | ||||
|  | ||||
| 				} | ||||
| 				writeRawBits(trackdata.idam_byte(), 16); | ||||
| 				conventionalHeaderStart += 1; | ||||
|  | ||||
| 				writeBytes(header.slice(conventionalHeaderStart)); | ||||
| 			} | ||||
|  | ||||
| 			writeFillerBytes(trackdata.gap2(), gapFill); | ||||
|  | ||||
| 			{ | ||||
| 				Bytes data; | ||||
| 				ByteWriter bw(data); | ||||
|  | ||||
| 				writeFillerBytes(trackdata.use_fm() ? 6 : 12, 0x00); | ||||
| 				if (!trackdata.use_fm()) | ||||
| 				{ | ||||
| 					for (int i=0; i<3; i++) | ||||
| 						bw.write_8(MFM_RECORD_SEPARATOR_BYTE); | ||||
| 				} | ||||
| 				bw.write_8(damUnencoded); | ||||
|  | ||||
| 				Bytes truncatedData = sectorData->data.slice(0, trackdata.sector_size()); | ||||
| 				bw += truncatedData; | ||||
| 				uint16_t crc = crc16(CCITT_POLY, data); | ||||
| 				bw.write_be16(crc); | ||||
|  | ||||
| 				int conventionalHeaderStart = 0; | ||||
| 				if (!trackdata.use_fm()) | ||||
| 				{ | ||||
| 					for (int i=0; i<3; i++) | ||||
| 						writeRawBits(MFM_RECORD_SEPARATOR, 16); | ||||
| 					conventionalHeaderStart += 3; | ||||
|  | ||||
| 				} | ||||
| 				writeRawBits(trackdata.dam_byte(), 16); | ||||
| 				conventionalHeaderStart += 1; | ||||
|  | ||||
| 				writeBytes(data.slice(conventionalHeaderStart)); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (_cursor >= bitsPerRevolution) | ||||
| 			Error() << fmt::format("track data overrun by {} bits ({:.3} ms)", | ||||
| 					_cursor - bitsPerRevolution, | ||||
| 					(_cursor - bitsPerRevolution) / (clockRateUs*1000.0)); | ||||
| 		while (_cursor < _bits.size()) | ||||
| 			writeFillerBytes(1, gapFill); | ||||
|  | ||||
| 		std::unique_ptr<Fluxmap> fluxmap(new Fluxmap); | ||||
| 		_bits.resize(bitsPerRevolution); | ||||
| 		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,8 +1,6 @@ | ||||
| #ifndef IBM_H | ||||
| #define IBM_H | ||||
|  | ||||
| #include "decoders/decoders.h" | ||||
|  | ||||
| /* IBM format (i.e. ordinary PC floppies). */ | ||||
|  | ||||
| #define IBM_MFM_SYNC   0xA1   /* sync byte for MFM */ | ||||
| @@ -28,71 +26,12 @@ struct IbmIdam | ||||
|     uint8_t crc[2]; | ||||
| }; | ||||
|  | ||||
| class IbmDecoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
|     IbmDecoder(unsigned sectorBase, bool ignoreSideByte=false): | ||||
|         _sectorBase(sectorBase), | ||||
|         _ignoreSideByte(ignoreSideByte) | ||||
|     {} | ||||
| class AbstractEncoder; | ||||
| class AbstractDecoder; | ||||
| class DecoderProto; | ||||
| class EncoderProto; | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
|     void decodeSectorRecord(); | ||||
|     void decodeDataRecord(); | ||||
|  | ||||
| private: | ||||
|     unsigned _sectorBase; | ||||
|     bool _ignoreSideByte; | ||||
|     unsigned _currentSectorSize; | ||||
|     unsigned _currentHeaderLength; | ||||
| }; | ||||
|  | ||||
| #if 0 | ||||
| class AbstractIbmDecoder : public AbstractSoftSectorDecoder | ||||
| { | ||||
| public: | ||||
|     AbstractIbmDecoder(unsigned sectorIdBase): | ||||
|         _sectorIdBase(sectorIdBase) | ||||
|     {} | ||||
|     virtual ~AbstractIbmDecoder() {} | ||||
|  | ||||
|     SectorVector decodeToSectors(const RawRecordVector& rawRecords, unsigned physicalTrack, unsigned physicalSide); | ||||
|  | ||||
| protected: | ||||
|     virtual int skipHeaderBytes() const = 0; | ||||
|  | ||||
| private: | ||||
|     unsigned _sectorIdBase; | ||||
| }; | ||||
|  | ||||
| class IbmFmDecoder : public AbstractIbmDecoder | ||||
| { | ||||
| public: | ||||
|     IbmFmDecoder(unsigned sectorIdBase): | ||||
|         AbstractIbmDecoder(sectorIdBase) | ||||
|     {} | ||||
|  | ||||
|     int recordMatcher(uint64_t fifo) const; | ||||
|  | ||||
| protected: | ||||
|     int skipHeaderBytes() const | ||||
|     { return 0; } | ||||
| }; | ||||
|  | ||||
| class IbmMfmDecoder : public AbstractIbmDecoder | ||||
| { | ||||
| public: | ||||
|     IbmMfmDecoder(unsigned sectorIdBase): | ||||
|         AbstractIbmDecoder(sectorIdBase) | ||||
|     {} | ||||
|  | ||||
|     nanoseconds_t guessClock(Fluxmap& fluxmap) const; | ||||
|     int recordMatcher(uint64_t fifo) const; | ||||
|  | ||||
| protected: | ||||
|     int skipHeaderBytes() const | ||||
|     { return 3; } | ||||
| }; | ||||
| #endif | ||||
| extern std::unique_ptr<AbstractDecoder> createIbmDecoder(const DecoderProto& config); | ||||
| extern std::unique_ptr<AbstractEncoder> createIbmEncoder(const EncoderProto& config); | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										43
									
								
								arch/ibm/ibm.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								arch/ibm/ibm.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| import "lib/common.proto"; | ||||
|  | ||||
| // Next: 6 | ||||
| message IbmDecoderProto { | ||||
| 	message SectorsProto { | ||||
| 		repeated int32 sector = 1            [(help) = "require these sectors to exist for a good read"]; | ||||
| 	} | ||||
|  | ||||
| 	optional bool ignore_side_byte = 2       [default = false, (help) = "ignore side byte in sector header"]; | ||||
| 	optional bool swap_sides = 4             [default = false, (help) = "put logical side 1 on physical side 0"]; | ||||
| 	optional SectorsProto sectors = 5        [(help) = "require these sectors to exist for a good read"]; | ||||
| } | ||||
|  | ||||
| message IbmEncoderProto { | ||||
| 	// Next: 18 | ||||
| 	message TrackdataProto { | ||||
| 		message SectorsProto { | ||||
| 			repeated int32 sector = 1		[(help) = "write these sectors (in order) on each track"]; | ||||
| 		} | ||||
|  | ||||
| 		optional int32 cylinder = 15        [(help) = "if set, the format applies only to this track"]; | ||||
| 		optional int32 head = 16            [(help) = "if set, the format applies only to this head"]; | ||||
|  | ||||
| 		optional double track_length_ms = 1 [(help) = "length of track"]; | ||||
| 		optional int32 sector_size = 2      [default=512, (help) = "number of bytes per sector"]; | ||||
| 		optional bool emit_iam = 3          [default=true, (help) = "whether to emit an IAM record"]; | ||||
| 		optional double clock_rate_khz = 5  [(help) = "data clock rate"]; | ||||
| 		optional bool use_fm = 6            [default=false, (help) = "whether to use FM encoding rather than MFM"]; | ||||
| 		optional int32 idam_byte = 7        [default=0x5554, (help) = "16-bit raw bit pattern of IDAM byte"]; | ||||
| 		optional int32 dam_byte = 8         [default=0x5545, (help) = "16-bit raw bit pattern of DAM byte"]; | ||||
| 		optional int32 gap0 = 9             [default=80, (help) = "size of gap 1 (the post-index gap)"]; | ||||
| 		optional int32 gap1 = 10            [default=50, (help) = "size of gap 2 (the post-ID gap)"]; | ||||
| 		optional int32 gap2 = 11            [default=22, (help) = "size of gap 3 (the pre-data gap)"]; | ||||
| 		optional int32 gap3 = 12            [default=80, (help) = "size of gap 4 (the post-data or format gap)"]; | ||||
| 		optional bool swap_sides = 14       [default=false, (help) = "swap side bytes when writing"]; | ||||
| 		optional SectorsProto sectors = 17	[(help) = "write these sectors (in order) on each track"]; | ||||
| 	} | ||||
|  | ||||
| 	repeated TrackdataProto trackdata = 1; | ||||
| } | ||||
|  | ||||
| @@ -2,10 +2,8 @@ | ||||
| #include "fluxmap.h" | ||||
| #include "decoders/fluxmapreader.h" | ||||
| #include "protocol.h" | ||||
| #include "record.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "sector.h" | ||||
| #include "track.h" | ||||
| #include "macintosh.h" | ||||
| #include "bytes.h" | ||||
| #include "fmt/format.h" | ||||
| @@ -26,7 +24,7 @@ static int decode_data_gcr(uint8_t gcr) | ||||
| 		#undef GCR_ENTRY | ||||
|     } | ||||
|     return -1; | ||||
| }; | ||||
| } | ||||
|  | ||||
| /* This is extremely inspired by the MESS implementation, written by Nathan Woods | ||||
|  * and R. Belmont: https://github.com/mamedev/mame/blob/4263a71e64377db11392c458b580c5ae83556bc7/src/lib/formats/ap_dsk35.cpp | ||||
| @@ -118,69 +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)); | ||||
| } | ||||
|   | ||||
							
								
								
									
										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,19 +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(); | ||||
| }; | ||||
| 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. */ | ||||
| static uint8_t checksum(const Bytes& bytes) { | ||||
| 	ByteReader br(bytes); | ||||
| 	uint16_t sum = 0; | ||||
| 	while (!br.eof()) { | ||||
| 		if (sum > 0xFF) { | ||||
| 			sum -= 0x100 - 1; | ||||
| 		} | ||||
| 		sum += br.read_8(); | ||||
| 	} | ||||
| 	/* The last carry is ignored */ | ||||
| 	return sum & 0xFF; | ||||
| } | ||||
|  | ||||
| class MicropolisDecoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	MicropolisDecoder(const DecoderProto& config): | ||||
| 		AbstractDecoder(config) | ||||
| 	{} | ||||
|  | ||||
| 	RecordType advanceToNextRecord() | ||||
| 	{ | ||||
| 		_fmr->seekToIndexMark(); | ||||
| 		const FluxMatcher* matcher = nullptr; | ||||
| 		_sector->clock = _fmr->seekToPattern(SECTOR_SYNC_PATTERN, matcher); | ||||
| 		if (matcher == &SECTOR_SYNC_PATTERN) { | ||||
| 			readRawBits(16); | ||||
| 			return SECTOR_RECORD; | ||||
| 		} | ||||
| 		return UNKNOWN_RECORD; | ||||
| 	} | ||||
|  | ||||
| 	void decodeSectorRecord() | ||||
| 	{ | ||||
| 		auto rawbits = readRawBits(MICROPOLIS_ENCODED_SECTOR_SIZE*16); | ||||
| 		auto bytes = decodeFmMfm(rawbits).slice(0, MICROPOLIS_ENCODED_SECTOR_SIZE); | ||||
| 		ByteReader br(bytes); | ||||
|  | ||||
| 		br.read_8();  /* sync */ | ||||
| 		_sector->logicalTrack = br.read_8(); | ||||
| 		_sector->logicalSide = _sector->physicalHead; | ||||
| 		_sector->logicalSector = br.read_8(); | ||||
| 		if (_sector->logicalSector > 15) | ||||
| 			return; | ||||
| 		if (_sector->logicalTrack > 77) | ||||
| 			return; | ||||
|  | ||||
| 		br.read(10);  /* OS data or padding */ | ||||
| 		_sector->data = br.read(256); | ||||
| 		uint8_t wantChecksum = br.read_8(); | ||||
| 		uint8_t gotChecksum = checksum(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)); | ||||
| } | ||||
|  | ||||
							
								
								
									
										8
									
								
								arch/micropolis/micropolis.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								arch/micropolis/micropolis.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| #ifndef MICROPOLIS_H | ||||
| #define MICROPOLIS_H | ||||
|  | ||||
| #define MICROPOLIS_ENCODED_SECTOR_SIZE (1+2+266+6) | ||||
|  | ||||
| extern std::unique_ptr<AbstractDecoder> createMicropolisDecoder(const DecoderProto& config); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										4
									
								
								arch/micropolis/micropolis.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/micropolis/micropolis.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message MicropolisDecoderProto {} | ||||
|  | ||||
| @@ -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() | ||||
| 	{ | ||||
| 		nanoseconds_t now = _fmr->tell().ns(); | ||||
|  | ||||
| 		/* For all but the first sector, seek to the next sector pulse. | ||||
| 		 * The first sector does not contain the sector pulse in the fluxmap. | ||||
| 		 */ | ||||
| 		if (now != 0) { | ||||
| 			_fmr->seekToIndexMark(); | ||||
| 			now = _fmr->tell().ns(); | ||||
| 		} | ||||
|  | ||||
| 		/* Discard a possible partial sector at the end of the track. | ||||
| 		 * This partial sector could be mistaken for a conflicted sector, if | ||||
| 		 * whatever data read happens to match the checksum of 0, which is | ||||
| 		 * rare, but has been observed on some disks. | ||||
| 		 */ | ||||
| 		if (now > (_fmr->getDuration() - 21e6)) { | ||||
| 			_fmr->seekToIndexMark(); | ||||
| 			return(UNKNOWN_RECORD); | ||||
| 		} | ||||
|  | ||||
| 		int msSinceIndex = std::round(now / 1e6); | ||||
|  | ||||
| 		const FluxMatcher* matcher = nullptr; | ||||
|  | ||||
| 		/* Note that the seekToPattern ignores the sector pulses, so if | ||||
| 		 * a sector is not found for some reason, the seek will advance | ||||
| 		 * past one or more sector pulses.  For this reason, calculate | ||||
| 		 * _hardSectorId after the sector header is found. | ||||
| 		 */ | ||||
| 		_sector->clock = _fmr->seekToPattern(ANY_SECTOR_PATTERN, matcher); | ||||
|  | ||||
| 		int sectorFoundTimeRaw = std::round((_fmr->tell().ns()) / 1e6); | ||||
| 		int sectorFoundTime; | ||||
|  | ||||
| 		/* Round time to the nearest 20ms */ | ||||
| 		if ((sectorFoundTimeRaw % 20) < 10) { | ||||
| 			sectorFoundTime = (sectorFoundTimeRaw / 20) * 20; | ||||
| 		} | ||||
| 		else { | ||||
| 			sectorFoundTime = ((sectorFoundTimeRaw + 20) / 20) * 20; | ||||
| 		} | ||||
|  | ||||
| 		/* Calculate the sector ID based on time since the index */ | ||||
| 		_hardSectorId = (sectorFoundTime / 20) % 10; | ||||
|  | ||||
| 	//	std::cout << fmt::format( | ||||
| 	//		"Sector ID {}: hole at {}ms, sector start at {}ms", | ||||
| 	//		_hardSectorId, msSinceIndex, sectorFoundTimeRaw) << std::endl; | ||||
|  | ||||
| 		if (matcher == &MFM_PATTERN) { | ||||
| 			_sectorType = SECTOR_TYPE_MFM; | ||||
| 			readRawBits(48); | ||||
| 			return SECTOR_RECORD; | ||||
| 		} | ||||
|  | ||||
| 		if (matcher == &FM_PATTERN) { | ||||
| 			_sectorType = SECTOR_TYPE_FM; | ||||
| 			readRawBits(48); | ||||
| 			return SECTOR_RECORD; | ||||
| 		} | ||||
|  | ||||
| 		return UNKNOWN_RECORD; | ||||
| 	} | ||||
|  | ||||
| 	void decodeSectorRecord() | ||||
| 	{ | ||||
| 		unsigned recordSize, payloadSize, headerSize; | ||||
|  | ||||
| 		if (_sectorType == SECTOR_TYPE_MFM) { | ||||
| 			recordSize = NORTHSTAR_ENCODED_SECTOR_SIZE_DD; | ||||
| 			payloadSize = NORTHSTAR_PAYLOAD_SIZE_DD; | ||||
| 			headerSize = NORTHSTAR_HEADER_SIZE_DD; | ||||
| 		} | ||||
| 		else { | ||||
| 			recordSize = NORTHSTAR_ENCODED_SECTOR_SIZE_SD; | ||||
| 			payloadSize = NORTHSTAR_PAYLOAD_SIZE_SD; | ||||
| 			headerSize = NORTHSTAR_HEADER_SIZE_SD; | ||||
| 		} | ||||
|  | ||||
| 		auto rawbits = readRawBits(recordSize * 16); | ||||
| 		auto bytes = decodeFmMfm(rawbits).slice(0, recordSize); | ||||
| 		ByteReader br(bytes); | ||||
| 		uint8_t sync_char; | ||||
|  | ||||
| 		_sector->logicalSide = _sector->physicalHead; | ||||
| 		_sector->logicalSector = _hardSectorId; | ||||
| 		_sector->logicalTrack = _sector->physicalCylinder; | ||||
|  | ||||
| 		sync_char = br.read_8();	/* Sync char: 0xFB */ | ||||
| 		if (_sectorType == SECTOR_TYPE_MFM) { | ||||
| 			sync_char = br.read_8();/* MFM second Sync char, usually 0xFB */ | ||||
| 		} | ||||
|  | ||||
| 		_sector->data = br.read(payloadSize); | ||||
|  | ||||
| 		uint8_t wantChecksum = br.read_8(); | ||||
| 		uint8_t gotChecksum = northstarChecksum(bytes.slice(headerSize, payloadSize)); | ||||
|  | ||||
| 		_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM; | ||||
| 	} | ||||
|  | ||||
| 	std::set<unsigned> requiredSectors(unsigned cylinder, unsigned head) const override | ||||
| 	{ | ||||
| 		static std::set<unsigned> sectors = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; | ||||
| 		return sectors; | ||||
| 	} | ||||
|  | ||||
| private: | ||||
| 	const NorthstarDecoderProto& _config; | ||||
| 	uint8_t _sectorType = SECTOR_TYPE_MFM; | ||||
| 	uint8_t _hardSectorId; | ||||
| }; | ||||
|  | ||||
| std::unique_ptr<AbstractDecoder> createNorthstarDecoder(const DecoderProto& config) | ||||
| { | ||||
| 	return std::unique_ptr<AbstractDecoder>(new NorthstarDecoder(config)); | ||||
| } | ||||
|  | ||||
							
								
								
									
										166
									
								
								arch/northstar/encoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								arch/northstar/encoder.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,166 @@ | ||||
| #include "globals.h" | ||||
| #include "northstar.h" | ||||
| #include "sector.h" | ||||
| #include "bytes.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
| #include "image.h" | ||||
| #include "lib/encoders/encoders.pb.h" | ||||
|  | ||||
| #define GAP_FILL_SIZE_SD 30 | ||||
| #define PRE_HEADER_GAP_FILL_SIZE_SD 9 | ||||
| #define GAP_FILL_SIZE_DD 62 | ||||
| #define PRE_HEADER_GAP_FILL_SIZE_DD 16 | ||||
|  | ||||
| #define GAP1_FILL_BYTE	(0x4F) | ||||
| #define GAP2_FILL_BYTE	(0x4F) | ||||
|  | ||||
| #define TOTAL_SECTOR_BYTES () | ||||
|  | ||||
| static void write_sector(std::vector<bool>& bits, unsigned& cursor, const std::shared_ptr<Sector>& sector) | ||||
| { | ||||
| 	int preambleSize = 0; | ||||
| 	int encodedSectorSize = 0; | ||||
| 	int gapFillSize = 0; | ||||
| 	int preHeaderGapFillSize = 0; | ||||
|  | ||||
| 	bool doubleDensity; | ||||
|  | ||||
| 	switch (sector->data.size()) { | ||||
| 	case NORTHSTAR_PAYLOAD_SIZE_SD: | ||||
| 		preambleSize = NORTHSTAR_PREAMBLE_SIZE_SD; | ||||
| 		encodedSectorSize = PRE_HEADER_GAP_FILL_SIZE_SD + NORTHSTAR_ENCODED_SECTOR_SIZE_SD + GAP_FILL_SIZE_SD; | ||||
| 		gapFillSize = GAP_FILL_SIZE_SD; | ||||
| 		preHeaderGapFillSize = PRE_HEADER_GAP_FILL_SIZE_SD; | ||||
| 		doubleDensity = false; | ||||
| 		break; | ||||
| 	case NORTHSTAR_PAYLOAD_SIZE_DD: | ||||
| 		preambleSize = NORTHSTAR_PREAMBLE_SIZE_DD; | ||||
| 		encodedSectorSize = PRE_HEADER_GAP_FILL_SIZE_DD + NORTHSTAR_ENCODED_SECTOR_SIZE_DD + GAP_FILL_SIZE_DD; | ||||
| 		gapFillSize = GAP_FILL_SIZE_DD; | ||||
| 		preHeaderGapFillSize = PRE_HEADER_GAP_FILL_SIZE_DD; | ||||
| 		doubleDensity = true; | ||||
| 		break; | ||||
| 	default: | ||||
| 		Error() << "unsupported sector size --- you must pick 256 or 512"; | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	int fullSectorSize = preambleSize + encodedSectorSize; | ||||
| 	auto fullSector = std::make_shared<std::vector<uint8_t>>(); | ||||
| 	fullSector->reserve(fullSectorSize); | ||||
|  | ||||
| 	/* sector gap after index pulse */ | ||||
| 	for (int i = 0; i < preHeaderGapFillSize; i++) | ||||
| 		fullSector->push_back(GAP1_FILL_BYTE); | ||||
|  | ||||
| 	/* sector preamble */ | ||||
| 	for (int i = 0; i < preambleSize; i++) | ||||
| 		fullSector->push_back(0); | ||||
|  | ||||
| 	Bytes sectorData; | ||||
| 	if (sector->data.size() == encodedSectorSize) | ||||
| 		sectorData = sector->data; | ||||
| 	else { | ||||
| 		ByteWriter writer(sectorData); | ||||
| 		writer.write_8(0xFB);     /* sync character */ | ||||
| 		if (doubleDensity == true) { | ||||
| 			writer.write_8(0xFB); /* Double-density has two sync characters */ | ||||
| 		} | ||||
| 		writer += sector->data; | ||||
| 		if (doubleDensity == true) { | ||||
| 			writer.write_8(northstarChecksum(sectorData.slice(2))); | ||||
| 		} else { | ||||
| 			writer.write_8(northstarChecksum(sectorData.slice(1))); | ||||
| 		} | ||||
| 	} | ||||
| 	for (uint8_t b : sectorData) | ||||
| 		fullSector->push_back(b); | ||||
|  | ||||
| 	if (sector->logicalSector != 9) { | ||||
| 		/* sector postamble */ | ||||
| 		for (int i = 0; i < gapFillSize; i++) | ||||
| 			fullSector->push_back(GAP2_FILL_BYTE); | ||||
|  | ||||
| 		if (fullSector->size() != fullSectorSize) | ||||
| 			Error() << "sector mismatched length (" << sector->data.size() << ") expected: " << fullSector->size() << " got " << fullSectorSize; | ||||
| 	} else { | ||||
| 		/* sector postamble */ | ||||
| 		for (int i = 0; i < gapFillSize; i++) | ||||
| 			fullSector->push_back(GAP2_FILL_BYTE); | ||||
| 	} | ||||
|  | ||||
| 	bool lastBit = false; | ||||
|  | ||||
| 	if (doubleDensity == true) { | ||||
| 		encodeMfm(bits, cursor, fullSector, lastBit); | ||||
| 	} | ||||
| 	else { | ||||
| 		encodeFm(bits, cursor, fullSector); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class NorthstarEncoder : public AbstractEncoder | ||||
| { | ||||
| public: | ||||
| 	NorthstarEncoder(const EncoderProto& config): | ||||
| 		AbstractEncoder(config), | ||||
| 		_config(config.northstar()) | ||||
| 	{} | ||||
|  | ||||
| 	std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override | ||||
| 	{ | ||||
| 		std::vector<std::shared_ptr<Sector>> sectors; | ||||
|  | ||||
| 		if ((physicalTrack >= 0) && (physicalTrack < 35)) | ||||
| 		{ | ||||
| 			for (int sectorId = 0; sectorId < 10; sectorId++) | ||||
| 			{ | ||||
| 				const auto& sector = image.get(physicalTrack, physicalSide, sectorId); | ||||
| 				if (sector) | ||||
| 					sectors.push_back(sector); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return sectors; | ||||
| 	} | ||||
|  | ||||
| 	std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, | ||||
| 			const std::vector<std::shared_ptr<Sector>>& sectors, const Image& image) override | ||||
| 	{ | ||||
| 		int bitsPerRevolution = 100000; | ||||
| 		double clockRateUs = 4.00; | ||||
|  | ||||
| 		if ((physicalTrack < 0) || (physicalTrack >= 35) || sectors.empty()) | ||||
| 			return std::unique_ptr<Fluxmap>(); | ||||
|  | ||||
| 		const auto& sector = *sectors.begin(); | ||||
| 		if (sector->data.size() == NORTHSTAR_PAYLOAD_SIZE_SD) { | ||||
| 			bitsPerRevolution /= 2;		// FM | ||||
| 		} else { | ||||
| 			clockRateUs /= 2.00; | ||||
| 		} | ||||
|  | ||||
| 		std::vector<bool> bits(bitsPerRevolution); | ||||
| 		unsigned cursor = 0; | ||||
|  | ||||
| 		for (const auto& sectorData : sectors) | ||||
| 			write_sector(bits, cursor, sectorData); | ||||
|  | ||||
| 		if (cursor > bits.size()) | ||||
| 			Error() << "track data overrun"; | ||||
|  | ||||
| 		std::unique_ptr<Fluxmap> fluxmap(new Fluxmap); | ||||
| 		fluxmap->appendBits(bits, clockRateUs * 1e3); | ||||
| 		return fluxmap; | ||||
| 	} | ||||
|  | ||||
| private: | ||||
| 	const NorthstarEncoderProto& _config; | ||||
| }; | ||||
|  | ||||
| std::unique_ptr<AbstractEncoder> createNorthstarEncoder(const EncoderProto& config) | ||||
| { | ||||
| 	return std::unique_ptr<AbstractEncoder>(new NorthstarEncoder(config)); | ||||
| } | ||||
|  | ||||
							
								
								
									
										38
									
								
								arch/northstar/northstar.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								arch/northstar/northstar.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| #ifndef NORTHSTAR_H | ||||
| #define NORTHSTAR_H | ||||
|  | ||||
| /* Northstar floppies are 10-hard sectored disks with a sector format as follows: | ||||
|  * | ||||
|  * |----------------------------------| | ||||
|  * | SYNC Byte  | Payload  | Checksum | | ||||
|  * |------------+----------+----------| | ||||
|  * | 1 (0xFB)   | 256 (SD) |    1     | | ||||
|  * | 2 (0xFBFB) | 512 (DD) |          | | ||||
|  * |----------------------------------| | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #define NORTHSTAR_PREAMBLE_SIZE_SD		(16) | ||||
| #define NORTHSTAR_PREAMBLE_SIZE_DD		(32) | ||||
| #define NORTHSTAR_HEADER_SIZE_SD		(1) | ||||
| #define NORTHSTAR_HEADER_SIZE_DD		(2) | ||||
| #define NORTHSTAR_PAYLOAD_SIZE_SD		(256) | ||||
| #define NORTHSTAR_PAYLOAD_SIZE_DD		(512) | ||||
| #define NORTHSTAR_CHECKSUM_SIZE		(1) | ||||
| #define NORTHSTAR_ENCODED_SECTOR_SIZE_SD	(NORTHSTAR_HEADER_SIZE_SD + NORTHSTAR_PAYLOAD_SIZE_SD + NORTHSTAR_CHECKSUM_SIZE) | ||||
| #define NORTHSTAR_ENCODED_SECTOR_SIZE_DD	(NORTHSTAR_HEADER_SIZE_DD + NORTHSTAR_PAYLOAD_SIZE_DD + NORTHSTAR_CHECKSUM_SIZE) | ||||
|  | ||||
| #define SECTOR_TYPE_MFM			(0) | ||||
| #define SECTOR_TYPE_FM				(1) | ||||
|  | ||||
| class AbstractDecoder; | ||||
| class AbstractEncoder; | ||||
| class EncoderProto; | ||||
| class DecoderProto; | ||||
|  | ||||
| extern uint8_t northstarChecksum(const Bytes& bytes); | ||||
|  | ||||
| extern std::unique_ptr<AbstractDecoder> createNorthstarDecoder(const DecoderProto& config); | ||||
| extern std::unique_ptr<AbstractEncoder> createNorthstarEncoder(const EncoderProto& config); | ||||
|  | ||||
| #endif /* NORTHSTAR */ | ||||
							
								
								
									
										5
									
								
								arch/northstar/northstar.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								arch/northstar/northstar.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message NorthstarDecoderProto {} | ||||
| message NorthstarEncoderProto {} | ||||
|  | ||||
							
								
								
									
										98
									
								
								arch/tids990/decoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								arch/tids990/decoder.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| #include "globals.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
| #include "tids990/tids990.h" | ||||
| #include "crc.h" | ||||
| #include "fluxmap.h" | ||||
| #include "decoders/fluxmapreader.h" | ||||
| #include "sector.h" | ||||
| #include <string.h> | ||||
| #include <fmt/format.h> | ||||
|  | ||||
| /* The Texas Instruments DS990 uses MFM with a scheme similar to a simplified | ||||
|  * version of the IBM record scheme (it's actually easier to parse than IBM). | ||||
|  * There are 26 sectors per track, each holding a rather weird 288 bytes. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Sector record: | ||||
|  * data:    0  1  0  1  0  1  0  1 .0  0  0  0  1  0  1  0  = 0x550a | ||||
|  * mfm:     00 01 00 01 00 01 00 01.00 10 10 10 01 00 01 00 = 0x11112a44 | ||||
|  * special: 00 01 00 01 00 01 00 01.00 10 00 10 01 00 01 00 = 0x11112244 | ||||
|  *                                        ^^ | ||||
|  * When shifted out of phase, the special 0xa1 byte becomes an illegal | ||||
|  * encoding (you can't do 10 00). So this can't be spoofed by user data. | ||||
|  */ | ||||
| const FluxPattern SECTOR_RECORD_PATTERN(32, 0x11112244); | ||||
|  | ||||
| /* | ||||
|  * Data record: | ||||
|  * data:    0  1  0  1  0  1  0  1 .0  0  0  0  1  0  1  1  = 0x550c | ||||
|  * mfm:     00 01 00 01 00 01 00 01.00 10 10 10 01 00 01 01 = 0x11112a45 | ||||
|  * special: 00 01 00 01 00 01 00 01.00 10 00 10 01 00 01 01 = 0x11112245 | ||||
|  *                                        ^^ | ||||
|  * When shifted out of phase, the special 0xa1 byte becomes an illegal | ||||
|  * encoding (you can't do 10 00). So this can't be spoofed by user data. | ||||
|  */ | ||||
| const FluxPattern DATA_RECORD_PATTERN(32, 0x11112245); | ||||
|  | ||||
| const FluxMatchers ANY_RECORD_PATTERN({ &SECTOR_RECORD_PATTERN, &DATA_RECORD_PATTERN }); | ||||
|  | ||||
| class Tids990Decoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	Tids990Decoder(const DecoderProto& config): | ||||
| 		AbstractDecoder(config) | ||||
| 	{} | ||||
|  | ||||
|     RecordType advanceToNextRecord() | ||||
| 	{ | ||||
| 		const FluxMatcher* matcher = nullptr; | ||||
| 		_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher); | ||||
| 		if (matcher == &SECTOR_RECORD_PATTERN) | ||||
| 			return RecordType::SECTOR_RECORD; | ||||
| 		if (matcher == &DATA_RECORD_PATTERN) | ||||
| 			return RecordType::DATA_RECORD; | ||||
| 		return RecordType::UNKNOWN_RECORD; | ||||
| 	} | ||||
|  | ||||
|     void decodeSectorRecord() | ||||
| 	{ | ||||
| 		auto bits = readRawBits(TIDS990_SECTOR_RECORD_SIZE*16); | ||||
| 		auto bytes = decodeFmMfm(bits).slice(0, TIDS990_SECTOR_RECORD_SIZE); | ||||
|  | ||||
| 		ByteReader br(bytes); | ||||
| 		uint16_t gotChecksum = crc16(CCITT_POLY, bytes.slice(1, TIDS990_SECTOR_RECORD_SIZE-3)); | ||||
|  | ||||
| 		br.seek(2); | ||||
| 		_sector->logicalSide = br.read_8() >> 3; | ||||
| 		_sector->logicalTrack = br.read_8(); | ||||
| 		br.read_8(); /* number of sectors per track */ | ||||
| 		_sector->logicalSector = br.read_8(); | ||||
| 		br.read_be16(); /* sector size */ | ||||
| 		uint16_t wantChecksum = br.read_be16(); | ||||
|  | ||||
| 		if (wantChecksum == gotChecksum) | ||||
| 			_sector->status = Sector::DATA_MISSING; /* correct but unintuitive */ | ||||
| 	} | ||||
|  | ||||
| 	void decodeDataRecord() | ||||
| 	{ | ||||
| 		auto bits = readRawBits(TIDS990_DATA_RECORD_SIZE*16); | ||||
| 		auto bytes = decodeFmMfm(bits).slice(0, TIDS990_DATA_RECORD_SIZE); | ||||
|  | ||||
| 		ByteReader br(bytes); | ||||
| 		uint16_t gotChecksum = crc16(CCITT_POLY, bytes.slice(1, TIDS990_DATA_RECORD_SIZE-3)); | ||||
|  | ||||
| 		br.seek(2); | ||||
| 		_sector->data = br.read(TIDS990_PAYLOAD_SIZE); | ||||
| 		uint16_t wantChecksum = br.read_be16(); | ||||
| 		_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| std::unique_ptr<AbstractDecoder> createTids990Decoder(const DecoderProto& config) | ||||
| { | ||||
| 	return std::unique_ptr<AbstractDecoder>(new Tids990Decoder(config)); | ||||
| } | ||||
|  | ||||
							
								
								
									
										168
									
								
								arch/tids990/encoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								arch/tids990/encoder.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | ||||
| #include "globals.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
| #include "tids990.h" | ||||
| #include "crc.h" | ||||
| #include "writer.h" | ||||
| #include "image.h" | ||||
| #include "arch/tids990/tids990.pb.h" | ||||
| #include "lib/encoders/encoders.pb.h" | ||||
| #include <fmt/format.h> | ||||
|  | ||||
| static int charToInt(char c) | ||||
| { | ||||
| 	if (isdigit(c)) | ||||
| 		return c - '0'; | ||||
| 	return 10 + tolower(c) - 'a'; | ||||
| } | ||||
|  | ||||
| static uint8_t decodeUint16(uint16_t raw) | ||||
| { | ||||
| 	Bytes b; | ||||
| 	ByteWriter bw(b); | ||||
| 	bw.write_be16(raw); | ||||
| 	return decodeFmMfm(b.toBits())[0]; | ||||
| } | ||||
|  | ||||
| class Tids990Encoder : public AbstractEncoder | ||||
| { | ||||
| public: | ||||
| 	Tids990Encoder(const EncoderProto& config): | ||||
| 		AbstractEncoder(config), | ||||
| 		_config(config.tids990()) | ||||
| 	{} | ||||
|  | ||||
| private: | ||||
| 	void writeRawBits(uint32_t data, int width) | ||||
| 	{ | ||||
| 		_cursor += width; | ||||
| 		_lastBit = data & 1; | ||||
| 		for (int i=0; i<width; i++) | ||||
| 		{ | ||||
| 			unsigned pos = _cursor - i - 1; | ||||
| 			if (pos < _bits.size()) | ||||
| 				_bits[pos] = data & 1; | ||||
| 			data >>= 1; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	void writeBytes(const Bytes& bytes) | ||||
| 	{ | ||||
| 		encodeMfm(_bits, _cursor, bytes, _lastBit); | ||||
| 	} | ||||
|  | ||||
| 	void writeBytes(int count, uint8_t byte) | ||||
| 	{ | ||||
| 		Bytes bytes = { byte }; | ||||
| 		for (int i=0; i<count; i++) | ||||
| 			writeBytes(bytes); | ||||
| 	} | ||||
|  | ||||
| public: | ||||
| 	std::vector<std::shared_ptr<Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override | ||||
| 	{ | ||||
| 		std::vector<std::shared_ptr<Sector>> sectors; | ||||
|  | ||||
| 		for (char sectorChar : _config.sector_skew()) | ||||
|         { | ||||
| 			int sectorId = charToInt(sectorChar); | ||||
| 			const auto& sector = image.get(physicalTrack, physicalSide, sectorId); | ||||
| 			if (sector) | ||||
| 				sectors.push_back(sector); | ||||
|         } | ||||
|  | ||||
| 		return sectors; | ||||
| 	} | ||||
|  | ||||
|     std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, | ||||
| 			const std::vector<std::shared_ptr<Sector>>& sectors, const Image& image) override | ||||
| 	{ | ||||
| 		double clockRateUs = 1e3 / _config.clock_rate_khz() / 2.0; | ||||
| 		int bitsPerRevolution = (_config.track_length_ms() * 1000.0) / clockRateUs; | ||||
| 		_bits.resize(bitsPerRevolution); | ||||
| 		_cursor = 0; | ||||
|  | ||||
| 		uint8_t am1Unencoded = decodeUint16(_config.am1_byte()); | ||||
| 		uint8_t am2Unencoded = decodeUint16(_config.am2_byte()); | ||||
|  | ||||
| 		writeBytes(_config.gap1_bytes(), 0x55); | ||||
|  | ||||
| 		bool first = true; | ||||
| 		for (char sectorChar : _config.sector_skew()) | ||||
| 		{ | ||||
| 			int sectorId = charToInt(sectorChar); | ||||
| 			if (!first) | ||||
| 				writeBytes(_config.gap3_bytes(), 0x55); | ||||
| 			first = false; | ||||
|  | ||||
| 			const auto& sectorData = image.get(physicalTrack, physicalSide, sectorId); | ||||
| 			if (!sectorData) | ||||
| 				Error() << fmt::format("format tried to find sector {} which wasn't in the input file", sectorId); | ||||
|  | ||||
| 			/* Writing the sector and data records are fantastically annoying. | ||||
| 			 * The CRC is calculated from the *very start* of the record, and | ||||
| 			 * include the malformed marker bytes. Our encoder doesn't know | ||||
| 			 * about this, of course, with the result that we have to construct | ||||
| 			 * the unencoded header, calculate the checksum, and then use the | ||||
| 			 * same logic to emit the bytes which require special encoding | ||||
| 			 * before encoding the rest of the header normally. */ | ||||
|  | ||||
| 			{ | ||||
| 				Bytes header; | ||||
| 				ByteWriter bw(header); | ||||
|  | ||||
| 				writeBytes(12, 0x55); | ||||
| 				bw.write_8(am1Unencoded); | ||||
| 				bw.write_8(sectorData->logicalSide << 3); | ||||
| 				bw.write_8(sectorData->logicalTrack); | ||||
| 				bw.write_8(_config.sector_count()); | ||||
| 				bw.write_8(sectorData->logicalSector); | ||||
| 				bw.write_be16(sectorData->data.size()); | ||||
| 				uint16_t crc = crc16(CCITT_POLY, header); | ||||
| 				bw.write_be16(crc); | ||||
|  | ||||
| 				writeRawBits(_config.am1_byte(), 16); | ||||
| 				writeBytes(header.slice(1)); | ||||
| 			} | ||||
|  | ||||
| 			writeBytes(_config.gap2_bytes(), 0x55); | ||||
|  | ||||
| 			{ | ||||
| 				Bytes data; | ||||
| 				ByteWriter bw(data); | ||||
|  | ||||
| 				writeBytes(12, 0x55); | ||||
| 				bw.write_8(am2Unencoded); | ||||
|  | ||||
| 				bw += sectorData->data; | ||||
| 				uint16_t crc = crc16(CCITT_POLY, data); | ||||
| 				bw.write_be16(crc); | ||||
|  | ||||
| 				writeRawBits(_config.am2_byte(), 16); | ||||
| 				writeBytes(data.slice(1)); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (_cursor >= _bits.size()) | ||||
| 			Error() << "track data overrun"; | ||||
| 		while (_cursor < _bits.size()) | ||||
| 			writeBytes(1, 0x55); | ||||
| 		 | ||||
| 		std::unique_ptr<Fluxmap> fluxmap(new Fluxmap); | ||||
| 		fluxmap->appendBits(_bits, clockRateUs*1e3); | ||||
| 		return fluxmap; | ||||
| 	} | ||||
|  | ||||
| private: | ||||
| 	const Tids990EncoderProto& _config; | ||||
| 	std::vector<bool> _bits; | ||||
| 	unsigned _cursor; | ||||
| 	bool _lastBit; | ||||
| }; | ||||
|  | ||||
| std::unique_ptr<AbstractEncoder> createTids990Encoder(const EncoderProto& config) | ||||
| { | ||||
| 	return std::unique_ptr<AbstractEncoder>(new Tids990Encoder(config)); | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										18
									
								
								arch/tids990/tids990.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								arch/tids990/tids990.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| #ifndef TIDS990_H | ||||
| #define TIDS990_H | ||||
|  | ||||
| #define TIDS990_PAYLOAD_SIZE       288 /* bytes */ | ||||
| #define TIDS990_SECTOR_RECORD_SIZE 10 /* bytes */ | ||||
| #define TIDS990_DATA_RECORD_SIZE   (TIDS990_PAYLOAD_SIZE + 4) /* bytes */ | ||||
|  | ||||
| class AbstractEncoder; | ||||
| class AbstractDecoder; | ||||
| class DecoderProto; | ||||
| class EncoderProto; | ||||
|  | ||||
| extern std::unique_ptr<AbstractDecoder> createTids990Decoder(const DecoderProto& config); | ||||
| extern std::unique_ptr<AbstractEncoder> createTids990Encoder(const EncoderProto& config); | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
							
								
								
									
										26
									
								
								arch/tids990/tids990.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								arch/tids990/tids990.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| import "lib/common.proto"; | ||||
|  | ||||
| message Tids990DecoderProto {} | ||||
| message Tids990EncoderProto { | ||||
| 	optional double track_length_ms = 1 [ default = 166, | ||||
| 		(help) = "length of a track" ]; | ||||
| 	optional int32 sector_count = 2 [ default = 26, | ||||
| 		(help) = "number of sectors per track" ]; | ||||
| 	optional double clock_rate_khz = 3 [ default = 500, | ||||
| 		(help) = "clock rate of data to write" ]; | ||||
| 	optional int32 am1_byte = 4 [ default = 0x2244, | ||||
| 		(help) = "16-bit RAW bit pattern to use for the AM1 ID byte" ]; | ||||
| 	optional int32 am2_byte = 5 [ default = 0x2245, | ||||
| 		(help) = "16-bit RAW bit pattern to use for the AM2 ID byte" ]; | ||||
| 	optional int32 gap1_bytes = 6 [ default = 80, | ||||
| 		(help) = "size of gap 1 (the post-index gap)" ]; | ||||
| 	optional int32 gap2_bytes = 7 [ default = 21, | ||||
| 		(help) = "size of gap 2 (the post-ID gap)" ]; | ||||
| 	optional int32 gap3_bytes = 8 [ default = 51, | ||||
| 		(help) = "size of gap 3 (the post-data or format gap)" ]; | ||||
| 	optional string sector_skew = 9 [ default = "1mhc72nid83oje94pkfa50lgb6", | ||||
| 		(help) = "order to emit sectors" ]; | ||||
| } | ||||
|  | ||||
| @@ -2,13 +2,11 @@ | ||||
| #include "fluxmap.h" | ||||
| #include "decoders/fluxmapreader.h" | ||||
| #include "protocol.h" | ||||
| #include "record.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "sector.h" | ||||
| #include "victor9k.h" | ||||
| #include "crc.h" | ||||
| #include "bytes.h" | ||||
| #include "track.h" | ||||
| #include "fmt/format.h" | ||||
| #include <string.h> | ||||
| #include <algorithm> | ||||
| @@ -27,7 +25,7 @@ static int decode_data_gcr(uint8_t gcr) | ||||
| 		#undef GCR_ENTRY | ||||
|     } | ||||
|     return -1; | ||||
| }; | ||||
| } | ||||
|  | ||||
| static Bytes decode(const std::vector<bool>& bits) | ||||
| { | ||||
| @@ -54,58 +52,73 @@ static Bytes decode(const std::vector<bool>& bits) | ||||
|     return output; | ||||
| } | ||||
|  | ||||
| AbstractDecoder::RecordType Victor9kDecoder::advanceToNextRecord() | ||||
| class Victor9kDecoder : public AbstractDecoder | ||||
| { | ||||
| 	const FluxMatcher* matcher = nullptr; | ||||
| 	_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher); | ||||
| 	if (matcher == &SECTOR_RECORD_PATTERN) | ||||
| 		return SECTOR_RECORD; | ||||
| 	if (matcher == &DATA_RECORD_PATTERN) | ||||
| 		return DATA_RECORD; | ||||
| 	return UNKNOWN_RECORD; | ||||
| public: | ||||
| 	Victor9kDecoder(const DecoderProto& config): | ||||
| 		AbstractDecoder(config) | ||||
| 	{} | ||||
|  | ||||
|     RecordType advanceToNextRecord() | ||||
| 	{ | ||||
| 		const FluxMatcher* matcher = nullptr; | ||||
| 		_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher); | ||||
| 		if (matcher == &SECTOR_RECORD_PATTERN) | ||||
| 			return SECTOR_RECORD; | ||||
| 		if (matcher == &DATA_RECORD_PATTERN) | ||||
| 			return DATA_RECORD; | ||||
| 		return UNKNOWN_RECORD; | ||||
| 	} | ||||
|  | ||||
|     void decodeSectorRecord() | ||||
| 	{ | ||||
| 		/* Skip the sync marker bit. */ | ||||
| 		readRawBits(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 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; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| 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; | ||||
| } | ||||
|   | ||||
| @@ -6,17 +6,6 @@ | ||||
|  | ||||
| #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); | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										4
									
								
								arch/victor9k/victor9k.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/victor9k/victor9k.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message Victor9kDecoderProto {} | ||||
|  | ||||
| @@ -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
											
										
									
								
							Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user