;; This is a dissassembly of the cassette functions in the
;; CPC6128 operating system/firmware ROM.
;;

.
.
.

;;--------------------------------------------------------------
;; read byte from IX with roms disabled
;; IX = address of byte to read
;; used by cassette functions to read/write a byte
;; C' = current rom selection and mode

057d d9        exx						;; switch to alternative register set
057e 79        ld      a,c				;; rom configuration
057f f60c      or      $0c				;; %00001100 	
0581 ed79      out     (c),a			;; disable upper and lower rom

0583 dd7e00    ld      a,(ix+$00)		;; read byte

0586 ed49      out     (c),c			;; restore original rom configuration
0588 d9        exx						;; switch back from alternative register set
0589 c9        ret     
;;---------------------------------------------------------------

.
.
.

23fd af        xor     a
23fe cdde23    call    $23de
2401 f3        di      
2402 4e        ld      c,(hl)
2403 3e07      ld      a,$07
2405 c36308    jp      $0863
2408 cd8124    call    $2481
240b 7b        ld      a,e
240c cdab24    call    $24ab
240f d0        ret     nc

2410 7e        ld      a,(hl)
2411 e67f      and     $7f
2413 c8        ret     z

2414 dd7511    ld      (ix+$11),l
2417 dd7412    ld      (ix+$12),h
241a cd7024    call    $2470
241d 1809      jr      $2428            ; (+$09)
241f dd6e14    ld      l,(ix+$14)
2422 dd6615    ld      h,(ix+$15)
2425 dd5e18    ld      e,(ix+$18)
2428 4e        ld      c,(hl)
2429 23        inc     hl
242a 7b        ld      a,e
242b d6f0      sub     $f0
242d 3804      jr      c,$2433          ; (+$04)
242f 1e00      ld      e,$00
2431 180e      jr      $2441            ; (+$0e)
2433 1d        dec     e
2434 79        ld      a,c
2435 87        add     a,a
2436 9f        sbc     a,a
2437 57        ld      d,a
2438 dd7e16    ld      a,(ix+$16)
243b 81        add     a,c
243c 4f        ld      c,a
243d dd7e17    ld      a,(ix+$17)
2440 8a        adc     a,d
2441 57        ld      d,a
2442 cd8124    call    $2481
2445 4e        ld      c,(hl)
2446 7b        ld      a,e
2447 b7        or      a
2448 2019      jr      nz,$2463         ; (+$19)
244a dd7e13    ld      a,(ix+$13)
244d 3d        dec     a
244e 2010      jr      nz,$2460         ; (+$10)
2450 dd6e11    ld      l,(ix+$11)
2453 dd6612    ld      h,(ix+$12)
2456 7e        ld      a,(hl)
2457 c680      add     a,$80
2459 3805      jr      c,$2460          ; (+$05)
245b dd360400  ld      (ix+$04),$00
245f c9        ret     

2460 cd7024    call    $2470
2463 dd7318    ld      (ix+$18),e
2466 f3        di      
2467 dd7105    ld      (ix+$05),c
246a dd360480  ld      (ix+$04),$80
246e fb        ei      
246f c9        ret     

2470 dd7713    ld      (ix+$13),a
2473 23        inc     hl
2474 5e        ld      e,(hl)
2475 23        inc     hl
2476 dd7514    ld      (ix+$14),l
2479 dd7415    ld      (ix+$15),h
247c 7b        ld      a,e
247d b7        or      a
247e c0        ret     nz

247f 1c        inc     e
2480 c9        ret     

2481 dd7e00    ld      a,(ix+$00)
2484 87        add     a,a
2485 f5        push    af
2486 dd7116    ld      (ix+$16),c
2489 cd6308    call    $0863
248c f1        pop     af
248d 3c        inc     a
248e 4a        ld      c,d
248f dd7117    ld      (ix+$17),c
2492 c36308    jp      $0863
2495 11a6b2    ld      de,$b2a6
2498 1803      jr      $249d            ; (+$03)
249a 1196b3    ld      de,$b396
249d eb        ex      de,hl
249e cdae24    call    $24ae
24a1 eb        ex      de,hl
24a2 d0        ret     nc

24a3 edb0      ldir    
24a5 c9        ret     

24a6 21a6b2    ld      hl,$b2a6
24a9 1803      jr      $24ae            ; (+$03)
24ab 2196b3    ld      hl,$b396
24ae b7        or      a
24af c8        ret     z

24b0 fe10      cp      $10
24b2 d0        ret     nc

24b3 011000    ld      bc,$0010
24b6 09        add     hl,bc
24b7 3d        dec     a
24b8 20fc      jr      nz,$24b6         ; (-$04)
24ba 37        scf     
24bb c9        ret     

24bc cd5725    call    $2557
24bf cd9925    call    $2599
24c2 af        xor     a
24c3 cde124    call    $24e1
24c6 cdbf2b    call    $2bbf			; stop cassette motor
24c9 214d01    ld      hl,$014d
24cc 3e19      ld      a,$19
24ce 29        add     hl,hl
24cf 29        add     hl,hl
24d0 29        add     hl,hl
24d1 29        add     hl,hl
24d2 29        add     hl,hl
24d3 29        add     hl,hl
24d4 0f        rrca    
24d5 0f        rrca    
24d6 e63f      and     $3f
24d8 6f        ld      l,a
24d9 22e9b1    ld      ($b1e9),hl
24dc 3ae7b1    ld      a,($b1e7)
24df 37        scf     
24e0 c9        ret     

24e1 3218b1    ld      ($b118),a
24e4 c9        ret     

24e5 dd211ab1  ld      ix,$b11a
24e9 cd0225    call    $2502
24ec e5        push    hl
24ed dcac26    call    c,$26ac
24f0 e1        pop     hl
24f1 d0        ret     nc

24f2 ed5b34b1  ld      de,($b134)
24f6 ed4b37b1  ld      bc,($b137)
24fa 3a31b1    ld      a,($b131)
24fd c9        ret     

24fe dd215fb1  ld      ix,$b15f
2502 dd7e00    ld      a,(ix+$00)
2505 b7        or      a
2506 3e0e      ld      a,$0e
2508 c0        ret     nz

2509 dde5      push    ix
250b e3        ex      (sp),hl
250c 34        inc     (hl)
250d 23        inc     hl
250e 73        ld      (hl),e
250f 23        inc     hl
2510 72        ld      (hl),d
2511 23        inc     hl
2512 73        ld      (hl),e
2513 23        inc     hl
2514 72        ld      (hl),d
2515 23        inc     hl
2516 eb        ex      de,hl
2517 e1        pop     hl
2518 d5        push    de
2519 0e40      ld      c,$40
251b af        xor     a
251c 12        ld      (de),a
251d 13        inc     de
251e 0d        dec     c
251f 20fb      jr      nz,$251c         ; (-$05)
2521 d1        pop     de
2522 d5        push    de
2523 78        ld      a,b
2524 fe10      cp      $10
2526 3802      jr      c,$252a          ; (+$02)
2528 0610      ld      b,$10
252a 04        inc     b
252b 48        ld      c,b
252c 1807      jr      $2535            ; (+$07)

