print80.inc 24 KB

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