?login_element?

Subversion Repositories NedoOS

Rev

Rev 1636 | Go to most recent revision | 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. fclose_f ;поправить каталог
  283.         ld a,(f_w_len+2) ;самый старший байт длины файла
  284.         ld hl,(f_w_len+0)
  285.         or h
  286.         or l
  287.         jp z,fclose_ex ;выход если длина 0
  288.        
  289.         ;проверки на заполнение
  290.         ld a,(cat_buf+8*256+#e4) ; общее количество файлов
  291.         cp 128
  292.         jp nc,fclose_ex ;если уже максимум
  293.         ld hl,(cat_buf+8*256+#e5) ; количество свободных секторов на диске
  294.         ld a,h
  295.         or l
  296.         jp z,fclose_ex ;если места нет     
  297.        
  298.         ld a,(f_w_len+2) ;самый старший байт длины файла
  299.         or a
  300.         jr nz,fclose_f_multi ;если файл больше 255 секторов (65280)
  301.         ld a,(f_w_len+1)
  302.         cp 255
  303.         jr nz,fclose_f1
  304.         ld a,(f_w_len+0)
  305.         jr nz,fclose_f_multi ;если файл больше 255 секторов (65280)
  306. fclose_f1
  307.         ;файл не превышает максимальный размер для trdos
  308.         ld de,(f_w_len+0)      
  309.         ld hl,f_name+11 ;длина файла
  310.         ld (hl),e
  311.         inc hl
  312.         ld (hl),d
  313.         inc hl
  314.         ld a,(f_w_len+1) ;длина секторов
  315.         ld (hl),a
  316.         ld a,(f_w_len+0) ;длина младший
  317.         or a
  318.         jr z,fclose_f2
  319.         inc (hl) ;коррекция секторов
  320. fclose_f2
  321.         call fclose_f_one ;записать информацию
  322.         jp fclose_ex ;готово
  323.        
  324. fclose_f_multi ;файл большой, будет несколько записей в каталоге      
  325.         ld hl,f_name+11 ;длина файла
  326.         ld (hl),0
  327.         inc hl
  328.         ld (hl),#ff ;65280
  329.         inc hl
  330.         ;длина секторов
  331.         ld (hl),#ff
  332.         call fclose_f_one ;записать информацию
  333.        
  334.         ;вычесть длину записанного
  335.         ld hl,(f_w_len+1) ;старший и средний байт   
  336.         ld bc,255
  337.         and a
  338.         sbc hl,bc ;вычесть 255 секторов
  339.         ld (f_w_len+1),hl
  340.        
  341.         ld hl,f_name+8 ;расширение
  342.         inc (hl) ;изменить на следующее по алфавиту
  343.  
  344.         jr fclose_f ;сначала
  345.  
  346.        
  347. fclose_f_one ;запись об одном файле
  348.                         ld a,(cat_buf+8*256+#e4) ; общее количество файлов
  349.                         ld l,a ;узнать в каком секторе будет запись о файле
  350.                         ld h,0
  351.                         add hl,hl ;*2
  352.                         add hl,hl ;*4
  353.                         add hl,hl ;*8
  354.                         add hl,hl ;*16
  355.                         ld a,h ;запомнить номер сетора в каталоге
  356.                         ld (sec_cat),a
  357.                         ld bc,cat_buf
  358.                         add hl,bc ;здесь будет запись о новом файле
  359.                         ex de,hl
  360.                        
  361.                         ld hl,f_name ;запись о файле
  362.                         ld bc,16
  363.                         ldir ;скопировать
  364.                         ex de,hl
  365.                         dec hl
  366.                         ld de,(cat_buf+8*256+#e1) ;первые свободные сектор-дорожка назначения
  367.                         ld (hl),d ;дорожка
  368.                         dec hl
  369.                         ld (hl),e ;сектор
  370.                        
  371.                         ld l,0 ;записать сектор целиком по ровному адресу
  372.                         ld d,0
  373.                         ld a,(sec_cat)
  374.                         ld e,a ;номер сектора
  375.                         ld bc,#0106 ;1 сектор записать
  376.                         call call3d13                  
  377.                        
  378.                         ;служебный сектор
  379.                         ld de,(cat_buf+8*256+#e1) ;первые свободные сектор-дорожка
  380.                         ld a,(f_name+13) ;размер файла в секторах
  381.                         ld b,a
  382.                         call calc_next_pos2
  383.                         ld (cat_buf+8*256+#e1),de
  384.  
  385.                         ld hl,(cat_buf+8*256+#e5) ; количество свободных секторов на диске
  386.                         ld a,(f_name+13) ;размер файла в секторах
  387.                         ld c,a
  388.                         ld b,0
  389.                         and a
  390.                         sbc hl,bc
  391.                         jr nc,fclose_f_one2
  392.                         ld hl,0 ;если было отрицательное
  393. fclose_f_one2
  394.                         ld (cat_buf+8*256+#e5),hl
  395.                        
  396.                         ld hl,cat_buf+8*256+#e4 ; общее количество файлов                 
  397.                         inc (hl)
  398.                        
  399.                         ld hl,cat_buf+8*256
  400.                         ld de,#0008
  401.                         ld bc,#0106 ;1 сектор записать
  402.                         call call3d13
  403.                         ret
  404.        
  405.        
  406. fclose_scl     
  407.         cp 4 ;если scl
  408.         jr nz,fclose_ex
  409.         ld hl,sec_buf ;
  410.         ld b,1
  411.         call scl_write_buf ;допишем остаток scl, если есть
  412.        
  413. fclose_ex      
  414.         xor a ;как бы закрываем все файлы
  415.         ld (f_r_flag),a
  416.         ld (f_w_flag),a
  417.         ;call restore_drive ;вернуть диск, какой был
  418.     ret
  419.  
  420.  
  421.  
  422.  
  423. ; A - file stream id
  424. ; BC - length
  425. ; HL - buffer
  426. ; Returns
  427. ;  BC - length(how much was actually read)
  428. fread: ;(id=1)
  429.     ; push hl : pop ix
  430.     ; esxCall ESX_FREAD
  431.         ; push af
  432.         ; ld a,4
  433.         ; out (254),a
  434. ; WAITKEY       XOR A:IN A,(#FE):CPL:AND #1F:JR Z,WAITKEY
  435.         ; xor a
  436.         ; out (254),a
  437.         ; pop af
  438.  
  439.         cp 1 ;id = 1?
  440.         jr nz,fread_no_chek ;выход если номер потока не = 1
  441.         ld a,(f_r_flag)
  442.         or a
  443.         jr nz,fread_chek ;файл уже открыт?
  444. fread_no_chek ;выход с ошибкой
  445.         xor a
  446.         scf ;флаг ошибки
  447.         ld bc,0 ;ничего мы не считали
  448.         ret
  449.        
  450. fread_chek
  451.         ld bc,(f_r_len_sec-1) ;загружаем файл целиком, не смотря на то, сколько байт было запрошено
  452.     ld      c,5 ;read читаем целыми секторами
  453.         ld de,(f_r_cur_trk)
  454.     call    call3d13   
  455.         ld bc,(f_r_len) ;возвратим сколько считали байт (длину файла)
  456.         xor a ;флаги сбросим
  457.     ret
  458.  
  459. ; A - file stream id
  460. ; BC - length
  461. ; HL - buffer
  462. ; Returns:
  463. ;   BC - actually written bytes
  464. fwrite: ;
  465.     ; push hl : pop ix
  466.     ; esxCall ESX_FWRITE
  467.        
  468.         ; push af
  469.         ; ld a,2
  470.         ; out (254),a
  471. ; WAITKEY1      XOR A:IN A,(#FE):CPL:AND #1F:JR Z,WAITKEY1
  472.         ; xor a
  473.         ; out (254),a
  474.         ; pop af
  475.  
  476.         cp 2 ;id = 2?
  477.         jr z,fwrite_chek ;проверка id потока
  478.         cp 3 ;id = 3?
  479.         jr z,fwrite_chek_trd ;проверка id потока
  480.         cp 4 ;id = 4?
  481.         jp z,fwrite_chek_scl ;проверка id потока
  482.  
  483.        
  484. fwrite_no_chek ;выход с ошибкой
  485.         xor a
  486.         scf ;флаг ошибки
  487.         ld bc,0 ;ничего мы не записали
  488.         ret
  489.        
  490. fwrite_chek ;запись произвольного типа файла (id=2)
  491.  
  492.         ;не отличается от записи trd, пишется входящий поток на диск, отличия при открытии и закрытии файла
  493.  
  494.  
  495.  
  496.  
  497.  
  498. fwrite_chek_trd ;запись trd файла (разворачивание образа, id=3)
  499.         ; ld a,2
  500.         ; out (254),a
  501. ; WAITKEY_t     XOR A:IN A,(#FE):CPL:AND #1F:JR Z,WAITKEY_t
  502.         ; xor a
  503.         ; out (254),a
  504.         ld a,(f_w_flag)
  505.         or a
  506.         jr z,fwrite_no_chek ;файл уже открыт?
  507.         ld (temp_bc),bc ;длина
  508.         ld (temp_hl),hl ;адрес данных
  509.         ld a,b
  510.         or c
  511.         jr z,fwrite_no_chek ; если длина 0, то выход
  512.        
  513.         ;защита от переполнения диска
  514.         ld de,(#5cf4)
  515.         ld a,d
  516.         cp #a0 ;последняя дорожка 160
  517.         jr nc,fwrite_no_chek
  518.        
  519.         xor a
  520.         ld (sec_part),a ;обнулить переменные
  521.         ld (sec_shift2),a
  522.         ld (sec_shift2+1),a
  523.         ld (sec_shift_flag),a
  524.         ld (write_end_flag),a ;
  525.        
  526.  
  527.         ld a,(sec_shift)
  528.         or a
  529.         jr z,fwrite_trd3 ;если смещения нет, то первую часть пропустим
  530.        
  531.  
  532.         ld c,a
  533.         ld b,0
  534.         ld hl,(temp_bc) ;проверка заполнится ли целый сектор
  535.         add hl,bc
  536.        
  537.         ld a,1
  538.         ld (write_end_flag),a ;флаг что не нужно дописывать остаток
  539.        
  540.         ld a,h
  541.         or a
  542.         jr nz,fwrite_trd4
  543.         ld a,1
  544.         ld (sec_shift_flag),a ;флаг что не заполнен сектор
  545.        
  546. fwrite_trd4    
  547.         ld hl,sec_buf ;буфер последнего сектора  
  548.         add hl,bc ;на этой точке остановились
  549.         ex de,hl
  550.         ld hl,(temp_hl) ;присоединим начало данных в конец предыдущих
  551.         ; ld a,c
  552.         ; or a
  553.         ; jr nz,fwrite_trd2
  554.         ; inc b ;коррекция
  555. ; fwrite_trd2          
  556.         ; ld c,a
  557.         xor a
  558.         sub c
  559.         ld c,a ;сколько осталось перенести до заполнения сектора
  560.         ld (sec_shift2),bc ;сохраним сколько добавили байт
  561.         ldir
  562.  
  563.         ld a,(sec_shift_flag)
  564.         or a
  565.         jr nz,fwrite_trd3 ;если сектор ещё не заполнен писать не будем
  566.  
  567.         ld hl,sec_buf
  568.         ld de,(#5cf4)
  569.         ;ld (f_w_cur_trk),de    ;запомним позицию
  570.     ld      bc,#0106 ;пишем 1 сектор из буфера
  571.     call    call3d13   
  572.         ld a,c
  573.         cp 255
  574.         jp z,fwrite_no_chek ;выход если ошибка  
  575.  
  576.         xor a
  577.         ld (write_end_flag),a ;флаг что нужно дописывать остаток  
  578.         ; ld de,(f_w_cur_trk) ;если сектор ещё не заполнен, останемся на старой позиции
  579.         ; ld (#5cf4),de
  580.         ; ld b,1 ;на сектор вперёд
  581.         ; ld de,(f_w_cur_trk)
  582.         ; call calc_next_pos
  583.         ; ld (f_w_cur_trk),de  
  584.  
  585. fwrite_trd3    
  586.         ld hl,(temp_hl) ;запишем остаток данных
  587.         ;ld a,(sec_shift)
  588.         ;ld c,a
  589.         ;ld b,0
  590.         ld bc,(sec_shift2)
  591.         add hl,bc ;с этой точки пишем
  592.         ld (temp_hl2),hl ;сохраним начало записи второго сектора
  593.        
  594.         ld hl,(temp_bc) ;вычисление на чём остановимся в этот раз
  595.         and a
  596.         sbc hl,bc ;вычтем то, что добавили к первому сектору
  597.         ld c,l
  598.         ld b,h
  599.         jr nc,fwrite_trd5
  600.         ld b,0 ;коррекция если вышел минус
  601. fwrite_trd5
  602.         ld hl,(temp_hl)
  603.         add hl,bc
  604.        
  605.         ld de,outputBuffer
  606.         and a
  607.         sbc hl,de
  608.        
  609.         ld a,l
  610.         ld (sec_shift),a ;смещение на следующий раз
  611.         ;ld hl,(temp_hl)       
  612.        
  613.  
  614.         ; or a
  615.         ; jr z,fwrite_trd1
  616.         ; inc b  ;коррекция количества секторов
  617.        
  618.         ld a,b ;нужна проверка на количество секторов!!!
  619.         ld (sec_part),a ;запомним сколько секторов во второй части
  620.        
  621.         ;ld a,b
  622.         or a
  623.         jr z,fwrite_trd1 ;если размер данных меньше сектора, то пропустим запись
  624.        
  625.         ld hl,(temp_hl2)
  626.         ;push bc
  627.         ld de,(#5cf4)
  628.     ld      c,6 ;пишем целыми секторами
  629.     call    call3d13   
  630.         ld a,c
  631.         ;pop bc
  632.         cp 255
  633.         jp z,fwrite_no_chek ;выход если ошибка
  634.         ; ld de,(f_w_cur_trk)
  635.         ; call calc_next_pos
  636.         ; ld (f_w_cur_trk),de
  637.        
  638.         xor a
  639.         ld (write_end_flag),a ;флаг что нужно дописывать остаток  
  640.        
  641. fwrite_trd1    
  642.         ld a,(write_end_flag) ;нужно записывать остаток?
  643.         or a
  644.         jr nz,fwrite_trd_ex ;не нужно
  645.  
  646.         ld hl,(temp_hl2) ;сохраним незаписанный остаток
  647.         ld a,(sec_part)
  648.         ld b,a
  649.         ld c,0
  650.         add hl,bc
  651.         ld de,sec_buf
  652.         ld bc,256
  653.         ldir
  654. ;fwrite_trd2   
  655.  
  656.        
  657. fwrite_trd_ex  
  658.         ld bc,(temp_bc) ;возвратим, что сколько запрашивали, столько и записали байт
  659.         ;посчитаем общую длину записанного
  660.         ld hl,(f_w_len)
  661.         add hl,bc
  662.         ld (f_w_len),hl
  663.         jr nc,fwrite_trd_ex1
  664.         ld hl,(f_w_len+2)
  665.         inc hl
  666.         ld (f_w_len+2),hl
  667.        
  668. fwrite_trd_ex1
  669.         xor a ;флаги сбросим
  670.     ret
  671.  
  672.  
  673.  
  674.  
  675.  
  676. ;------------------scl----------------------
  677. fwrite_chek_scl ;запись scl файла (разворачивание образа, id=4)
  678.         ; ld a,2
  679.         ; out (254),a
  680. ; WAITKEY_t     XOR A:IN A,(#FE):CPL:AND #1F:JR Z,WAITKEY_t
  681.         ; xor a
  682.         ; out (254),a
  683.         ld a,(f_w_flag)
  684.         or a
  685.         jp z,fwrite_no_chek ;файл уже открыт?
  686.         ld (temp_bc),bc ;длина
  687.         ld (temp_hl),hl ;адрес данных
  688.         ld a,b
  689.         or c
  690.         jp z,fwrite_no_chek ; если длина 0, то выход
  691.        
  692.         ; ld a,b
  693.         ; or a
  694.         ; jr nz,testt1
  695.         ; nop
  696.        
  697. ; testt1
  698.        
  699.         xor a
  700.         ld (sec_part),a ;обнулить переменные
  701.         ld (sec_shift2),a
  702.         ld (sec_shift2+1),a
  703.         ld (sec_shift_flag),a
  704.         ld (write_end_flag),a ;
  705.        
  706.  
  707.         ld a,(sec_shift)
  708.         or a
  709.         jr z,fwrite_scl3 ;если смещения нет, то первую часть пропустим
  710.        
  711.  
  712.         ld c,a
  713.         ld b,0
  714.         ld hl,(temp_bc) ;проверка заполнится ли целый сектор
  715.         add hl,bc
  716.        
  717.         ld a,1
  718.         ld (write_end_flag),a ;флаг что не нужно дописывать остаток
  719.        
  720.         ld a,h
  721.         or a
  722.         jr nz,fwrite_scl4
  723.         ld a,1
  724.         ld (sec_shift_flag),a ;флаг что не заполнен сектор
  725.        
  726. fwrite_scl4    
  727.         ld hl,sec_buf ;буфер последнего сектора  
  728.         add hl,bc ;на этой точке остановились
  729.         ex de,hl
  730.         ld hl,(temp_hl) ;присоединим начало данных в конец предыдущих
  731.         ; ld a,c
  732.         ; or a
  733.         ; jr nz,fwrite_scl2
  734.         ; inc b ;коррекция
  735. ; fwrite_scl2          
  736.         ; ld c,a
  737.         xor a
  738.         sub c
  739.         ld c,a ;сколько осталось перенести до заполнения сектора
  740.         ld (sec_shift2),bc ;сохраним сколько добавили байт
  741.         ldir
  742.  
  743.         ld a,(sec_shift_flag)
  744.         or a
  745.         jr nz,fwrite_scl3 ;если сектор ещё не заполнен писать не будем
  746.  
  747.         ld hl,sec_buf
  748.         ;ld de,(#5cf4)
  749.         ;ld (f_w_cur_trk),de    ;запомним позицию
  750.     ld      b,#01 ;пишем 1 сектор из буфера
  751.     call    scl_write_buf      
  752.         ; ld a,c
  753.         ; cp 255
  754.         ; jp z,fwrite_no_chek ;выход если ошибка
  755.  
  756.         xor a
  757.         ld (write_end_flag),a ;флаг что нужно дописывать остаток  
  758.         ; ld de,(f_w_cur_trk) ;если сектор ещё не заполнен, останемся на старой позиции
  759.         ; ld (#5cf4),de
  760.         ; ld b,1 ;на сектор вперёд
  761.         ; ld de,(f_w_cur_trk)
  762.         ; call calc_next_pos
  763.         ; ld (f_w_cur_trk),de  
  764.  
  765. fwrite_scl3    
  766.         ld hl,(temp_hl) ;запишем остаток данных
  767.         ;ld a,(sec_shift)
  768.         ;ld c,a
  769.         ;ld b,0
  770.         ld bc,(sec_shift2)
  771.         add hl,bc ;с этой точки пишем
  772.         ld (temp_hl2),hl ;сохраним начало записи второго сектора
  773.        
  774.         ld hl,(temp_bc) ;вычисление на чём остановимся в этот раз
  775.         and a
  776.         sbc hl,bc ;вычтем то, что добавили к первому сектору
  777.         ld c,l
  778.         ld b,h
  779.         jr nc,fwrite_scl5
  780.         ld b,0 ;коррекция если вышел минус
  781. fwrite_scl5
  782.         ld hl,(temp_hl)
  783.         add hl,bc
  784.        
  785.         ld de,outputBuffer
  786.         and a
  787.         sbc hl,de
  788.        
  789.         ld a,l
  790.         ld (sec_shift),a ;смещение на следующий раз
  791.         ;ld hl,(temp_hl)       
  792.        
  793.  
  794.         ; or a
  795.         ; jr z,fwrite_scl1
  796.         ; inc b  ;коррекция количества секторов
  797.        
  798.         ld a,b ;нужна проверка на количество секторов!!!
  799.         ld (sec_part),a ;запомним сколько секторов во второй части
  800.        
  801.         ;ld a,b
  802.         or a
  803.         jr z,fwrite_scl1 ;если размер данных меньше сектора, то пропустим запись
  804.        
  805.         ld hl,(temp_hl2)
  806.         ;push bc
  807.         ;ld de,(#5cf4)
  808.     ;ld      c,6 ;пишем целыми секторами
  809.     call    scl_write_buf      
  810.         ;ld a,c
  811.         ;pop bc
  812.         ; cp 255
  813.         ; jp z,fwrite_no_chek ;выход если ошибка
  814.         ; ld de,(f_w_cur_trk)
  815.         ; call calc_next_pos
  816.         ; ld (f_w_cur_trk),de
  817.        
  818.         xor a
  819.         ld (write_end_flag),a ;флаг что нужно дописывать остаток  
  820.        
  821. fwrite_scl1    
  822.         ld a,(write_end_flag) ;нужно записывать остаток?
  823.         or a
  824.         jr nz,fwrite_scl_ex ;не нужно
  825.  
  826.         ld hl,(temp_hl2) ;сохраним незаписанный остаток
  827.         ld a,(sec_part)
  828.         ld b,a
  829.         ld c,0
  830.         add hl,bc
  831.         ld de,sec_buf
  832.         ld bc,256
  833.         ldir
  834. ;fwrite_scl2   
  835.  
  836.        
  837. fwrite_scl_ex  
  838.         ld bc,(temp_bc) ;возвратим, что сколько запрашивали, столько и записали байт
  839.         ;посчитаем общую длину записанного
  840.         ld hl,(f_w_len)
  841.         add hl,bc
  842.         ld (f_w_len),hl
  843.         jr nc,fwrite_scl_ex1
  844.         ld hl,(f_w_len+2)
  845.         inc hl
  846.         ld (f_w_len+2),hl
  847.        
  848. fwrite_scl_ex1
  849.         xor a ;флаги сбросим
  850.     ret
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857. scl_write_buf ;заполнение промежуточного буфера
  858.         push bc ;сколько пакетов указано в b
  859.         ld de,scl_buf ;перенесём сектор во временный буфер
  860.         ld bc,256
  861.         ldir
  862.         ld (scl_temp_hl2),hl ;сохраним адрес данных
  863.         ld a,(scl_que) ;проверим флаг что нужны данные
  864.         or a
  865.         jr z,scl_write_buf_ret ;не будем вызывать парсер если не нужны
  866.         ld hl,scl_write_buf_ret ;адрес возврата
  867.         push hl
  868.         ld hl,(scl_parse_ret_adr) ;адрес для продолжения основного цикла сборки
  869.         jp (hl) ;отдадим пакет 256 байт парсеру
  870. scl_write_buf_ret
  871.         ld hl,(scl_temp_hl2)
  872.         pop bc
  873.         djnz scl_write_buf
  874.  
  875.         ret
  876.        
  877.        
  878.        
  879. scl_parse ;разбор образа scl в trd, основной цикл
  880.         ;получить первый сектор
  881. ;запрос порции данных по 256 байт
  882.         ld (scl_temp_hl),hl
  883.         ld (scl_temp_de),de
  884.         ld (scl_temp_bc),bc
  885.         ld a,1
  886.         ld (scl_que),a ;включим флаг что нужны данные
  887.         ld hl,scl_parse_ret ;сохраним адрес возврата
  888.         ld (scl_parse_ret_adr),hl
  889.         ret ;вернёмся для ожидания данных
  890. scl_parse_ret  
  891.         xor a
  892.         ld (scl_que),a
  893.         ld hl,(scl_temp_hl)
  894.         ld de,(scl_temp_de)
  895.         ld bc,(scl_temp_bc)
  896.        
  897.         ld de,scl_buf ;проверка метки образа
  898.         ld hl,scl_sign
  899.         ld b,8
  900. scl_parse_chk
  901.         ld a,(de)
  902.         cp (hl)
  903.         jr nz,scl_parse_chk_no
  904.         inc hl
  905.         inc de
  906.         djnz scl_parse_chk
  907.         jr scl_parse_chk_ok
  908. scl_parse_chk_no ;если не совпало, значит плохой образ
  909.     ld hl, scl_err
  910.     call DialogBox.msgBox ;предуреждение
  911.         xor a
  912.         ld (scl_que),a ;выключим флаг что нужны данные
  913.         ld a,4 ;закроем файл
  914.         call fclose
  915.         ret
  916. scl_parse_chk_ok ;сигнатура правильная
  917.  
  918. ;формирование каталога
  919.         ld a,(scl_buf+8)
  920.         ld (scl_files),a ;всего файлов
  921.         ld (scl_cat_cycl),a ;цикл
  922.         ld hl,scl_buf+9 ;адрес первого заголовка
  923.         ld de,cat_buf ;адрес формируемого каталога trd
  924. scl_parse_cat2 
  925.         ld b,14 ;14 байт одна запись
  926. scl_parse_cat  
  927.         ld a,(hl)
  928.         ld (de),a
  929.         inc de
  930.         inc l ;адрес увеличиваем только в пределах младшего регистра
  931.         jr nz,scl_parse_cat1
  932.         ;тут пора запросить следующий сектор
  933. ;запрос порции данных по 256 байт
  934.         ld (scl_temp_hl),hl
  935.         ld (scl_temp_de),de
  936.         ld (scl_temp_bc),bc
  937.         ld a,1
  938.         ld (scl_que),a ;включим флаг что нужны данные
  939.         ld hl,scl_parse_ret1 ;сохраним адрес возврата
  940.         ld (scl_parse_ret_adr),hl
  941.         ret ;вернёмся для ожидания данных
  942. scl_parse_ret1
  943.         xor a
  944.         ld (scl_que),a
  945.         ld hl,(scl_temp_hl)
  946.         ld de,(scl_temp_de)
  947.         ld bc,(scl_temp_bc)
  948.        
  949. scl_parse_cat1
  950.         djnz scl_parse_cat
  951.         inc de
  952.         inc de
  953.         ld a,(scl_cat_cycl)
  954.         dec a
  955.         ld (scl_cat_cycl),a
  956.         jr nz,scl_parse_cat2
  957.        
  958.         ld (scl_temp_hl),hl ;запомнить где остановились
  959.        
  960. ;подсчёт секторов и дорожек
  961.         push ix
  962.         ld a,(scl_files)
  963.         ld de,#0100 ;данные с первой дорожки
  964.         ld ix,cat_buf
  965.         ld (ix+14),e
  966.         ld (ix+15),d
  967.         ld hl,0 ;общее количество секторов
  968. scl_cacl
  969.         ld (scl_cat_cycl),a ;цикл
  970.         ld a,(ix+13) ;длина файла в секторах
  971.         ld c,a
  972.         ld b,0
  973.         add hl,bc ;секторов
  974.        
  975.         ld bc,16
  976.         add ix,bc
  977.         ld b,a
  978.         call calc_next_pos
  979.         ld a,(scl_cat_cycl)
  980.         cp 1
  981.         jr z,scl_cacl2 ;в последний раз пропусим
  982.         ld (ix+14),e
  983.         ld (ix+15),d
  984. scl_cacl2
  985.         dec a
  986.         jr nz,scl_cacl
  987.         ;теперь узнаем первый свободный сектор
  988.         ld a,(ix+13) ;длина файла в секторах
  989.         ld c,a
  990.         ld b,0
  991.         add hl,bc
  992.         ; ld b,a
  993.         ; call calc_next_pos
  994.         ld (cat_buf+8*256+#e1),de ;Первый свободный сектор и дорожка на дискете
  995.         ld de,16*159
  996.         ex de,hl
  997.         and a
  998.         sbc hl,de
  999.         ld (cat_buf+8*256+#e5),hl ;Число свободных секторов на диске
  1000.         pop ix
  1001.  
  1002.  
  1003.        
  1004. ;запись содержимого файлов
  1005.         ld a,(scl_files) ;всего файлов
  1006.         ld (scl_cat_cycl),a ;цикл
  1007.         ld hl,cat_buf+13 ;адрес размер секторов файла
  1008.         ld (cat_cur_adr),hl
  1009.  
  1010.         ld hl,#0100 ;начиная с первой дорожки
  1011.         ld (#5cf4),hl
  1012. scl_parse_file2
  1013.         ld hl,(scl_temp_hl) ;адрес данных
  1014.         ld de,(cat_cur_adr) ;адрес сектор дорожка файла
  1015.         ;dec de
  1016.         ld a,(de) ;количество секторов, цикл
  1017.         ld c,a
  1018. scl_parse_file3
  1019.         ld de,scl_buf2 ;адрес ещё одного буфера
  1020.         ld b,0 ;256 байт один сектор, цикл
  1021. scl_parse_file 
  1022.         ld a,(hl)
  1023.         ld (de),a
  1024.         inc de
  1025.         inc l ;адрес увеличиваем только в пределах младшего регистра
  1026.         jr nz,scl_parse_file1
  1027.         ;тут пора запросить следующий сектор
  1028. ;запрос порции данных по 256 байт
  1029.         ld (scl_temp_hl),hl
  1030.         ld (scl_temp_de),de
  1031.         ld (scl_temp_bc),bc
  1032.         ld a,1
  1033.         ld (scl_que),a ;включим флаг что нужны данные
  1034.         ld hl,scl_parse_ret2 ;сохраним адрес возврата
  1035.         ld (scl_parse_ret_adr),hl
  1036.         ret ;вернёмся для ожидания данных
  1037. scl_parse_ret2
  1038.         xor a
  1039.         ld (scl_que),a
  1040.         ld hl,(scl_temp_hl)
  1041.         ld de,(scl_temp_de)
  1042.         ld bc,(scl_temp_bc)
  1043.        
  1044. scl_parse_file1
  1045.         djnz scl_parse_file
  1046.         ld (scl_temp_hl),hl    
  1047.         ld (scl_temp_bc),bc
  1048.        
  1049.         ld hl,scl_buf2 ;;запишем один сектор
  1050.         ld  de,(#5cf4)
  1051.     ld      bc,#0106 ;
  1052.     call    call3d13   
  1053.         ; ld a,c
  1054.         ; cp 255
  1055.         ; jp z,fwrite_no_chek ;выход если ошибка
  1056.         ld hl,(scl_temp_hl)
  1057.         ld bc,(scl_temp_bc)
  1058.        
  1059.         dec c
  1060.         jr nz,scl_parse_file3
  1061.        
  1062.         ld hl,(cat_cur_adr) ;адрес сектор дорожка файла
  1063.         ; ld e,(hl)
  1064.         ; inc hl
  1065.         ; ld d,(hl)
  1066.         ld bc,16
  1067.         add hl,bc ;на следующий файл
  1068.         ld (cat_cur_adr),hl    
  1069.        
  1070.        
  1071.         ld a,(scl_cat_cycl)
  1072.         dec a
  1073.         ld (scl_cat_cycl),a
  1074.         jr nz,scl_parse_file2   ;на следующий файл
  1075.        
  1076.        
  1077.  
  1078. ;формирование системного сектора №9 (8)
  1079.         ;
  1080.         ;ld (cat_buf+8*256+#e1),a ;// #E1 Первый свободный сектор на дискете
  1081.         ;
  1082.         ;ld (cat_buf+8*256+#e2),a ;// #E2 Первый свободный трек
  1083.         ld a,#16
  1084.         ld (cat_buf+8*256+#e3),a ;// #E3 16 80 дорожек, 2 стороны
  1085.         ld a,(scl_files)
  1086.         ld (cat_buf+8*256+#e4),a ;// #E4 Общее количество файлов записанных на диск
  1087.         ;
  1088.         ;ld (cat_buf+8*256+#e5),a ;// #Е5,Е6 Число свободных секторов на диске
  1089.         ;ld (cat_buf+8*256+#e6),a
  1090.         ld a,#10
  1091.         ld (cat_buf+8*256+#e7),a ;// #E7 Код  #10,определяющий принадлежность к TR-DOS   
  1092.  
  1093.         ld hl,f_name ;запишем имя диска, взяв для этого имя файла
  1094.         ld de,cat_buf+8*256+#f5 ;// #F5-#FC Имя диска в ASCII формате
  1095.         ld bc,8
  1096.         ldir
  1097.        
  1098.         ld hl,cat_buf ;запишем каталог на диск
  1099.         ld de,0
  1100.     ld      bc,#0906 ;
  1101.     call    call3d13   
  1102.         ; ld a,c
  1103.         ; cp 255
  1104.         ; jp z,fwrite_no_chek ;выход если ошибка
  1105.         ret
  1106.  
  1107.  
  1108. ;-----------scl end --------------------
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.    
  1119. ; A - file stream id
  1120. ; fsync:
  1121. ;     esxCall ESX_FSYNC
  1122.     ; ret
  1123.  
  1124.  
  1125. ; HL - name (name.ext)
  1126. ; Returns:
  1127. ; HL - name (name    e)
  1128. format_name ;подгоняет имя файла под стандарт trdos (8+1)
  1129.  
  1130.         ;сначала попробуем убрать из пути подпапку, если она есть
  1131.         ld (temp_hl),hl ;сохраним адрес исходного имени
  1132.         ld b,#00 ;не больше 255 символов       
  1133. format_name5   
  1134.         ld a,(hl)
  1135.         cp "/" ;если есть подпапка
  1136.         jr z,format_name_path_yep
  1137.         ld a,(hl)
  1138.         cp "." ;если ещё не дошли до расширения
  1139.         jr nz,format_name6
  1140.         ld hl,(temp_hl) ;если дошли до расширения, то путей нет, вернёмся на начало имени
  1141.         jr format_name_7 ;на выход
  1142. format_name6
  1143.         inc hl
  1144.         djnz format_name5
  1145.        
  1146. format_name_path_yep ;нашли
  1147.         inc hl ;пропустим знак "/"
  1148.        
  1149. format_name_7  
  1150.  
  1151.  
  1152.         push hl ;очистим место для нового имени
  1153.         ld hl,f_name
  1154.         ld de,f_name+1
  1155.         ld (hl)," "
  1156.         ld bc,8
  1157.         ldir
  1158.         pop hl
  1159.  
  1160.         ld bc,#09ff ;длина имени 9 символов
  1161.         ld de,f_name ;куда
  1162. format_name2   
  1163.         ld a,(hl)
  1164.         cp "."
  1165.         jr nz,format_name1
  1166.         inc hl
  1167.         ld a,(hl)
  1168.         ld (f_name+8),a ; и в конце первую букву расширения
  1169.         ex de,hl ;сохраним адрес исходного расширения
  1170.         jr format_name_e
  1171. format_name1
  1172.         ldi
  1173.         djnz format_name2
  1174.        
  1175.         ;если имя длинное, пропустим лишнее до расширения
  1176.         ld b,#00 ;не больше 255 символов       
  1177. format_name3   
  1178.         ld a,(hl)
  1179.         cp "."
  1180.         jr nz,format_name4
  1181.         inc hl
  1182.         ld a,(hl)
  1183.         ld (f_name+8),a ; и в конце первую букву расширения
  1184.         ex de,hl ;сохраним адрес исходного расширения
  1185.         jr format_name_e
  1186. format_name4
  1187.         inc hl
  1188.         djnz format_name3
  1189.        
  1190. format_name_e ;выход
  1191.         ld hl,f_name ;вернём результат
  1192.         ret
  1193.  
  1194. ; DE - trk/sec
  1195. ; B - sectors step
  1196. ; Returns:
  1197. ; DE - trk/sec 
  1198. calc_next_pos           ;вперёд на N секторов  
  1199.                         ;ld b,4
  1200.                         ;ld  de,(#5ceb)
  1201. calc_next_pos2         
  1202.                         inc e
  1203.                         ld a,e
  1204.                         cp 16
  1205.                         jr c,calc_next_pos1
  1206.                         inc d
  1207.                         ld e,0
  1208. calc_next_pos1
  1209.                         ;ld (#5ceb),de
  1210.                         djnz calc_next_pos2
  1211.                         ret
  1212.                        
  1213.  
  1214. ;testt db "123.trd"
  1215. write_ima db "Select disk "
  1216. write_ima_d db "A: (A-D). "
  1217.                 db "All data may be lost! Press Y or N.",0
  1218. ;prev_drive db 0 ;предыдущий номер дисковода
  1219.                
  1220. trdExt1 db ".trd", 0
  1221. trdExt2 db ".TRD", 0
  1222.  
  1223. sclExt1 db ".scl", 0
  1224. sclExt2 db ".SCL", 0
  1225.  
  1226. f_name ds 16 ;имя файла
  1227. f_r_cur_trk dw   0 ;текущие сектор-дорожка файла на чтение
  1228. f_r_len_sec db 0 ;длина файла на чтение в секторах
  1229. f_r_len dw 0;длина файла в байтах
  1230. f_r_flag db 0 ;флаг что открыт файл на чтение
  1231.  
  1232. f_w_cur_trk dw   0 ;текущие сектор-дорожка файла на запись
  1233. f_w_len_sec db 0 ;длина файла на запись в секторах
  1234. f_w_flag db 0 ;флаг что открыт файл на запись
  1235. f_w_len ds 4 ;длина записанных данных
  1236. write_end_flag db 0 ;флаг что нужно записать остаток
  1237.  
  1238. temp_bc dw 0 ;хранение регистра
  1239. temp_hl dw 0 ;хранение регистра
  1240. temp_hl2 dw 0 ;хранение регистра
  1241.  
  1242. sec_shift db 0 ;указатель на каком байте остановлена запись
  1243. sec_shift2 db 0 ;указатель на каком байте остановлена запись (остаток)
  1244. sec_part db 0 ;сколько секторов во второй порции для записи
  1245. sec_shift_flag db 0 ;флаг что буфер сектора не заполнен
  1246.  
  1247. ;секция scl
  1248. scl_sign db "SINCLAIR" ;метка
  1249. scl_que db 0 ;флаг запроса порции данных
  1250. scl_err db "SCL image error!",0
  1251. scl_parse_ret_adr dw 0; адрес возврата в цикл
  1252. scl_cat_cycl db 0 ;переменная цикла
  1253. scl_files db 0 ;всего файлов
  1254. scl_temp_hl dw 0;;хранение регистра
  1255. scl_temp_hl2 dw 0;
  1256. scl_temp_de dw 0;
  1257. scl_temp_bc dw 0;
  1258. cat_cur_adr dw 0;
  1259. ;scl end
  1260.  
  1261. ;секция сохранения любого файла
  1262. file_err db "Not enough space!",0
  1263. sec_cat db 0 ;сектор каталога
  1264.  
  1265.         ;по адресу #4000 шрифт
  1266. cat_buf equ #4800 ;буфер для кататога диска 9*256
  1267. sec_buf equ cat_buf + 9*256 ;буфер сектора для записи 256
  1268. scl_buf equ sec_buf + 512 ;промежуточный буфер 256
  1269. scl_buf2 equ scl_buf + 512 ;промежуточный буфер 256
  1270.  
  1271.     ENDMODULE