252e e7        rst     $20
252f 23        inc     hl
2530 cd2629    call    $2926			; convert character to upper case
2533 12        ld      (de),a
2534 13        inc     de
2535 10f7      djnz    $252e            ; (-$09)

2537 0d        dec     c
2538 2809      jr      z,$2543          ; (+$09)
253a 1b        dec     de
253b 1a        ld      a,(de)
253c ee20      xor     $20
253e 2003      jr      nz,$2543         ; (+$03)
2540 12        ld      (de),a
2541 18f4      jr      $2537            ; (-$0c)
2543 e1        pop     hl
2544 dd3415    inc     (ix+$15)
2547 dd361716  ld      (ix+$17),$16
254b dd351c    dec     (ix+$1c)
254e 37        scf     
254f c9        ret     

2550 3a1ab1    ld      a,($b11a)
2553 b7        or      a
2554 3e0e      ld      a,$0e
2556 c8        ret     z

2557 211ab1    ld      hl,$b11a
255a 0601      ld      b,$01
255c 7e        ld      a,(hl)
255d 3600      ld      (hl),$00
255f c5        push    bc
2560 cd6d25    call    $256d
2563 f1        pop     af
2564 21e4b1    ld      hl,$b1e4
2567 ae        xor     (hl)
2568 37        scf     
2569 c0        ret     nz

256a 77        ld      (hl),a
256b 9f        sbc     a,a
256c c9        ret     

256d fe04      cp      $04
256f d8        ret     c

2570 23        inc     hl
2571 5e        ld      e,(hl)
2572 23        inc     hl
2573 56        ld      d,(hl)
2574 6b        ld      l,e
2575 62        ld      h,d
2576 13        inc     de
2577 3600      ld      (hl),$00
2579 01ff07    ld      bc,$07ff
257c c3a1ba    jp      $baa1
257f 3a5fb1    ld      a,($b15f)
2582 fe03      cp      $03
2584 2813      jr      z,$2599          ; (+$13)
2586 c6ff      add     a,$ff
2588 3e0e      ld      a,$0e
258a d0        ret     nc

258b 2175b1    ld      hl,$b175
258e 35        dec     (hl)
258f 23        inc     hl
2590 23        inc     hl
2591 7e        ld      a,(hl)
2592 23        inc     hl
2593 b6        or      (hl)
2594 37        scf     
2595 c48627    call    nz,$2786
2598 d0        ret     nc

2599 215fb1    ld      hl,$b15f
259c 0602      ld      b,$02
259e 18bc      jr      $255c            ; (-$44)
25a0 e5        push    hl
25a1 d5        push    de
25a2 c5        push    bc
25a3 0605      ld      b,$05
25a5 cdf625    call    $25f6
25a8 201a      jr      nz,$25c4         ; (+$1a)
25aa 2a32b1    ld      hl,($b132)
25ad 7c        ld      a,h
25ae b5        or      l
25af 37        scf     
25b0 ccac26    call    z,$26ac
25b3 300f      jr      nc,$25c4         ; (+$0f)
25b5 2a32b1    ld      hl,($b132)
25b8 2b        dec     hl
25b9 2232b1    ld      ($b132),hl
25bc 2a1db1    ld      hl,($b11d)
25bf e7        rst     $20
25c0 23        inc     hl
25c1 221db1    ld      ($b11d),hl
25c4 182c      jr      $25f2            ; (+$2c)
25c6 e5        push    hl
25c7 d5        push    de
25c8 c5        push    bc
25c9 4f        ld      c,a
25ca 215fb1    ld      hl,$b15f
25cd 0605      ld      b,$05
25cf cdf925    call    $25f9
25d2 201e      jr      nz,$25f2         ; (+$1e)
25d4 2a77b1    ld      hl,($b177)
25d7 110008    ld      de,$0800
25da ed52      sbc     hl,de
25dc c5        push    bc
25dd d48627    call    nc,$2786
25e0 c1        pop     bc
25e1 300f      jr      nc,$25f2         ; (+$0f)
25e3 2a77b1    ld      hl,($b177)
25e6 23        inc     hl
25e7 2277b1    ld      ($b177),hl
25ea 2a62b1    ld      hl,($b162)
25ed 71        ld      (hl),c
25ee 23        inc     hl
25ef 2262b1    ld      ($b162),hl
25f2 c1        pop     bc
25f3 d1        pop     de
25f4 e1        pop     hl
25f5 c9        ret     

25f6 211ab1    ld      hl,$b11a
25f9 7e        ld      a,(hl)
25fa b8        cp      b
25fb c8        ret     z

25fc ee01      xor     $01
25fe 3e0e      ld      a,$0e
2600 c0        ret     nz

2601 70        ld      (hl),b
2602 c9        ret     

2603 cda025    call    $25a0
2606 d0        ret     nc

2607 e5        push    hl
2608 2a32b1    ld      hl,($b132)
260b 23        inc     hl
260c 2232b1    ld      ($b132),hl
260f 2a1db1    ld      hl,($b11d)
2612 2b        dec     hl
2613 221db1    ld      ($b11d),hl
2616 e1        pop     hl
2617 c9        ret     

2618 eb        ex      de,hl
2619 0602      ld      b,$02
261b cdf625    call    $25f6
261e c0        ret     nz

261f ed5334b1  ld      ($b134),de
2623 cd3c26    call    $263c
2626 2a34b1    ld      hl,($b134)
2629 ed5b32b1  ld      de,($b132)
262d 19        add     hl,de
262e 2234b1    ld      ($b134),hl
2631 cdac26    call    $26ac
2634 38f0      jr      c,$2626          ; (-$10)
2636 c8        ret     z

2637 2abeb1    ld      hl,($b1be)
263a 37        scf     
263b c9        ret     

263c 2a1bb1    ld      hl,($b11b)
263f ed4b32b1  ld      bc,($b132)
2643 7b        ld      a,e
2644 95        sub     l
2645 7a        ld      a,d
2646 9c        sbc     a,h
2647 daa1ba    jp      c,$baa1
264a 09        add     hl,bc
264b 2b        dec     hl
264c eb        ex      de,hl
264d 09        add     hl,bc
264e 2b        dec     hl
264f eb        ex      de,hl
2650 c3a7ba    jp      $baa7
2653 e5        push    hl
2654 c5        push    bc
2655 4f        ld      c,a
2656 215fb1    ld      hl,$b15f
2659 0602      ld      b,$02
265b cdf925    call    $25f9
265e 202d      jr      nz,$268d         ; (+$2d)
2660 79        ld      a,c
2661 c1        pop     bc
2662 e1        pop     hl
2663 3276b1    ld      ($b176),a
2666 ed537cb1  ld      ($b17c),de
266a ed437eb1  ld      ($b17e),bc
266e 2260b1    ld      ($b160),hl
2671 ed5377b1  ld      ($b177),de
2675 21fff7    ld      hl,$f7ff
2678 19        add     hl,de
2679 3f        ccf     
267a d8        ret     c

