READ-DMK.Z80 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843
  1. org #0100
  2. ld hl,debug_buffer ; circular buffer for debug output
  3. ld (debug_ptr),hl
  4. ; TODO simplify commandline parsing
  5. ; parse commandline
  6. ld hl,#0081
  7. parse_loop ld a,(hl)
  8. inc hl
  9. or a
  10. jp z,parse_end
  11. cp 13
  12. jp z,parse_end
  13. cp ' '
  14. jr z,parse_loop ; skip space
  15. cp 9
  16. jr z,parse_loop ; skip tab
  17. ld c,a
  18. and #df ; to upper case
  19. cp 'D'
  20. jp z,check_debug
  21. cp 'S'
  22. jp z,check_s
  23. cp 'T'
  24. jp nz,unknown_option
  25. check_t ld a,(hl)
  26. inc hl
  27. and #df
  28. cp 'Y'
  29. jp nz,unknown_option
  30. ld a,(hl)
  31. inc hl
  32. and #df
  33. cp 'P'
  34. jp nz,unknown_option
  35. ld a,(hl)
  36. inc hl
  37. and #df
  38. cp 'E'
  39. jp nz,unknown_option
  40. ld a,(hl)
  41. inc hl
  42. cp '='
  43. jp nz,unknown_option
  44. check_type ld a,(hl)
  45. inc hl
  46. and #df
  47. cp 'P'
  48. jp z,check_philips
  49. cp 'M'
  50. jr z,check_microsol
  51. cp 'N'
  52. jp nz,unknown_option
  53. check_national ld a,(hl)
  54. inc hl
  55. and #df
  56. cp 'A'
  57. jp nz,unknown_option
  58. ld a,(hl)
  59. inc hl
  60. and #df
  61. cp 'T'
  62. jp nz,unknown_option
  63. ld a,(hl)
  64. inc hl
  65. and #df
  66. cp 'I'
  67. jp nz,unknown_option
  68. ld a,(hl)
  69. inc hl
  70. and #df
  71. cp 'O'
  72. jp nz,unknown_option
  73. ld a,(hl)
  74. inc hl
  75. and #df
  76. cp 'N'
  77. jp nz,unknown_option
  78. ld a,(hl)
  79. inc hl
  80. and #df
  81. cp 'A'
  82. jp nz,unknown_option
  83. ld a,(hl)
  84. inc hl
  85. and #df
  86. cp 'L'
  87. jp nz,unknown_option
  88. ld de,natl_driver
  89. ld (driver),de
  90. jp parse_loop
  91. check_microsol ld a,(hl)
  92. inc hl
  93. and #df
  94. cp 'I'
  95. jp nz,unknown_option
  96. ld a,(hl)
  97. inc hl
  98. and #df
  99. cp 'C'
  100. jp nz,unknown_option
  101. ld a,(hl)
  102. inc hl
  103. and #df
  104. cp 'R'
  105. jp nz,unknown_option
  106. ld a,(hl)
  107. inc hl
  108. and #df
  109. cp 'O'
  110. jp nz,unknown_option
  111. ld a,(hl)
  112. inc hl
  113. and #df
  114. cp 'S'
  115. jp nz,unknown_option
  116. ld a,(hl)
  117. inc hl
  118. and #df
  119. cp 'O'
  120. jp nz,unknown_option
  121. ld a,(hl)
  122. inc hl
  123. and #df
  124. cp 'L'
  125. jp nz,unknown_option
  126. ld de,mics_driver
  127. ld (driver),de
  128. jp parse_loop
  129. check_philips ld a,(hl)
  130. inc hl
  131. and #df
  132. cp 'H'
  133. jp nz,unknown_option
  134. ld a,(hl)
  135. inc hl
  136. and #df
  137. cp 'I'
  138. jp nz,unknown_option
  139. ld a,(hl)
  140. inc hl
  141. and #df
  142. cp 'L'
  143. jp nz,unknown_option
  144. ld a,(hl)
  145. inc hl
  146. and #df
  147. cp 'I'
  148. jp nz,unknown_option
  149. ld a,(hl)
  150. inc hl
  151. and #df
  152. cp 'P'
  153. jp nz,unknown_option
  154. ld a,(hl)
  155. inc hl
  156. and #df
  157. cp 'S'
  158. jp nz,unknown_option
  159. ld de,phil_driver
  160. ld (driver),de
  161. jp parse_loop
  162. check_s ld a,(hl)
  163. inc hl
  164. and #df
  165. cp 'T'
  166. jp nz,unknown_option
  167. ld a,(hl)
  168. inc hl
  169. and #df
  170. cp 'A'
  171. jr z,check_start
  172. cp 'O'
  173. jp nz,unknown_option
  174. check_stop ld a,(hl)
  175. inc hl
  176. and #df
  177. cp 'P'
  178. jp nz,unknown_option
  179. ld a,(hl)
  180. inc hl
  181. cp '='
  182. jp nz,unknown_option
  183. stop_option call parse_dec
  184. ld (stop_track),a
  185. ld a,1
  186. ld (stop_set),a
  187. jp parse_loop
  188. check_start ld a,(hl)
  189. inc hl
  190. and #df
  191. cp 'R'
  192. jp nz,unknown_option
  193. ld a,(hl)
  194. inc hl
  195. and #df
  196. cp 'T'
  197. jp nz,unknown_option
  198. ld a,(hl)
  199. inc hl
  200. cp '='
  201. jp nz,unknown_option
  202. start_option call parse_dec
  203. ld (start_track),a
  204. jp parse_loop
  205. check_debug ld a,(hl)
  206. inc hl
  207. and #df
  208. cp 'E'
  209. jp nz,unknown_option
  210. ld a,(hl)
  211. inc hl
  212. and #df
  213. cp 'B'
  214. jp nz,unknown_option
  215. ld a,(hl)
  216. inc hl
  217. and #df
  218. cp 'U'
  219. jp nz,unknown_option
  220. ld a,(hl)
  221. inc hl
  222. and #df
  223. cp 'G'
  224. jp nz,unknown_option
  225. ld a,(hl)
  226. inc hl
  227. cp '='
  228. jp nz,unknown_option
  229. debug_option call parse_dec
  230. ld (debug),a
  231. jp parse_loop
  232. parse_end
  233. ; TODO check start_track <= stop_track
  234. ; and both <= 85
  235. ; Select the correct driver routines
  236. ; For now we only have a driver for Philps machines
  237. ld hl,(driver)
  238. ld de,driver_routines
  239. ld bc,driver_size
  240. ldir
  241. ld a,'S'
  242. call debug_log
  243. call print_pc
  244. db "Read-DMK version 0.41",13,10
  245. db 13,10
  246. db "Insert source disk in drive A",13,10
  247. db "Insert destination disk in drive B",13,10
  248. db "Press any key to continue ...",0
  249. ld ix,#009f
  250. ld iy,(#fcc0)
  251. call #001c
  252. call print_pc
  253. db 13,10,13,10,0
  254. ; loop over all cylinders and both sides
  255. ld a,(start_track)
  256. cylinder_loop ld (cylinder),a
  257. xor a
  258. side_loop ld (side),a ; start at side 0
  259. ; delete debug file, so that we never by accident end up with a leftover
  260. ; old debug file
  261. ld de,fcb_debug
  262. ld c,#13 ; delete file
  263. call #0005
  264. ; Prepare drive:
  265. ; - select drive, turn motor on
  266. ; - select side
  267. ; - seek to correct track
  268. ld a,'L'
  269. call debug_log
  270. call select_fdc
  271. call seek
  272. ;; TODO currently we always restore the head to track 0 followed by a seek to
  273. ;; the destination track. I tried to use a 'step-in' command instead, but I
  274. ;; couldn't get this to work correctly. I suspect it's because I'm using the
  275. ;; BDOS routines to save a file (although to the B drive) and that interferes
  276. ;; with the state of the A drive. A possible improvement would be to buffer as
  277. ;; much data in (v)ram before writing it out to disk. So minimize the number
  278. ;; of switches between the A and B drives.
  279. call print_pc
  280. db 13,10
  281. db "Cylinder: ",0
  282. ld a,(cylinder)
  283. call print_dec_a
  284. call print_pc
  285. db " side: ",0
  286. ld a,(side)
  287. call print_dec_a
  288. call select_fdc ; TODO is/was this call still/ever needed?
  289. ; Use the "read address" WD2793 command in a loop to read all address marks
  290. ; on this track. We start this loop right after the index pulse. During the
  291. ; wait-for-next-byte-loop we also increase a counter, and the value of this
  292. ; counter is stored together with the read-address-data. This counter value
  293. ; will later be used to estimate the location of the address mark in the raw
  294. ; track data.
  295. ;
  296. ; We also use this counter to make sure we have read all address marks of the
  297. ; whole track. Experiments on a real MSX have shown that the counter has
  298. ; approximately the value 0x38E0 after one revolution (though rotation speed
  299. ; can vary). We stop the loop after the counter has reached value 0xc000. So
  300. ; this makes sure we have read each address mark at least 3 times (see below
  301. ; why this is needed).
  302. ld a,'R'
  303. call debug_log
  304. xor a ; for reasons explained below, we
  305. ld (retries),a ; sometimes need to retry
  306. retry call print_pc
  307. db " (attempt ",0
  308. ld a,(retries)
  309. inc a
  310. call print_dec_a
  311. call print_pc
  312. db ")",13,10,0
  313. xor a
  314. ld (addr_retries),a
  315. do_addr_retry
  316. ld a,'r'
  317. call debug_log
  318. call print_pc
  319. db "Read addresses ...",0
  320. ld iy,(driver_rd_addr)
  321. jp (iy)
  322. addr_error ; 'Record not found' status bit was set. This means there
  323. ; wasn't any address mark in this track. This e.g. happens
  324. ; if you read the 81th track on a normal disk.
  325. ; don't retry on this
  326. jr skip_addr
  327. read_addr_err call print_pc
  328. db "Read address command didn't return 6 bytes.",13,10,0
  329. addr_retry ld a,(addr_retries)
  330. inc a
  331. ld (addr_retries),a
  332. cp 20
  333. jp c,do_addr_retry
  334. call print_pc
  335. db "Couldn't reliably read address marks ... skipped",13,10,0
  336. skip_addr ld de,addr_buffer+1 ; as long as it's > addr_buffer
  337. ld (addr_buf_end),de
  338. ld hl,0
  339. jr addr_found
  340. addr_done ld (addr_buf_end),de
  341. ; Now each address mark is read for at least 3 full revolutions. Analyze this
  342. ; data to detect the number of address marks in one revolution. Note that it's
  343. ; possible a single track contains several identical address marks. So
  344. ; detecting the number of sectors in the track is not as simple as searching
  345. ; for the 2nd occurrence of the 1st read address mark.
  346. ;
  347. ; Some examples (the latters 'A'-'Z' each represent a unique address mark):
  348. ; * ABCDEFGHIABCDEFGHIABCDEFGHIABCD
  349. ; -> 'normal' track with 9 unique address marks
  350. ; * ABCDABEABCDABEABCDABEABC
  351. ; -> 8 unique address marks, the marks A and B appear twice
  352. ; * ABCABCABCABCABCABCABCA
  353. ; -> the current algorithm detects a track with 3 unique address marks
  354. ; so it cannot distinguish the track 'ABC' from 'ABCABC'
  355. ; TODO fix this by taking the timing into account
  356. ;
  357. ; Note that the detection can fail if we did not read at least 2 full
  358. ; revolutions. For example, suppose the actual track contains these marks:
  359. ; 'AAAAAAABAA' (10 unique marks, mark A is duplicated 9 times). Now suppose we
  360. ; only read 'AAAAAAABAAAAAAA'. Valid periods for this sequence could be 8, 9
  361. ; or 10. (The current algorithm would return 8). This ambiguity disappears if
  362. ; we read at least 2 full revolutions.
  363. ld hl,0
  364. next_period ld ix,(addr_buf_end)
  365. ld a,ixl
  366. and 7
  367. jp nz,read_addr_err
  368. ld de,addr_buffer
  369. call get_period
  370. addr_found ld (nb_sectors),hl
  371. ; TODO check not more than 64 (DMK cannot handle that)
  372. ; if (nb_sectors > 64) error("not supported by dmk");
  373. call print_pc
  374. db " found ",0
  375. ld hl,(nb_sectors)
  376. call print_dec_hl ; TODO print_dec_a
  377. call print_pc
  378. db " sectors",13,10,0
  379. ; We now know the period after which the address marks start repeating.
  380. ; Take the difference of the counter value that was stored at the 1st
  381. ; and address mark and the 1st replica of this mark.
  382. ;
  383. ; This difference should be around 0x38E0 (tested on real machine).
  384. ; TODO if measured value is far below 0x38E0, try doubling, tripling, ...
  385. ; until it gets in range.
  386. ld hl,(nb_sectors)
  387. ld a,h
  388. or l
  389. jp z,read_track ; skip ticks-check
  390. add hl,hl
  391. add hl,hl
  392. add hl,hl
  393. ld de,addr_buffer
  394. add hl,de
  395. ld de,(addr_buf_end)
  396. or a
  397. sbc hl,de
  398. jr c,ok_periodic
  399. ; period is whole buffer -> not periodic
  400. call print_pc
  401. db "Not periodic (read noise?)",13,10,0
  402. jp addr_retry
  403. ok_periodic add hl,de
  404. ld de,ofst_amark_tick
  405. add hl,de
  406. ld a,(hl)
  407. inc hl
  408. ld h,(hl)
  409. ld l,a
  410. ld de,(addr_buffer+ofst_amark_tick)
  411. or a
  412. sbc hl,de
  413. ld (ticks),hl
  414. ld a,(debug)
  415. or a
  416. jr z,debug_2
  417. call print_pc
  418. db ", ticks: ",0
  419. ld hl,(ticks)
  420. call print_dec_hl ; is this info useful?
  421. call print_pc
  422. db 13,10,0
  423. debug_2
  424. ; If there were read errors during the 'read address' command, then it's
  425. ; possible the detected period is larger than one disk revolution. This for
  426. ; example happened for the disks of 'New Vision Benelux'.
  427. ; We read the address marks for about 3 revolutions, but if there was a read
  428. ; error for e.g. an address mark in the 2nd revolution (so the read address
  429. ; command didn't return the exact same 6 bytes than for revolution 1 and 3),
  430. ; then the get_period routine won't detect the true period, but instead it
  431. ; returns the full 3 revolutions as the period (without internal repetition).
  432. ; We can detect this error by looking at the detected number of ticks for
  433. ; the period. If the detected period is for a single revolution, it should
  434. ; be in range [13834, 15290]. But if it's higher we've probably estimated
  435. ; more than one revolution.
  436. ; TODO also check for lower than 13834.
  437. ld hl,(ticks)
  438. ld de,(ticks_min) ; depends on driver
  439. or a
  440. sbc hl,de
  441. jr c,too_short
  442. add hl,de
  443. ld de,(ticks_max) ; depends on driver
  444. or a
  445. sbc hl,de
  446. jp nc,addr_retry ; maybe it works in the next attempt
  447. jr read_track
  448. too_short ld hl,(nb_sectors)
  449. jp next_period
  450. ; Use the WD2793 "read track" command to get the raw track data.
  451. ; Also store the number of read bytes. This is the track length.
  452. ; The 'normal' track length is 6250 bytes, but this can also vary.
  453. read_track
  454. ld a,'t'
  455. call debug_log
  456. call print_pc
  457. db "Read track ...",0
  458. ;; TODO is this call required?
  459. ;; Quibus reported a hang during 'Read track' at one point.
  460. ;; The LED of drive B was turned on when that happened.
  461. ;; The only way I can see how that's possible is that the
  462. ;; slot in page was somehow changed. Any other explanations???
  463. track_retry call select_fdc
  464. ld iy,(driver_rd_trck)
  465. jp (iy)
  466. track_too_much call print_pc
  467. db "Read track returned too much data",13,10,0
  468. jr read_track
  469. track_err call print_pc
  470. db "Read track error",13,10,0
  471. jp debug_exit
  472. track_no_start call print_pc
  473. db "Read track command failed to start!",13,10,0
  474. jp debug_exit
  475. track_end
  476. ex de,hl
  477. ld (track_stop),hl ; store for later
  478. ld de,trck_buffer
  479. or a
  480. sbc hl,de
  481. ld (track_len),hl
  482. ; TODO check in range [5938, 6562]?
  483. call print_pc
  484. db " length: ",0
  485. ld hl,(track_len)
  486. call print_dec_hl
  487. call print_pc
  488. db 13,10,0
  489. ; Quibus reported a hang after the tool printed "Read track .. length=12438"
  490. ; So it seemed the FDC somehow missed the index pulse and read the track data
  491. ; twice. This causes a buffer overflow later in the tool. To workaround this
  492. ; hardware quirk, we check that the tracklength in in range [5800..6700].
  493. ; That's +/-5% of the nominal track length.
  494. ld hl,(track_len)
  495. ld bc,6700+1
  496. or a
  497. sbc hl,bc
  498. jr nc,wrong_length
  499. ld hl,(track_len)
  500. ld bc,5800
  501. or a
  502. sbc hl,bc
  503. jr nc,length_ok
  504. wrong_length call print_pc
  505. db "Unexpected track length .. retrying ...",0
  506. jp track_retry
  507. length_ok
  508. ; Calculate the ratio between the number of ticks (the difference in counter
  509. ; value) and the track length. A typical value for the former is around 14560,
  510. ; for the latter it's around 6250. So the ratio between the two is smaller
  511. ; than 1. We calculate this ration as a 0.16-bit fractional number.
  512. ; Later this ratio will be used to estimate the position of the address marks
  513. ; in the raw track.
  514. ld hl,(track_len)
  515. ld bc,(ticks)
  516. call frac_div
  517. ld (ratio),de
  518. ; Copy the track data so that it is twice directly after each other in memory.
  519. ; This is a cheap way to implement 'circular-reads': on a real disk, if you
  520. ; read past the end of a track, you simply wrap around to the beginning of the
  521. ; track. With the copy reads (that only wrap once!) now behave the same.
  522. ;
  523. ; Note that the first dozen or so bytes returned by the read track command are
  524. ; totally unreliable. This is because the FDC has not yet seen any
  525. ; synchronization marks, so it has no idea which bit in the stream is the first
  526. ; bit of a byte. For us this is not a big problem because in the code below we
  527. ; only scan for these synchronization marks.
  528. ld bc,(track_len)
  529. ld hl,trck_buffer
  530. ld d,h
  531. ld e,l
  532. add hl,bc
  533. ex de,hl
  534. ldir
  535. ; Clear the DMK header. There is room for 64 IDAM entries. Unused position
  536. ; should contain the value 0x0000.
  537. ld hl,dmk_header
  538. ld de,dmk_header+1
  539. ld bc,sizeof_dmk_h-1
  540. ld (hl),0
  541. ldir
  542. ; Later we fill search the position of address and data marks in the raw track
  543. ; data. Clear that table now. Note that this table partly overlaps with the
  544. ; addr_buffer (where we stored the result of the "read address" commands).
  545. ; That's OK, from this point on we only need the first 64 entries from the
  546. ; that table anymore.
  547. ld hl,offset_buffer
  548. ld de,offset_buffer+1
  549. ld bc,sizeof_off_buf-1
  550. ld (hl),0
  551. ldir
  552. ; Now, for each data adress mark (returned by the "read address" command), try
  553. ; to locate it in the raw track data. For this we use the recorded counter
  554. ; value for that address mark and the earlier calculated ratio.
  555. ld a,(nb_sectors)
  556. or a ; if there are no address marks on
  557. jp z,no_sectors ; this track we're done
  558. ld a,'A'
  559. call debug_log
  560. ld a,(debug)
  561. or a
  562. jr z,skip_ana_prt
  563. call print_pc
  564. db "Analyze raw track ... ",0
  565. skip_ana_prt
  566. ld a,(nb_sectors)
  567. ld hl,offset_buffer ; store results in this table
  568. ld (ofst_buf_ptr),hl
  569. ld hl,addr_buffer
  570. addr_mark_loop ld (sector_cntr),a
  571. ld (addr_buf_ptr),hl
  572. ld a,(debug)
  573. or a
  574. jr z,skip_ana_prt2
  575. push hl
  576. ld a,(sector_cntr)
  577. call print_dec_a
  578. call print_pc
  579. db " ",0
  580. pop hl
  581. skip_ana_prt2
  582. ld a,'a'
  583. call debug_log
  584. ld de,ofst_amark_tick
  585. add hl,de
  586. ld e,(hl)
  587. inc hl
  588. ld d,(hl)
  589. ld bc,(ratio)
  590. call mul_hi ; hl = (de * bc) >> 16
  591. ld bc,trck_buffer
  592. add hl,bc
  593. ld (addr_estimate),hl
  594. ; We can only use this calculated position as a (fairly good) estimate of the
  595. ; position. The real position can be different for the following reasons:
  596. ; - we recorded the counter at the end of the "read address" command, while
  597. ; here we're looking for the start of the address mark
  598. ; - the counter we've used does not 100% increase with a constant rate (e.g.
  599. ; at the end of a command we have to do some extra stuff, and we don't
  600. ; increase the counter during that time)
  601. ; - the rotation speed (and maybe also the flux density?) is not 100%
  602. ; constant
  603. ; To compensate for this we only use the calculated position as the starting
  604. ; point for the search. If we don't find the mark at exactly this position, we
  605. ; try the adjacent few bytes (both up and down). Tests on a real machine have
  606. ; shown that usually we find the mark withing 2 or 3 bytes from the calculated
  607. ; position (but here we try up to 5 bytes (up and down) from the calculated
  608. ; position).
  609. ; TODO more tests on Quibus machine indicated that (in rare cases?) 5 bytes is
  610. ; not enough. I've currently increased it up to 20 bytes. But that's most
  611. ; likely too much (searching too far from the initial position has a risk of
  612. ; finding a different mark in the wrong position)
  613. ;
  614. ; We look for the bytes 0xA1 0xA1 0xFE. The real address mark still has a 3rd
  615. ; byte 0xA1 in front of this sequence. But tests on a real WD2793 have shown
  616. ; that this byte is very often read wrong by the "read track" command. (Later
  617. ; we will correct this so that the data in the DMK file has the correct
  618. ; sequence A1 A1 A1 FE).
  619. ;
  620. ; The disk "Demo Kit Deluxe" has at the start of the track the sequence
  621. ; "A1 A1 A1 FC" (instead of the usual sequence C2 C2 C2 FC). When doing tests
  622. ; with this disk on a real machine, we found that the "read address" command
  623. ; also returns the 6 bytes following the "A1 A1 A1 FC" sequence (the expected
  624. ; sequence for an address mark is A1 A1 A1 FE). So it seems the WD2793 accepts
  625. ; both FC and FE in the address mark sequence.
  626. ld de,ofst_tab
  627. ofst_next ld hl,(addr_estimate) ; restore initial estimate
  628. ld a,(de)
  629. inc de
  630. cp #80
  631. jp z,ofst_err ; reached the end of the offset table
  632. ld c,a
  633. ld a,(de)
  634. inc de
  635. ld b,a ; 16-bit offset
  636. add hl,bc ; add offset
  637. ld a,(hl)
  638. cp #A1
  639. jr nz,ofst_next
  640. inc hl
  641. ld a,(hl)
  642. cp #A1
  643. jr nz,ofst_next
  644. inc hl
  645. ld a,(hl)
  646. cp #FE
  647. jr z,ofst_1
  648. cp #FC ; see comments above
  649. jr nz,ofst_next
  650. ofst_1
  651. dec hl
  652. dec hl
  653. dec hl ; points to start of A1 A1 A1 FE sequence
  654. ex de,hl
  655. ld hl,(ofst_buf_ptr)
  656. ld (hl),e
  657. inc hl
  658. ld (hl),d ; store location in offset_buffer
  659. ;;push de
  660. ;;call print_pc
  661. ;;db " addr_mark=0x",0
  662. ;;pop hl
  663. ;;call print_hex_hl
  664. ; Now verify the CRC of the address mark. We use the data returned by the
  665. ; "read address" command (not the data in the raw track). If there is a CRC
  666. ; error we don't need to look for the data mark.
  667. ;
  668. ; Alternatively we could use the CRC-error-bit in the WD2793 status register
  669. ; to see if there was a CRC error. Though I prefered to not do that to keep
  670. ; the read-all-address-marks loop as fast as possible.
  671. ;
  672. ; The CRC value includes the 4 bytes of the address mark header (A1 A1 A1 FE)
  673. ; and the 4 actual "C H R N" bytes stored in the address.
  674. ld hl,#B230 ; precalculated CRC for A1 A1 A1 FE
  675. ld de,(addr_buf_ptr)
  676. ld a,(de) ; C
  677. call crc_byte
  678. inc de
  679. ld a,(de) ; H
  680. call crc_byte
  681. inc de
  682. ld a,(de) ; R
  683. call crc_byte
  684. inc de
  685. ld a,(de) ; N
  686. call crc_byte
  687. inc de
  688. ld a,(de) ; CRC (high byte)
  689. cp h
  690. jr nz,addr_crc_err
  691. inc de
  692. ld a,(de) ; CRC (low byte)
  693. cp l
  694. jr nz,addr_crc_err
  695. ;;call print_pc
  696. ;;db " CRC-OK",0
  697. ; We found the address mark and it has a valid CRC. Now search for the data
  698. ; mark. According to the WD2793 datasheet, the data mark should occur within
  699. ; 43 bytes from (the end of) the address mark.
  700. ;
  701. ; A data mark starts with the sequence "A1 A1 A1 FB" (normal data mark) or
  702. ; "A1 A1 A1 F8" (deleted data mark). But just as for the address mark, the
  703. ; WD2793 "read track" command cannot reliably read the first A1 byte of this
  704. ; sequence, so we ignore it while searching.
  705. ld hl,(ofst_buf_ptr)
  706. ld a,(hl)
  707. inc hl
  708. ld h,(hl)
  709. ld l,a ; hl = start of address mark
  710. ld de,10-1
  711. add hl,de ; end of address mark
  712. ld b,43+4 ; should find data mark within 43 bytes
  713. data_mark_1 dec b
  714. jp z,data_err
  715. inc hl
  716. ld a,(hl)
  717. cp #A1
  718. jr nz,data_mark_1
  719. data_mark_2 dec b
  720. jp z,data_err
  721. inc hl
  722. ld a,(hl)
  723. cp #A1
  724. jr nz,data_mark_1
  725. data_mark_3 dec b
  726. jp z,data_err
  727. inc hl
  728. ld a,(hl) ; data mark type (deleted or normal)
  729. cp #A1
  730. jr z,data_mark_3
  731. cp #FB
  732. jr z,data_mark_found
  733. cp #F8
  734. jr nz,data_mark_1
  735. data_mark_found
  736. dec hl
  737. dec hl
  738. dec hl ; points to start of A1 A1 A1 FB sequence
  739. ld de,(track_stop)
  740. or a
  741. sbc hl,de
  742. jr c,data_mark_4
  743. ld de,trck_buffer
  744. data_mark_4 add hl,de
  745. ex de,hl
  746. ld hl,(ofst_buf_ptr)
  747. inc hl
  748. inc hl
  749. ld (hl),e
  750. inc hl
  751. ld (hl),d ; data mark offset
  752. inc hl
  753. ld (hl),a ; data mark type
  754. ;;push af
  755. ;;push de
  756. ;;call print_pc
  757. ;;db " data_mark=0x",0
  758. ;;pop hl
  759. ;;call print_hex_hl
  760. ;;call print_pc
  761. ;;db " type=0x",0
  762. ;;pop af
  763. ;;call print_hex_a
  764. jr next_addr_mark
  765. addr_crc_err ; address mark had a CRC error (not an error for us)
  766. ;;call print_pc
  767. ;;db " CRC-ERR",0
  768. jr next_addr_mark
  769. data_err ; didn't find data mark in time (not an error for us)
  770. ;;call print_pc
  771. ;;db " data mark not found",0
  772. jr next_addr_mark
  773. ; Also locate address and data marks for the other sectors in this track
  774. next_addr_mark
  775. ;;call print_pc
  776. ;;db 13,10,0
  777. ld hl,(ofst_buf_ptr)
  778. ld de,sizeof_offinfo
  779. add hl,de
  780. ld (ofst_buf_ptr),hl
  781. ld hl,(addr_buf_ptr)
  782. ld de,sizeof_amark
  783. add hl,de
  784. ld a,(sector_cntr)
  785. dec a
  786. jp nz,addr_mark_loop
  787. ld a,(debug)
  788. or a
  789. jr z,skip_ana_prt3
  790. call print_pc
  791. db 13,10,0
  792. skip_ana_prt3
  793. ; We've located the address and data mark for each sector in the raw track
  794. ; data. Now start overwriting the sector data in the raw track data with
  795. ; data from an actual "read sector" command. Do this because tests on a real
  796. ; WD2793 have shown that the data returned by "read sector" is more reliable
  797. ; than the same data returned by "read track". This is especially true for a
  798. ; sector that wrap around the end of the track (so past the index point).
  799. ld a,'S'
  800. call debug_log
  801. call print_pc
  802. db "Read sectors ... ",0
  803. ld hl,sector_buffer
  804. ld (sector_buf_ptr),hl
  805. ; The appraoch below reads the correct sector data even if there are multiple
  806. ; sectors with the same ID present in the same track. It works well, but it's
  807. ; very slow (see below for details about the used approach). It can take 45
  808. ; minutes to dump a whole disk using this appraoch!
  809. ; In the majority of the cases the track does not have duplicate sectors IDs,
  810. ; in that case we can use a much faster approach.
  811. ld hl,unique_buffer
  812. ld de,unique_buffer+1
  813. ld bc,256-1
  814. ld (hl),#ff
  815. ldir ; fill unique_buffer with #ff
  816. ld a,(nb_sectors)
  817. ld bc,sizeof_amark
  818. ld hl,addr_buffer+ofst_amark_R
  819. ld d,unique_buffer/256
  820. count_loop ld e,(hl) ; 'R'-value of address-mark
  821. ex de,hl
  822. inc (hl)
  823. jr nz,read_slow ; if we increase #ff more than once
  824. ex de,hl ; it's non-zero, in that case there's
  825. add hl,bc ; a duplicate and we must use the
  826. dec a ; slow approach
  827. jr nz,count_loop
  828. read_fast ld a,1
  829. jr set_speed
  830. read_slow xor a
  831. set_speed ld (read_speed),a
  832. ld hl,offset_buffer
  833. ld (ofst_buf_ptr),hl
  834. ld a,(nb_sectors)
  835. ld hl,addr_buffer
  836. sector_loop ld (sector_cntr),a
  837. ld (addr_buf_ptr),hl
  838. call print_dec_a
  839. call print_pc
  840. db " ",0
  841. ; Skip sectors for which we didn't find a data mark previously.
  842. ld hl,(ofst_buf_ptr)
  843. inc hl
  844. inc hl
  845. ld a,(hl)
  846. inc hl
  847. or (hl)
  848. jp z,next_sector
  849. ; Reading a specific sector on some copy protected disks is not that simple
  850. ; because it can happen that a sector with the same identification header (so
  851. ; same address mark) appears multiple times on the same track. It's really
  852. ; important that we read the correct version.
  853. ;
  854. ; To solve this, we wait till the index pulse, then execute some delay loop
  855. ; (delay is based on the counter value we recorded during the "read address"
  856. ; phase above) and only then we execute the "read sector" command. For extra
  857. ; safety we measure the time between the start of the command and the moment
  858. ; we receive the first data from the command. If this difference is too big we
  859. ; adjust the delay value and try again.
  860. ld a,'s'
  861. call debug_log
  862. ld hl,64
  863. ld (adjust_ofst),hl
  864. ld (adjust_scale),hl
  865. try_read_sector xor a
  866. retry_crc ld (crc_retries),a
  867. ld hl,(addr_buf_ptr)
  868. ld b,(hl) ; 'C' value from read address command
  869. inc hl ; 'H'
  870. inc hl
  871. ld c,(hl) ; 'R'
  872. inc hl ; 'N'
  873. inc hl ; CRC1
  874. inc hl ; CRC2
  875. inc hl
  876. ld a,(hl)
  877. inc hl
  878. ld h,(hl)
  879. ld l,a ; hl = counter value
  880. ld de,(adjust_ofst)
  881. or a ; counter value was recorded at end of the
  882. sbc hl,de ; "read address" command, we need to wait
  883. ; till the start of the address mark, so
  884. ; wait a bit less
  885. ld de,(sector_buf_ptr)
  886. ld iy,(driver_rd_sect)
  887. jp (iy)
  888. sector_end
  889. ex de,hl
  890. ld de,(sector_buf_ptr)
  891. or a ; sector length, should be one of
  892. sbc hl,de ; 128, 256, 512 or 1024
  893. ld (sector_size),hl
  894. ex de,hl
  895. ld hl,(ofst_buf_ptr)
  896. ld bc,ofst_oi_size
  897. add hl,bc
  898. ld (hl),e
  899. inc hl
  900. ld (hl),d ; store sector size
  901. inc hl
  902. ld bc,(sector_buf_ptr)
  903. ld (hl),c
  904. inc hl
  905. ld (hl),b ; store pointer to sector data
  906. ld b,a
  907. and 8 ; crc error?
  908. jr z,read_no_crc_err
  909. ld a,(crc_retries) ; Only when we have 5 crc errors, we
  910. inc a ; believe it's an intentional crc error
  911. cp 5 ; on the disk (and not some random read
  912. jp c,retry_crc ; error on an (old) disk).
  913. read_no_crc_err
  914. ld a,(read_speed)
  915. or a
  916. jr nz,sector_ok
  917. ld a,ixh
  918. or a
  919. jr nz,sector_retry
  920. ld a,ixl
  921. cp 150
  922. jr c,sector_ok
  923. sector_retry
  924. ld a,'t'
  925. call debug_log
  926. ld a,(debug)
  927. or a
  928. jr z,debug_1
  929. push ix
  930. call print_pc
  931. db 13,10,"|",0
  932. pop hl
  933. push hl
  934. call print_hex_hl
  935. call print_pc
  936. db " ",0
  937. ld hl,(adjust_ofst)
  938. call print_hex_hl
  939. call print_pc
  940. db " ",0
  941. ld hl,(adjust_scale)
  942. call print_hex_hl
  943. call print_pc
  944. db "|",0
  945. pop ix
  946. debug_1
  947. ld hl,(adjust_scale)
  948. ld d,h
  949. ld e,l
  950. srl d
  951. rr e
  952. srl d
  953. rr e
  954. srl d
  955. rr e
  956. or a
  957. sbc hl,de
  958. ld (adjust_scale),hl ; scale = scale - scale/8
  959. ex de,hl
  960. ld hl,(adjust_ofst)
  961. ld a,ixh
  962. cp 5
  963. jr c,sector_sub
  964. add hl,de
  965. jr sector_2
  966. sector_sub or a
  967. sbc hl,de
  968. sector_2: ld (adjust_ofst),hl
  969. jp try_read_sector
  970. sector_ok ld a,'o'
  971. call debug_log
  972. ld hl,(ofst_buf_ptr)
  973. ld de,ofst_oi_status
  974. add hl,de
  975. ld (hl),b ; b = status register
  976. ; We've read the sector, now copy it to the correct location in the raw track
  977. ; buffer. We can't immediately read it in the correct place because we have
  978. ; to perform a copy to a circular destination buffer (doing it inside the
  979. ; read-sector loop might be too slow).
  980. ld hl,(ofst_buf_ptr)
  981. ld bc,ofst_oi_ptr+1
  982. add hl,bc
  983. ld b,(hl)
  984. dec hl
  985. ld c,(hl)
  986. dec hl ; bc = pointer to sector data
  987. push bc
  988. ld b,(hl)
  989. dec hl
  990. ld c,(hl) ; bc = sector size
  991. dec hl
  992. dec hl
  993. dec hl
  994. dec hl
  995. ld a,(hl)
  996. inc hl
  997. ld h,(hl)
  998. ld l,a ; hl = pos of data mark
  999. inc hl
  1000. inc hl
  1001. inc hl
  1002. inc hl ; position of actual sector data
  1003. ld de,(track_stop)
  1004. or a
  1005. sbc hl,de
  1006. jr c,circular_1
  1007. ld de,trck_buffer
  1008. circular_1 add hl,de
  1009. ex de,hl
  1010. pop hl ; hl = pointer to sector data
  1011. call circular_ldir
  1012. ld (sector_stop),de
  1013. ; Did the "read sector" command return a CRC error? If so, we keep the CRC value
  1014. ; from the raw track data. But if there was no CRC error, we calculate the
  1015. ; correct CRC value and store that in the raw track data. Most of the time this
  1016. ; calculated value will be the same as the value that is already present in the
  1017. ; raw track data, though not in case the sector wrapped around the end of the
  1018. ; track.
  1019. ld hl,(ofst_buf_ptr)
  1020. ld bc,ofst_oi_status
  1021. add hl,bc
  1022. ld a,(hl) ; sector status
  1023. and 8
  1024. jr nz,sector_crc_err ; skip calculating CRC
  1025. ;;push hl
  1026. ;;call print_pc
  1027. ;;db " CRC-OK",0
  1028. ;;pop hl
  1029. dec hl
  1030. ld a,(hl) ; a = data mark type (is part of CRC)
  1031. inc hl
  1032. inc hl
  1033. ld c,(hl)
  1034. inc hl
  1035. ld b,(hl) ; bc = sector size
  1036. inc hl
  1037. ld e,(hl)
  1038. inc hl
  1039. ld d,(hl) ; de = pointer to sector data
  1040. ld hl,#CDB4 ; precalculated CRC for sequence "A1 A1 A1"
  1041. push bc
  1042. call crc_byte
  1043. pop bc
  1044. sector_crc_loop ld a,(de)
  1045. inc de
  1046. push bc
  1047. call crc_byte
  1048. pop bc
  1049. dec bc
  1050. ld a,b
  1051. or c
  1052. jr nz,sector_crc_loop
  1053. ex de,hl ; de = CRC value
  1054. ld hl,(sector_stop)
  1055. ld (hl),d ; CRC is stored big endian
  1056. inc hl
  1057. ld a,(track_stop)
  1058. cp l
  1059. jr nz,copy_crc_next
  1060. ld a,(track_stop+1)
  1061. cp h
  1062. jr nz,copy_crc_next
  1063. ld hl,trck_buffer
  1064. copy_crc_next ld (hl),e
  1065. jr next_sector
  1066. sector_crc_err ;;call print_pc
  1067. ;;db " CRC-ERR",0
  1068. ; Sector data (and possibly CRC value) is stored in raw track buffer.
  1069. ; Continue with the next sector.
  1070. next_sector
  1071. ld hl,(sector_buf_ptr)
  1072. ld bc,(sector_size)
  1073. add hl,bc
  1074. ld (sector_buf_ptr),hl
  1075. ld a,h
  1076. cp unique_buffer/256
  1077. jp nc,buffer_overflow
  1078. ;;call print_pc
  1079. ;;db 13,10,0
  1080. ld hl,(ofst_buf_ptr)
  1081. ld de,sizeof_offinfo
  1082. add hl,de
  1083. ld (ofst_buf_ptr),hl
  1084. ld hl,(addr_buf_ptr)
  1085. ld de,sizeof_amark
  1086. add hl,de
  1087. ld a,(sector_cntr)
  1088. dec a
  1089. jp nz,sector_loop
  1090. call print_pc
  1091. db 13,10,0
  1092. ; At this point we've read the raw track data and overwritten it with data
  1093. ; from "read sector" commands. Though we still need to make some more
  1094. ; adjustments:
  1095. ; - the read track command doesn't reliably read the first A1 byte in a
  1096. ; address or data mark sequence.
  1097. ; - I found that sometimes the "read sector" command had overwritten the
  1098. ; address mark of another sector with different data (e.g. this happened
  1099. ; while experimenting with the Pixess game disk which intentionally has
  1100. ; overlapping sector)
  1101. ; To fix both problems we now restore the address and data marks.
  1102. ;
  1103. ; We also record the position of the address marks in the DMK track header.
  1104. ld a,'F'
  1105. call debug_log
  1106. ld a,(debug)
  1107. or a
  1108. jr z,skip_fix_prt
  1109. call print_pc
  1110. db "Fixup markers ...",13,10,0
  1111. skip_fix_prt
  1112. ld hl,offset_buffer
  1113. ld (ofst_buf_ptr),hl
  1114. ld hl,dmk_header
  1115. ld (dmk_ptr),hl
  1116. ld a,(nb_sectors)
  1117. ld hl,addr_buffer
  1118. fixup_loop ld (sector_cntr),a
  1119. ld (addr_buf_ptr),hl
  1120. ld a,'f'
  1121. call debug_log
  1122. ld hl,(ofst_buf_ptr)
  1123. ld e,(hl)
  1124. inc hl
  1125. ld d,(hl) ; de = pos of addr mark
  1126. inc hl
  1127. push hl
  1128. push de
  1129. ld hl,addr_mark
  1130. ld bc,4
  1131. call circular_ldir
  1132. ld hl,(addr_buf_ptr)
  1133. ld bc,6
  1134. call circular_ldir
  1135. pop hl ; pos of addr mark
  1136. ld de,trck_buffer
  1137. or a
  1138. sbc hl,de
  1139. ld de,#8083
  1140. add hl,de
  1141. ex de,hl
  1142. ld hl,(dmk_ptr)
  1143. ld (hl),e
  1144. inc hl
  1145. ld (hl),d
  1146. inc hl
  1147. ld (dmk_ptr),hl
  1148. pop hl
  1149. ld e,(hl)
  1150. inc hl
  1151. ld d,(hl)
  1152. ld a,e
  1153. or d
  1154. jr z,fixup_next ; no data mark
  1155. inc hl
  1156. push hl
  1157. ld hl,addr_mark
  1158. ld bc,3
  1159. call circular_ldir
  1160. pop hl
  1161. ld a,(hl)
  1162. ld (de),a ; copy data mark type
  1163. fixup_next ld hl,(ofst_buf_ptr)
  1164. ld de,sizeof_offinfo
  1165. add hl,de
  1166. ld (ofst_buf_ptr),hl
  1167. ld hl,(addr_buf_ptr)
  1168. ld de,sizeof_amark
  1169. add hl,de
  1170. ld a,(sector_cntr)
  1171. dec a
  1172. jr nz,fixup_loop
  1173. ; Done. ... Well, not quite ...
  1174. ; In theory everything should be done at this point. However tests on a real
  1175. ; machine have shown that for some disks we *sometimes* still get the wrong
  1176. ; data at this point. This happened for disks which have overlapping sectors
  1177. ; (e.g. sunrise disks). When I did a "read track" on such a disk, I found that
  1178. ; the distance in bytes between the start of the sectors is sometimes N but
  1179. ; sometimes N+1! Normally this doesn't matter (and this variation might be the
  1180. ; reason why there are gaps between sectors). Though in case of overlapping
  1181. ; sectors, if the relative start of the two sectors is shifted by a byte, then
  1182. ; the CRC of the sectors will be different (in case of the sunrise protection,
  1183. ; the CRC of the first sector is part of the data of the second sector). The
  1184. ; only way I found to detect/correct this problem is to verify the CRCs of the
  1185. ; sectors and if we find one that is not correct (while it should be) just try
  1186. ; again and hope we get the correct relative distance on the next attempt.
  1187. ; On a real machine I found that trying 3-4 times is enough to get the correct
  1188. ; data. Here we try up to 20 times.
  1189. ;
  1190. ; ... And it gets even more complicated. Compjoetania disks (e.g. Pixess or
  1191. ; NoiseDisk(?)) contain a track with a sector with the 'wrong' sectorsize. I
  1192. ; mean in the track layout that sector completely looks like a 512 byte sector
  1193. ; (so stuff like headers, gaps, CRC, ...). Only the sector size field has the
  1194. ; value 255 instead of 2. The WD2793 only looks at the lowest 2 bits of this
  1195. ; field, so for the WD2793 this is a 1024 byte sector. But with this larger
  1196. ; size the sector actually overlaps with the next sector. And because only the
  1197. ; size field was changed, the CRC of the sector is wrong (there's no correct
  1198. ; CRC 1024 bytes after the start of the sector). And to make it even more
  1199. ; complex: the distance between both sectors is not a multiple of 8 bits (I
  1200. ; think). At least if you read the 1024-byte sector, the last part of that data
  1201. ; does not show the sector headers etc of the next sector. The DMK file format
  1202. ; cannot represent non-integer byte offsets. But luckily the content of that
  1203. ; 1024 byte sector isn't checked by the software. That is the MSX software, but
  1204. ; it was checked in earlier versions of READ-DMK in this verify step. And
  1205. ; verification then failed.
  1206. ;
  1207. ; So what we do now is skip verification for overlapping sectors that have a
  1208. ; CRC error. So for sunrise disks we do verify the (overlapping) sector, but
  1209. ; for Compjoetania disks we don't. Non-overlapping sectors are always verified.
  1210. ld a,'V'
  1211. call debug_log
  1212. call print_pc
  1213. db "Verifying ... ",0
  1214. ld hl,offset_buffer
  1215. ld a,(nb_sectors)
  1216. verify_loop ld (sector_cntr),a
  1217. ld (ofst_buf_ptr),hl
  1218. ld a,'v'
  1219. call debug_log
  1220. ;;push hl
  1221. ;;call print_dec_a ; TODO print_dec
  1222. ;;call print_pc
  1223. ;;db ": ",0
  1224. ;;pop hl
  1225. inc hl
  1226. inc hl
  1227. ld e,(hl)
  1228. inc hl
  1229. ld d,(hl) ; de = location of data mark
  1230. ld a,e
  1231. or d
  1232. jp z,verify_next
  1233. inc hl
  1234. inc hl
  1235. ld a,(hl) ; a = read sector status
  1236. ld (crc_status),a
  1237. inc hl
  1238. ld c,(hl)
  1239. inc hl
  1240. ld b,(hl) ; bc = sector length
  1241. inc hl
  1242. push bc
  1243. ld c,(hl)
  1244. inc hl
  1245. ld b,(hl) ; bc = sector data
  1246. inc hl
  1247. push bc
  1248. pop ix ; ix = sector data
  1249. ld c,(hl)
  1250. inc hl
  1251. ld b,(hl)
  1252. push bc
  1253. pop iy ; iy = addr mark of next sector
  1254. verify_mark ld b,4 ; length of data mark
  1255. ld hl,#ffff ; initialize CRC
  1256. circular_crc1 ld a,(de)
  1257. inc de
  1258. push bc
  1259. call crc_byte
  1260. pop bc
  1261. ld a,(track_stop)
  1262. cp e
  1263. jr nz,circ_crc_next1
  1264. ld a,(track_stop+1)
  1265. cp d
  1266. jr nz,circ_crc_next1
  1267. ld de,trck_buffer
  1268. circ_crc_next1 djnz circular_crc1
  1269. ld a,'w'
  1270. call debug_log
  1271. pop bc ; bc = sector length
  1272. check_overlap push hl
  1273. push de
  1274. push bc
  1275. push iy
  1276. pop hl ; hl = addr mark of next sector
  1277. or a
  1278. sbc hl,de ; hl = distance between this sector data and next sector header
  1279. jr nc,check_overlap1
  1280. ld de,(track_len)
  1281. add hl,de ; handle wrapping
  1282. check_overlap1 inc bc
  1283. inc bc ; 2 CRC bytes
  1284. or a
  1285. sbc hl,bc ; distance smaller than sector size?
  1286. pop bc
  1287. pop de
  1288. pop hl
  1289. jr nc,verify_content ; not smaller -> no overlap
  1290. overlap ld a,'0'
  1291. call debug_log
  1292. ld a,(crc_status)
  1293. and 8
  1294. jr z,verify_content ; no CRC error -> verify sector content
  1295. ld a,'C'
  1296. call debug_log
  1297. jp verify_next ; overlap with CRC error -> skip verify
  1298. verify_content
  1299. circular_crc ld a,(de)
  1300. cp (ix+0)
  1301. jr nz,verify_data
  1302. inc de
  1303. inc ix
  1304. push bc
  1305. call crc_byte
  1306. pop bc
  1307. ld a,(track_stop)
  1308. cp e
  1309. jr nz,circ_crc_next
  1310. ld a,(track_stop+1)
  1311. cp d
  1312. jr nz,circ_crc_next
  1313. ld de,trck_buffer
  1314. circ_crc_next dec bc
  1315. ld a,b
  1316. or c
  1317. jr nz,circular_crc
  1318. ld a,'x'
  1319. call debug_log
  1320. ex de,hl
  1321. ld b,(hl)
  1322. inc hl
  1323. ld c,(hl) ; bc = on-disk CRC (stored big endian)
  1324. ex de,hl ; hl = calculated CRC
  1325. or a
  1326. sbc hl,bc
  1327. jr z,crc_match
  1328. ;;call print_pc
  1329. ;;db " should have CRC error ... ", 0
  1330. crc_mismatch
  1331. ld a,'m'
  1332. call debug_log
  1333. ld a,(crc_status)
  1334. and 8
  1335. jr nz,verify_next ; ok, read sector command also returned CRC err
  1336. ld a,'M'
  1337. jr verify_retry
  1338. verify_data ld a,'D'
  1339. verify_retry call debug_log
  1340. call print_pc
  1341. db "FAILED",13,10,0
  1342. maybe_retry ld a,(retries)
  1343. inc a
  1344. ld (retries),a
  1345. cp 20
  1346. jr c,do_retry
  1347. jp retry_error
  1348. do_retry ld a,(debug)
  1349. or a
  1350. jr z,no_debug_write
  1351. call write_debug
  1352. call select_fdc
  1353. call seek
  1354. no_debug_write jp retry
  1355. crc_match
  1356. ld a,'n'
  1357. call debug_log
  1358. ;;call print_pc
  1359. ;;db " should not have CRC error ... ", 0
  1360. ld a,(crc_status)
  1361. and 8
  1362. ld a,'N'
  1363. jr nz,verify_retry ; CRC did match, but it shouldn't have
  1364. verify_next ;;call print_pc
  1365. ;;db "OK",13,10,0
  1366. ld hl,(ofst_buf_ptr)
  1367. ld de,sizeof_offinfo
  1368. add hl,de
  1369. ld a,(sector_cntr)
  1370. dec a
  1371. jp nz,verify_loop
  1372. verify_done
  1373. ; Really done.
  1374. ; Write the data to disk (the second drive).
  1375. ; TODO this tool should also be usuable on machines with only one disk drive.
  1376. ; So we should ask the user to swap disks. To make it more comfortable, we
  1377. ; should try to minimize the number of required swaps. So we should buffer the
  1378. ; data in (v)ram.
  1379. success call enable_irq
  1380. call print_pc
  1381. db "Success!!!",13,10,0
  1382. ld a,(cylinder)
  1383. ld hl,fcb+1+4
  1384. ld b,'0'-1
  1385. dec_loop inc b
  1386. sub 10
  1387. jr nc,dec_loop
  1388. ld (hl),b
  1389. add a,'0'+10
  1390. inc hl
  1391. ld (hl),a
  1392. ld a,(side)
  1393. add a,'0'
  1394. inc hl
  1395. inc hl
  1396. ld (hl),a
  1397. retry_open ld de,fcb
  1398. ld c,#16 ; create file
  1399. call #0005
  1400. or a
  1401. jp nz,open_error
  1402. ld hl,1
  1403. ld (fcb+14),hl ; set record size (1 byte)
  1404. ld hl,0
  1405. ld (fcb+33),hl
  1406. ld (fcb+35),hl ; record number
  1407. ld de,dmk_header
  1408. ld c,#1a ; set disk transfer address
  1409. call #0005
  1410. ld hl,(track_len)
  1411. ld bc,128
  1412. add hl,bc ; hl = #bytes to write
  1413. ld de,fcb
  1414. ld c,#26 ; random block write
  1415. call #0005
  1416. or a
  1417. jp nz,write_error
  1418. ld de,fcb
  1419. ld c,#10 ; close file
  1420. call #0005
  1421. or a
  1422. jp nz,close_error
  1423. ld a,(side)
  1424. inc a
  1425. cp 2
  1426. jp nz,side_loop
  1427. ;; TODO use step-in
  1428. ld a,(stop_track)
  1429. inc a
  1430. ld b,a
  1431. ld a,(cylinder)
  1432. inc a
  1433. cp b
  1434. jp nz,cylinder_loop
  1435. exit call deselect_fdc
  1436. call enable_irq
  1437. ld c,#00
  1438. jp #0005 ; exit program
  1439. ; We didn't find any sectors in this track. If we're already at cylinder 80 or
  1440. ; higher this means we're done. Though if the user explicitly set the
  1441. ; stop-cylinder, we continue until that cylinder.
  1442. ;
  1443. ; In case there's a 81th track on side 0, but not on side 1 we don't want to
  1444. ; stop dumping because the combine-dmk tool expects to see always track info
  1445. ; for both sides.
  1446. no_sectors ld a,(cylinder)
  1447. cp 80
  1448. jp c,verify_done ; not yet at cylinder 80
  1449. ld a,(stop_set)
  1450. or a
  1451. jp nz,verify_done ; user explicitly set end-cylinder
  1452. ld a,(side)
  1453. or a
  1454. jp nz,verify_done ; if we're not on side 0, then continue
  1455. call print_pc
  1456. db 13,10
  1457. db "End of disk detected.",13,10,0
  1458. jp exit
  1459. open_error call print_pc
  1460. db "Error opening file",0
  1461. err_retry call print_pc
  1462. db " ... press key to retry ...",0
  1463. ld ix,#009f
  1464. ld iy,(#fcc0)
  1465. call #001c
  1466. call print_pc
  1467. db 13,10,0
  1468. jp retry_open
  1469. write_error call print_pc
  1470. db "Error writing file",13,10,0
  1471. delete_file ld de,fcb
  1472. ld c,#13 ; delete file
  1473. call #0005 ; when the disk is full we get a write error
  1474. ; but it also leaves a zero-sized file behind
  1475. jr err_retry ; so here we delete it
  1476. close_error call print_pc
  1477. db "Error closing file",13,10,0
  1478. jr delete_file
  1479. ofst_err call print_pc
  1480. db "Failed to find address mark in raw track data 0x",0
  1481. ld hl,(addr_estimate)
  1482. call print_hex_hl
  1483. call print_pc
  1484. db 13,10,0
  1485. jp maybe_retry
  1486. sector_err call print_pc
  1487. db "Read sector command didn't find sector",0
  1488. jp maybe_retry
  1489. retry_error call print_pc
  1490. db "Unsuccessful after 20 retries :-(",13,10,0
  1491. jr debug_exit
  1492. buffer_overflow call print_pc
  1493. db "Sector buffer overflow",13,10,0
  1494. debug_exit call write_debug
  1495. jp exit
  1496. write_debug call print_pc
  1497. db "Writing debug file ...",13,10,0
  1498. ld de,fcb_debug
  1499. ld c,#16 ; create file
  1500. call #0005
  1501. or a
  1502. jr nz,debug_error
  1503. ld hl,1
  1504. ld (fcb_debug+14),hl ; set record size (1 byte)
  1505. ld hl,0
  1506. ld (fcb_debug+33),hl
  1507. ld (fcb_debug+35),hl ; record number
  1508. ld de,#8000
  1509. ld c,#1a ; set disk transfer address
  1510. call #0005
  1511. ld hl,#4000
  1512. ld de,fcb_debug
  1513. ld c,#26 ; random block write
  1514. call #0005
  1515. or a
  1516. jr nz,debug_error
  1517. ld de,fcb_debug
  1518. ld c,#10 ; close file
  1519. call #0005
  1520. or a
  1521. jr nz,debug_error
  1522. ret
  1523. debug_error call print_pc
  1524. db "Error while writing debug file",13,10,0
  1525. ret
  1526. unknown_option call print_pc
  1527. db "Unknown command line option",13,10,0
  1528. jp exit
  1529. expected_int call print_pc
  1530. db "Error parsing command line: expected integer",13,10,0
  1531. jp exit
  1532. ; We disable VDP IRQs because the BIOS print routine enables interrupts (EI)
  1533. ; and that interferes with the low level drive settings we're doing (e.g. it
  1534. ; can turn the motor off) a better solution would be to make sure we only print
  1535. ; at non-critical places and/or restore all FDC state after a print. Or write
  1536. ; our own printing routine. And of course there could be other IRQ sources in
  1537. ; the MSX machine, so this is really only a hack (though would those other
  1538. ; sources also trigger the motor timeout mechanism??)
  1539. disable_irq di
  1540. ld a,(#f3e0)
  1541. and #df
  1542. out (#99),a
  1543. ld (#f3e0),a
  1544. ld a,1+128
  1545. out (#99),a ; disable VDP IRQs
  1546. ret
  1547. enable_irq di
  1548. ld a,(#f3e0)
  1549. or #20
  1550. out (#99),a
  1551. ld (#f3e0),a
  1552. ld a,1+128
  1553. out (#99),a
  1554. ei
  1555. ret
  1556. select_fdc call disable_irq
  1557. ld iy,(driver_select)
  1558. jp (iy)
  1559. deselect_fdc ld iy,(driver_deselect)
  1560. jp (iy)
  1561. seek ld iy,(driver_seek)
  1562. jp (iy)
  1563. circular_ldir ld a,(hl)
  1564. ld (de),a
  1565. inc de
  1566. inc hl
  1567. ld a,(track_stop)
  1568. cp e
  1569. jr nz,ldir_next
  1570. ld a,(track_stop+1)
  1571. cp d
  1572. jr nz,ldir_next
  1573. ld de,trck_buffer
  1574. ldir_next dec bc
  1575. ld a,b
  1576. or c
  1577. jr nz,circular_ldir
  1578. ret
  1579. delay: ld hl,50000
  1580. delay0 ex (sp),hl
  1581. ex (sp),hl
  1582. dec hl
  1583. ld a,h
  1584. or l
  1585. jr nz,delay0
  1586. ret
  1587. ; Input: [DE] = ptr to start of block
  1588. ; [IX] = ptr to end of block (right after end)
  1589. ; [HL] = previous result (or zero), now search for a longer period
  1590. ; Output [HL] = period
  1591. get_period: inc hl
  1592. p_loop: push hl
  1593. push de
  1594. call test_period
  1595. pop de
  1596. pop hl
  1597. ret z
  1598. inc hl
  1599. jr p_loop
  1600. ; In: [de] = start
  1601. ; [ix] = end
  1602. ; [hl] = candidate period
  1603. ; Out: Z -> period found
  1604. ; NZ -> period not found
  1605. test_period: add hl,hl
  1606. add hl,hl
  1607. add hl,hl
  1608. add hl,de
  1609. t_loop: ld a,l
  1610. cp ixl
  1611. jr nz,test_1
  1612. ld a,h
  1613. cp ixh
  1614. ret z
  1615. test_1: ld b,6
  1616. c_loop ld a,(de)
  1617. cp (hl)
  1618. ret nz
  1619. inc hl
  1620. inc de
  1621. djnz c_loop
  1622. inc de
  1623. inc de
  1624. inc hl
  1625. inc hl
  1626. jr t_loop
  1627. ; Fractional division.
  1628. ; Requires that the divisor is strictly bigger than the dividend (BC > HL).
  1629. ; In: [HL] Dividend
  1630. ; [BC] Divisor
  1631. ; Out: [DE] = fractional part of [HL]/[BC]
  1632. frac_div: ld a,b
  1633. cpl
  1634. ld b,a
  1635. ld a,c
  1636. cpl
  1637. ld c,a
  1638. inc bc ; bc = -divider
  1639. ld de,1 ; stop after 16 iterations
  1640. fdiv_loop add hl,hl ; hl <<= 1
  1641. add hl,bc ; hl -= divider
  1642. jr c,fdiv1 ; hl.prev >= divider
  1643. sbc hl,bc ; restore hl (carry flag remains clear)
  1644. fdiv1 rl e
  1645. rl d ; adc de,de
  1646. jr nc,fdiv_loop
  1647. ret
  1648. ; [HL] = mul-high([DE], [BC])
  1649. mul_hi: ld hl,0
  1650. ld a,16
  1651. mul_loop srl d
  1652. rr e
  1653. jr nc,mul_skip
  1654. add hl,bc
  1655. mul_skip rr h
  1656. rr l
  1657. dec a
  1658. jr nz,mul_loop
  1659. ret
  1660. ; In: [HL] = current CRC value
  1661. ; [A] = input byte
  1662. ; Out [HL] = updated CRC Value
  1663. crc_byte: ld c,a
  1664. ld b,8
  1665. crc_l: add hl,hl
  1666. jr c,crc_1
  1667. crc_0: rlc c
  1668. jr c,crc_2
  1669. jr crc_3
  1670. crc_1: rlc c
  1671. jr c,crc_3
  1672. crc_2 ld a,h
  1673. xor #10
  1674. ld h,a
  1675. ld a,l
  1676. xor #21
  1677. ld l,a
  1678. crc_3: djnz crc_l
  1679. ret
  1680. parse_dec ld b,0
  1681. ld a,(hl)
  1682. parse_dec_loop inc hl
  1683. sub '0'
  1684. jp c,expected_int
  1685. cp '9'+1
  1686. jp nc,expected_int
  1687. ld c,a
  1688. ld a,b
  1689. add a,a
  1690. add a,a
  1691. add a,a
  1692. add a,b
  1693. add a,b ; b*10
  1694. add a,c
  1695. ld b,a
  1696. ld a,(hl)
  1697. or a
  1698. jr z,parse_dec_end
  1699. cp 13
  1700. jr z,parse_dec_end
  1701. cp ' '
  1702. jr z,parse_dec_end
  1703. cp 9
  1704. jr nz,parse_dec_loop
  1705. parse_dec_end ld a,b
  1706. ret
  1707. print_pc: pop hl
  1708. call print_str
  1709. jp (hl)
  1710. print_str: ld a,(hl)
  1711. or a
  1712. ret z
  1713. ld ix,#00A2
  1714. ld iy,(#fcc0)
  1715. call #001c
  1716. inc hl
  1717. jr print_str
  1718. print_hex_hl: ld a,h
  1719. call print_hex_a
  1720. ld a,l
  1721. print_hex_a: ld b,a
  1722. rrca
  1723. rrca
  1724. rrca
  1725. rrca
  1726. call print_hdig
  1727. ld a,b
  1728. print_hdig: and #0f
  1729. cp 10
  1730. jr c,prt_1
  1731. add a,'A'-'0'-10
  1732. prt_1 add a,'0'
  1733. ld ix,#00A2
  1734. ld iy,(#fcc0)
  1735. jp #001c
  1736. print_dec_hl ld e,0 ; number of non-zero digits
  1737. ld a,h
  1738. or l
  1739. jr z,print_dec_hl_3 ; hl==0 -> print at least one 0-digit
  1740. ld bc,-10000
  1741. call print_dec_hl_1
  1742. ld bc,-1000
  1743. call print_dec_hl_1
  1744. ld bc,-100
  1745. call print_dec_hl_1
  1746. ld c,-10
  1747. call print_dec_hl_1
  1748. ld c,-1
  1749. print_dec_hl_1 ld a,-1
  1750. print_dec_hl_2 inc a
  1751. add hl,bc
  1752. jr c,print_dec_hl_2
  1753. sbc hl,bc
  1754. inc e
  1755. or a
  1756. jr nz,print_dec_hl_3
  1757. dec e
  1758. ret z ; skip leading zeros
  1759. print_dec_hl_3 add a,'0'
  1760. ld ix,#00A2
  1761. ld iy,(#fcc0)
  1762. jp #001c
  1763. print_dec_a ld e,0
  1764. or a
  1765. jr z,print_dec_a_3
  1766. ld b,100
  1767. call print_dec_a_1
  1768. ld b,10
  1769. call print_dec_a_1
  1770. ld b,1
  1771. print_dec_a_1 ld c,-1
  1772. print_dec_a_2 inc c
  1773. sub b
  1774. jr nc,print_dec_a_2
  1775. add a,b
  1776. ld b,a
  1777. inc e
  1778. ld a,c
  1779. or a
  1780. jr nz,print_dec_a_3
  1781. dec e
  1782. jr z,print_dec_a_4
  1783. print_dec_a_3 add a,'0'
  1784. ld ix,#00A2
  1785. ld iy,(#fcc0)
  1786. call #001c
  1787. print_dec_a_4 ld a,b
  1788. ret
  1789. debug_log push hl
  1790. ld hl,(debug_ptr)
  1791. ld (hl),a
  1792. inc l
  1793. ld (debug_ptr),hl
  1794. pop hl
  1795. ret
  1796. ;---
  1797. ; Machine specific routines
  1798. ; All these routine are still very much based on a WD2793 FDC. They only
  1799. ; differ in how the WD2793 is connected to the MSX. Each 'driver' needs
  1800. ; to implement 6 routines:
  1801. ; 1) select
  1802. ; input:
  1803. ; 'side' global variable
  1804. ; output: -
  1805. ; description:
  1806. ; Needs to select the disk rom in page 1 (for memory mapped FDCs).
  1807. ; Needs to select correct side, select drive A, turn motor on.
  1808. ; 2) deselct
  1809. ; input: -
  1810. ; output: -
  1811. ; description:
  1812. ; Called right before program exit. Should e.g. turn drive motor off.
  1813. ; 3) seek
  1814. ; input: 'cylinder'
  1815. ; output: -
  1816. ; description:
  1817. ; Should seek to the correct cylinder. E.g. by first seeking to track 0
  1818. ; and then seek to the requested cylinder. It's not allowed to use the data
  1819. ; in the track for this seek (e.g. verify the destination track).
  1820. ; TODO in the future we may add a step-in command as well.
  1821. ; 4) rd_addr
  1822. ; input: -
  1823. ; output:
  1824. ; 'addr_buffer' is filled in
  1825. ; [DE] points to end of addr_buffer
  1826. ; description:
  1827. ; Executes 'read address' commands in a loop and put the result in a buffer.
  1828. ; During this loop it keep a counter running and on each successful read
  1829. ; address command, the value of this counter is also stored in the buffer.
  1830. ; return:
  1831. ; on success this routine jumps to 'addr_done'
  1832. ; on error it jumps to 'addr_error'
  1833. ; 5) rd_track
  1834. ; input: -
  1835. ; output:
  1836. ; 'trck_buffer' is filled in
  1837. ; [DE] points to the end of trck_buffer
  1838. ; description:
  1839. ; return:
  1840. ; on success this routine jumps to 'track_end'
  1841. ; on error it jumps to 'track_err' or 'track_too_much'
  1842. ; 6) rd_sector
  1843. ; input:
  1844. ; [B] = track number (number found in address mark, not physical track number)
  1845. ; [C] = Sector number (found in address mark)
  1846. ; [DE] = pointer to output buffer
  1847. ; [HL] = delay value
  1848. ; 'read_speed' global variable
  1849. ; output:
  1850. ; buffer is filled in
  1851. ; [A] = WD2793 status register after command has ended (e.g. contains CRC status)
  1852. ; [DE] = points to end of buffer
  1853. ; [IX] = time between end-of-delay and first-byte-received
  1854. ; description:
  1855. ; Reads the sector with given number in the given buffer. This routine should
  1856. ; wait for the index pulse and then delay for the given amount of time before
  1857. ; actually starting the read sector command
  1858. ; return:
  1859. ; on success this routine jumps to sector_end
  1860. ; on error it jumps to sector_err
  1861. driver_routines
  1862. driver_select dw 0
  1863. driver_deselect dw 0
  1864. driver_seek dw 0
  1865. driver_rd_addr dw 0
  1866. driver_rd_trck dw 0
  1867. driver_rd_sect dw 0
  1868. ticks_min dw 0
  1869. ticks_max dw 0
  1870. driver_size equ $ - driver_routines
  1871. driver dw phil_driver
  1872. ;---
  1873. ; Philips
  1874. phil_status equ #7ff8
  1875. phil_command equ #7ff8
  1876. phil_track equ #7ff9
  1877. phil_sector equ #7ffa
  1878. phil_data equ #7ffb
  1879. phil_control1 equ #7ffc
  1880. phil_control2 equ #7ffd
  1881. phil_stat2 equ #7fff
  1882. phil_driver dw phil_select
  1883. dw phil_deselect
  1884. dw phil_seek
  1885. dw phil_rd_addr
  1886. dw phil_rd_trck
  1887. dw phil_rd_sector
  1888. dw 13834
  1889. dw 15290
  1890. ; 1) select
  1891. phil_select ld a,(#f348)
  1892. ld h,#40
  1893. call #0024 ; select FDC slot in page 1
  1894. ld a,(side)
  1895. ld (phil_control1),a
  1896. ld a,#c0 ; motor on, led on, drive A
  1897. ld (phil_control2),a
  1898. ret
  1899. ; 2) deselct
  1900. phil_deselect ld a,3
  1901. ld (phil_control2),a
  1902. ret
  1903. ; 3) seek
  1904. phil_seek
  1905. wait_busy_3 ld a,(phil_status)
  1906. and 1
  1907. jr nz,wait_busy_3
  1908. ld a,#0b ; restore, load head
  1909. ld (phil_command),a
  1910. call delay
  1911. wait_busy_4 ld a,(phil_status)
  1912. and 1
  1913. jr nz,wait_busy_4
  1914. ld a,(cylinder)
  1915. ld (phil_data),a ; track
  1916. ld a,#18 ; seek
  1917. ld (phil_command),a
  1918. ret
  1919. ; 4) rd_addr
  1920. phil_rd_addr:
  1921. ld de,addr_buffer
  1922. ld ix,0 ; counter
  1923. ld hl,phil_stat2 ; irq/dtrq
  1924. ld bc,phil_data
  1925. wait_busy_1 ld a,(phil_status)
  1926. and 1
  1927. jr nz,wait_busy_1
  1928. ld a,#d0 ; Forced interrupt command
  1929. ld (phil_command),a ; otherwise we don't see the index
  1930. ex (sp),hl
  1931. ex (sp),hl ; needed?
  1932. wait_index_a1 ld a,(phil_status)
  1933. and 2 ; wait till index pulse = 0
  1934. jr nz,wait_index_a1
  1935. wait_index_b1 ld a,(phil_status)
  1936. and 2 ; wait till index pulse = 1
  1937. jr z,wait_index_b1
  1938. addr_loop ld a,#c0
  1939. ld (phil_command),a ; read addr
  1940. ; Note: the timinig of this loop is important! Don't change
  1941. ; the instructions (e.g. JP->JR) without also changing the
  1942. ; other timing critical routines below.
  1943. addr_wait inc ix ; 12 cycles <-- this subset
  1944. ld a,(hl) ; 8 <-- of the loop
  1945. add a,a ; 5 <-- takes
  1946. jp p,addr_end ; 11 <-- 47
  1947. jp c,addr_wait ; 11 <-- cycles
  1948. ld a,(bc) ; 8
  1949. ld (de),a ; 8
  1950. inc de ; 7
  1951. jp addr_wait ; 11
  1952. addr_end
  1953. ld a,(phil_status)
  1954. and 16
  1955. jr nz,addr_error_ ; prefer to keep this a short jump
  1956. ld a,ixl
  1957. ld (de),a
  1958. inc de
  1959. ld a,ixh
  1960. ld (de),a ; store counter
  1961. inc de
  1962. inc ix
  1963. inc ix
  1964. cp #c0
  1965. jp c,addr_loop
  1966. jp addr_done
  1967. addr_error_ jp addr_error
  1968. ; 5) rd_track
  1969. phil_rd_trck ld de,trck_buffer
  1970. ld hl,phil_stat2 ; irq/dtrq
  1971. ld bc,phil_data
  1972. ld ix,0
  1973. ld a,#e0 ; read track
  1974. ld (phil_command),a
  1975. track_wait2 ld a,(hl)
  1976. add a,a
  1977. jp p,track_err
  1978. jp nc,track_first
  1979. inc ix
  1980. ld a,ixh
  1981. inc a
  1982. jp nz,track_wait2
  1983. jp track_no_start
  1984. track_wait ld a,(hl)
  1985. add a,a
  1986. jp p,track_end
  1987. jp c,track_wait
  1988. track_first ld a,(bc)
  1989. ld (de),a
  1990. inc de
  1991. ld a,d
  1992. cp #be
  1993. jp c,track_wait
  1994. jp track_too_much
  1995. ; 6) rd_sector
  1996. phil_rd_sector
  1997. ld a,#d0 ; Forced interrupt command
  1998. ld (phil_command),a ; otherwise we don't see the index
  1999. ; pulse status bits
  2000. ld a,b
  2001. ld (phil_track),a
  2002. ld a,c
  2003. ld (phil_sector),a
  2004. ld bc,phil_data
  2005. ld ix,0
  2006. ld a,(read_speed)
  2007. or a
  2008. jr nz,fast_read_1
  2009. wait_index_a2 ld a,(phil_status)
  2010. and 2 ; wait till index pulse = 0
  2011. jr nz,wait_index_a2
  2012. wait_index_b2 ld a,(phil_status)
  2013. and 2 ; wait till index pulse = 1
  2014. jr z,wait_index_b2
  2015. ; This loop is tuned for an exact number of Z80 cycles!
  2016. delay_loop dec hl ; 7 cycles
  2017. ld a,(0) ; dummy read 14 cycles
  2018. nop ; 5 cycles
  2019. ld a,h ; 5
  2020. or l ; 5
  2021. jp nz,delay_loop ; 11 together 47 cycles
  2022. fast_read_1 ld hl,phil_stat2 ; irq/dtrq
  2023. ld a,#80 ; read sector
  2024. ld (phil_command),a
  2025. sector_wait1 inc ix ; count till first byte is received
  2026. ld a,(hl)
  2027. add a,a
  2028. jp p,sector_err ; command stopped before we got 1st byte
  2029. jp c,sector_wait1
  2030. ld a,(bc)
  2031. ld (de),a
  2032. inc de
  2033. sector_wait2 ld a,(hl)
  2034. add a,a
  2035. jp p,sector_end_
  2036. jp c,sector_wait2
  2037. ld a,(bc)
  2038. ld (de),a
  2039. inc de
  2040. jp sector_wait2
  2041. sector_end_ ld a,(phil_status)
  2042. jp sector_end
  2043. ;---
  2044. ; National
  2045. natl_status equ #7fb8
  2046. natl_command equ #7fb8
  2047. natl_track equ #7fb9
  2048. natl_sector equ #7fba
  2049. natl_data equ #7fbb
  2050. natl_control equ #7fbc
  2051. natl_stat2 equ #7fbc
  2052. natl_driver dw natl_select
  2053. dw natl_deselect
  2054. dw natl_seek
  2055. dw natl_rd_addr
  2056. dw natl_rd_trck
  2057. dw natl_rd_sector
  2058. dw 13834
  2059. dw 15290
  2060. ; 1) select
  2061. natl_select ld a,(#f348)
  2062. ld h,#40
  2063. call #0024 ; select FDC slot in page 1
  2064. ld a,(side)
  2065. rlca
  2066. rlca ; bit 2 = side
  2067. or #09 ; motor on, drive A
  2068. ld (natl_control),a
  2069. ret
  2070. ; 2) deselct
  2071. natl_deselect xor a
  2072. ld (natl_control),a
  2073. ret
  2074. ; 3) seek
  2075. natl_seek
  2076. natl_wait_3 ld a,(natl_status)
  2077. and 1
  2078. jr nz,natl_wait_3
  2079. ld a,#0b ; restore, load head
  2080. ld (natl_command),a
  2081. call delay
  2082. natl_wait_4 ld a,(natl_status)
  2083. and 1
  2084. jr nz,natl_wait_4
  2085. ld a,(cylinder)
  2086. ld (natl_data),a ; track
  2087. ld a,#18 ; seek
  2088. ld (natl_command),a
  2089. ret
  2090. ; 4) rd_addr
  2091. natl_rd_addr:
  2092. ld de,addr_buffer
  2093. ld ix,0 ; counter
  2094. ld hl,natl_stat2 ; irq/dtrq
  2095. ld bc,natl_data
  2096. natl_busy_1 ld a,(natl_status)
  2097. and 1
  2098. jr nz,natl_busy_1
  2099. ld a,#d0 ; Forced interrupt command
  2100. ld (natl_command),a ; otherwise we don't see the index
  2101. ex (sp),hl
  2102. ex (sp),hl ; needed?
  2103. natl_index_a1 ld a,(natl_status)
  2104. and 2 ; wait till index pulse = 0
  2105. jr nz,natl_index_a1
  2106. natl_index_b1 ld a,(natl_status)
  2107. and 2 ; wait till index pulse = 1
  2108. jr z,natl_index_b1
  2109. natl_addr_loop ld a,#c0
  2110. ld (natl_command),a ; read addr
  2111. ; Note: the timinig of this loop is important! Don't change
  2112. ; the instructions (e.g. JP->JR) without also changing the
  2113. ; other timing critical routines below.
  2114. natl_addr_wait inc ix ; 12 cycles <-- this subset
  2115. ld a,(hl) ; 8 <-- of the loop
  2116. add a,a ; 5 <-- takes
  2117. jp c,natl_addr_end ; 11 <-- 47
  2118. jp m,natl_addr_wait; 11 <-- cycles
  2119. ld a,(bc) ; 8
  2120. ld (de),a ; 8
  2121. inc de ; 7
  2122. jp natl_addr_wait ; 11
  2123. natl_addr_end
  2124. ld a,(natl_status)
  2125. and 16
  2126. jr nz,natl_addr_err ; prefer to keep this a short jump
  2127. ld a,ixl
  2128. ld (de),a
  2129. inc de
  2130. ld a,ixh
  2131. ld (de),a ; store counter
  2132. inc de
  2133. inc ix
  2134. inc ix
  2135. cp #c0
  2136. jp c,natl_addr_loop
  2137. jp addr_done
  2138. natl_addr_err jp addr_error
  2139. ; 5) rd_track
  2140. natl_rd_trck ld de,trck_buffer
  2141. ld hl,natl_stat2 ; irq/dtrq
  2142. ld bc,natl_data
  2143. ld ix,0
  2144. ld a,#e0 ; read track
  2145. ld (natl_command),a
  2146. natl_trk_wt2 ld a,(hl)
  2147. add a,a
  2148. jp c,track_err
  2149. jp p,natl_trk_first
  2150. inc ix
  2151. ld a,ixh
  2152. inc a
  2153. jp nz,natl_trk_wt2
  2154. jp track_no_start
  2155. natl_trk_wait ld a,(hl)
  2156. add a,a
  2157. jp c,track_end
  2158. jp m,natl_trk_wait
  2159. natl_trk_first ld a,(bc)
  2160. ld (de),a
  2161. inc de
  2162. ld a,d
  2163. cp #be
  2164. jp c,natl_trk_wait
  2165. jp track_too_much
  2166. ; 6) rd_sector
  2167. natl_rd_sector
  2168. ld a,#d0 ; Forced interrupt command
  2169. ld (natl_command),a ; otherwise we don't see the index
  2170. ; pulse status bits
  2171. ld a,b
  2172. ld (natl_track),a
  2173. ld a,c
  2174. ld (natl_sector),a
  2175. ld bc,natl_data
  2176. ld ix,0
  2177. ld a,(read_speed)
  2178. or a
  2179. jr nz,natl_fast_read
  2180. natl_index_a2 ld a,(natl_status)
  2181. and 2 ; wait till index pulse = 0
  2182. jr nz,natl_index_a2
  2183. natl_index_b2 ld a,(natl_status)
  2184. and 2 ; wait till index pulse = 1
  2185. jr z,natl_index_b2
  2186. ; This loop is tuned for an exact number of Z80 cycles!
  2187. natl_delay dec hl ; 7 cycles
  2188. ld a,(0) ; dummy read 14 cycles
  2189. nop ; 5 cycles
  2190. ld a,h ; 5
  2191. or l ; 5
  2192. jp nz,natl_delay ; 11 together 47 cycles
  2193. natl_fast_read ld hl,natl_stat2 ; irq/dtrq
  2194. ld a,#80 ; read sector
  2195. ld (natl_command),a
  2196. natl_sect_wt1 inc ix ; count till first byte is received
  2197. ld a,(hl)
  2198. add a,a
  2199. jp c,sector_err ; command stopped before we got 1st byte
  2200. jp m,natl_sect_wt1
  2201. ld a,(bc)
  2202. ld (de),a
  2203. inc de
  2204. natl_sect_wt2 ld a,(hl)
  2205. add a,a
  2206. jp c,natl_sect_end
  2207. jp m,natl_sect_wt2
  2208. ld a,(bc)
  2209. ld (de),a
  2210. inc de
  2211. jp natl_sect_wt2
  2212. natl_sect_end ld a,(natl_status)
  2213. jp sector_end
  2214. ;---
  2215. ; Microsol
  2216. mics_status equ #d0
  2217. mics_command equ #d0
  2218. mics_track equ #d1
  2219. mics_sector equ #d2
  2220. mics_data equ #d3
  2221. mics_control equ #d4
  2222. mics_stat2 equ #d4
  2223. mics_driver dw mics_select
  2224. dw mics_deselect
  2225. dw mics_seek
  2226. dw mics_rd_addr
  2227. dw mics_rd_trck
  2228. dw mics_rd_sector
  2229. dw 14135
  2230. dw 15622
  2231. ; 1) select
  2232. mics_select ld a,(side)
  2233. rlca
  2234. rlca
  2235. rlca
  2236. rlca ; bit 4 = side
  2237. or #21 ; bit 5 = motor, bit 0 = drive A
  2238. out (mics_control),a
  2239. ret
  2240. ; 2) deselct
  2241. mics_deselect xor a ; no drive selected, motor off
  2242. out (mics_control),a
  2243. ret
  2244. ; 3) seek
  2245. mics_seek
  2246. mics_busy_3 in a,(mics_status)
  2247. and 1
  2248. jr nz,mics_busy_3
  2249. ld a,#0b ; restore, load head
  2250. out (mics_command),a
  2251. call delay
  2252. mics_busy_4 in a,(mics_status)
  2253. and 1
  2254. jr nz,mics_busy_4
  2255. ld a,(cylinder)
  2256. out (mics_data),a ; track
  2257. ld a,#18 ; seek
  2258. out (mics_command),a
  2259. ret
  2260. ; 4) rd_addr
  2261. mics_rd_addr:
  2262. ld de,addr_buffer
  2263. ld hl,0 ; counter
  2264. mics_busy_1 in a,(mics_status)
  2265. and 1
  2266. jr nz,mics_busy_1
  2267. ld a,#d0 ; Forced interrupt command
  2268. out (mics_command),a ; otherwise we don't see the index
  2269. ex (sp),hl
  2270. ex (sp),hl ; needed?
  2271. mics_index_a1 in a,(mics_status)
  2272. and 2 ; wait till index pulse = 0
  2273. jr nz,mics_index_a1
  2274. mics_index_b1 in a,(mics_status)
  2275. and 2 ; wait till index pulse = 1
  2276. jr z,mics_index_b1
  2277. mics_addr_loop ld a,#c0 ; read addr
  2278. out (mics_command),a
  2279. ; Note: the timinig of this loop is important! Don't change
  2280. ; the instructions (e.g. JP->JR) without also changing the
  2281. ; other timing critical routines below.
  2282. mics_addr_wait inc hl ; 7 cycles <-- this
  2283. in a,(mics_stat2) ; 12 <-- takes
  2284. add a,a ; 5 <-- 46
  2285. jp c,mics_addr_end ; 11 <-- cycles
  2286. jp m,mics_addr_wait ; 11 <--
  2287. in a,(mics_data) ; 12
  2288. ld (de),a ; 8
  2289. inc de ; 7
  2290. jp mics_addr_wait ; 11
  2291. mics_addr_end
  2292. in a,(mics_status)
  2293. and 16 ; record not found
  2294. jr nz,mics_addr_err ; prefer to keep this a short jump
  2295. ld a,l
  2296. ld (de),a
  2297. inc de
  2298. ld a,h
  2299. ld (de),a ; store counter
  2300. inc de
  2301. inc hl
  2302. inc hl
  2303. cp #c0
  2304. jp c,mics_addr_loop
  2305. jp addr_done
  2306. mics_addr_err jp addr_error
  2307. ; 5) rd_track
  2308. mics_rd_trck ld de,trck_buffer
  2309. ld hl,0
  2310. ld a,#e0 ; read track
  2311. out (mics_command),a
  2312. mics_trk_wait2 in a,(mics_stat2)
  2313. add a,a
  2314. jp c,track_err
  2315. jp p,mics_trk_first
  2316. inc hl
  2317. ld a,h
  2318. inc a
  2319. jp nz,mics_trk_wait2
  2320. jp track_no_start
  2321. mics_trk_wait in a,(mics_stat2)
  2322. add a,a
  2323. jp c,track_end
  2324. jp m,mics_trk_wait
  2325. mics_trk_first in a,(mics_data)
  2326. ld (de),a
  2327. inc de
  2328. ld a,d
  2329. cp #be
  2330. jp c,mics_trk_wait
  2331. jp track_too_much
  2332. ; 6) rd_sector
  2333. mics_rd_sector
  2334. ld a,#d0 ; Forced interrupt command
  2335. out (mics_command),a ; otherwise we don't see the index
  2336. ; pulse status bits
  2337. ld a,b
  2338. out (mics_track),a
  2339. ld a,c
  2340. out (mics_sector),a
  2341. ld ix,0
  2342. ld a,(read_speed)
  2343. or a
  2344. jr nz,mics_fast_1
  2345. mics_index_a2 in a,(mics_status)
  2346. and 2 ; wait till index pulse = 0
  2347. jr nz,mics_index_a2
  2348. mics_index_b2 in a,(mics_status)
  2349. and 2 ; wait till index pulse = 1
  2350. jr z,mics_index_b2
  2351. ; This loop is tuned for an exact number of Z80 cycles!
  2352. mics_delay dec hl ; 7 cycles
  2353. cp 0 ; 8 (dummy compare)
  2354. nop ; 5
  2355. nop ; 5
  2356. ld a,h ; 5
  2357. or l ; 5
  2358. jp nz,mics_delay ; 11 together 46 cycles
  2359. mics_fast_1 ld a,#80 ; read sector
  2360. out (mics_command),a
  2361. mics_sctr_wt1 inc ix ; count till first byte is received
  2362. in a,(mics_stat2)
  2363. add a,a
  2364. jp c,sector_err ; command stopped before we got 1st byte
  2365. jp m,mics_sctr_wt1
  2366. in a,(mics_data)
  2367. ld (de),a
  2368. inc de
  2369. mics_sctr_wt2 in a,(mics_stat2)
  2370. add a,a
  2371. jp c,mics_sctr_end
  2372. jp m,mics_sctr_wt2
  2373. in a,(mics_data)
  2374. ld (de),a
  2375. inc de
  2376. jp mics_sctr_wt2
  2377. mics_sctr_end in a,(mics_status)
  2378. jp sector_end
  2379. ; -----
  2380. ofst_tab: dw -6,-7,-5,-8,-4,-9,-3,-10,-2,-11,-1,-12,0
  2381. dw -13,1,-14,2,-15,3,-16,4,-17,5,-18,6,-19,7
  2382. dw -20,8,-21,9,-22,10,-23,11,-24,12,-25,13,-26
  2383. dw 14,-27,15,-28,16,-29,17,-30,18,-31,29,-32
  2384. dw 20,-33,21,-34,22,-35,23,-36,24,-37,25,-38
  2385. dw 26,-39,27,-40,28,-41,29,-42,30,-43,31,-44
  2386. dw #8080
  2387. addr_mark db #A1,#A1,#A1,#FE
  2388. debug db 0
  2389. start_track db 0 ; initial value matters
  2390. stop_track db 81 ; by default we try 2 extra cylinders
  2391. stop_set db 0
  2392. fcb db 2 ; drive B
  2393. db "DMK-TT-S" ; filename
  2394. db "DAT" ; extension
  2395. ds 37-12
  2396. fcb_debug db 2 ; drive B
  2397. db "DEBUG " ; filename
  2398. db "DAT" ; extension
  2399. ds 37-12
  2400. ; struct Addr_Mark
  2401. ; byte C
  2402. ; byte H
  2403. ; byte R
  2404. ; byte N
  2405. ; word CRC
  2406. ; word ticks
  2407. sizeof_amark equ 8
  2408. ofst_amark_C equ 0
  2409. ofst_amark_H equ 1
  2410. ofst_amark_R equ 2
  2411. ofst_amark_N equ 3
  2412. ofst_amark_CRC equ 4
  2413. ofst_amark_tick equ 6
  2414. ; struct Offset_Info
  2415. ; word address_mark_offset
  2416. ; word data_mark_offset
  2417. ; byte data_mark_type
  2418. ; byte read_sector_status
  2419. ; word sector_size
  2420. sizeof_offinfo equ 10
  2421. ofst_oi_addr equ 0
  2422. ofst_oi_data equ 2
  2423. ofst_oi_type equ 4
  2424. ofst_oi_status equ 5
  2425. ofst_oi_size equ 6
  2426. ofst_oi_ptr equ 8
  2427. sizeof_off_buf equ 64 * sizeof_offinfo
  2428. sizeof_dmk_h equ 128
  2429. cylinder equ #8000 ; db 0 0
  2430. side equ cylinder+ 1 ; db 0 1
  2431. retries equ side+1 ; db 0 2
  2432. nb_sectors equ retries+1 ; dw 0 3
  2433. track_len equ nb_sectors+2 ; dw 0 5
  2434. track_stop equ track_len+2 ; dw 0 7
  2435. ticks equ track_stop+2 ; dw 0 9
  2436. ratio equ ticks+2 ; dw 0 11
  2437. crc_retries equ ratio+2 ; db 0 13
  2438. adjust_ofst equ crc_retries+1 ; dw 0 14
  2439. adjust_scale equ adjust_ofst+2 ; dw 0 16
  2440. sector_cntr equ adjust_scale+2 ; db 0 18
  2441. sector_stop equ sector_cntr+1 ; dw 0 19
  2442. addr_buf_ptr equ sector_stop+2 ; dw 0 21
  2443. ofst_buf_ptr equ addr_buf_ptr+2 ; dw 0 23
  2444. dmk_ptr equ ofst_buf_ptr+2 ; dw 0 25
  2445. addr_estimate equ dmk_ptr+2 ; dw 0 27
  2446. read_speed equ addr_estimate+2 ; db 0 29
  2447. sector_buf_ptr equ read_speed+1 ; dw 0 30
  2448. crc_status equ sector_buf_ptr+2; db 0 32
  2449. debug_ptr equ crc_status+1 ; dw 0 33
  2450. sector_size equ debug_ptr+2 ; dw 0 35
  2451. addr_buf_end equ sector_size+2 ; dw 0 37
  2452. addr_retries equ addr_buf_end+2 ; db 0 39
  2453. addr_buffer equ #8100
  2454. offset_buffer equ addr_buffer+64*sizeof_amark ; can overlap part of addr_buffer
  2455. dmk_header equ offset_buffer+sizeof_off_buf
  2456. trck_buffer equ dmk_header+sizeof_dmk_h
  2457. sector_buffer equ trck_buffer+#1A00 ; overlaps 2nd copy of track``
  2458. unique_buffer equ #BE00 ; possibly overlaps sector buffer (that's OK)
  2459. ; must start at a 256-byte boundary
  2460. debug_buffer equ #BF00 ; must be 256-bytes aligned