home *** CD-ROM | disk | FTP | other *** search
/ Emulator Universe CD / emulatoruniversecd1998.iso / Speccy / Emulators / winemu / SOURCES / TAPE2TAP / TAPE2TAP.ASM < prev    next >
Encoding:
Assembly Source File  |  1996-06-06  |  15.7 KB  |  625 lines

  1.  
  2.  ; Tape2Tap.asm : DOS Spectrum tape sampler.
  3.  ;
  4.  ; Copyright 1995 Rui Fernando Ferreira Ribeiro.
  5.  ;
  6.  ; This program is free software; you can redistribute it and/or modify
  7.  ; it under the terms of the GNU General Public License as published by
  8.  ; the Free Software Foundation; either version 2 of the License, or
  9.  ; (at your option) any later version.
  10.  ;
  11.  ; This program is distributed in the hope that it will be useful,
  12.  ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  ; GNU General Public License for more details.
  15.  ;
  16.  ; You should have received a copy of the GNU General Public License
  17.  ; along with this program; if not, write to the Free Software
  18.  ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  ;
  20.  
  21.  
  22.         name    tape2tap
  23.         page    55,132
  24.         title   'TAPE2TAP'
  25.  
  26. ; **** Rui Fernando ****
  27. ;
  28. ; v1.00 95/08/23        .  original version
  29. ; v1.01 95/10/06        .  source better structured
  30. ;                       .  false block detection reduced
  31. ;                       .  colours added to make border stripes like real 
  32. ;                         Spectrum
  33. ; v1.10 95/10/17        . added SB support
  34. ; v1.11 95/10/29        .  better noise immunity
  35. ; v1.12 95/12/27        . input pin modified to busy pin
  36. ; v1.13 96/06/06        .  Line-In Input modified, the volume was not properly
  37. ;                       . adjusted for SB Pro 16 and better cards
  38.  
  39. INCLUDE         TAPE.INC
  40. INCLUDE         PIT.INC
  41. INCLUDE         SB.INC
  42.  
  43.         .model  tiny
  44.         .code
  45.         org     0100h           ; tiny model
  46.                     ; resident part of program
  47. begin_code:
  48.         ; release memory (DOS gives .COM all the memory)
  49.         ;
  50.         push    ds
  51.         pop     es              ; es = segment of memory
  52.         mov     bx,4096         ; reserve only 64k (4096 para)
  53.         mov     ah,4ah          ; realloc
  54.         int     21h
  55.  
  56.         xor     ax,ax
  57.         mov     ds,ax
  58.         mov     ax,word ptr ds:[0408h]
  59.         push    cs
  60.         pop     ds
  61.         inc     ax
  62.         mov     word ptr ds:[printer_port],ax
  63.  
  64.         call    ReadCmdLine
  65.  
  66.         INIT_PIT
  67.  
  68.         lea     dx,copyright
  69.         PRINT_STRING
  70.  
  71.         mov     ax,1600h        ; see if in Windows
  72.         int     2fh
  73.         cmp     ax,1600h
  74.         jz      not_windows
  75.  
  76.         lea     dx,w_error
  77.         PRINT_STRING
  78.  
  79.         mov     ax,4c01h
  80.         int     21h
  81.  
  82.  
  83. not_windows:    lea     dx,messg_begin
  84.         PRINT_STRING
  85.  
  86.         mov     ah,48h          ; allocate a memory DOS block
  87.         mov     bx,4096         ; 64K
  88.         int     21h             ; return data segment in AX
  89.         jnc     enough_memory
  90.  
  91.                     ; Print unsuficient memory
  92.                     ; message
  93. not_enough:     lea     dx,error_mem
  94.         PRINT_STRING
  95.         
  96.         mov     ax,4c02h        ; leave
  97.         int     21h
  98.  
  99. enough_memory:  cmp     bx,4096         ; we wan't a 64K block.
  100.         jnz     not_enough
  101.  
  102.         mov     es,ax
  103.         cmp     byte ptr ds:[sb_on],0
  104.         jnz     sb_is_enabled
  105.         jmp     no_sblaster
  106.  
  107. sb_is_enabled:  call    ResetDSP        ; tests for the presence of a SB card
  108.         or      dx,dx
  109.         jnz     sb_is_present
  110.         jmp     no_sblaster
  111.  
  112. sb_is_present:  cmp     byte ptr ds:[speaker_on],2
  113.         jz      dont_disable
  114.  
  115.         mov     byte ptr ds:[speaker_on],0
  116.  
  117. dont_disable:   SAVE_MIXER
  118.         INIT_MIXER
  119.  
  120. no_sblaster:    cli
  121.         in      al,61h          ; keeps old 61h port contents
  122.         mov     byte ptr ds:[copy_p61h],al
  123.  
  124. begin:          cli
  125.         mov     si,2
  126.  
  127.         ; clean table used by error detection logic
  128. ;               lea     di,berr_tab
  129. ;               mov     cx,8
  130. ;@@loop_clean:  mov     word ptr ds:[di],0
  131. ;               inc     di
  132. ;               loop    @@loop_clean
  133.  
  134.         ; WARNING: don't modify dx in the main input routine!           
  135.         ; It must always yeld the printer port status address
  136.         ; or the SoundBlaster port address
  137.  
  138.         mov     dx,word ptr ds:[sb_base_addr]
  139.         or      dx,dx
  140.         jnz     no_imp
  141.  
  142.         mov     dx,word ptr ds:[printer_port]   ; LPT port
  143.  
  144.  
  145. ; try to find
  146. no_imp:         mov     byte ptr ds:[colour],RED
  147.         mov     bh,0            ; init counter of impulse blocks
  148.  
  149. imp_again:      call    ReadVal
  150.         jnz     no_imp
  151.  
  152. imp_low:        call    ReadCycle
  153. another_imp:    cmp     ax,LOW_IMP
  154.         jc      no_imp
  155.         cmp     ax,HI_IMP
  156.         jnc     no_imp
  157.         cmp     cx,LOW_IMP
  158.         jc      no_imp
  159.         cmp     cx,HI_IMP
  160.         jnc     no_imp
  161.         inc     bh              ; has read one more impulse
  162.         cmp     bh,NIMP         ; read enough
  163.         jz      wait_sync
  164.         jmp     short imp_again
  165.  
  166.  
  167.  
  168. wait_sync:      call    ReadCycle
  169.         cmp     ax,HI_SYNC
  170.         jnc     no_sync
  171.         cmp     ax,LOW_SYNC
  172.         jc      prep_l8bits
  173. no_sync:        mov     bh,NIMP-1
  174.         jmp     short another_imp
  175.  
  176.  
  177. ;       The routine as found as impulse folowed by a syncronishm pulse.
  178. ; Now its time to load the data.
  179.  
  180. prep_l8bits:    mov     bl,0            ; load CRC-tape with 0
  181.         mov     byte ptr ds:[colour],YELLOW
  182. l8bits:         mov     bh,1            ; init reg with end-of-loop bit mark
  183.  
  184.         mov     word ptr ds:[bit_num],0
  185.  
  186. lbits:          call    ReadCycle
  187.         cmp     ax,BAD_HI
  188.         jnc     end_load
  189.  
  190.         ; detect error logic (1)
  191. ;               cmp     cx,TRANSITION
  192. ;               cmc
  193. ;               rcl     byte ptr ds:[low_val],1
  194.         ; end of error logic (1)
  195.  
  196.         ; signal means a 0 or 1? (the actual data bit is 0 or 1?)
  197.         cmp     ax,TRANSITION
  198.         cmc
  199.         rcl     bh,1            ; insert bit in register
  200.  
  201.         ; detect error logic (2)
  202. ;               pushf
  203. ;               xor     byte ptr ds:[low_val],1
  204. ;               test    byte ptr ds:[low_val],1
  205. ;               jz      no_biterr
  206. ;               lea     di, berr_tab
  207. ;               add     di, word ptr ds:[bit_num]
  208. ;               cmp     di,1
  209. ;               jz      no_biterr
  210. ;               cmp     di,0
  211. ;               jnz     another_bit
  212. ;               mov     word ptr ds:[di],si
  213. ;               jmp     short no_biterr
  214. ;another_bit:    mov    word ptr ds:[di],1
  215. ;no_biterr:     popf
  216.         ; end of error logic (2)
  217.  
  218.         jc      byte_read       ; jump if end mark found
  219.  
  220.         inc     word ptr cs:[bit_num]
  221.  
  222.         jmp     short lbits
  223.  
  224.                         ; now a byte was read
  225. byte_read:      mov     byte ptr es:[si],bh     ; keep it
  226.         xor     bl,bh                   ; update Spectrum CRC
  227.         inc     si                      ; increment pointer
  228.         jmp     l8bits                  ; load next byte
  229.  
  230. end_load:       ; as this is a pure read from tape with no help from a 
  231.         ; emulator, we have no chances to know when we're 
  232.         ; finished. We only arrive here after a error in the
  233.         ; main routine. [error == end of data]
  234.  
  235.  
  236.         mov     al,byte ptr ds:[copy_p61h]
  237.         out     61h,al                  ; restore value
  238.  
  239.         mov     ah,0
  240.         call    Border
  241.  
  242.         sti
  243.  
  244.         cmp     si,1                    ; null body?
  245.         ja      sa_block                ; 
  246.         jmp     leave_this              ; go away...
  247.  
  248. sa_block:       dec     si
  249.         dec     si
  250.         mov     word ptr es:[0],si      ; len of block in .TAP file
  251.         inc     si
  252.         inc     si
  253.  
  254.         cmp     byte ptr ds:[SpecCRC],0
  255.         jz      ok_2_load
  256.  
  257.         ; error correction logic here...
  258. ;               or      bl,bl
  259. ;               jz      all_korret
  260.  
  261. ;               mov     byte ptr ds:[CRC_block],bl
  262. ;               lea     di,bit_val
  263. ;               lea     dx,berr_tab
  264. ;               mov     cx,8
  265.  
  266. ;@@loop_bits:    mov    bx,dx
  267. ;               mov     ax,word ptr ds:[bx]
  268. ;               mov     bx,ax
  269. ;               cmp     bx,1
  270. ;               jbe     @@no_good
  271. ;
  272. ;                mov    al, byte ptr ds:[di]
  273. ;               test    [CRC_block],al
  274. ;               jz      @@no_good
  275.  
  276. ;               xor     byte ptr es:[bx],al
  277. ;               xor     byte ptr es:[si-1],al
  278. ;               xor     byte ptr ds:[CRC_block],al
  279.  
  280. ;@@no_good:      inc    di
  281. ;               inc     dx
  282. ;               inc     dx
  283. ;               loop    @@loop_bits
  284. ;               mov     bl, byte ptr ds:[CRC_block]
  285.         ; end of error correction logic
  286.  
  287. all_korret:     cmp     bl,0
  288.         jz      ok_2_load
  289.         lea     dx,tape_error
  290.         PRINT_STRING
  291.  
  292.         jmp     leave_this
  293.  
  294.         ; try to open file      (.TAP file)
  295. ok_2_load:      mov     ax,3d01h
  296.         mov     dx,offset file
  297.         int     21h
  298.         jnc     file_open2
  299.  
  300.         ; if it doesn't exist create it
  301.         mov     ah,3ch
  302.         xor     cx,cx
  303.         int     21h
  304.         jc      leave_prog
  305.  
  306. file_open2:     ; copy file handle to bx
  307.         mov     bx,ax
  308.  
  309.         ; seek to end of file
  310.         mov     ax,4202h
  311.         xor     cx,cx
  312.         xor     dx,dx
  313.         int     21h
  314.  
  315.         push    ds
  316.         push    es
  317.         pop     ds
  318.  
  319.         mov     dx,0                    ; beginning of block in DS
  320.         mov     cx,si                   ; len of block (+2 for len)
  321.         mov     ah,40h                  ; write it
  322.         int     21h
  323.  
  324.         pop     ds
  325.  
  326.                    ; close file
  327.         mov     ah,3eh
  328.         int     21h
  329.  
  330.         cmp     si,21                   ; not a header block
  331.         jnz     exit
  332.         cmp     byte ptr es:[2],0
  333.         jne     exit
  334.         cmp     byte ptr es:[3],0
  335.         jnz     no_basic
  336.         lea     dx,b_program
  337.         jmp     all_ok
  338. no_basic:       cmp     byte ptr es:[3],3
  339.         jnz     exit
  340.         lea     dx,b_code
  341.  
  342. all_ok:         PRINT_STRING
  343.  
  344.         mov     bh,0
  345.         mov     di,4
  346. another_char:   mov     al,byte ptr es:[di]
  347.         cmp     al,32
  348.         jnc     char_ok
  349.         mov     al,'?'
  350. char_ok:        mov     ah,0eh
  351.         int     10h
  352.         inc     di
  353.         cmp     di,14
  354.         jnz     another_char            
  355.  
  356. exit:           lea     dx,messg_good
  357.         PRINT_STRING
  358.  
  359. leave_this:     jmp     begin
  360.  
  361. leave_prog:     
  362.         mov     al,byte ptr ds:[copy_p61h]
  363.         out     61h,al                  ; restore value
  364.  
  365.         mov     ah,0
  366.         call    Border
  367.         sti
  368.  
  369.         cmp     word ptr ds:[sb_base_addr],0
  370.         jz      no_sb_present
  371.  
  372.         RESTORE_MIXER
  373. no_sb_present:
  374.         RTC2DOSCLK
  375.  
  376.         mov     ax,4c00h
  377.         int     21h
  378.  
  379. bcd_2_dec       proc    near
  380.         mov     dl,al
  381.         shr     al,4
  382.         mul     byte ptr ds:[value_10]
  383.         and     dl,0fh
  384.         add     al,dl
  385.         ret
  386. bcd_2_dec       endp
  387.  
  388. InitRead        proc    near
  389.  
  390. @@wait_v:       READ_PIT
  391.         call    GiveCount
  392.  
  393.         cmp     byte ptr ds:[colour],YELLOW
  394.         jne     @@leave_r
  395.         cmp     ax,WAIT_VAL
  396.         jc      @@wait_v
  397. ;               cmp     ax,cx
  398. ;               jc      @@wait_v
  399.  
  400. @@leave_r:      ret
  401. InitRead        endp
  402.  
  403. GiveCount       proc    near
  404.         sub     ax,bp           ; find difference
  405.         jns     @@end_cnt       ; if difference negative
  406.         neg     ax              ; correct value
  407. @@end_cnt:
  408.         ret
  409. GiveCount       endp
  410.  
  411. ReadVal         proc    near
  412.         TEST_BREAK
  413.         cmp     word ptr ds:[sb_base_addr],0
  414.         jnz     @@use_sb
  415.  
  416.         READ_LPT
  417.         jmp     short @@sound
  418.  
  419. @@use_sb:       READ_SB
  420.  
  421. @@sound:        pushf
  422.         cmp     byte ptr ds:[speaker_on],0
  423.         jz      @@leave
  424.  
  425.         pushf
  426.         popf
  427. @@noisy:        BEEP_IT
  428.  
  429. @@leave:        popf
  430.         ret
  431. ReadVal         endp
  432.  
  433. Border          proc    near            ; ah = border colour
  434.         COLOUR_BORDER   ah
  435.         ret
  436. Border          endp
  437.  
  438. n_zeros         dw      0
  439. n_ones          dw      0
  440. l_zero          dw      0
  441. l_one           dw      0
  442.  
  443. SampleVal       proc    near    ; Read (or try) to read a pulse from the tape
  444.         READ_PIT
  445.         mov     word ptr ds:[init_sampl],ax
  446.  
  447.         xor     ax,ax
  448.         mov     word ptr ds:[n_zeros],ax
  449.         mov     word ptr ds:[n_ones],ax
  450. @@loop:         call    ReadVal
  451.         jz      @@is_zero
  452.         READ_PIT
  453.         mov     word ptr ds:[l_one],ax
  454.         cmp     word ptr ds:[n_zeros],0
  455.         jnz     @@dec_czeros
  456.         cmp     word ptr ds:[n_ones],0ffffh
  457.         jz      short @@end
  458.         inc     word ptr ds:[n_ones]
  459.         jmp     short @@end
  460. @@dec_czeros:   dec     word ptr ds:[n_zeros]
  461.         jmp     short @@end
  462.  
  463. @@is_zero:      READ_PIT
  464.         mov     word ptr ds:[l_zero],ax
  465.         cmp     word ptr ds:[n_ones],0
  466.         jnz     @@dec_cones
  467.         cmp     word ptr ds:[n_zeros],0ffffh
  468.         jz      short @@end
  469.         inc     word ptr ds:[n_zeros]
  470.         jmp     short @@end
  471. @@dec_cones:    dec     word ptr ds:[n_ones]
  472.  
  473. @@end:          READ_PIT
  474.         sub     ax,word ptr ds:[init_sampl]
  475.         jns     @@sign_ok
  476.         neg     ax
  477. @@sign_ok:      cmp     ax,100
  478.         jb      @@loop
  479.  
  480.         mov     ax,word ptr ds:[n_zeros]
  481.         cmp     ax,word ptr ds:[n_ones]
  482.         ret
  483. SampleVal       endp
  484.  
  485.  
  486. ReadCycle       proc    near            ; try to read a bit from the tape.
  487.         mov     ah,BLUE
  488.         call    Border
  489.         mov     bp,word ptr ds:[l_one]
  490.         xor     cx,cx
  491.         call    InitRead
  492. @@low_part:     ;call   ReadVal
  493.         call    SampleVal
  494.         jae     @@low_part
  495.         mov     ax,word ptr ds:[l_zero]
  496.         call    GiveCount
  497.         mov     cx,ax
  498.  
  499.         cmp     ax,BAD_HI
  500.         jnc     @@leave_read
  501.  
  502.         mov     ah,byte ptr ds:[colour]
  503.         call    Border
  504.         mov     bp,word ptr ds:[l_zero]
  505.         call    InitRead
  506.  
  507. @@hi_part:      ;call   ReadVal
  508.         call    SampleVal
  509.         jbe     @@hi_part
  510.         mov     ax,word ptr ds:[l_one]
  511.         call    GiveCount
  512. @@leave_read:   ret
  513. ReadCycle       endp
  514.  
  515. ; * SB prog part
  516. ResetDSP        proc    near
  517.         RESET_DSP
  518.         ret
  519. ResetDSP        endp
  520.  
  521. ; get arguments from  command line
  522. ReadCmdLine     proc    near
  523.         mov     ah,51h         
  524.         int     21h
  525.         mov     es,bx   ; DS=PSP
  526.         mov     bx,080h ; PSP:80 = line arguments
  527. @@another_ch:   inc     bx
  528.         mov     ah,byte ptr es:[bx]
  529.         cmp     ah,0dh  ; end of line?
  530.         jz      @@exit  ; jump if yes
  531.         cmp     ah,'d'  ; disable soundblaster detection (and use)?
  532.         jnz     @@another_ch
  533.         mov     byte ptr ds:[sb_on],0
  534. @@exit:         ret
  535. ReadCmdLine     endp
  536.  
  537. ; DATA part
  538. input_s         db      0
  539. line_vol        db      0
  540. cd_vol          db      0
  541. mic_vol         db      0
  542. master_vol      db      0
  543.  
  544. sb_on           db      1       ; SB detection is ON by default
  545. speaker_on      db      1       ; speaker is on by default
  546.  
  547. init_sampl      dw      0
  548.  
  549. SpecCRC         db      1       ; if CRC is active==1
  550. CRC_block       db      0       ; the actual CRC value
  551. low_val         db      0
  552. bit_num         dw      0
  553. berr_tab        dw      8 dup (0)
  554. bit_val         db      01h, 02h, 04h, 08h, 10h, 20h, 40h, 80h
  555.  
  556. file            db 'w1.tap', 0  ; name of the file created in current dir
  557. value_10        db      10
  558. copy_p61h       db      0
  559. colour          db      0       ; actual color of border
  560. printer_port    dw      0379h
  561. b_program       db      0dh, 0ah, 'Program : $'
  562. b_code          db      0dh, 0ah, 'Bytes   : $'
  563. w_error         db      0dh, 0ah, 'This program cannot be run under Windows'
  564.         db      0dh, 0ah
  565.         db      'It must run outside a multitasking environment'
  566.         db      0dh, 0ah, '$'
  567. copyright       db      0dh, 0ah
  568.         db      'Tape2Tap v1.13 --- reads ZX Spectrum`s tapes in Pc'
  569.         db      0dh, 0ah
  570.         db      'Copyright December 1995-June 1996'
  571.         db      ', Rui Fernando Ferreira Ribeiro'
  572.         db      ' [aka Star Man]'
  573.         db      0dh, 0ah
  574.         db      0dh, 0ah
  575.         db      '$'
  576.  
  577. messg_begin     db      0dh, 0ah
  578.         db      'You can press at any time:'
  579.         db      0dh, 0ah, 0dh, 0ah
  580.         db      ' - ESC exit program', 0dh, 0ah
  581.         db      ' - S   turn speaker on', 0dh, 0ah
  582.         db      ' - N   turn speaker off', 0dh, 0ah
  583.         db      ' - 1   disable block CRC', 0dh, 0ah
  584.         db      ' - 2   enable  block CRC', 0dh, 0ah
  585.         db      0dh, 0ah
  586.         db      '$'
  587.  
  588. error_mem       db      0dh, 0ah
  589.         db      ' Not enough free memory to run the program'
  590.         db      0dh, 0ah, '$'
  591.  
  592. tape_error      db      0dh, 0ah
  593.         db      ' Tape loading error! Rewind and try again this block'
  594.         db      0dh, 0ah, '$'
  595.  
  596. messg_good      db      0dh, 0ah
  597.         db      ' Tape block load suceffuly'
  598.         db      0dh, 0ah, '$'
  599.  
  600. ;* SB data part
  601.  
  602. sb_base_addr    dw      0
  603.  
  604. sb_not_found    db      0dh, 0ah
  605.         db      ' SoundBlaster not found'
  606.         db      0dh, 0ah
  607.         db      ' Using printer port to digitalize data.'
  608.         db      0dh, 0ah, 0dh, 0ah, '$'
  609.  
  610. sb_found        db      0dh, 0ah
  611.         db      ' SoundBlaster found at port 2'
  612. port_sb         db      '00', 0dh, 0ah 
  613.         db      'Using it to digitalize data.'
  614.         db      0dh, 0ah, 0dh, 0ah, '$'
  615.  
  616. stackseg  segment para STACK 'STACK'    ; Definition of stack segment
  617.  
  618.         db 512 dup ('S')        ; The stack comprises 256 words
  619.  
  620. stackseg  ends                          ; End of stack segment
  621.  
  622.         end     begin_code
  623.  
  624. ; EOF: Tape2Tap.asm
  625.