267b 210008    ld      hl,$0800
267e 2277b1    ld      ($b177),hl
2681 eb        ex      de,hl
2682 ed52      sbc     hl,de
2684 e5        push    hl
2685 2a60b1    ld      hl,($b160)
2688 19        add     hl,de
2689 e5        push    hl
268a cd8627    call    $2786
268d e1        pop     hl
268e d1        pop     de
268f d0        ret     nc

2690 18dc      jr      $266e            ; (-$24)
2692 211ab1    ld      hl,$b11a
2695 7e        ld      a,(hl)
2696 b7        or      a
2697 3e0e      ld      a,$0e
2699 c0        ret     nz

269a 3604      ld      (hl),$04
269c ed531bb1  ld      ($b11b),de
26a0 af        xor     a
26a1 cde124    call    $24e1
26a4 cdb326    call    $26b3
26a7 38fb      jr      c,$26a4          ; (-$05)
26a9 c35725    jp      $2557

26ac 3a30b1    ld      a,($b130)		; last block flag
26af b7        or      a
26b0 3e0f      ld      a,$0f
26b2 c0        ret     nz

26b3 010183    ld      bc,$8301
26b6 cde527    call    $27e5
26b9 305f      jr      nc,$271a         ; (+$5f)

;; read header
;;
;; B1A4-B1B3	filename
;; B1B4			block number
;; B1B5			last block flag
;; B1B6			file type 
;; B1B7,B1B8	length
;; B1B9,B1BA	location
;; B1BB			first block flag

;; stored header:
;; 
;; B11F-B12E	filename
;; B12F			block number
;; B130			last block flag
;; B131			file type
;; B132,B133	length
;; B134,B135	location
;; B136			first block flag


26bb 21a4b1    ld      hl,$b1a4
26be 114000    ld      de,$0040
26c1 3e2c      ld      a,$2c			; header sync 
26c3 cda629    call    $29a6			; cas read: read header

26c6 3052      jr      nc,$271a         ; (+$52)


26c8 068b      ld      b,$8b			; no message
26ca cd2f29    call    $292f			; cassette messages disabled?
26cd 2807      jr      z,$26d6          

;; cassette messages are not disabled, so check filenames and display loading
;; message.

26cf cd3727    call    $2737			; compare filenames
26d2 2053      jr      nz,$2727         ; if nz, display "Found xxx block x"

26d4 0689      ld      b,$89			; "Loading"
26d6 cd0428    call    $2804			; display "Loading xxx block x"

26d9 ed5bb7b1  ld      de,($b1b7)		; length from loaded header
26dd 2a34b1    ld      hl,($b134)		; location from stored header

26e0 3a1ab1    ld      a,($b11a)
26e3 fe02      cp      $02
26e5 280e      jr      z,$26f5          ; (+$0e)

26e7 21fff7    ld      hl,$f7ff
26ea 19        add     hl,de
26eb 3e04      ld      a,$04
26ed 382b      jr      c,$271a          ; (+$2b)
26ef 2a1bb1    ld      hl,($b11b)
26f2 221db1    ld      ($b11d),hl

26f5 3e16      ld      a,$16			; data sync
26f7 cda629    call    $29a6			; cas read: read data

26fa 301e      jr      nc,$271a         ;

;; increment block number in internal header
26fc 212fb1    ld      hl,$b12f			; block number
26ff 34        inc     (hl)				; increment block number

;; get last block flag from loaded header and store into
;; internal header
2700 3ab5b1    ld      a,($b1b5)		
2703 23        inc     hl
2704 77        ld      (hl),a			

;; clear first block flag
2705 af        xor     a				
2706 3236b1    ld      ($b136),a

2709 2ab7b1    ld      hl,($b1b7)		; get length from loaded header
270c 2232b1    ld      ($b132),hl		; store in internal header

270f cd2f29    call    $292f			; cassette messages disabled?

2712 3e8c      ld      a,$8c			; "OK"
2714 cc7e28    call    z,$287e			; display message
2717 37        scf     
2718 1865      jr      $277f            ; (+$65)

;;===========================================================================

271a b7        or      a
271b 211ab1    ld      hl,$b11a
271e 2858      jr      z,$2778          ; (+$58)

2720 0685      ld      b,$85			; "Read error"
2722 cd8528    call    $2885
2725 1894      jr      $26bb            ; (-$6c)

;;===========================================================================

2727 f5        push    af
2728 0688      ld      b,$88			; "Found "
272a cd0428    call    $2804			; "Found xxx block x"
272d f1        pop     af
272e 308b      jr      nc,$26bb         ; (-$75)

2730 0687      ld      b,$87			; "Rewind tape"
2732 cd8328    call    $2883
2735 1884      jr      $26bb            ; (-$7c)

;;========================================================================
;; compare filenames

2737 3a36b1    ld      a,($b136)		; first block flag in internal header?
273a b7        or      a
273b 281b      jr      z,$2758          

273d 3abbb1    ld      a,($b1bb)		; first block flag in loaded header?
2740 2f        cpl     
2741 b7        or      a
2742 c0        ret     nz

;; if user specified a filename, compare it against the filename in the loaded
;; header, otherwise accept the file

2743 3a1fb1    ld      a,($b11f)		; did user specify a filename?
										; e.g. LOAD"bob
2746 b7        or      a

2747 c46027    call    nz,$2760			; compare filenames
274a c0        ret     nz				; if filenames do not match, quit

;; gets here if:

;; 1. if a filename was specified by user and filename matches with 
;; filename in loaded header
;;
;; 2. no filename was specified by user

;; copy loaded header to internal header
274b 21a4b1    ld      hl,$b1a4
274e 111fb1    ld      de,$b11f
2751 014000    ld      bc,$0040
2754 edb0      ldir    

2756 af        xor     a
2757 c9        ret     

;;=========================================================================

;; not first block

2758 cd6027    call    $2760			; compare filenames
275b c0        ret     nz

275c eb        ex      de,hl
275d 1a        ld      a,(de)
275e be        cp      (hl)
275f c9        ret     

;;============================================================================
;; compare strings
;;
;; nz = filenames are different
;; z = filenames are identical

2760 211fb1    ld      hl,$b11f			; in-memory header
2763 11a4b1    ld      de,$b1a4			; loaded header

;; compare filenames
2766 0610      ld      b,$10			; 16 characters

2768 1a        ld      a,(de)			; get character from loaded header
2769 cd2629    call    $2926			; convert character to upper case
276c 4f        ld      c,a
276d 7e        ld      a,(hl)			; get character from in-memory header
276e cd2629    call    $2926			; convert character to upper case

2771 a9        xor     c				
2772 c0        ret     nz				; quit if characters are not the same

2773 23        inc     hl				; increment pointer
2774 13        inc     de				; increment pointer
2775 10f1      djnz    $2768            ; 

;; the filenames are identical
2777 c9        ret     
;;============================================================================

2778 7e        ld      a,(hl)
2779 3603      ld      (hl),$03
277b cd6d25    call    $256d
277e b7        or      a
277f 9f        sbc     a,a
2780 f5        push    af
2781 cdbf2b    call    $2bbf			; stop cassette motor
2784 f1        pop     af
2785 c9        ret     

