print80.inc 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303
  1. ;;; -*- asm -*-
  2. ;
  3. ;;; Simple option ROM for printer for ABC80; this is not authentic, but
  4. ;;; uses a hardware interface implementable with an FT232H USB module.
  5. ;;; It is (hopefully) at least similar to an ABC80 printer interface.
  6. ;
  7. ;;; - ABC-bus select code 60 decimal;
  8. ;;; OUT 0 - (OUT) output data
  9. ;;; IN 0 - (INP) input data
  10. ;;; IN 1 - (STAT) bit 0 - Rx data available
  11. ;;; bit 1 - Tx space available
  12. ;;; bit 2 - USB suspended (not ready)
  13. ;;; bit 3 - USB configured (host ready)
  14. ;;; OUT 2 - (C1) flush Tx buffer immediately
  15. ;;; OUT 3 - (C2) discard all input - only supported in some hw versions
  16. ;;;
  17. ;;;
  18. ;;; FF is used as an escape character for the file I/O and console
  19. ;;; interfaces (FF A0..BF for file, FF C0 for console)
  20. ;;;
  21. ;;; FF FE is used to represent an FF character in the printer stream,
  22. ;;; and FF FD is send on CLOSE (end of job).
  23. ;;; For other escape sequences, see print.c.
  24. ;;;
  25. ;;; To auto-initialize this, we need a modified DOS that looks for
  26. ;;; additional ROM entry points (ABC800 has this, but not ABC80.)
  27. #include "z80.inc"
  28. #include "abc80.inc"
  29. #include "auxram.inc"
  30. defc selcode=60 ; ABC-bus select code
  31. defc LARGE=(ROMSIZE >= 2048)
  32. ;; Maximum number of remote volumes
  33. defc MAX_VOLS = 32
  34. ;; Console device, probably doesn't fit anymore
  35. defc console_dev = LARGE
  36. ;; Support strict text file access
  37. defc pra_dev = 0
  38. ;; ABC800-style CON: and NUL: devices
  39. defc connul = LARGE
  40. ;; Quicklib routine
  41. defc quicklib = 1
  42. ;; Return real error codes or always zero?
  43. defc return_real_errors = 0 ; Match UFD-DOS 80
  44. ;; PR: using raw protocol (not a chardev volume?)
  45. defc raw_pr = 0
  46. ;; CMD routine if in IEC area?
  47. defc have_cmd = LARGE && (ROMSTART == 0x7000)
  48. if !have_cmd
  49. defc c_cmd = ERR_8
  50. defc e_cmd = ERR_8
  51. defc e_iec = ERR_8
  52. endif
  53. ;; Device timeout
  54. defc timeout = 100 ; 100/50 Hz = 2 s
  55. .globl _org
  56. _org = ROMSTART
  57. .section .text
  58. .globl _start
  59. _start:
  60. ;; If in the IEC area, add the IEC area entry points
  61. ;; IEC: jump table follows; simply treat it as PR:
  62. if ROMSTART == 0x7000
  63. jp c_cmd
  64. jp e_cmd
  65. jp e_iec
  66. endif
  67. if raw_pr
  68. ; jp table for PR: (if in printer area, should be first)
  69. pr_jptable:
  70. jp trivial ; OPEN
  71. jp trivial ; PREPARE
  72. jp pr_close ; CLOSE
  73. jp notforme ; INPUT
  74. jp pr_print ; PRINT
  75. jp notforme ; RDBLK
  76. jp notforme ; WRBLK
  77. jp notforme ; DELETE
  78. jp notforme ; RENAME
  79. endif
  80. prb_jptable:
  81. jp prb_open ; OPEN
  82. jp prb_prepare ; PREPARE
  83. jp prb_close ; CLOSE
  84. jp prb_input ; INPUT - might be generally useful
  85. jp prb_print ; PRINT
  86. jp prb_rdblk ; RDBLK
  87. jp prb_wrblk ; WRBLK
  88. ; Supporting DELETE and RENAME requires fixes to the DOS ROM;
  89. ; the DOS ROM contains the BASIC interpreter for these and
  90. ; it assumes it only applies to disk files.
  91. jp prx_delete ; DELETE
  92. jp prx_rename ; RENAME
  93. ;; Fixed entry points, reserved for future use
  94. fixfunc:
  95. .org 0x4a, 0xff
  96. ;; Magic number that this entry point is valid
  97. dec a
  98. ;; Init entry point, same offset as in DOS
  99. jp start
  100. if pra_dev
  101. ; jp table for PRA:
  102. pra_jptable:
  103. jp pra_open ; OPEN
  104. jp pra_prepare ; PREPARE
  105. jp pra_close ; CLOSE
  106. jp pra_input ; INPUT
  107. jp pra_print ; PRINT
  108. jp notforme ; RDBLK
  109. jp notforme ; WRBLK
  110. ; Supporting DELETE and RENAME requires fixes to the DOS ROM;
  111. ; the DOS ROM contains the BASIC interpreter for these and
  112. ; it assumes it only applies to disk files.
  113. jp prx_delete ; DELETE
  114. jp prx_rename ; RENAME
  115. endif
  116. if raw_pr
  117. pr_print:
  118. call select
  119. ld a,0F3h ; Printer data
  120. call send_esc
  121. pr_print_loop:
  122. ld a,b
  123. or c
  124. ld a,0EFh
  125. jr z,done_esc
  126. ld a,(hl)
  127. call send_byte
  128. inc a
  129. jr nz,pr_not_ff
  130. ld a,0FEh
  131. call send_byte
  132. pr_not_ff:
  133. dec bc
  134. inc hl
  135. jr pr_print_loop
  136. pr_close:
  137. call select
  138. ld a,0FDh
  139. jr done_esc
  140. endif
  141. ;; Select the current device, and save the stack pointer
  142. ;; to allow for an error unwind. This should be called from the
  143. ;; topmost stack so that a RET on error returns to BASIC;
  144. ;; if called in a nested context that context will be returned
  145. ;; to on error. After an error the carry flag is set and only
  146. ;; A is defined.
  147. select:
  148. ld (errsp),sp
  149. push af
  150. ld a,(SELECT) ; Old select code
  151. ld (ram_select),a ; Save old select code
  152. ld a,selcode ; Select code
  153. ld (SELECT),a ; Is this correct?
  154. out (1),a
  155. pop af
  156. ret
  157. done_esc:
  158. call send_esc
  159. done_ok:
  160. xor a
  161. done:
  162. ld sp,(errsp) ; Restore stack
  163. inc sp ; Drop return address from select
  164. inc sp
  165. push af
  166. ld a,(ram_select)
  167. ld (SELECT),a
  168. out (1),a
  169. pop af
  170. rlca ; CF <- bit 7
  171. if return_real_errors
  172. srl a ; Strip bit 7 from result but is in CF
  173. else
  174. ld a,0 ; This is what UFD-DOS 80 does?!
  175. endif
  176. ret
  177. if pra_dev
  178. pra_open:
  179. ld a,0xA0
  180. jr prx_open
  181. pra_prepare:
  182. ld a,0xA2
  183. jr prx_open
  184. endif
  185. prb_prepare:
  186. ld a,0xA3
  187. jr prb_open_prepare
  188. prb_open:
  189. ld a,0xA1
  190. prb_open_prepare:
  191. call prb_setup_buf
  192. ;; Fall through...
  193. prx_open:
  194. ;; ABC80-BASIC expects DE to be preserved across this routine,
  195. ;; otherwise .BAC -> .BAS searching does not work.
  196. if pra_dev ; Handled by prb_setup_buf
  197. ld (ix+7),132 ; Line length, seems to be standard?
  198. endif
  199. call select
  200. push af ; Save command code
  201. call send_cmd ; Returns with CF = 0
  202. ld l,(ix+3) ; Get volume name
  203. ld h,(ix+4)
  204. ld bc,3
  205. sbc hl,bc
  206. ld (ix+6),b ; 0
  207. call send_buf
  208. ;; HL <- filename. Do not use EX DE,HL here: if send_buf
  209. ;; aborts we have to have DE intact on return to BASIC.
  210. ld l,e
  211. ld h,d
  212. ld c,11 ; B = 0 already
  213. call send_buf
  214. call recv_reply
  215. pop hl ; H = command
  216. if quicklib
  217. and (iy+14) ; Bit 0 = command mode
  218. add a ; Bit 0 -> bit 1
  219. and h ; Check for PREPARE (bit 1)
  220. ;; bit 1 in A is now set if quicklib
  221. endif
  222. ;; Mark buffer busy if successful, any value other than 0xff
  223. ;; works, so just use zero...
  224. if pra_dev
  225. bit 0,h ; PRA -> no buffer, no quicklib
  226. jr z,nohazbuf
  227. endif
  228. call prb_dosfd
  229. ld (hl),b ; B = 0 on exit here
  230. nohazbuf:
  231. if !quicklib
  232. jr done
  233. else
  234. ;; A is as set up above...
  235. and 2
  236. jr z,done ; Not quicklib (A = 0 here)
  237. ;; -------- Show library listing on screen --------
  238. prx_quicklib:
  239. ;; Restore the original select code in memory. It isn't
  240. ;; necessary to send the select code to the bus, because
  241. ;; the subsequent I/O operations will do that for us.
  242. ld a,(ram_select) ; Restore original select code
  243. ld (SELECT),a
  244. call crlf
  245. ld (ix+6),22 ; 22 lines before wait
  246. ql_getline:
  247. call S_CHECKCTRLC
  248. jr nz,ql_done
  249. ld hl,PCODE_BUF
  250. push hl
  251. ld bc,PCODE_SIZE
  252. call IX_INPUT
  253. pop hl
  254. jr c,ql_done
  255. call S_CUR_MAX_X
  256. ld bc,+(12 << 8) + 13
  257. add c ; Space needed
  258. sub e
  259. jr c,ql_nocrlf
  260. call crlf
  261. dec (ix+6)
  262. jr nz,ql_nocrlf
  263. push ix
  264. call CON_GET
  265. pop ix
  266. ld (ix+6),1 ; <Return> = one line only
  267. cp c
  268. jr z,ql_nocrlf
  269. ld (ix+6),22
  270. ql_nocrlf:
  271. push hl
  272. ql_find_comma:
  273. ld a,(hl)
  274. cp '.' ; Lowest valid filename character
  275. jr c,ql_found_comma ; Comma, CR, or other non-filename character
  276. inc hl
  277. djnz ql_find_comma
  278. ql_found_comma:
  279. inc b
  280. ql_pad_space:
  281. ld (hl),' '
  282. inc hl
  283. djnz ql_pad_space
  284. ql_cleaned_comma:
  285. pop hl
  286. ; BC = 13 here
  287. call CON_PRINT
  288. jr ql_getline
  289. ql_done:
  290. call S_CLOSEFILE
  291. jp S_CMD ; Forcible return to command loop -
  292. ; abort LIST command
  293. crlf:
  294. push bc
  295. call CON_CRLF
  296. pop bc
  297. ret
  298. endif ; quicklib
  299. prx_rename:
  300. call select
  301. ld a,0xAA
  302. call send_cmd
  303. ex de,hl ; HL -> new filename
  304. ld bc,11
  305. call send_buf
  306. jr prx_reply_done
  307. prb_close:
  308. call select
  309. xor a
  310. cp (ix+14)
  311. jr z,pbc_noflush
  312. call prb_getbufaddr
  313. ld b,a
  314. ld a,(ix+10) ; End data
  315. sub l ; Skip non-data at start of buffer
  316. ld c,a
  317. call output_common
  318. pbc_noflush:
  319. call prb_dosfd
  320. ld (hl),255 ; Buffer now free
  321. ;; Returns with B=0
  322. ld (ix+14),b
  323. if pra_dev
  324. pra_close:
  325. ld (ix+5),0
  326. else
  327. ld (ix+5),b
  328. endif
  329. ld a,0xA7
  330. prx_simple_command: ; Just command and response, no data
  331. call send_cmd
  332. prx_reply_done: ; Reply, then done
  333. call recv_reply
  334. done2:
  335. jp done
  336. prx_delete:
  337. ld a,0xAB
  338. call select
  339. jr prx_simple_command
  340. if pra_dev
  341. pra_print:
  342. call select
  343. call output_common
  344. jr done2
  345. endif
  346. output_common:
  347. ld a,0xA6
  348. prx_length_command:
  349. call send_cmd
  350. call send_word
  351. call send_buf
  352. jp recv_reply
  353. if pra_dev
  354. pra_input:
  355. call select
  356. ld a,0xA4 ; INPUT
  357. endif
  358. ;; This routine can be called to handle a command with a
  359. ;; reply + len + data response.
  360. ;; HL -> target_buf, A = command, BC = buffer size
  361. ; XXX: USB is fast enough that INIR/OTIR should be possible
  362. input_command:
  363. call send_cmd
  364. call recv_reply
  365. call recv_byte
  366. ld e,a
  367. call recv_byte
  368. ld d,a
  369. ; Now HL -> target buf; DE -> expected byte count;
  370. ; BC -> buffer size
  371. prai_loop:
  372. ld a,d
  373. or e
  374. ret z
  375. dec de
  376. ld a,b
  377. or c
  378. jr nz,prai_space
  379. ld hl,ram_dummy
  380. inc c
  381. prai_space:
  382. dec bc
  383. call recv_byte
  384. ld (hl),a
  385. inc hl
  386. jr prai_loop
  387. prbr_protoerr:
  388. ld a,128+37
  389. jr done2
  390. prb_rdblk:
  391. call select
  392. prb_rdblk_nosel:
  393. ld a,0xA5
  394. call send_cmd
  395. ld b,253
  396. ld a,b
  397. call send_byte
  398. xor a
  399. call send_byte
  400. call recv_reply
  401. call recv_byte
  402. cp b
  403. jr nz,prbr_protoerr
  404. call recv_byte
  405. and a
  406. jr nz,prbr_protoerr
  407. call prb_getbufaddr
  408. push hl
  409. prbr_recv:
  410. call recv_byte
  411. ld (hl),a
  412. inc hl
  413. djnz prbr_recv
  414. pop hl ; HL -> buf address
  415. jp done_ok
  416. ;; This is a slightly modified version of the BLK_INPUT routine
  417. ;; in the BASIC ROM. It has the following modifications:
  418. ;; 1. Accept <LF> or <CR><LF> line endings as well as just <CR>
  419. ;; 2. Handle a block without an <ETX> terminator
  420. ;; 3. Handle a file without <NUL> terminator
  421. ;; These changes allow a text file in modern Unix/DOS format
  422. ;; to be parsed, as long as it does not have embedded <TAB>
  423. ;; characters. It would be possible to heuristically handle
  424. ;; <TAB> by looking for <LF> or <ETX>; the first block ought to have
  425. ;; at least one <LF> if "modern", or <ETX> if ABC.
  426. ;;
  427. ;; This is intended to be a general routine, usable for other
  428. ;; devices than these.
  429. prb_input:
  430. ex de,hl ; DE -> destination pointer
  431. ld (ix+13),1 ; Inhibit output
  432. ld l,(ix+10) ; HL -> pointer into the buffer
  433. ld h,(ix+11)
  434. pbi_nextchar:
  435. xor a
  436. cp c
  437. jr z,pbi_overlong ; Output buffer overflow?
  438. call pbi_peekchar
  439. cp 9 ; TAB = compressed spaces
  440. jr z,pbi_tab
  441. cp 10 ; LF = convert to CR
  442. jr z,pbi_lf
  443. and a
  444. jr z,pbi_eof ; NUL = end of file
  445. jp m,pbi_badchar ; >= 128 -> error
  446. pbi_emit:
  447. ldi ; (DE) <- (HL), DE++, HL++, BC--
  448. cp 13 ; CR = end of line
  449. jr nz,pbi_nextchar
  450. ;; For a CR character, look to see if the next one if LF,
  451. ;; if so eat the LF rather than having it converted to CR next time.
  452. ;; Only do this exactly once, so <CR><LF><LF> = 2 lines.
  453. call pbi_peekchar
  454. cp 10
  455. jr nz,pbi_done
  456. inc hl ; Skip exactly one LF character
  457. pbi_done:
  458. xor a
  459. pbi_return:
  460. ld (ix+10),l
  461. ld (ix+11),h
  462. ret
  463. pbi_eof:
  464. pbi_err:
  465. scf
  466. jr pbi_return
  467. pbi_overlong:
  468. ld a,128 + 20 ; Line too long
  469. jr pbi_err
  470. pbi_badchar:
  471. ld a,128 + 58 ; Bad character
  472. jr pbi_err
  473. pbi_lf: ; Convert to CR and EOL, but don't eat LF
  474. ld (hl),13
  475. ldi
  476. jr pbi_done
  477. pbi_tab:
  478. inc l ; Next byte; note that 3 = ETX is valid
  479. jr z,pbi_nextchar ; <TAB> at end of block -> ignore
  480. ld b,(hl)
  481. inc l
  482. ld a,c
  483. sub b
  484. jr c,pbi_overlong
  485. ld c,a
  486. ld a,' '
  487. pbi_tab_expand:
  488. ld (de),a
  489. inc de
  490. djnz pbi_tab_expand
  491. jr pbi_nextchar
  492. ;; Get the next character, but don't advance HL beyond
  493. ;; it. However, handle ETX and buffer overrun here.
  494. pbi_peekchar:
  495. xor a
  496. cp l ; 256-byte wrap: assume end of block
  497. jr z,pbi_newblock
  498. ld a,(hl)
  499. cp 3
  500. ret nz
  501. pbi_newblock:
  502. call pbi_eofbuf ; Just in case IX_BLKRD fails silently...
  503. push bc
  504. push de
  505. call IX_BLKRD
  506. pop de
  507. pop bc
  508. ;; HL points to start of buffer here (we hope)
  509. jr nc,pbi_peekchar
  510. ;; On error, return EOF and also set the first byte in the buffer
  511. ;; to EOF in case input gets called again.
  512. ;; Fall through...
  513. pbi_eofbuf:
  514. call prb_getbufaddr
  515. xor a
  516. ld (hl),a
  517. ret
  518. ; Write a binary output block. Similar to
  519. ; pra_print, but with a few different buffer
  520. ; management bits.
  521. prb_wrblk:
  522. call select
  523. call prb_getbufaddr
  524. ld bc,253
  525. call output_common
  526. call prb_empty_buf
  527. done3:
  528. jp done
  529. ;; Blocking PRINT without converting to ABC-DOS text format.
  530. ;; This simply stuffs a buffer full of the PRINT contents;
  531. ;; it also assumes the buffer is full when there is a 256-byte
  532. ;; address wraparound as (ix+13) is not expected to reflect the
  533. ;; buffer length without space for ETX... and is set to 1 on
  534. ;; read (what?!)
  535. prb_print:
  536. ld a,c
  537. or b
  538. ret z ; Nothing to do...
  539. ld e,(ix+10)
  540. ld d,(ix+11)
  541. pbp_output:
  542. xor a
  543. sub e
  544. jr z,pbp_nextbuf ; No space left in buffer
  545. push bc
  546. inc b
  547. ;; A now has the number of free bytes in the buffer
  548. ;; If BC > A need to use the rest of the buffer
  549. djnz pbp_limitlen
  550. cp c
  551. jr c,pbp_limitlen
  552. ld a,c
  553. pbp_limitlen:
  554. ld c,a
  555. xor a ; Assume all good, clear carry
  556. ld b,a
  557. ex (sp),hl
  558. sbc hl,bc ; Decrement bytes left to write
  559. ex (sp),hl
  560. ldir
  561. ld (ix+10),e
  562. ld (ix+11),d
  563. ld (ix+14),1 ; Buffer dirty
  564. pop bc
  565. ret z ; Z still set from SBC HL,BC
  566. pbp_nextbuf:
  567. push hl
  568. push bc
  569. call IX_BLKWR
  570. pop bc
  571. pop hl
  572. jr nc,pbp_output
  573. ret ; Error
  574. pbp_allbuf:
  575. sub e
  576. jr pbp_limitlen
  577. ;; Get the address of the DOS file description corresponding
  578. ;; to the allocated buffer.
  579. ;; Returns with B = 0, C = DOSBUF*16, HL = DOS file description
  580. prb_dosfd:
  581. ld b,0
  582. ld c,(ix+12)
  583. ld hl,0xFD41
  584. add hl,bc
  585. ret
  586. ;; Set up a BUF for PRB: (open/prepare)
  587. ;; This uses routines from UFD-DOS due to space
  588. prb_setup_buf:
  589. push af
  590. push bc
  591. push hl
  592. call 65F4h ; Allocate buffer
  593. call 662Bh ; Initialize buffer pointers
  594. pop hl
  595. pop bc
  596. pop af
  597. ret
  598. ;; This returns with DE -> buffer start. It seems ABC80-BASIC
  599. ;; requires this to work...
  600. prb_empty_buf: ; Returns with A=0, HL->buf
  601. push af
  602. ex de,hl
  603. ld a,(ix+12)
  604. call 662Fh ; Returns with HL -> buffer
  605. ex de,hl
  606. pop af
  607. ret
  608. ;;; Load the address of the start of the current buffer into HL
  609. prb_getbufaddr:
  610. ld l,3
  611. ld h,(ix+9)
  612. ret
  613. ;; Send a command header, A = command
  614. ;; Returns with CF = 0
  615. send_cmd:
  616. push bc
  617. ld (ram_cmd),a
  618. call send_esc
  619. ld a,(ram_serial)
  620. call send_byte
  621. push ix
  622. pop bc
  623. call send_word
  624. pop bc
  625. ret
  626. ;; Send a word in BC, preserves AF
  627. send_word:
  628. push af
  629. ld a,c
  630. call send_byte
  631. ld a,b
  632. call send_byte
  633. pop af
  634. ret
  635. ;; Send FF + byte; reset running checksum
  636. ;; Returns with CF = 0!
  637. send_esc:
  638. push af
  639. ld a,0FFh
  640. call send_byte
  641. ld (ram_csum),a
  642. pop af
  643. ;; Fall through
  644. ;; Send a single byte and add to running checksum
  645. ;; Returns with CF = 0!
  646. send_byte:
  647. push hl
  648. ld l,a
  649. ld a,(ram_csum)
  650. add l
  651. ld (ram_csum),a
  652. in a,(1)
  653. and 2 ; TX space available
  654. call z,wait_for_tx
  655. ld a,l
  656. out (0),a
  657. pop hl
  658. ret
  659. ;; Send a buffer HL->data BC=count
  660. ;; On return HL advanced, BC=0, A clobbered
  661. ;;
  662. ; XXX: USB is fast enough that INIR/OTIR should be possible
  663. send_buf:
  664. ld a,b
  665. or c
  666. ret z
  667. ld a,(hl)
  668. call send_byte
  669. dec bc
  670. inc hl
  671. jr send_buf
  672. ;; Receive a byte. Return with C flag on timeout.
  673. recv_byte:
  674. ;; Optimistically...
  675. in a,(1)
  676. and 0Dh
  677. cp 09h
  678. call nz,wait_for_rx
  679. in a,(0) ; Data immediately available
  680. ret ; C=0 already
  681. ;; This routine waits until the status bit given in A is zero;
  682. ;; if the the high bits of the status are anything other than
  683. ;; xxxx10xx (configured, not suspended) then immediately issue
  684. ;; device not ready.
  685. wait_for_tx:
  686. push hl
  687. ld hl,0x0A0E
  688. jr wait_for
  689. wait_for_rx:
  690. push hl
  691. ld hl,0x090D ; Mask, expected value
  692. wait_for:
  693. push bc
  694. ld b,timeout
  695. wf_ctr:
  696. ld a,(CLOCK)
  697. ld c,a
  698. wf_loop:
  699. in a,(1)
  700. and l
  701. cp h
  702. jr nz,wf_nope
  703. pop bc
  704. pop hl
  705. ret
  706. wf_nope:
  707. and 0x0C ; Invalid status bits?
  708. cp 0x08
  709. jr nz,wf_error ; Not connected
  710. ld a,(CLOCK)
  711. cp c
  712. jr z,wf_loop
  713. djnz wf_ctr
  714. wf_error:
  715. ld a,128+42 ; Device not ready
  716. done4:
  717. jp done
  718. send_endframe:
  719. ld a,0EFh ; End of frame
  720. call send_byte
  721. ld a,(ram_csum)
  722. neg ; Total checksum = 0
  723. call send_byte
  724. out (2),a ; Immediately transmit any pending output
  725. ret
  726. ;; Send end of frame, and receive a reply header.
  727. ;; If the reply is an error, terminate command and return
  728. ;; the error code to BASIC (or other caller) by calling done.
  729. recv_reply:
  730. push bc
  731. call send_endframe
  732. ld bc,(ram_cmd)
  733. rr_loop:
  734. call recv_byte
  735. rr_isff:
  736. inc a ; FF?
  737. jr nz,rr_loop
  738. call recv_byte
  739. cp c ; Command
  740. jr nz,rr_isff
  741. call recv_byte
  742. cp b ; Serial
  743. jr nz,rr_isff
  744. call recv_byte ; Error code (if any)
  745. ;; Got this far, bump sequence number
  746. inc b
  747. ld (ram_cmd),bc
  748. pop bc
  749. and a
  750. ret p ; Bit 7 = 0 -> no error
  751. jr done4
  752. rr_timeout:
  753. dec b ; Drop the sequence number to allow resend
  754. jr wf_error
  755. ;;;
  756. ;;; Discard any (stale) input, if any. Terminate immediately if suspended,
  757. ;;; not configured, or not present. Clobbers A.
  758. ;;;
  759. flush_rx:
  760. in a,(1)
  761. and 0Dh
  762. sub 09h
  763. ret nz
  764. out (3),a ; Fast flush if supported by the hardware
  765. in a,(0) ; Consume byte
  766. jr flush_rx
  767. if console_dev
  768. prc_jptable:
  769. jp trivial ; OPEN
  770. jp trivial ; PREPARE
  771. jp trivial ; CLOSE
  772. jp notforme ; INPUT
  773. jp prc_print ; PRINT
  774. jp notforme ; RDBLK
  775. jp notforme ; WRBLK
  776. jp notforme ; DELETE
  777. jp notforme ; RENAME
  778. prc_print:
  779. call select
  780. ld a,0xFF
  781. call send_byte
  782. ld a,0xc0
  783. call send_byte
  784. prc_print_loop:
  785. ld a,b
  786. or c
  787. jr z,send_byte_done ; A=00 here
  788. ld a,(hl)
  789. and a
  790. jr z,prc_skip
  791. call send_byte
  792. prc_skip:
  793. dec bc
  794. inc hl
  795. jr prc_print_loop
  796. send_byte_done:
  797. call send_byte
  798. jp done_ok
  799. endif ; console_dev
  800. start:
  801. if have_cmd
  802. ld hl,new_basic_jumps
  803. ld bc,old_basic_jumps - new_basic_jumps
  804. ld a,(65h) ; First byte different between old and new
  805. and a
  806. jr z,is_new_basic
  807. add hl,bc
  808. is_new_basic:
  809. ld de,basic_jumps
  810. ldir
  811. endif
  812. call init ; Unwind to here on error or return
  813. ld hl,__end + INIT_OFFS ; Where to search next
  814. ret
  815. init:
  816. call select
  817. ld hl,-256
  818. add hl,sp
  819. ld sp,hl
  820. push hl
  821. ld a,0xA9 ; CLOSE ALL NO REPLY
  822. call send_cmd
  823. call recv_reply
  824. ld a,0xBA ; LIST VOLUMES
  825. pop hl
  826. push hl
  827. ld bc,4*MAX_VOLS+1 ; B=0
  828. call input_command
  829. pop hl
  830. ;; Create device list entries
  831. ;; HL -> CRAD here, A = 0
  832. push hl
  833. ld bc,4*MAX_VOLS
  834. add hl,bc
  835. ld (hl),b ; Make sure it is null-terminated on overflow
  836. pop hl
  837. ld de,voldevs
  838. ;; Are we running with auxram on the stack?
  839. bit 7,d
  840. jr z,1f
  841. ld (STACK),de ; Move down the user stack
  842. 1:
  843. mk_vols:
  844. ld a,(hl)
  845. and a
  846. jr z,link_volumes ; Done
  847. inc hl
  848. push hl
  849. ld hl,7
  850. add hl,de
  851. ex de,hl
  852. ld (hl),e
  853. inc hl
  854. ld (hl),d
  855. inc hl
  856. ex de,hl
  857. pop hl
  858. ld bc,3 ; Copy volume name
  859. ldir
  860. if pra_dev
  861. ;; This requires pra_jptable and prb_jptable have the same upper bytes
  862. dec a ; Z = 1 if A = 1 = text/PRA
  863. ld a,pra_jptable & 0xff
  864. jr z,have_voltype
  865. endif
  866. ld a,prb_jptable & 0xff
  867. have_voltype:
  868. ld (de),a
  869. inc de
  870. ld a,prb_jptable >> 8
  871. ld (de),a
  872. inc de
  873. jr mk_vols
  874. link_volumes:
  875. ;; A = 0 here
  876. ld hl,-7
  877. add hl,de
  878. ld de,(DEVLIST)
  879. ld (hl),e
  880. inc hl
  881. ld (hl),d
  882. ld hl,device_list
  883. ld (DEVLIST),hl
  884. jp done
  885. notforme:
  886. ld a,128+52 ; Ej till denna enhet
  887. scf
  888. ret
  889. if connul
  890. con_open:
  891. ;; Be nice and initialize the position fields, even though
  892. ;; we aren't really able to keep them updated...
  893. call S_CUR_MAX_X
  894. ld (ix+6),a
  895. ld (ix+7),e
  896. ;; Fall through
  897. endif
  898. trivial: ; Trivially successful call
  899. xor a ; A <- 0 carry <- 0
  900. ret
  901. if connul
  902. alwayseof: ; End of file or file not found
  903. xor a
  904. scf
  905. ret
  906. ;;;
  907. ;;; Simple CON and NUL devices for ABC800 compatibility
  908. ;;;
  909. con_jptable:
  910. jp con_open ; OPEN
  911. jp con_open ; PREPARE
  912. jp trivial ; CLOSE
  913. jp CON_INPUT ; INPUT
  914. jp CON_PRINT ; PRINT
  915. jp notforme ; RDBLK
  916. jp notforme ; WRBLK
  917. jp notforme ; DELETE
  918. jp notforme ; RENAME
  919. nul_jptable:
  920. jp trivial ; OPEN
  921. jp trivial ; PREPARE
  922. jp trivial ; CLOSE
  923. jp alwayseof ; INPUT
  924. jp trivial ; PRINT
  925. jp notforme ; RDBLK
  926. jp notforme ; WRBLK
  927. jp notforme ; DELETE
  928. jp notforme ; RENAME
  929. endif
  930. ;;;
  931. ;;; Support for CMD (via the IEC area)
  932. ;;;
  933. ;;; CMD [#device,] expr [,expr] ...
  934. ;;;
  935. ;;; Similar to PRINT except that each argument is terminated by
  936. ;;; a null byte before sending
  937. ;;;
  938. if have_cmd
  939. defc CMD_BUF = LINE_BUF
  940. defc CMD_BUF_LEN = LINE_SIZE
  941. ;; Need 16 bytes of overflow space for numbers
  942. defc CMD_BUF_END = CMD_BUF + CMD_BUF_LEN - 16
  943. defc e_iec = ERR_8 ; Not implemented
  944. e_cmd:
  945. ld l,0 ; No file number
  946. ld a,(de) ; Next byte code
  947. cp '#'
  948. jr nz,e_cmd_find_file
  949. inc de
  950. rst 56 ; Compute expression
  951. e_cmd_find_file:
  952. ld (iy+13),l
  953. ld ix,0 ; No file map
  954. ld a,l
  955. and a
  956. jr z,e_cmd_start ; Device 0
  957. ;; L = file number to find
  958. ld ix,FILELIST
  959. e_cmd_find_file_next:
  960. ld c,(ix+0) ; Link
  961. ld b,(ix+1)
  962. ld a,c
  963. or b
  964. jp z,ERR_32 ; File not open
  965. push bc
  966. pop ix
  967. ld a,(ix+2) ; File number
  968. cp l
  969. jr nz,e_cmd_find_file_next
  970. ;; IX -> file map
  971. e_cmd_start:
  972. push ix
  973. ld hl,CMD_BUF
  974. ld (e_cmd_buf_ptr),hl
  975. ld (errsp),sp ; SAve stack pointer for reset
  976. e_cmd_start_expr:
  977. ld a,(de)
  978. inc de
  979. cp ','
  980. jr z,e_cmd_start_expr
  981. cp ';'
  982. jr z,e_cmd_start_expr
  983. dec de
  984. cp 192 ; Byte code for expression
  985. jr c,e_cmd_done ; Not an expression?
  986. rst 56 ; Compute expression
  987. push de ; Save P-code pointer
  988. ld de,(e_cmd_buf_ptr)
  989. dec b ; Integer?
  990. jr nz,e_cmd_not_integer
  991. e_cmd_integer:
  992. call INT_TO_STR
  993. jr e_cmd_finish_num
  994. e_cmd_not_integer:
  995. dec b ; String?
  996. jr z,e_cmd_string
  997. e_cmd_float: ;; Floating point
  998. ld hl,2
  999. add hl,sp ; -> exponent on stack
  1000. call FLOAT_TO_STR
  1001. e_cmd_finish_num:
  1002. call e_cmd_check_overflow
  1003. e_cmd_finish:
  1004. ld (de),a
  1005. inc de
  1006. ld (e_cmd_buf_ptr),de
  1007. pop de ; P-code pointer
  1008. ld sp,(errsp) ; Reset stack
  1009. jr e_cmd_start_expr
  1010. e_cmd_string:
  1011. pop hl ; P-code pointer
  1012. pop bc ; Stack adjustment (not used)
  1013. pop bc ; String address
  1014. ex (sp),hl ; String length in HL, P-code pointer on stack
  1015. push bc ; String address
  1016. push hl ; String length
  1017. push de ; Output pointer
  1018. add hl,de ; End of string
  1019. ex de,hl
  1020. call e_cmd_check_overflow
  1021. pop de ; Output pointer
  1022. pop bc ; String length
  1023. pop hl ; String pointer
  1024. ldir
  1025. jr e_cmd_finish
  1026. e_cmd_done:
  1027. ;; Output generated, now send it
  1028. pop ix ; Restore IX map pointer
  1029. push de ; P-code pointer
  1030. ld hl,(e_cmd_buf_ptr)
  1031. ld de,CMD_BUF
  1032. xor a
  1033. sbc hl,de
  1034. ex de,hl
  1035. ld c,e
  1036. ld b,d
  1037. pop de
  1038. call select
  1039. ld a,0BBh ; GENERIC COMMAND
  1040. call prx_length_command
  1041. jp done
  1042. e_cmd_check_overflow:
  1043. ;; DE -> end of string data
  1044. push hl
  1045. ld hl,CMD_BUF_END-1 ; -1 for terminal null
  1046. xor a
  1047. sbc hl,de
  1048. pop hl
  1049. ret nc ; All good
  1050. e_cmd_space_overflow:
  1051. rst 10h
  1052. defb 128 + 20 ; "För lång rad"
  1053. endif ; have_cmd
  1054. defc need_device_list = console_dev | connul | raw_pr
  1055. if need_device_list
  1056. device_list:
  1057. if console_dev
  1058. prc_device:
  1059. if connul | raw_pr
  1060. defw . + 7 ; Next entry follows
  1061. else
  1062. defw voldevs
  1063. endif
  1064. defm "PRC"
  1065. defw prc_jptable
  1066. endif
  1067. if connul
  1068. con_device:
  1069. defw . + 7 ; Next entry follows
  1070. defm "CON"
  1071. defw con_jptable
  1072. nul_device:
  1073. if raw_pr
  1074. defw . + 7 ; Next entry follows
  1075. else
  1076. defw voldevs
  1077. endif
  1078. defm "NUL"
  1079. defw nul_jptable
  1080. endif
  1081. if raw_pr
  1082. pr_device:
  1083. defw voldevs
  1084. defm "PR "
  1085. defw pr_jptable
  1086. endif
  1087. endif
  1088. ;; Jump table for BASIC functions that are inconsistent
  1089. new_basic_jumps: ; Checksum 9913, 10042
  1090. if have_cmd
  1091. jp 3392h ; Check space on stack
  1092. jp 1853h ; Integer to string
  1093. jp 1675h ; Float to string
  1094. jp 2152h ; Compile PRINT
  1095. endif
  1096. old_basic_jumps: ; Checksum 11273
  1097. if have_cmd
  1098. jp 339Bh ; Check space on stack
  1099. jp 1855h ; Integer to string
  1100. jp 1679h ; Float to string
  1101. jp 2154h ; Compile PRINT
  1102. endif
  1103. ;; Check for overflow and pad to desired ROM size
  1104. .org ROMSIZE, 0xff
  1105. __end:
  1106. ;;
  1107. ;; In RAM; this is assuming external SRAM or equivalent at 20-22K.
  1108. ;; The top 64 bytes are used by UFD-DOS.
  1109. ;;
  1110. defc ram_end = AUXRAM_PRINTNET_END
  1111. defc ram_start = AUXRAM_PRINTNET_BASE
  1112. .globl _bss
  1113. _bss = AUXRAM_PRINTNET_BASE
  1114. section .bss
  1115. __bss:
  1116. if !need_device_list
  1117. device_list:
  1118. endif
  1119. voldevs:
  1120. defs 7*MAX_VOLS ; Up to 32 volume device entries
  1121. errsp:
  1122. defs 2 ; SP rollback on error return
  1123. e_cmd_buf_ptr:
  1124. defs 2 ; Current data buffer pointer
  1125. ram_select:
  1126. defs 1 ; Previous select code
  1127. ram_csum:
  1128. defs 1 ; Running output checksum
  1129. ram_cmd:
  1130. defs 1 ; Latest sent command
  1131. ram_serial:
  1132. defs 1 ; Latest serial number (must be immediately after ram_cmd)
  1133. ram_dummy:
  1134. defs 1 ; Scratch byte
  1135. basic_jumps:
  1136. if have_cmd
  1137. CHECK_STACK_SPACE: defs 3 ; Check space on stack
  1138. INT_TO_STR: defs 3 ; Integer to string
  1139. FLOAT_TO_STR: defs 3 ; Float to string
  1140. c_cmd: ; Compile CMD = same as PRINT
  1141. C_PRINT: defs 3 ; Compile PRINT
  1142. endif
  1143. ;;; Check for overflow
  1144. .org AUXRAM_PRINTNET_SIZE
  1145. __end_bss: