?login_element?

Subversion Repositories NedoOS

Rev

Rev 1987 | Blame | Compare with Previous | Last modification | View Log | Download

  1. ;trdos driver (izzx)
  2.     MODULE Dos
  3. ; API methods
  4. ESX_GETSETDRV = #89
  5. ESX_FOPEN = #9A
  6. ESX_FCLOSE = #9B
  7. ESX_FSYNC = #9C
  8. ESX_FREAD = #9D
  9. ESX_FWRITE = #9E
  10.  
  11. ; File modes
  12. FMODE_READ = #01
  13. FMODE_WRITE = #06
  14. FMODE_CREATE = #0E
  15.  
  16.     ; MACRO esxCall func
  17.     ; rst #8 : db func
  18.     ; ENDM
  19.        
  20. ;id = 0 файл не открыт
  21. ;id = 1 файл для чтения
  22. ;id = 2 файл для записи
  23. ;id = 3 файл для записи тип TRD
  24. ;id = 4 файл для записи тип SCL
  25.  
  26. ; HL - filename in ASCIIZ
  27. loadBuffer:
  28.     ld b, Dos.FMODE_READ: call Dos.fopen
  29.     push af
  30.         ld hl, outputBuffer, bc, #ffff - outputBuffer : call Dos.fread
  31.         ld hl, outputBuffer : add hl, bc : xor a : ld (hl), a : inc hl : ld (hl), a
  32.     pop af
  33.     call Dos.fclose
  34.     ret
  35.  
  36.  
  37. ; Returns:
  38. ;  A - current drive
  39. ; getDefaultDrive: ;нигде не используется
  40.     ; ld a, 0 : esxCall ESX_GETSETDRV
  41.     ; ret
  42.  
  43.  
  44.  
  45. ; Opens file on default drive
  46. ; B - File mode
  47. ; HL - File name
  48. ; Returns:
  49. ;  A - file stream id
  50. fopen:
  51.     ; push bc : push hl
  52.     ; call getDefaultDrive
  53.     ; pop ix : pop bc
  54.     ; esxCall ESX_FOPEN
  55.     ; ret
  56.         ld a,b
  57.         cp FMODE_READ ;если режим открытие файла
  58.         jr z,fopen_r
  59.         cp FMODE_CREATE
  60.         jr z,fopen_c ;если режим создание файла
  61.         jr fopen_err ;иначе выход
  62.        
  63. fopen_r ;открытие существующего файла на чтение (id=1)
  64.         ; ld a,(#5D19) ;номер дисковода по умолчанию
  65.         ; ld    (prev_drive),a ;запомним
  66.                         call format_name ;
  67.                         ld      c,#13 ;move file info to syst var
  68.             call    call3d13
  69.             ld      c,#0a ;find file
  70.             call    call3d13
  71.             ld      a,c
  72.                         cp              #ff
  73.                         jr              z,fopen_err ;если не нашли файла
  74.             ld      c,#08 ;read file title
  75.             call    call3d13
  76.             ;ld      hl,loadadr ;куда
  77.             ld      de,(#5ceb) ;начало файла сектор дорожка
  78.             ld      (f_r_cur_trk),de
  79.  
  80.             ld      a,(#5cea)
  81.             ld      (f_r_len_sec),a ;длина в секторах
  82.             ;or      a
  83.             ;ret     z    ;выход если пустой
  84.                        
  85.                         ld de,(#5CE8) ; длина файла или программной части для BASIC
  86.                         ld      (f_r_len),de
  87.  
  88.             ; ld      de,(fcurtrk) ;текущие сектор дорожка
  89.             ; ld      (#5cf4),de ;восстановим
  90.                         xor a
  91.                         ld              a,1
  92.                         ld (f_r_flag),a ;флаг что файл для чтения открыт
  93.                         ;id канала будет 1
  94.         ret
  95.        
  96. fopen_err
  97.         xor a ;если никакой файл не открыли, то id = 0
  98.         scf ;флаг ошибки
  99.         ret
  100.  
  101.  
  102. fopen_c ;создание нового файла (id=2-4)
  103.         ; ld a,(#5D19) ;номер дисковода по умолчанию
  104.         ; ld    (prev_drive),a ;запомним
  105.         call format_name ;
  106.         ;выясним, не образ ли это для разворачивания
  107.     ld hl, trdExt1 : call CompareBuff.search : and a : jr nz, fopen_c_trd
  108.     ld hl, trdExt2 : call CompareBuff.search : and a : jr nz, fopen_c_trd
  109.         ld hl, sclExt1 : call CompareBuff.search : and a : jp nz, fopen_c_scl
  110.     ld hl, sclExt2 : call CompareBuff.search : and a : jp nz, fopen_c_scl
  111.  
  112.        
  113.         ;создание произвольного файла (id=2)
  114.         call select_drive
  115.         cp "y"
  116.         jr nz,fopen_err
  117.  
  118.         call cat_buf_cls
  119.  
  120.         ld hl,cat_buf ;считаем каталог диска
  121.         ld de,0
  122.     ld      bc,#0905 ;
  123.     call    call3d13
  124.        
  125.         ld a,(cat_buf+8*256+#e4) ; общее количество файлов
  126.         cp 128
  127.         jp c,fopen_c2 ;если уже максимум
  128.     ld hl, file_err
  129.     call DialogBox.msgBox ;предуреждение                       
  130.         jr fopen_err   
  131.        
  132. fopen_c2       
  133.         ld hl,(cat_buf+8*256+#e5) ; количество свободных секторов на диске
  134.         ld a,h
  135.         or l
  136.         jr nz,fopen_c3 ;если ещё есть место
  137.     ld hl, file_err
  138.     call DialogBox.msgBox ;предуреждение                       
  139.         jr fopen_err
  140.  
  141. fopen_c3       
  142.         ld de,(cat_buf+8*256+#e1) ;первые свободные сектор-дорожка
  143.     ld   (#5cf4),de ;отсюда будем писать файл  
  144.        
  145.         xor a
  146.         ld (sec_shift),a ;переменная
  147.         ld hl,0
  148.         ld (f_w_len+0),hl
  149.         ld (f_w_len+2),hl
  150.         ld a,2 ;id канала
  151.         ld (f_w_flag),a ;флаг что файл для записи открыт       
  152.         ret
  153.        
  154.        
  155. cat_buf_cls ;очистка буфера каталога
  156.         ld hl,cat_buf ;очистить место для каталога дискеты
  157.         ld de,cat_buf+1
  158.         ld (hl),0
  159.         ld bc,9*256-1
  160.         ldir
  161.         ret
  162.  
  163.  
  164.  
  165. fopen_c_trd     ;открытие файла для разворачивания образа trd (id=3)
  166.         call select_drive
  167.         cp "y"
  168.         jp nz,fopen_err
  169.        
  170.         ld      de,0 ;начало сектор дорожка
  171.     ld      (#5cf4),de
  172.        
  173.         xor a
  174.         ld (sec_shift),a ;переменная
  175.         ld hl,0
  176.         ld (f_w_len+0),hl
  177.         ld (f_w_len+2),hl
  178.         ld a,3 ;id канала
  179.         ld (f_w_flag),a ;флаг что trd для записи открыт
  180.         ret
  181.        
  182.  
  183.  
  184. fopen_c_scl     ;открытие файла для разворачивания образа scl (id=4)
  185.         call select_drive
  186.         cp "y"
  187.         jp nz,fopen_err
  188.        
  189.         ld      de,0 ;начало сектор дорожка
  190.     ld      (#5cf4),de
  191.        
  192.         call cat_buf_cls ;почистить место
  193.        
  194.         call scl_parse ;запуск цикла сборки образа
  195.        
  196.         xor a
  197.         ld (sec_shift),a ;переменная
  198.         ;ld (scl_que),a
  199.         ld hl,0
  200.         ld (f_w_len+0),hl
  201.         ld (f_w_len+2),hl
  202.         ld a,4 ;id канала
  203.         ld (f_w_flag),a ;флаг что scl для записи открыт
  204.         ret    
  205.  
  206.  
  207.  
  208.  
  209.  
  210. select_drive    ;запрос номера дисковода
  211.         ld a,(#5D19) ;номер дисковода по умолчанию
  212.         add a,"A"
  213.         ld (write_ima_d),a ;подставим букву в запросе
  214.     ld hl, write_ima
  215.     call DialogBox.msgNoWait ;предуреждение
  216. WAITKEY_trd    
  217.         ;halt
  218.         call Console.getC
  219.         cp 255
  220.         JR Z,WAITKEY_trd        ;ждём любую клавишу
  221.         cp "y"
  222.         ret z
  223.         cp "n"
  224.         ret z
  225.         cp "a"
  226.         jr c,WAITKEY_trd
  227.         cp "e"
  228.         jr nc,WAITKEY_trd
  229.         sub "a"
  230.     ld      (#5d19) ,a
  231.     ld      c,1
  232.     call    call3d13
  233.     ld      c,#18
  234.     call    call3d13
  235.         jr select_drive
  236.  
  237.  
  238. ; restore_drive ;восстановить дисковод по умолчанию
  239.         ; ld    a,(prev_drive)
  240.     ; ld      (#5d19) ,a
  241.     ; ld      c,1
  242.     ; call    call3d13
  243.     ; ld      c,#18
  244.     ; call    call3d13
  245.         ; ret
  246.  
  247.  
  248. call3d13 ;фикс для GMX
  249.         ifndef ZSGMX
  250.     jp    #3d13
  251.         endif
  252.        
  253.         ifdef ZSGMX
  254.     call    #3d13
  255.         exx
  256.         call TextMode.gmxscron
  257.         exx
  258.         endif
  259.         ret
  260.        
  261.        
  262.  
  263. ; A - file stream id
  264. fclose:
  265.     ;esxCall ESX_FCLOSE
  266.         ; push af
  267. ; WAITKEY2      XOR A:IN A,(#FE):CPL:AND #1F:JR Z,WAITKEY2
  268.         ; pop af
  269.         cp 2 ;если обычный файл
  270.         jp nz,fclose_scl
  271.  
  272.         ;дописать остаток файла
  273.         ld a,(write_end_flag) ;нужно записывать остаток?
  274.         or a
  275.         jr nz,fclose_f ;не нужно
  276.  
  277.         ld hl,sec_buf
  278.         ld bc,#0106
  279.         ld de,(#5cf4)
  280.         call call3d13
  281.        
  282.         ld a,"0" ;номер части файла
  283.         ld (file_num),a
  284.        
  285. fclose_f ;поправить каталог
  286.         ld a,(f_w_len+2) ;самый старший байт длины файла
  287.         ld hl,(f_w_len+0)
  288.         or h
  289.         or l
  290.         jp z,fclose_ex ;выход если длина 0
  291.        
  292.         ;проверки на заполнение
  293.         ld a,(cat_buf+8*256+#e4) ; общее количество файлов
  294.         cp 128
  295.         jp nc,fclose_ex ;если уже максимум
  296.         ld hl,(cat_buf+8*256+#e5) ; количество свободных секторов на диске
  297.         ld a,h
  298.         or l
  299.         jp z,fclose_ex ;если места нет 
  300.        
  301.         ld a,(f_w_len+2) ;самый старший байт длины файла
  302.         or a
  303.         jr nz,fclose_f_multi ;если файл больше 255 секторов (65280)
  304.         ld a,(f_w_len+1)
  305.         cp 255
  306.         jr nz,fclose_f1
  307.         ld a,(f_w_len+0)
  308.         jr nz,fclose_f_multi ;если файл больше 255 секторов (65280)
  309. fclose_f1
  310.         ;файл не превышает максимальный размер для trdos
  311.         ld de,(f_w_len+0)      
  312.         ld hl,f_name+11 ;длина файла
  313.         ld (hl),e
  314.         inc hl
  315.         ld (hl),d
  316.         inc hl
  317.         ld a,(f_w_len+1) ;длина секторов
  318.         ld (hl),a
  319.         ld a,(f_w_len+0) ;длина младший
  320.         or a
  321.         jr z,fclose_f2
  322.         inc (hl) ;коррекция секторов
  323. fclose_f2
  324.         call fclose_f_one ;записать информацию
  325.         jp fclose_ex ;готово
  326.        
  327. fclose_f_multi ;файл большой, будет несколько записей в каталоге       
  328.         ld a,(file_num)
  329.         ld (f_name+7),a ;в конце имени номер
  330.        
  331.         ld hl,f_name+11 ;длина файла
  332.         ld (hl),0
  333.         inc hl
  334.         ld (hl),#ff ;65280
  335.         inc hl
  336.         ;длина секторов
  337.         ld (hl),#ff
  338.         call fclose_f_one ;записать информацию
  339.        
  340.         ;вычесть длину записанного
  341.         ld hl,(f_w_len+1) ;старший и средний байт      
  342.         ld bc,255
  343.         and a
  344.         sbc hl,bc ;вычесть 255 секторов
  345.         ld (f_w_len+1),hl
  346.        
  347.         ld a,(file_num)
  348.         inc a
  349.         ld (file_num),a
  350.         ld (f_name+7),a ;в конце имени номер
  351.  
  352.         jr fclose_f ;сначала
  353.  
  354.        
  355. fclose_f_one ;запись об одном файле
  356.                         ld a,(cat_buf+8*256+#e4) ; общее количество файлов
  357.                         ld l,a ;узнать в каком секторе будет запись о файле
  358.                         ld h,0
  359.                         add hl,hl ;*2
  360.                         add hl,hl ;*4
  361.                         add hl,hl ;*8
  362.                         add hl,hl ;*16
  363.                         ld a,h ;запомнить номер сетора в каталоге
  364.                         ld (sec_cat),a
  365.                         ld bc,cat_buf
  366.                         add hl,bc ;здесь будет запись о новом файле
  367.                         ex de,hl
  368.                        
  369.                         ld hl,f_name ;запись о файле
  370.                         ld bc,16
  371.                         ldir ;скопировать
  372.                         ex de,hl
  373.                         dec hl
  374.                         ld de,(cat_buf+8*256+#e1) ;первые свободные сектор-дорожка назначения
  375.                         ld (hl),d ;дорожка
  376.                         dec hl
  377.                         ld (hl),e ;сектор
  378.                        
  379.                         ld l,0 ;записать сектор целиком по ровному адресу
  380.                         ld d,0
  381.                         ld a,(sec_cat)
  382.                         ld e,a ;номер сектора
  383.                         ld bc,#0106 ;1 сектор записать
  384.                         call call3d13                  
  385.                        
  386.                         ;служебный сектор
  387.                         ld de,(cat_buf+8*256+#e1) ;первые свободные сектор-дорожка
  388.                         ld a,(f_name+13) ;размер файла в секторах
  389.                         ld b,a
  390.                         call calc_next_pos2
  391.                         ld (cat_buf+8*256+#e1),de
  392.  
  393.                         ld hl,(cat_buf+8*256+#e5) ; количество свободных секторов на диске
  394.                         ld a,(f_name+13) ;размер файла в секторах
  395.                         ld c,a
  396.                         ld b,0
  397.                         and a
  398.                         sbc hl,bc
  399.                         jr nc,fclose_f_one2
  400.                         ld hl,0 ;если было отрицательное
  401. fclose_f_one2
  402.                         ld (cat_buf+8*256+#e5),hl
  403.                        
  404.                         ld hl,cat_buf+8*256+#e4 ; общее количество файлов                      
  405.                         inc (hl)
  406.                        
  407.                         ld hl,cat_buf+8*256
  408.                         ld de,#0008
  409.                         ld bc,#0106 ;1 сектор записать
  410.                         call call3d13
  411.                         ret
  412.        
  413.        
  414. fclose_scl     
  415.         cp 4 ;если scl
  416.         jr nz,fclose_ex
  417.         ld hl,sec_buf ;
  418.         ld b,1
  419.         call scl_write_buf ;допишем остаток scl, если есть
  420.        
  421. fclose_ex      
  422.         xor a ;как бы закрываем все файлы
  423.         ld (f_r_flag),a
  424.         ld (f_w_flag),a
  425.         ;call restore_drive ;вернуть диск, какой был
  426.     ret
  427.  
  428.  
  429.  
  430.  
  431. ; A - file stream id
  432. ; BC - length
  433. ; HL - buffer
  434. ; Returns
  435. ;  BC - length(how much was actually read)
  436. fread: ;(id=1)
  437.     ; push hl : pop ix
  438.     ; esxCall ESX_FREAD
  439.         ; push af
  440.         ; ld a,4
  441.         ; out (254),a
  442. ; WAITKEY       XOR A:IN A,(#FE):CPL:AND #1F:JR Z,WAITKEY
  443.         ; xor a
  444.         ; out (254),a
  445.         ; pop af
  446.  
  447.         cp 1 ;id = 1?
  448.         jr nz,fread_no_chek ;выход если номер потока не = 1
  449.         ld a,(f_r_flag)
  450.         or a
  451.         jr nz,fread_chek ;файл уже открыт?
  452. fread_no_chek ;выход с ошибкой
  453.         xor a
  454.         scf ;флаг ошибки
  455.         ld bc,0 ;ничего мы не считали
  456.         ret
  457.        
  458. fread_chek
  459.         ld bc,(f_r_len_sec-1) ;загружаем файл целиком, не смотря на то, сколько байт было запрошено
  460.     ld      c,5 ;read читаем целыми секторами
  461.         ld de,(f_r_cur_trk)
  462.     call    call3d13   
  463.         ld bc,(f_r_len) ;возвратим сколько считали байт (длину файла)
  464.         xor a ;флаги сбросим
  465.     ret
  466.  
  467. ; A - file stream id
  468. ; BC - length
  469. ; HL - buffer
  470. ; Returns:
  471. ;   BC - actually written bytes
  472. fwrite: ;
  473.     ; push hl : pop ix
  474.     ; esxCall ESX_FWRITE
  475.        
  476.         ; push af
  477.         ; ld a,2
  478.         ; out (254),a
  479. ; WAITKEY1      XOR A:IN A,(#FE):CPL:AND #1F:JR Z,WAITKEY1
  480.         ; xor a
  481.         ; out (254),a
  482.         ; pop af
  483.  
  484.         cp 2 ;id = 2?
  485.         jr z,fwrite_chek ;проверка id потока
  486.         cp 3 ;id = 3?
  487.         jr z,fwrite_chek_trd ;проверка id потока
  488.         cp 4 ;id = 4?
  489.         jp z,fwrite_chek_scl ;проверка id потока
  490.  
  491.        
  492. fwrite_no_chek ;выход с ошибкой
  493.         xor a
  494.         scf ;флаг ошибки
  495.         ld bc,0 ;ничего мы не записали
  496.         ret
  497.        
  498. fwrite_chek ;запись произвольного типа файла (id=2)
  499.  
  500.         ;не отличается от записи trd, пишется входящий поток на диск, отличия при открытии и закрытии файла
  501.  
  502.  
  503.  
  504.  
  505.  
  506. fwrite_chek_trd ;запись trd файла (разворачивание образа, id=3)
  507.         ; ld a,2
  508.         ; out (254),a
  509. ; WAITKEY_t     XOR A:IN A,(#FE):CPL:AND #1F:JR Z,WAITKEY_t
  510.         ; xor a
  511.         ; out (254),a
  512.         ld a,(f_w_flag)
  513.         or a
  514.         jr z,fwrite_no_chek ;файл уже открыт?
  515.         ld (temp_bc),bc ;длина
  516.         ld (temp_hl),hl ;адрес данных
  517.         ld a,b
  518.         or c
  519.         jr z,fwrite_no_chek ; если длина 0, то выход
  520.        
  521.         ;защита от переполнения диска
  522.         ld de,(#5cf4)
  523.         ld a,d
  524.         cp #a0 ;последняя дорожка 160
  525.         jr nc,fwrite_no_chek
  526.        
  527.         xor a
  528.         ld (sec_part),a ;обнулить переменные
  529.         ld (sec_shift2),a
  530.         ld (sec_shift2+1),a
  531.         ld (sec_shift_flag),a
  532.         ld (write_end_flag),a ;
  533.        
  534.  
  535.         ld a,(sec_shift)
  536.         or a
  537.         jr z,fwrite_trd3 ;если смещения нет, то первую часть пропустим
  538.        
  539.  
  540.         ld c,a
  541.         ld b,0
  542.         ld hl,(temp_bc) ;проверка заполнится ли целый сектор
  543.         add hl,bc
  544.        
  545.         ld a,1
  546.         ld (write_end_flag),a ;флаг что не нужно дописывать остаток
  547.        
  548.         ld a,h
  549.         or a
  550.         jr nz,fwrite_trd4
  551.         ld a,1
  552.         ld (sec_shift_flag),a ;флаг что не заполнен сектор
  553.        
  554. fwrite_trd4    
  555.         ld hl,sec_buf ;буфер последнего сектора
  556.         add hl,bc ;на этой точке остановились
  557.         ex de,hl
  558.         ld hl,(temp_hl) ;присоединим начало данных в конец предыдущих
  559.         ; ld a,c
  560.         ; or a
  561.         ; jr nz,fwrite_trd2
  562.         ; inc b ;коррекция
  563. ; fwrite_trd2          
  564.         ; ld c,a
  565.         xor a
  566.         sub c
  567.         ld c,a ;сколько осталось перенести до заполнения сектора
  568.         ld (sec_shift2),bc ;сохраним сколько добавили байт
  569.         ldir
  570.  
  571.         ld a,(sec_shift_flag)
  572.         or a
  573.         jr nz,fwrite_trd3 ;если сектор ещё не заполнен писать не будем
  574.  
  575.         ld hl,sec_buf
  576.         ld de,(#5cf4)
  577.         ;ld (f_w_cur_trk),de    ;запомним позицию
  578.     ld      bc,#0106 ;пишем 1 сектор из буфера
  579.     call    call3d13   
  580.         ld a,c
  581.         cp 255
  582.         jp z,fwrite_no_chek ;выход если ошибка 
  583.  
  584.         xor a
  585.         ld (write_end_flag),a ;флаг что нужно дописывать остаток       
  586.         ; ld de,(f_w_cur_trk) ;если сектор ещё не заполнен, останемся на старой позиции
  587.         ; ld (#5cf4),de
  588.         ; ld b,1 ;на сектор вперёд
  589.         ; ld de,(f_w_cur_trk)
  590.         ; call calc_next_pos
  591.         ; ld (f_w_cur_trk),de  
  592.  
  593. fwrite_trd3    
  594.         ld hl,(temp_hl) ;запишем остаток данных
  595.         ;ld a,(sec_shift)
  596.         ;ld c,a
  597.         ;ld b,0
  598.         ld bc,(sec_shift2)
  599.         add hl,bc ;с этой точки пишем
  600.         ld (temp_hl2),hl ;сохраним начало записи второго сектора
  601.        
  602.         ld hl,(temp_bc) ;вычисление на чём остановимся в этот раз
  603.         and a
  604.         sbc hl,bc ;вычтем то, что добавили к первому сектору
  605.         ld c,l
  606.         ld b,h
  607.         jr nc,fwrite_trd5
  608.         ld b,0 ;коррекция если вышел минус
  609. fwrite_trd5
  610.         ld hl,(temp_hl)
  611.         add hl,bc
  612.        
  613.         ld de,outputBuffer
  614.         and a
  615.         sbc hl,de
  616.        
  617.         ld a,l
  618.         ld (sec_shift),a ;смещение на следующий раз
  619.         ;ld hl,(temp_hl)       
  620.        
  621.  
  622.         ; or a
  623.         ; jr z,fwrite_trd1
  624.         ; inc b  ;коррекция количества секторов
  625.        
  626.         ld a,b ;нужна проверка на количество секторов!!!
  627.         ld (sec_part),a ;запомним сколько секторов во второй части
  628.        
  629.         ;ld a,b
  630.         or a
  631.         jr z,fwrite_trd1 ;если размер данных меньше сектора, то пропустим запись
  632.        
  633.         ld hl,(temp_hl2)
  634.         ;push bc
  635.         ld de,(#5cf4)
  636.     ld      c,6 ;пишем целыми секторами
  637.     call    call3d13   
  638.         ld a,c
  639.         ;pop bc
  640.         cp 255
  641.         jp z,fwrite_no_chek ;выход если ошибка
  642.         ; ld de,(f_w_cur_trk)
  643.         ; call calc_next_pos
  644.         ; ld (f_w_cur_trk),de
  645.        
  646.         xor a
  647.         ld (write_end_flag),a ;флаг что нужно дописывать остаток       
  648.        
  649. fwrite_trd1    
  650.         ld a,(write_end_flag) ;нужно записывать остаток?
  651.         or a
  652.         jr nz,fwrite_trd_ex ;не нужно
  653.  
  654.         ld hl,(temp_hl2) ;сохраним незаписанный остаток
  655.         ld a,(sec_part)
  656.         ld b,a
  657.         ld c,0
  658.         add hl,bc
  659.         ld de,sec_buf
  660.         ld bc,256
  661.         ldir
  662. ;fwrite_trd2   
  663.  
  664.        
  665. fwrite_trd_ex  
  666.         ld bc,(temp_bc) ;возвратим, что сколько запрашивали, столько и записали байт
  667.         ;посчитаем общую длину записанного
  668.         ld hl,(f_w_len)
  669.         add hl,bc
  670.         ld (f_w_len),hl
  671.         jr nc,fwrite_trd_ex1
  672.         ld hl,(f_w_len+2)
  673.         inc hl
  674.         ld (f_w_len+2),hl
  675.        
  676. fwrite_trd_ex1
  677.         xor a ;флаги сбросим
  678.     ret
  679.  
  680.  
  681.  
  682.  
  683.  
  684. ;------------------scl----------------------
  685. fwrite_chek_scl ;запись scl файла (разворачивание образа, id=4)
  686.         ; ld a,2
  687.         ; out (254),a
  688. ; WAITKEY_t     XOR A:IN A,(#FE):CPL:AND #1F:JR Z,WAITKEY_t
  689.         ; xor a
  690.         ; out (254),a
  691.         ld a,(f_w_flag)
  692.         or a
  693.         jp z,fwrite_no_chek ;файл уже открыт?
  694.         ld (temp_bc),bc ;длина
  695.         ld (temp_hl),hl ;адрес данных
  696.         ld a,b
  697.         or c
  698.         jp z,fwrite_no_chek ; если длина 0, то выход
  699.        
  700.         ; ld a,b
  701.         ; or a
  702.         ; jr nz,testt1
  703.         ; nop
  704.        
  705. ; testt1
  706.        
  707.         xor a
  708.         ld (sec_part),a ;обнулить переменные
  709.         ld (sec_shift2),a
  710.         ld (sec_shift2+1),a
  711.         ld (sec_shift_flag),a
  712.         ld (write_end_flag),a ;
  713.        
  714.  
  715.         ld a,(sec_shift)
  716.         or a
  717.         jr z,fwrite_scl3 ;если смещения нет, то первую часть пропустим
  718.        
  719.  
  720.         ld c,a
  721.         ld b,0
  722.         ld hl,(temp_bc) ;проверка заполнится ли целый сектор
  723.         add hl,bc
  724.        
  725.         ld a,1
  726.         ld (write_end_flag),a ;флаг что не нужно дописывать остаток
  727.        
  728.         ld a,h
  729.         or a
  730.         jr nz,fwrite_scl4
  731.         ld a,1
  732.         ld (sec_shift_flag),a ;флаг что не заполнен сектор
  733.        
  734. fwrite_scl4    
  735.         ld hl,sec_buf ;буфер последнего сектора
  736.         add hl,bc ;на этой точке остановились
  737.         ex de,hl
  738.         ld hl,(temp_hl) ;присоединим начало данных в конец предыдущих
  739.         ; ld a,c
  740.         ; or a
  741.         ; jr nz,fwrite_scl2
  742.         ; inc b ;коррекция
  743. ; fwrite_scl2          
  744.         ; ld c,a
  745.         xor a
  746.         sub c
  747.         ld c,a ;сколько осталось перенести до заполнения сектора
  748.         ld (sec_shift2),bc ;сохраним сколько добавили байт
  749.         ldir
  750.  
  751.         ld a,(sec_shift_flag)
  752.         or a
  753.         jr nz,fwrite_scl3 ;если сектор ещё не заполнен писать не будем
  754.  
  755.         ld hl,sec_buf
  756.         ;ld de,(#5cf4)
  757.         ;ld (f_w_cur_trk),de    ;запомним позицию
  758.     ld      b,#01 ;пишем 1 сектор из буфера
  759.     call    scl_write_buf      
  760.         ; ld a,c
  761.         ; cp 255
  762.         ; jp z,fwrite_no_chek ;выход если ошибка       
  763.  
  764.         xor a
  765.         ld (write_end_flag),a ;флаг что нужно дописывать остаток       
  766.         ; ld de,(f_w_cur_trk) ;если сектор ещё не заполнен, останемся на старой позиции
  767.         ; ld (#5cf4),de
  768.         ; ld b,1 ;на сектор вперёд
  769.         ; ld de,(f_w_cur_trk)
  770.         ; call calc_next_pos
  771.         ; ld (f_w_cur_trk),de  
  772.  
  773. fwrite_scl3    
  774.         ld hl,(temp_hl) ;запишем остаток данных
  775.         ;ld a,(sec_shift)
  776.         ;ld c,a
  777.         ;ld b,0
  778.         ld bc,(sec_shift2)
  779.         add hl,bc ;с этой точки пишем
  780.         ld (temp_hl2),hl ;сохраним начало записи второго сектора
  781.        
  782.         ld hl,(temp_bc) ;вычисление на чём остановимся в этот раз
  783.         and a
  784.         sbc hl,bc ;вычтем то, что добавили к первому сектору
  785.         ld c,l
  786.         ld b,h
  787.         jr nc,fwrite_scl5
  788.         ld b,0 ;коррекция если вышел минус
  789. fwrite_scl5
  790.         ld hl,(temp_hl)
  791.         add hl,bc
  792.        
  793.         ld de,outputBuffer
  794.         and a
  795.         sbc hl,de
  796.        
  797.         ld a,l
  798.         ld (sec_shift),a ;смещение на следующий раз
  799.         ;ld hl,(temp_hl)       
  800.        
  801.  
  802.         ; or a
  803.         ; jr z,fwrite_scl1
  804.         ; inc b  ;коррекция количества секторов
  805.        
  806.         ld a,b ;нужна проверка на количество секторов!!!
  807.         ld (sec_part),a ;запомним сколько секторов во второй части
  808.        
  809.         ;ld a,b
  810.         or a
  811.         jr z,fwrite_scl1 ;если размер данных меньше сектора, то пропустим запись
  812.        
  813.         ld hl,(temp_hl2)
  814.         ;push bc
  815.         ;ld de,(#5cf4)
  816.     ;ld      c,6 ;пишем целыми секторами
  817.     call    scl_write_buf      
  818.         ;ld a,c
  819.         ;pop bc
  820.         ; cp 255
  821.         ; jp z,fwrite_no_chek ;выход если ошибка
  822.         ; ld de,(f_w_cur_trk)
  823.         ; call calc_next_pos
  824.         ; ld (f_w_cur_trk),de
  825.        
  826.         xor a
  827.         ld (write_end_flag),a ;флаг что нужно дописывать остаток       
  828.        
  829. fwrite_scl1    
  830.         ld a,(write_end_flag) ;нужно записывать остаток?
  831.         or a
  832.         jr nz,fwrite_scl_ex ;не нужно
  833.  
  834.         ld hl,(temp_hl2) ;сохраним незаписанный остаток
  835.         ld a,(sec_part)
  836.         ld b,a
  837.         ld c,0
  838.         add hl,bc
  839.         ld de,sec_buf
  840.         ld bc,256
  841.         ldir
  842. ;fwrite_scl2   
  843.  
  844.        
  845. fwrite_scl_ex  
  846.         ld bc,(temp_bc) ;возвратим, что сколько запрашивали, столько и записали байт
  847.         ;посчитаем общую длину записанного
  848.         ld hl,(f_w_len)
  849.         add hl,bc
  850.         ld (f_w_len),hl
  851.         jr nc,fwrite_scl_ex1
  852.         ld hl,(f_w_len+2)
  853.         inc hl
  854.         ld (f_w_len+2),hl
  855.        
  856. fwrite_scl_ex1
  857.         xor a ;флаги сбросим
  858.     ret
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865. scl_write_buf ;заполнение промежуточного буфера
  866.         push bc ;сколько пакетов указано в b
  867.         ld de,scl_buf ;перенесём сектор во временный буфер
  868.         ld bc,256
  869.         ldir
  870.         ld (scl_temp_hl2),hl ;сохраним адрес данных
  871.         ld a,(scl_que) ;проверим флаг что нужны данные
  872.         or a
  873.         jr z,scl_write_buf_ret ;не будем вызывать парсер если не нужны
  874.         ld hl,scl_write_buf_ret ;адрес возврата
  875.         push hl
  876.         ld hl,(scl_parse_ret_adr) ;адрес для продолжения основного цикла сборки
  877.         jp (hl) ;отдадим пакет 256 байт парсеру
  878. scl_write_buf_ret
  879.         ld hl,(scl_temp_hl2)
  880.         pop bc
  881.         djnz scl_write_buf
  882.  
  883.         ret
  884.        
  885.        
  886.        
  887. scl_parse ;разбор образа scl в trd, основной цикл
  888.         ;получить первый сектор
  889. ;запрос порции данных по 256 байт
  890.         ld (scl_temp_hl),hl
  891.         ld (scl_temp_de),de
  892.         ld (scl_temp_bc),bc
  893.         ld a,1
  894.         ld (scl_que),a ;включим флаг что нужны данные
  895.         ld hl,scl_parse_ret ;сохраним адрес возврата
  896.         ld (scl_parse_ret_adr),hl
  897.         ret ;вернёмся для ожидания данных
  898. scl_parse_ret  
  899.         xor a
  900.         ld (scl_que),a
  901.         ld hl,(scl_temp_hl)
  902.         ld de,(scl_temp_de)
  903.         ld bc,(scl_temp_bc)
  904.        
  905.         ld de,scl_buf ;проверка метки образа
  906.         ld hl,scl_sign
  907.         ld b,8
  908. scl_parse_chk
  909.         ld a,(de)
  910.         cp (hl)
  911.         jr nz,scl_parse_chk_no
  912.         inc hl
  913.         inc de
  914.         djnz scl_parse_chk
  915.         jr scl_parse_chk_ok
  916. scl_parse_chk_no ;если не совпало, значит плохой образ
  917.     ld hl, scl_err
  918.     call DialogBox.msgBox ;предуреждение
  919.         xor a
  920.         ld (scl_que),a ;выключим флаг что нужны данные
  921.         ld a,4 ;закроем файл
  922.         call fclose
  923.         ret
  924. scl_parse_chk_ok ;сигнатура правильная
  925.  
  926. ;формирование каталога
  927.         ld a,(scl_buf+8)
  928.         ld (scl_files),a ;всего файлов
  929.         ld (scl_cat_cycl),a ;цикл
  930.         ld hl,scl_buf+9 ;адрес первого заголовка
  931.         ld de,cat_buf ;адрес формируемого каталога trd
  932. scl_parse_cat2 
  933.         ld b,14 ;14 байт одна запись
  934. scl_parse_cat  
  935.         ld a,(hl)
  936.         ld (de),a
  937.         inc de
  938.         inc l ;адрес увеличиваем только в пределах младшего регистра
  939.         jr nz,scl_parse_cat1
  940.         ;тут пора запросить следующий сектор
  941. ;запрос порции данных по 256 байт
  942.         ld (scl_temp_hl),hl
  943.         ld (scl_temp_de),de
  944.         ld (scl_temp_bc),bc
  945.         ld a,1
  946.         ld (scl_que),a ;включим флаг что нужны данные
  947.         ld hl,scl_parse_ret1 ;сохраним адрес возврата
  948.         ld (scl_parse_ret_adr),hl
  949.         ret ;вернёмся для ожидания данных
  950. scl_parse_ret1
  951.         xor a
  952.         ld (scl_que),a
  953.         ld hl,(scl_temp_hl)
  954.         ld de,(scl_temp_de)
  955.         ld bc,(scl_temp_bc)
  956.        
  957. scl_parse_cat1
  958.         djnz scl_parse_cat
  959.         inc de
  960.         inc de
  961.         ld a,(scl_cat_cycl)
  962.         dec a
  963.         ld (scl_cat_cycl),a
  964.         jr nz,scl_parse_cat2
  965.        
  966.         ld (scl_temp_hl),hl ;запомнить где остановились
  967.        
  968. ;подсчёт секторов и дорожек
  969.         push ix
  970.         ld a,(scl_files)
  971.         ld de,#0100 ;данные с первой дорожки
  972.         ld ix,cat_buf
  973.         ld (ix+14),e
  974.         ld (ix+15),d
  975.         ld hl,0 ;общее количество секторов
  976. scl_cacl
  977.         ld (scl_cat_cycl),a ;цикл
  978.         ld a,(ix+13) ;длина файла в секторах
  979.         ld c,a
  980.         ld b,0
  981.         add hl,bc ;секторов
  982.        
  983.         ld bc,16
  984.         add ix,bc
  985.         ld b,a
  986.         call calc_next_pos
  987.         ld a,(scl_cat_cycl)
  988.         cp 1
  989.         jr z,scl_cacl2 ;в последний раз пропусим
  990.         ld (ix+14),e
  991.         ld (ix+15),d
  992. scl_cacl2
  993.         dec a
  994.         jr nz,scl_cacl
  995.         ;теперь узнаем первый свободный сектор
  996.         ld a,(ix+13) ;длина файла в секторах
  997.         ld c,a
  998.         ld b,0
  999.         add hl,bc
  1000.         ; ld b,a
  1001.         ; call calc_next_pos
  1002.         ld (cat_buf+8*256+#e1),de ;Первый свободный сектор и дорожка на дискете
  1003.         ld de,16*159
  1004.         ex de,hl
  1005.         and a
  1006.         sbc hl,de
  1007.         ld (cat_buf+8*256+#e5),hl ;Число свободных секторов на диске
  1008.         pop ix
  1009.  
  1010.  
  1011.        
  1012. ;запись содержимого файлов
  1013.         ld a,(scl_files) ;всего файлов
  1014.         ld (scl_cat_cycl),a ;цикл
  1015.         ld hl,cat_buf+13 ;адрес размер секторов файла
  1016.         ld (cat_cur_adr),hl
  1017.  
  1018.         ld hl,#0100 ;начиная с первой дорожки
  1019.         ld (#5cf4),hl
  1020. scl_parse_file2
  1021.         ld hl,(scl_temp_hl) ;адрес данных
  1022.         ld de,(cat_cur_adr) ;адрес сектор дорожка файла
  1023.         ;dec de
  1024.         ld a,(de) ;количество секторов, цикл
  1025.         ld c,a
  1026. scl_parse_file3
  1027.         ld de,scl_buf2 ;адрес ещё одного буфера
  1028.         ld b,0 ;256 байт один сектор, цикл
  1029. scl_parse_file 
  1030.         ld a,(hl)
  1031.         ld (de),a
  1032.         inc de
  1033.         inc l ;адрес увеличиваем только в пределах младшего регистра
  1034.         jr nz,scl_parse_file1
  1035.         ;тут пора запросить следующий сектор
  1036. ;запрос порции данных по 256 байт
  1037.         ld (scl_temp_hl),hl
  1038.         ld (scl_temp_de),de
  1039.         ld (scl_temp_bc),bc
  1040.         ld a,1
  1041.         ld (scl_que),a ;включим флаг что нужны данные
  1042.         ld hl,scl_parse_ret2 ;сохраним адрес возврата
  1043.         ld (scl_parse_ret_adr),hl
  1044.         ret ;вернёмся для ожидания данных
  1045. scl_parse_ret2
  1046.         xor a
  1047.         ld (scl_que),a
  1048.         ld hl,(scl_temp_hl)
  1049.         ld de,(scl_temp_de)
  1050.         ld bc,(scl_temp_bc)
  1051.        
  1052. scl_parse_file1
  1053.         djnz scl_parse_file
  1054.         ld (scl_temp_hl),hl    
  1055.         ld (scl_temp_bc),bc
  1056.        
  1057.         ld hl,scl_buf2 ;;запишем один сектор
  1058.         ld  de,(#5cf4)
  1059.     ld      bc,#0106 ;
  1060.     call    call3d13   
  1061.         ; ld a,c
  1062.         ; cp 255
  1063.         ; jp z,fwrite_no_chek ;выход если ошибка       
  1064.         ld hl,(scl_temp_hl)
  1065.         ld bc,(scl_temp_bc)
  1066.        
  1067.         dec c
  1068.         jr nz,scl_parse_file3
  1069.        
  1070.         ld hl,(cat_cur_adr) ;адрес сектор дорожка файла
  1071.         ; ld e,(hl)
  1072.         ; inc hl
  1073.         ; ld d,(hl)
  1074.         ld bc,16
  1075.         add hl,bc ;на следующий файл
  1076.         ld (cat_cur_adr),hl    
  1077.        
  1078.        
  1079.         ld a,(scl_cat_cycl)
  1080.         dec a
  1081.         ld (scl_cat_cycl),a
  1082.         jr nz,scl_parse_file2   ;на следующий файл
  1083.        
  1084.        
  1085.  
  1086. ;формирование системного сектора №9 (8)
  1087.         ;
  1088.         ;ld (cat_buf+8*256+#e1),a ;// #E1 Первый свободный сектор на дискете
  1089.         ;
  1090.         ;ld (cat_buf+8*256+#e2),a ;// #E2 Первый свободный трек
  1091.         ld a,#16
  1092.         ld (cat_buf+8*256+#e3),a ;// #E3 16 80 дорожек, 2 стороны
  1093.         ld a,(scl_files)
  1094.         ld (cat_buf+8*256+#e4),a ;// #E4 Общее количество файлов записанных на диск
  1095.         ;
  1096.         ;ld (cat_buf+8*256+#e5),a ;// #Е5,Е6 Число свободных секторов на диске
  1097.         ;ld (cat_buf+8*256+#e6),a
  1098.         ld a,#10
  1099.         ld (cat_buf+8*256+#e7),a ;// #E7 Код  #10,определяющий принадлежность к TR-DOS 
  1100.  
  1101.         ld hl,f_name ;запишем имя диска, взяв для этого имя файла
  1102.         ld de,cat_buf+8*256+#f5 ;// #F5-#FC Имя диска в ASCII формате
  1103.         ld bc,8
  1104.         ldir
  1105.        
  1106.         ld hl,cat_buf ;запишем каталог на диск
  1107.         ld de,0
  1108.     ld      bc,#0906 ;
  1109.     call    call3d13   
  1110.         ; ld a,c
  1111.         ; cp 255
  1112.         ; jp z,fwrite_no_chek ;выход если ошибка       
  1113.         ret
  1114.  
  1115.  
  1116. ;-----------scl end --------------------
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.  
  1124.  
  1125.  
  1126.    
  1127. ; A - file stream id
  1128. ; fsync:
  1129. ;     esxCall ESX_FSYNC
  1130.     ; ret
  1131.  
  1132.  
  1133. ; HL - name (name.ext)
  1134. ; Returns:
  1135. ; HL - name (name    e)
  1136. format_name ;подгоняет имя файла под стандарт trdos (8+1)
  1137.  
  1138.         ;сначала попробуем убрать из пути подпапку, если она есть
  1139.         ld (temp_hl),hl ;сохраним адрес исходного имени
  1140.         ld b,#00 ;не больше 255 символов       
  1141. format_name5   
  1142.         ld a,(hl)
  1143.         cp "/" ;если есть подпапка
  1144.         jr z,format_name_path_yep
  1145.         ld a,(hl)
  1146.         cp "." ;если ещё не дошли до расширения
  1147.         jr nz,format_name6
  1148.         ld hl,(temp_hl) ;если дошли до расширения, то путей нет, вернёмся на начало имени
  1149.         jr format_name_7 ;на выход
  1150. format_name6
  1151.         inc hl
  1152.         djnz format_name5
  1153.        
  1154. format_name_path_yep ;нашли
  1155.         inc hl ;пропустим знак "/"
  1156.        
  1157. format_name_7  
  1158.  
  1159.         push hl ;очистим место для нового имени
  1160.         ld hl,f_name
  1161.         ld de,f_name+1
  1162.         ld (hl)," "
  1163.         ld bc,8+1
  1164.         ldir
  1165.         ld (hl),0
  1166.         ld bc,16-8-1-1
  1167.         ldir
  1168.         pop hl
  1169.  
  1170.         ld bc,#09ff ;длина имени 9 символов
  1171.         ld de,f_name ;куда
  1172. format_name2   
  1173.         ld a,(hl)
  1174.         cp "."
  1175.         jr nz,format_name1
  1176.         ld de,f_name+8
  1177.         inc hl
  1178.         ldi ; и в конце расширение 3 буквы
  1179.         ldi
  1180.         ldi
  1181.         ;ex de,hl ;сохраним адрес исходного расширения
  1182.         jr format_name_e
  1183. format_name1
  1184.         ldi
  1185.         djnz format_name2
  1186.        
  1187.         ;если имя длинное, пропустим лишнее до расширения
  1188.         ld b,#00 ;не больше 255 символов       
  1189. format_name3   
  1190.         ld a,(hl)
  1191.         cp "."
  1192.         jr nz,format_name4
  1193.         ld de,f_name+8
  1194.         inc hl
  1195.         ldi ; и в конце расширение 3 буквы
  1196.         ldi
  1197.         ldi
  1198.         ;ex de,hl ;сохраним адрес исходного расширения
  1199.         jr format_name_e
  1200. format_name4
  1201.         inc hl
  1202.         djnz format_name3
  1203.        
  1204. format_name_e ;выход
  1205.         ld hl,f_name ;вернём результат
  1206.         ret
  1207.  
  1208. ; DE - trk/sec
  1209. ; B - sectors step
  1210. ; Returns:
  1211. ; DE - trk/sec 
  1212. calc_next_pos           ;вперёд на N секторов  
  1213.                         ;ld b,4
  1214.                         ;ld  de,(#5ceb)
  1215. calc_next_pos2         
  1216.                         inc e
  1217.                         ld a,e
  1218.                         cp 16
  1219.                         jr c,calc_next_pos1
  1220.                         inc d
  1221.                         ld e,0
  1222. calc_next_pos1
  1223.                         ;ld (#5ceb),de
  1224.                         djnz calc_next_pos2
  1225.                         ret
  1226.                        
  1227.  
  1228. ;testt db "123.trd"
  1229. write_ima db "Select disk "
  1230. write_ima_d db "A: (A-D). "
  1231.                 db "All data may be lost! Press Y or N.",0
  1232. ;prev_drive db 0 ;предыдущий номер дисковода
  1233.                
  1234. trdExt1 db ".trd", 0
  1235. trdExt2 db ".TRD", 0
  1236.  
  1237. sclExt1 db ".scl", 0
  1238. sclExt2 db ".SCL", 0
  1239.  
  1240. f_name ds 16 ;имя файла
  1241. f_r_cur_trk dw   0 ;текущие сектор-дорожка файла на чтение
  1242. f_r_len_sec db 0 ;длина файла на чтение в секторах
  1243. f_r_len dw 0;длина файла в байтах
  1244. f_r_flag db 0 ;флаг что открыт файл на чтение
  1245.  
  1246. f_w_cur_trk dw   0 ;текущие сектор-дорожка файла на запись
  1247. f_w_len_sec db 0 ;длина файла на запись в секторах
  1248. f_w_flag db 0 ;флаг что открыт файл на запись
  1249. f_w_len ds 4 ;длина записанных данных
  1250. write_end_flag db 0 ;флаг что нужно записать остаток
  1251.  
  1252. temp_bc dw 0 ;хранение регистра
  1253. temp_hl dw 0 ;хранение регистра
  1254. temp_hl2 dw 0 ;хранение регистра
  1255.  
  1256. sec_shift db 0 ;указатель на каком байте остановлена запись
  1257. sec_shift2 db 0 ;указатель на каком байте остановлена запись (остаток)
  1258. sec_part db 0 ;сколько секторов во второй порции для записи
  1259. sec_shift_flag db 0 ;флаг что буфер сектора не заполнен
  1260.  
  1261. ;секция scl
  1262. scl_sign db "SINCLAIR" ;метка
  1263. scl_que db 0 ;флаг запроса порции данных
  1264. scl_err db "SCL image error!",0
  1265. scl_parse_ret_adr dw 0; адрес возврата в цикл
  1266. scl_cat_cycl db 0 ;переменная цикла
  1267. scl_files db 0 ;всего файлов
  1268. scl_temp_hl dw 0;;хранение регистра
  1269. scl_temp_hl2 dw 0;
  1270. scl_temp_de dw 0;
  1271. scl_temp_bc dw 0;
  1272. cat_cur_adr dw 0;
  1273. ;scl end
  1274.  
  1275. ;секция сохранения любого файла
  1276. file_err db "Not enough space!",0
  1277. sec_cat db 0 ;сектор каталога
  1278. file_num db "0" ;номер части для больших файлов
  1279.  
  1280.         ;по адресу #4000 шрифт
  1281. cat_buf equ #4800 ;буфер для кататога диска 9*256
  1282. sec_buf equ cat_buf + 9*256 ;буфер сектора для записи 256
  1283. scl_buf equ sec_buf + 512 ;промежуточный буфер 256
  1284. scl_buf2 equ scl_buf + 512 ;промежуточный буфер 256
  1285.  
  1286.     ENDMODULE