2786 010284    ld      bc,$8402
2789 cde527    call    $27e5
278c 304a      jr      nc,$27d8         ; (+$4a)
278e 068a      ld      b,$8a
2790 1164b1    ld      de,$b164
2793 cd0728    call    $2807
2796 217bb1    ld      hl,$b17b
2799 cdfa27    call    $27fa
279c 303a      jr      nc,$27d8         ; (+$3a)
279e 2a60b1    ld      hl,($b160)
27a1 2262b1    ld      ($b162),hl
27a4 2279b1    ld      ($b179),hl
27a7 e5        push    hl

27a8 2164b1    ld      hl,$b164
27ab 114000    ld      de,$0040
27ae 3e2c      ld      a,$2c			; header sync byte
27b0 cdaf29    call    $29af			; cas write: write header
27b3 e1        pop     hl
27b4 3022      jr      nc,$27d8         ; (+$22)
27b6 ed5b77b1  ld      de,($b177)
27ba 3e16      ld      a,$16			; data sync byte
27bc cdaf29    call    $29af			; cas write: write data block
27bf 2175b1    ld      hl,$b175
27c2 dcfa27    call    c,$27fa
27c5 3011      jr      nc,$27d8         ; (+$11)
27c7 210000    ld      hl,$0000
27ca 2277b1    ld      ($b177),hl
27cd 2174b1    ld      hl,$b174
27d0 34        inc     (hl)
27d1 af        xor     a
27d2 327bb1    ld      ($b17b),a
27d5 37        scf     
27d6 18a7      jr      $277f            ; (-$59)
27d8 b7        or      a
27d9 215fb1    ld      hl,$b15f
27dc 289a      jr      z,$2778          ; (-$66)
27de 0686      ld      b,$86
27e0 cd8528    call    $2885
27e3 18b9      jr      $279e            ; (-$47)
27e5 21e4b1    ld      hl,$b1e4
27e8 79        ld      a,c
27e9 be        cp      (hl)
27ea 71        ld      (hl),c
27eb 37        scf     
27ec e5        push    hl
27ed c5        push    bc
27ee c4d228    call    nz,$28d2
27f1 c1        pop     bc
27f2 e1        pop     hl
27f3 9f        sbc     a,a
27f4 d0        ret     nc

27f5 cdbb2b    call    $2bbb			; start cassette motor
27f8 9f        sbc     a,a
27f9 c9        ret     

27fa 7e        ld      a,(hl)
27fb b7        or      a
27fc 37        scf     
27fd c8        ret     z

27fe 012c01    ld      bc,$012c
2801 c3e22b    jp      $2be2

2804 11a4b1    ld      de,$b1a4
2807 3a18b1    ld      a,($b118)
280a b7        or      a
280b c0        ret     nz

280c 3219b1    ld      ($b119),a
280f cdf328    call    $28f3

2812 cd9828    call    $2898			; display message

2815 1a        ld      a,(de)			; is first character of filename = 0?
2816 b7        or      a
2817 200a      jr      nz,$2823         ; 

;; unnamed file

2819 3e8e      ld      a,$8e			; "Unnamed file"
281b cd9928    call    $2899			; display message

281e 011000    ld      bc,$0010
2821 182e      jr      $2851            ; (+$2e)

;;-----------------------------
;; named file
2823 cd2f29    call    $292f

2826 010010    ld      bc,$1000
2829 280d      jr      z,$2838          ; (+$0d)
282b 6b        ld      l,e
282c 62        ld      h,d
282d 7e        ld      a,(hl)
282e b7        or      a
282f 2804      jr      z,$2835          ; (+$04)
2831 0c        inc     c
2832 23        inc     hl
2833 10f8      djnz    $282d            ; (-$08)
2835 78        ld      a,b
2836 41        ld      b,c
2837 4f        ld      c,a

2838 cdfd28    call    $28fd			; insert new-line if word
										; can't fit onto current-line

283b 1a        ld      a,(de)			; get character from filename
283c cd2629    call    $2926			; convert character to upper case

283f b7        or      a				; zero?
2840 2002      jr      nz,$2844         

;; display a space if a zero is found

2842 3e20      ld      a,$20			; display a space

2844 c5        push    bc
2845 d5        push    de
2846 cd3513    call    $1335			; display character
2849 d1        pop     de
284a c1        pop     bc
284b 13        inc     de
284c 10ed      djnz    $283b            ; (-$13)

284e cdce28    call    $28ce			; display space

2851 eb        ex      de,hl
2852 09        add     hl,bc
2853 eb        ex      de,hl

2854 3e8d      ld      a,$8d			; "block "
2856 cd9928    call    $2899			; display message

2859 0602      ld      b,$02			; length of word
285b cdfd28    call    $28fd			; insert new-line if word
										; can't fit onto current-line

285e 1a        ld      a,(de)
285f cd1429    call    $2914			; display decimal number

2862 cdce28    call    $28ce			; display space

2865 13        inc     de
2866 cd2f29    call    $292f
2869 200b      jr      nz,$2876         ; (+$0b)
286b 13        inc     de
286c 1a        ld      a,(de)
286d e60f      and     $0f
286f c624      add     a,$24
2871 cdf028    call    $28f0

2874 1858      jr      $28ce            ; display space

2876 1a        ld      a,(de)
2877 2119b1    ld      hl,$b119
287a b6        or      (hl)
287b c8        ret     z

287c 186d      jr      $28eb            ; (+$6d)

287e cd9928    call    $2899			; display message
2881 1868      jr      $28eb            ; (+$68)

2883 3eff      ld      a,$ff

;; display message
2885 f5        push    af
2886 cd9128    call    $2891
2889 f1        pop     af
288a c660      add     a,$60
288c d4f028    call    nc,$28f0			; display character
288f 185a      jr      $28eb            ; (+$5a)

2891 cd7c11    call    $117c
2894 25        dec     h
2895 c4eb28    call    nz,$28eb

2898 78        ld      a,b

;;=========================================================================
;; display message
;;
;; - message is displayed using word-wrap
;;
;; a = message number (&80-&FF)
2899 e5        push    hl

289a e67f      and     $7f				; get message index (0-127)
289c 47        ld      b,a

289d 213529    ld      hl,$2935			; start of message list (points to first message)

;; first message in list? (message 0?)
28a0 2807      jr      z,$28a9          

;; not first. 
;; 
;; - each message is terminated by a zero byte
;; - keep fetching bytes until a zero is found.
;; - if a zero is found, decrement count. If count reaches zero, then 
;; the first byte following the zero, is the start of the message we want

28a2 7e        ld      a,(hl)			; get byte
28a3 23        inc     hl				; increment pointer

28a4 b7        or      a				; is it zero (0) ?
28a5 20fb      jr      nz,$28a2         ; if zero, it is the end of this string

;; got a zero byte, so at end of the current string

28a7 10f9      djnz    $28a2            ; decrement message count

;; HL = start of message to display

;; this part is looped; message may contain multiple strings

;; end of message?
28a9 7e        ld      a,(hl)
28aa b7        or      a
28ab 2805      jr      z,$28b2          ; (+$05)

;; display message
28ad cdb528    call    $28b5			; display message with word-wrap

;; at this point there might be a end of string marker (0), the start
;; of another string (next byte will have bit 7=0) or a continuation string
;; (next byte will have bit 7=1)
28b0 18f7      jr      $28a9           ; continue displaying string 

;; finished displaying complete string , or displayed part of string sequence
28b2 e1        pop     hl

28b3 23        inc     hl				; if part of a complete message, go to next sub-string or word
28b4 c9        ret     

;;=========================================================================
;; display message with word wrap

;; HL = address of message
;; A = first character in message

;; if -ve, then bit 7 is set. Bit 6..0 define the ID of the message to display
;; if +ve, then this is the first character in the message
28b5 fa9928    jp      m,$2899			


;;-------------------------------------
;; count number of letters in word

28b8 e5        push    hl			;; store start of word

;; count number of letters in world
28b9 0600      ld      b,$00
28bb 04        inc     b

28bc 7e        ld      a,(hl)		;; get character
28bd 23        inc     hl			;; increment pointer
28be 07        rlca					;; if bit 7 is set, then this is the last character of the current word
28bf 30fa      jr      nc,$28bb        

;; B = number of letters

;; if word will not fit onto end of current line, insert
;; a line break, and display on next line
28c1 cdfd28    call    $28fd

28c4 e1        pop     hl			;; restore start of word 

;;------------------------------------
;; display word

;; HL = location of characters
;; B = number of characters 
28c5 7e        ld      a,(hl)			; get byte
28c6 23        inc     hl				; increment counter
28c7 e67f      and     $7f				; isolate byte
28c9 cdf028    call    $28f0			; display char (txt output?)
28cc 10f7      djnz    $28c5            

;; display space
28ce 3e20      ld      a,$20			; " " (space) character
28d0 181e      jr      $28f0            ; display character

;;=========================================================================

28d2 3a18b1    ld      a,($b118)
28d5 b7        or      a
28d6 37        scf     
28d7 c0        ret     nz

28d8 cd9128    call    $2891
28db cdfe1b    call    $1bfe
28de cd7612    call    $1276
28e1 cddb1c    call    $1cdb
28e4 cd7e12    call    $127e
28e7 fefc      cp      $fc
28e9 c8        ret     z

28ea 37        scf     
28eb cdf328    call    $28f3

;; display cr
28ee 3e0a      ld      a,$0a
28f0 c3fe13    jp      $13fe

;;==========================================================================

28f3 f5        push    af
28f4 e5        push    hl
28f5 3e01      ld      a,$01
28f7 cd5a11    call    $115a
28fa e1        pop     hl
28fb f1        pop     af
28fc c9        ret     

;;==========================================================================
;; determine if word can be displayed on this line
28fd d5        push    de
28fe cd5212    call    $1252
2901 5c        ld      e,h
2902 cd7c11    call    $117c
2905 7c        ld      a,h
2906 3d        dec     a
2907 83        add     a,e
2908 80        add     a,b
2909 3d        dec     a
290a ba        cp      d
290b d1        pop     de
290c d8        ret     c

290d 3eff      ld      a,$ff
290f 3219b1    ld      ($b119),a
2912 18d7      jr      $28eb            ; (-$29)


;;============================================================================

;; divide by 10
2914 06ff      ld      b,$ff
2916 04        inc     b
2917 d60a      sub     $0a				
2919 30fb      jr      nc,$2916         ; (-$05)
;; B = result of division by 10
;; A = <10

291b c63a      add     a,$3a			; convert to ASCII digit
			
291d f5        push    af
291e 78        ld      a,b
291f b7        or      a
2920 c41429    call    nz,$2914			; continue with division

2923 f1        pop     af
2924 18ca      jr      $28f0            ; display character

;;============================================================================
;; convert character to upper case
2926 fe61      cp      $61				; "a"
2928 d8        ret     c

2929 fe7b      cp      $7b				; "z"
292b d0        ret     nc

292c c6e0      add     a,$e0
292e c9        ret     

;;============================================================================
;; cassette messages 
;; if "4" cassette messages are disabled, otherwise they are enabled

292f 3a1ab1    ld      a,($b11a)
2932 fe04      cp      $04
2934 c9        ret     

;;============================================================================
;; cassette messages
;; - a zero (0) byte indicates end of complete message
;; - a byte with bit 7 set indicates:
;;	 end of a word, the id of another continuing string
;; 0: "Press"
;; 1: "PLAY then any key:"
;; 2: "error"
;; 3: "Press PLAY then any key:"
;; 4: "Press REC and PLAY then any key:"
;; 5: "Read error"
;; 6: "Write error"
;; 7: "Rewind tape"
;; 8: "Found  "
;; 9: "Loading"
;; 10: "Saving"
;; 11: <blank>
;; 12: "Ok"
;; 13: "block"
;; 14: "Unnamed file"

defb "Pres","s"+&80,0
defb "PLA","Y"+&80,"the","n"+&80,"an","y"+&80,"key",":"+&80,0
defb "erro","r"+&80,0
defb 0+&80,1+&80,0
defb &80,"RE","C"+&80,"an","d"+&80,&81,defb 0
defb "Rea","d"+&80,&82
defb "Writ","e"+&80,&82
defb "Rewin","d"+&80,"tap","e"+&80,0
defb "Found "," "+&80,0
defb "Loadin","g"+&80,0
defb "Savin","g"+&80,0
defb 0
defb "O","k"+&80,0
defb "bloc","k"+&80,0
defb "Unname"d"+&80,"file   "," "+&80,0


;;=========================================================================
;; cas read
;; A = sync byte
;; HL = location of data
;; DE = length of data

29a6 cde329    call    $29e3			; enable key checking and start the cassette motor
29a9 f5        push    af
29aa 21282a    ld      hl,$2a28			; read block of data
29ad 1819      jr      $29c8            ; do read

;;=========================================================================
;; cas write
;; A = sync byte
;; HL = destination location for data
;; DE = length of data

29af cde329    call    $29e3			; enable key checking and start the cassette motor
29b2 f5        push    af
29b3 cdd42a    call    $2ad4			;; write start of block (pilot and syncs)
29b6 21672a    ld      hl,$2a67			;; write block of data
29b9 dc0d2a    call    c,$2a0d			;; read/write 256 byte blocks
29bc dce92a    call    c,$2ae9			;; write trailer
29bf 180f      jr      $29d0            ;; 

;;=========================================================================
;; cas check
29c1 cde329    call    $29e3			; enable key checking and start the cassette motor
29c4 f5        push    af
29c5 21372a    ld      hl,$2a37			;; check stored block with block in memory

;;------------------------------------------------------
;; do read
;; cas check or cas read
29c8 e5        push    hl
29c9 cd892a    call    $2a89			;; read pilot and sync
29cc e1        pop     hl
29cd dc0d2a    call    c,$2a0d			;; read/write 256 byte blocks


;;----------------------------------------------------------------
;; cas check, cas read or cas write
29d0 d1        pop     de
29d1 f5        push    af

29d2 0182f7    ld      bc,$f782			;; set PPI port A to output
29d5 ed49      out     (c),c

29d7 0110f6    ld      bc,$f610			;; cassette motor on
29da ed49      out     (c),c

;; if cassette motor is stopped, then it will stop immediatly
;; if cassette motor is running, then there will not be any pause.

29dc fb        ei						;; enable interrupts

29dd 7a        ld      a,d
29de cdc12b    call    $2bc1			;; return previous cassette motor state
29e1 f1        pop     af
29e2 c9        ret     

;;=========================================================================
;; enable key checking and start the cassette motor

;; store sync byte
29e3 32e5b1    ld      ($b1e5),a

29e6 1b        dec     de
29e7 1c        inc     e

29e8 e5        push    hl
29e9 d5        push    de
29ea cde91f    call    $1fe9			; ???
29ed d1        pop     de
29ee dde1      pop     ix

29f0 cdbb2b    call    $2bbb			; start cassette motor


29f3 f3        di					;; disable interrupts

;; select PSG register 14 (PSG port A)
;; (keyboard data is connected to PSG port A)
29f4 010ef4    ld      bc,$f40e		;; select keyboard line 14
29f7 ed49      out     (c),c

29f9 01d0f6    ld      bc,$f6d0		;; cassette motor on + PSG select register operation
29fc ed49      out     (c),c

29fe 0e10      ld      c,$10
2a00 ed49      out     (c),c		;; cassette motor on + PSG inactive operation

2a02 0192f7    ld      bc,$f792		;; set PPI port A to input
2a05 ed49      out     (c),c		
									;; PSG port A data can be read through PPI port A now

2a07 0158f6    ld      bc,$f658		;; cassette motor on + PSG read data operation + select keyboard line 8
2a0a ed49      out     (c),c
2a0c c9        ret     

;;========================================================================================
;; read/write blocks

;; DE = number of bytes to read/write

;; D = number of 256 blocks to read/write 
;; if D = 0, then there is a single block to write, which has E bytes
;; in it.
;; if D!=0, then there is more than one block to write, write 256 bytes
;; for each block except the last. Then write final block with remaining
;; bytes.

2a0d 7a        ld      a,d
2a0e b7        or      a
2a0f 280d      jr      z,$2a1e          ; (+$0d)

;; do each complete 256 byte block
2a11 e5        push    hl
2a12 d5        push    de
2a13 1e00      ld      e,$00			; number of bytes
2a15 cd1e2a    call    $2a1e			; read/write block
2a18 d1        pop     de
2a19 e1        pop     hl
2a1a d0        ret     nc

2a1b 15        dec     d
2a1c 20f3      jr      nz,$2a11         ; (-$0d)

;; E = number of bytes in last block to write

;;------------------------------------
;; initialise crc
2a1e 01ffff    ld      bc,$ffff
2a21 ed43ebb1  ld      ($b1eb),bc

;; do function
2a25 1601      ld      d,$01
2a27 e9        jp      (hl)

;;========================================================================================
;; IX = address to load data to 
;; read data
;; input:
;; D = block size
;; E = actual data size
;; output:
;; D = bytes remaining in block (block size - actual data size)

2a28 cd202b    call    $2b20			; read byte from cassette
2a2b d0        ret     nc

2a2c dd7700    ld      (ix+$00),a		; store byte
2a2f dd23      inc     ix				; increment pointer

2a31 15        dec     d				; decrement block count

2a32 1d        dec     e
2a33 20f3      jr      nz,$2a28         ; decrement actual data count

;; D = number of bytes remaining in block

;; read remaining bytes in block; but ignore
2a35 1812      jr      $2a49            ; (+$12)

;;========================================================================================
;; check stored block with block in memory
2a37 cd202b    call    $2b20			; read byte from cassette
2a3a d0        ret     nc

2a3b 47        ld      b,a
2a3c cdd7ba    call    $bad7			; get byte from IX with roms disabled
2a3f a8        xor     b				


2a40 3e03      ld      a,$03
2a42 c0        ret     nz

2a43 dd23      inc     ix
2a45 15        dec     d
2a46 1d        dec     e
2a47 20ee      jr      nz,$2a37         ; (-$12)

;; any more bytes remaining in block??
2a49 15        dec     d
2a4a 2806      jr      z,$2a52          ; 

;; bytes remaining
;; read the remaining bytes but ignore

2a4c cd202b    call    $2b20			; read byte from cassette	
2a4f d0        ret     nc

2a50 18f7      jr      $2a49            ; (-$09)

;;-----------------------------------------------------

2a52 cd162b    call    $2b16			; get 1's complemented crc

2a55 cd202b    call    $2b20			; read crc byte1 from cassette
2a58 d0        ret     nc

2a59 aa        xor     d
2a5a 2007      jr      nz,$2a63         ; (+$07)

2a5c cd202b    call    $2b20			; read crc byte2 from cassette
2a5f d0        ret     nc

2a60 ab        xor     e
2a61 37        scf     
2a62 c8        ret     z

2a63 3e02      ld      a,$02
2a65 b7        or      a
2a66 c9        ret     

;;========================================================================================
;; write block of data (pad with 0's if less than block size)
;; IX = address of data
;; E = actual byte count
;; D = block size count
 
2a67 cdd7ba    call    $bad7			; get byte from IX with roms disabled
2a6a cd682b    call    $2b68			; write data byte
2a6d d0        ret     nc

2a6e dd23      inc     ix				; increment pointer

2a70 15        dec     d				; decrement block size count
2a71 1d        dec     e				; decrement actual count
2a72 20f3      jr      nz,$2a67         ; (-$0d)

;; actual byte count = block size count?
2a74 15        dec     d
2a75 2807      jr      z,$2a7e          

;; no, actual byte count was less than block size
;; pad up to block size with zeros

2a77 af        xor     a
2a78 cd682b    call    $2b68			; write data byte
2a7b d0        ret     nc

2a7c 18f6      jr      $2a74            ; (-$0a)


;; get 1's complemented crc
2a7e cd162b    call    $2b16

;; write crc 1
2a81 cd682b    call    $2b68			; write data byte
2a84 d0        ret     nc

;; write crc 2
2a85 7b        ld      a,e
2a86 c3682b    jp      $2b68			; write data byte

;;========================================================================================
;; read pilot and sync

2a89 d5        push    de
2a8a cd932a    call    $2a93			; read pilot and sync
2a8d d1        pop     de

2a8e d8        ret     c			

2a8f b7        or      a
2a90 c8        ret     z

2a91 18f6      jr      $2a89            ; (-$0a)

;;==========================================================================
;; read pilot and sync

;;---------------------------------
;; wait for start of leader/pilot

2a93 2e55      ld      l,$55			; %01010101
										; this is used to generate the cassette input data comparison 
										; used in the edge detection

2a95 cd3d2b    call    $2b3d			; sample edge
2a98 d0        ret     nc

;;------------------------------------------
;; get 256 pulses of leader/pilot
2a99 110000    ld      de,$0000			; initial total

2a9c 62        ld      h,d

2a9d cd3d2b    call    $2b3d			; sample edge
2aa0 d0        ret     nc

2aa1 eb        ex      de,hl
;; C = measured time
;; add measured time to total
2aa2 0600      ld      b,$00
2aa4 09        add     hl,bc
2aa5 eb        ex      de,hl

2aa6 25        dec     h
2aa7 20f4      jr      nz,$2a9d         ; (-$0c)


;; C = duration of last pulse read

;; look for sync bit
;; and adjust the average for every non-sync

;; DE = sum of 256 edges
;; D:E forms a 8.8 fixed point number
;; D = integer part of number (integer average of 256 pulses)
;; E = fractional part of number

2aa9 61        ld      h,c				; time of last pulse

2aaa 79        ld      a,c
2aab 92        sub     d				; subtract initial average 
2aac 4f        ld      c,a
2aad 9f        sbc     a,a
2aae 47        ld      b,a

;; if C>D then BC is +ve; BC = +ve delta
;; if C<D then BC is -ve; BC = -ve delta

;; adjust average
2aaf eb        ex      de,hl
2ab0 09        add     hl,bc			; DE = DE + BC
2ab1 eb        ex      de,hl

2ab2 cd3d2b    call    $2b3d			; sample edge
2ab5 d0        ret     nc

; A = D * 5/4
2ab6 7a        ld      a,d				; average so far			
2ab7 cb3f      srl     a				; /2
2ab9 cb3f      srl     a				; /4
										; A = D * 1/4
2abb 8a        adc     a,d				; A = D + (D*1/4)

;; sync pulse will have a duration which is half that of a pulse in a 1 bit
;; average<previous 


2abc 94        sub     h				; time of last pulse
2abd 38ea      jr      c,$2aa9          ; carry set if H>A

;; average>=previous (possibly read first pulse of sync or second of sync)

2abf 91        sub     c				; time of current pulse
2ac0 38e7      jr      c,$2aa9          ; carry set if C>(A-H)

;; to get here average>=(previous*2)
;; and this means we have just read the second pulse of the sync bit


;; calculate bit 1 timing
2ac2 7a        ld      a,d				; average
2ac3 1f        rra						; /2
										; A = D/2
2ac4 8a        adc     a,d				; A = D + (D/2)
										; A = D * (3/2)
2ac5 67        ld      h,a
										; this is the middle time
										; to calculate difference between 0 and 1 bit

;; if pulse measured is > this time, then we have a 1 bit
;; if pulse measured is < this time, then we have a 0 bit

;; H = timing constant
;; L = initial cassette data input state
2ac6 22e6b1    ld      ($b1e6),hl

;; read sync byte
2ac9 cd202b    call    $2b20			; read data-byte
2acc d0        ret     nc

2acd 21e5b1    ld      hl,$b1e5			; sync byte
2ad0 ae        xor     (hl)
2ad1 c0        ret     nz

2ad2 37        scf     
2ad3 c9        ret     

;;========================================================================================
;; write start of block
2ad4 cdf92b    call    $2bf9		;; delay

;; write leader
2ad7 210108    ld      hl,$0801		;; 2049
2ada cdec2a    call    $2aec		;; write leader (2049 1 bits; 4096 pulses)
2add d0        ret     nc

;; write sync bit
2ade b7        or      a
2adf cd782b    call    $2b78		;; write data-bit
2ae2 d0        ret     nc

;; write sync byte
2ae3 3ae5b1    ld      a,($b1e5)
2ae6 c3682b    jp      $2b68		;; write data byte

;;=============================================================================
;; write trailer = 33 "1" bits

2ae9 212100    ld      hl,$0021		;; 33

;; check for escape
2aec 06f4      ld      b,$f4		;; PPI port A
2aee ed78      in      a,(c)		;; read keyboard data through PPI port A (connected to PSG port A)
2af0 e604      and     $04			;; escape key pressed?
									;; bit 2 is 0 if escape key pressed
2af2 c8        ret     z			

;; write trailer bit
2af3 e5        push    hl
2af4 37        scf					;; a "1" bit   
2af5 cd782b    call    $2b78		;; write data-bit
2af8 e1        pop     hl
2af9 2b        dec     hl			;; decrement trailer bit count

2afa 7c        ld      a,h
2afb b5        or      l
2afc 20ee      jr      nz,$2aec         ; (-$12)

2afe 37        scf     
2aff c9        ret     
;;=============================================================================

;; update crc
2b00 2aebb1    ld      hl,($b1eb)
2b03 ac        xor     h
2b04 f2102b    jp      p,$2b10
2b07 7c        ld      a,h
2b08 ee08      xor     $08
2b0a 67        ld      h,a
2b0b 7d        ld      a,l
2b0c ee10      xor     $10
2b0e 6f        ld      l,a
2b0f 37        scf     
2b10 ed6a      adc     hl,hl
2b12 22ebb1    ld      ($b1eb),hl
2b15 c9        ret     

;;========================================================================================
;; get stored data crc and 1's complement it

2b16 2aebb1    ld      hl,($b1eb)		;; block crc

;; 1's complement crc
2b19 7d        ld      a,l
2b1a 2f        cpl     
2b1b 5f        ld      e,a
2b1c 7c        ld      a,h
2b1d 2f        cpl     
2b1e 57        ld      d,a
2b1f c9        ret     

;;========================================================================================
;; read data-byte

2b20 d5        push    de
2b21 1e08      ld      e,$08

2b23 2ae6b1    ld      hl,($b1e6)	
;; H = timing constant
;; L = initial cassette data input state

2b26 cd442b    call    $2b44			;; get edge

2b29 dc4d2b    call    c,$2b4d			;; get edge
2b2c 300d      jr      nc,$2b3b         

2b2e 7c        ld      a,h				;; ideal time
2b2f 91        sub     c				;; subtract measured time
										;; -ve (1 pulse) or +ve (0 pulse)
2b30 9f        sbc     a,a				
										;; if -ve, set carry
										;; if +ve, clear carry

;; carry flag = bit state: carry set = 1 bit, carry clear = 0 bit

2b31 cb12      rl      d				;; shift carry state into bit 0
										;; updating data-byte
										
2b33 cd002b    call    $2b00			;; update crc
2b36 1d        dec     e
2b37 20ea      jr      nz,$2b23         ; (-$16)

2b39 7a        ld      a,d
2b3a 37        scf     
2b3b d1        pop     de
2b3c c9        ret     

;;========================================================================================
;; sample edge and check for escape
;; L = bit-sequence which is shifted after each edge detected
;; starts of as &55 (%01010101)

;; check for escape
2b3d 06f4      ld      b,$f4		;; PPI port A
2b3f ed78      in      a,(c)		;; read keyboard data through PPI port A (connected to PSG port A)
2b41 e604      and     $04			;; escape key pressed?
									;; bit 2 is 0 if escape key pressed
2b43 c8        ret     z			


;; precompensation?
2b44 ed5f      ld      a,r

;; round up to divisible by 4
;; i.e.
;; 0->0, 
;; 1->4, 
;; 2->4, 
;; 3->4, 
;; 4->8, 
;; 5->8
;; etc

2b46 c603      add     a,$03
2b48 0f        rrca					;; /2
2b49 0f        rrca					;; /4

2b4a e61f      and     $1f			;; 

2b4c 4f        ld      c,a

2b4d 06f5      ld      b,$f5		; PPI port B input (includes cassette data input)

;; -----------------------------------------------------
;; loop to count time between edges
;; C = time in 17us units (68T states)
;; carry set = edge arrived within time
;; carry clear = edge arrived too late

2b4f 79        ld      a,c		; [1] update edge timer
2b50 c602      add     a,$02		; [2]
2b52 4f        ld      c,a		; [1]
2b53 380e      jr      c,$2b63          ; [3] overflow?

2b55 ed78      in      a,(c)		; [4] read cassette input data
2b57 ad        xor     l		; [1]
2b58 e680      and     $80		; [2] isolate cassette input in bit 7
2b5a 20f3      jr      nz,$2b4f         ; [3] has bit 7 (cassette data input) changed state?

;; pulse successfully read

2b5c af        xor     a
2b5d ed4f      ld      r,a

2b5f cb0d      rrc     l		; toggles between 0 and 1 

2b61 37        scf     
2b62 c9        ret     

;; time-out
2b63 af        xor     a
2b64 ed4f      ld      r,a
2b66 3c        inc     a
2b67 c9        ret     

;;========================================================================================
;; write data byte to cassette
;; A = data byte
2b68 d5        push    de
2b69 1e08      ld      e,$08			;; number of bytes
2b6b 57        ld      d,a

2b6c cb02      rlc     d				;; shift bit into carry
2b6e cd782b    call    $2b78			;; write bit to cassette
2b71 3003      jr      nc,$2b76         

2b73 1d        dec     e
2b74 20f6      jr      nz,$2b6c         ;; loop for next bit

2b76 d1        pop     de
2b77 c9        ret     

;;========================================================================================
;; write bit to cassette
;; carry flag = state of bit

2b78 ed4be8b1  ld      bc,($b1e8)
2b7c 2aeab1    ld      hl,($b1ea)
2b7f 9f        sbc     a,a
2b80 67        ld      h,a
2b81 2807      jr      z,$2b8a          ; (+$07)
2b83 7d        ld      a,l
2b84 87        add     a,a
2b85 80        add     a,b
2b86 6f        ld      l,a
2b87 79        ld      a,c
2b88 90        sub     b
2b89 4f        ld      c,a
2b8a 7d        ld      a,l
2b8b 32e8b1    ld      ($b1e8),a

;; write a low level
2b8e 2e0a      ld      l,$0a			; %00001010 = clear bit 5 (cassette write data)
2b90 cda72b    call    $2ba7
2b93 3806      jr      c,$2b9b          ; (+$06)
2b95 91        sub     c
2b96 300c      jr      nc,$2ba4         ; (+$0c)
2b98 2f        cpl     
2b99 3c        inc     a
2b9a 4f        ld      c,a
2b9b 7c        ld      a,h
2b9c cd002b    call    $2b00			; update crc

;; write a high level
2b9f 2e0b      ld      l,$0b			; %00001011 = set bit 5 (cassette write data)
2ba1 cda72b    call    $2ba7

2ba4 3e01      ld      a,$01
2ba6 c9        ret     


;;=====================================================================
;; write level to cassette
;; uses PPI control bit set/clear function
;; L = PPI Control byte 
;;   bit 7 = 0
;;   bit 3,2,1 = bit index
;;   bit 0: 1=bit set, 0=bit clear

2ba7 ed5f      ld      a,r
2ba9 cb3f      srl     a
2bab 91        sub     c
2bac 3003      jr      nc,$2bb1         ; (+$03)

;; delay in 4us (16T-state) units
2bae 3c        inc     a				; [1]
2baf 20fd      jr      nz,$2bae         ; [3] 

;; set low/high level
2bb1 06f7      ld      b,$f7			; PPI control 
2bb3 ed69      out     (c),l			; set control

2bb5 f5        push    af
2bb6 af        xor     a
2bb7 ed4f      ld      r,a
2bb9 f1        pop     af
2bba c9        ret     

;;=====================================================================

;; start cassette motor (if cassette motor was previously off
;; allow to to achieve full rotational speed)
2bbb 3e10      ld      a,$10			; start cassette motor
2bbd 1802      jr      $2bc1            ; 

;;=====================================================================
;; stop cassette motor
2bbf 3eef      ld      a,$ef			; stop cassette motor

;;=====================================================================
;; start or stop the cassette motor. 
;;
;; - if motor was switched from off->on, delay for a time to allow
;; cassette motor to achieve full rotational speed
;; - if motor was switched from on->off, do nothing

;; bit 4 of register A = cassette motor state
2bc1 c5        push    bc

2bc2 06f6      ld      b,$f6		; PPI port C 
2bc4 ed48      in      c,(c)		; read inputs (includes cassette input data)
2bc6 04        inc     b			; PPI control		

2bc7 e610      and     $10			; 

2bc9 3e08      ld      a,$08		; %00001000	= cassette motor off
2bcb 2801      jr      z,$2bce

2bcd 3c        inc     a			; %00001001 = cassette motor on

2bce ed79      out     (c),a		; set motor state

2bd0 37        scf     
2bd1 280c      jr      z,$2bdf          

2bd3 79        ld      a,c
2bd4 e610      and     $10			; previous state

2bd6 c5        push    bc
2bd7 01c800    ld      bc,$00c8
2bda 37        scf     
2bdb cce22b    call    z,$2be2		; delay and check for escape
2bde c1        pop     bc

2bdf 79        ld      a,c
2be0 c1        pop     bc
2be1 c9        ret     

;;=================================================================
;; delay & check for escape; allows cassette motor to achieve full
;; rotational speed

;; entry conditions:
;; B = delay factor

;; exit conditions:
;; c = delay completed and escape was not pressed
;; nc = escape was pressed

2be2 c5        push    bc
2be3 e5        push    hl
2be4 cdf92b    call    $2bf9		;; delay

2be7 3e42      ld      a,$42
2be9 cd451e    call    $1e45		;; check for escape pressed
		
2bec e1        pop     hl
2bed c1        pop     bc
2bee 2007      jr      nz,$2bf7         ; (+$07)

2bf0 0b        dec     bc
2bf1 78        ld      a,b
2bf2 b1        or      c
2bf3 20ed      jr      nz,$2be2         ; (-$13)

2bf5 37        scf     
2bf6 c9        ret     

;; escape was pressed
2bf7 af        xor     a
2bf8 c9        ret     

;;========================================================================================
;; delay
2bf9 018206    ld      bc,$0682			; [3]

2bfc 0b        dec     bc				; [2]
2bfd 78        ld      a,b				; [1]
2bfe b1        or      c				; [1]
2bff 20fb      jr      nz,$2bfc         ; [3]
2c01 c9        ret     
;;========================================================================================



