mirror of
https://github.com/romychs/Ocean-240.2-Emulator.git
synced 2026-04-21 11:03:21 +03:00
883 lines
18 KiB
NASM
883 lines
18 KiB
NASM
; =======================================================
|
|
; Ocean-240.2
|
|
; CPM CPP, ROM PART
|
|
; AT 0xDB00
|
|
;
|
|
; Disassembled by Romych 2025-09-09
|
|
; =======================================================
|
|
|
|
INCLUDE "equates.inc"
|
|
INCLUDE "ram.inc"
|
|
|
|
IFNDEF BUILD_ROM
|
|
OUTPUT ccp_rom.bin
|
|
ENDIF
|
|
|
|
MODULE CCP_ROM
|
|
|
|
ORG 0xDB00
|
|
|
|
@ccp_entry:
|
|
LD HL, 0x0 ; prevent stack overflow
|
|
ADD HL, SP
|
|
LD (CPM_VARS.saved_stack_ptr), HL
|
|
LD SP, CPM_VARS.ccp_safe_stack
|
|
|
|
CALL get_cmd_index
|
|
LD HL, ccp_commands ;= DB6Ch
|
|
LD E, A
|
|
LD D, 0x0
|
|
ADD HL, DE
|
|
ADD HL, DE
|
|
LD A, (HL)
|
|
INC HL
|
|
LD H, (HL)
|
|
LD L, A
|
|
JP (HL) ; jump to command
|
|
|
|
ccp_commands_str:
|
|
DB "SDIR READ WRITE"
|
|
|
|
; -------------------------------------------------------
|
|
; Search user command position in available commands list
|
|
; -------------------------------------------------------
|
|
get_cmd_index:
|
|
LD HL, ccp_commands_str ; -> 'DIR'
|
|
LD C, 0x0
|
|
.cmd_next:
|
|
LD A, C
|
|
CP CCP_COMMAND_COUNT
|
|
RET NC
|
|
LD DE, CCP_RAM.ccp_current_fcb_fn
|
|
LD B, CCP_COMMAND_SIZE
|
|
.cmp_nxt:
|
|
LD A, (DE)
|
|
CP (HL) ; -> 'DIR'
|
|
JP NZ, .no_eq
|
|
INC DE
|
|
INC HL
|
|
DEC B
|
|
JP NZ, .cmp_nxt
|
|
LD A, (DE)
|
|
CP ASCII_SP
|
|
JP NZ, .inc_next
|
|
LD A, C
|
|
RET
|
|
.no_eq:
|
|
INC HL
|
|
DEC B
|
|
JP NZ, .no_eq
|
|
.inc_next:
|
|
INC C
|
|
JP .cmd_next
|
|
|
|
; --------------------------------------------------
|
|
; Command handlers ref table
|
|
; --------------------------------------------------
|
|
ccp_commands:
|
|
DW ccp_dir
|
|
DW ccp_read
|
|
DW ccp_write
|
|
DW ccp_ret ; r8
|
|
; DW ccp_exit1 ; r8
|
|
|
|
ccp_ret:
|
|
LD HL, (CPM_VARS.saved_stack_ptr)
|
|
LD SP, HL
|
|
JP CCP_RAM.ccp_unk_cmd
|
|
|
|
;ccp_exit1:
|
|
; JP MON.mon_hexb
|
|
; --------------------------------------------------
|
|
; DIR [filemask] command handler
|
|
; --------------------------------------------------
|
|
ccp_dir:
|
|
CALL CCP_RAM.ccp_cv_first_to_fcb
|
|
CALL CCP_RAM.ccp_drive_sel
|
|
; chech some filemask specified in command line
|
|
LD HL, CCP_RAM.ccp_current_fcb_fn
|
|
LD A, (HL)
|
|
CP ' '
|
|
JP NZ, .has_par
|
|
|
|
; no filemask, fill with wildcard '?'
|
|
LD B, 11
|
|
.fill_wildcard:
|
|
LD (HL), '?'
|
|
INC HL
|
|
DEC B
|
|
JP NZ, .fill_wildcard
|
|
|
|
; find file by specified mask
|
|
.has_par:
|
|
CALL CCP_RAM.ccp_find_first
|
|
JP NZ, .f_found
|
|
; no files found, print and exit
|
|
CALL CCP_RAM.ccp_out_no_file
|
|
JP CCP_RAM.ccp_cmdline_back
|
|
|
|
.f_found:
|
|
CALL CCP_RAM.ccp_out_crlf
|
|
LD HL, 0x0
|
|
LD (CPM_VARS.tmp_dir_total), HL
|
|
LD E, 0
|
|
|
|
.do_next_direntry:
|
|
PUSH DE
|
|
CALL CCP_RAM.ccp_find_first
|
|
POP DE
|
|
PUSH DE
|
|
|
|
; Find file with e number
|
|
.find_file_e:
|
|
DEC E
|
|
JP M, .file_out_next
|
|
PUSH DE
|
|
CALL CCP_RAM.ccp_bdos_find_next
|
|
POP DE
|
|
JP Z, .file_e_found
|
|
JP .find_file_e
|
|
|
|
.file_out_next:
|
|
LD A, (CCP_RAM.ccp_bdos_result_code)
|
|
; calc address of DIR entry in DMA buffer
|
|
; A[6:5] = A[1:0] = 32*A
|
|
RRCA ; [C] -> [7:0] -> [C]
|
|
RRCA ;
|
|
RRCA ;
|
|
AND 01100000b ; mask
|
|
LD C, A
|
|
PUSH BC
|
|
CALL CCP_RAM.ccp_out_crlf ; start new line
|
|
CALL CCP_RAM.ccp_bdos_drv_get
|
|
INC A
|
|
LD (dma_buffer), A ; disk
|
|
POP BC
|
|
LD B, 0x0
|
|
LD HL, dma_buffer+FCB_FN ; filename
|
|
LD E, L
|
|
LD D, H
|
|
ADD HL, BC
|
|
|
|
; copy filename to tmp FCB and out to screen
|
|
LD B, 0x1
|
|
.copy_next:
|
|
LD A, (HL)
|
|
LD (DE), A
|
|
LD C, A
|
|
CALL BIOS.conout_f
|
|
INC HL
|
|
INC DE
|
|
INC B
|
|
LD A, B
|
|
CP FN_LEN ; >12 end of name
|
|
JP C, .copy_next
|
|
|
|
.zero_up_36:
|
|
XOR A
|
|
LD (DE), A ; zero at end
|
|
INC B
|
|
LD A, B
|
|
CP 36
|
|
JP C, .zero_up_36
|
|
|
|
; calc file size for current entry
|
|
LD DE, dma_buffer
|
|
CALL cpp_bdos_f_size
|
|
LD HL, (fcb_ra_record_num) ; file size in blocks
|
|
|
|
; get disk blk size
|
|
LD A, (CPM_VARS.bdos_curdsk)
|
|
OR A
|
|
JP NZ, .no_dsk_a0
|
|
LD B, 3 ; for A - blk=3
|
|
JP .dsk_a0
|
|
|
|
.no_dsk_a0:
|
|
LD B, 4 ; for other disks - blk=4
|
|
.dsk_a0:
|
|
LD C, L
|
|
|
|
; convert 128b OS block to disk blocks
|
|
.mul_to_dsk_blk:
|
|
XOR A
|
|
LD A, H
|
|
RRA
|
|
LD H, A
|
|
LD A, L
|
|
RRA
|
|
LD L, A
|
|
DEC B
|
|
JP NZ, .mul_to_dsk_blk
|
|
; round up
|
|
LD A, (CPM_VARS.bdos_curdsk)
|
|
OR A
|
|
JP NZ, .no_dsk_a1
|
|
LD A, 00000111b ; for A - ~(~0 << 3)
|
|
JP .ds_skip1
|
|
.no_dsk_a1:
|
|
LD A, 00001111b ; for other dsk - ~(~0 << 4)
|
|
.ds_skip1:
|
|
AND C
|
|
JP Z, .cvt_blk_kb
|
|
INC HL
|
|
|
|
; Convert blocks to kilobytes (A-1k B-2k)
|
|
.cvt_blk_kb:
|
|
LD A, (CPM_VARS.bdos_curdsk)
|
|
OR A
|
|
JP Z, .ds_skip2
|
|
ADD HL, HL ; 2k
|
|
|
|
; add file size to total dir size
|
|
.ds_skip2:
|
|
EX DE, HL
|
|
LD HL, (CPM_VARS.tmp_dir_total)
|
|
ADD HL, DE
|
|
LD (CPM_VARS.tmp_dir_total), HL
|
|
|
|
; display size in K
|
|
LD C, ' '
|
|
CALL BIOS.conout_f
|
|
CALL BIOS.conout_f
|
|
CALL ccp_cout_num
|
|
LD C, 'K'
|
|
CALL BIOS.conout_f
|
|
CALL CCP_RAM.ccp_getkey_no_wait
|
|
JP NZ, CCP_RAM.ccp_cmdline_back
|
|
POP DE
|
|
INC E
|
|
JP .do_next_direntry
|
|
|
|
.file_e_found:
|
|
POP DE
|
|
LD HL, msg_free_space ;= "\r\nFREE SPACE "
|
|
|
|
; Out: FREE SPACE
|
|
CALL ccp_out_str_z
|
|
LD A, (CPM_VARS.bdos_curdsk)
|
|
OR A
|
|
JP NZ, .no_ram_dsk
|
|
LD HL, (BIOS.disk_a_size)
|
|
JP .calc_remanis_ds
|
|
|
|
.no_ram_dsk:
|
|
DEC A
|
|
LD HL, (BIOS.disk_b_size)
|
|
JP Z, .calc_remanis_ds
|
|
|
|
LD HL, (BIOS.disk_c_size)
|
|
LD A, (disk_sw_trk)
|
|
OR A
|
|
JP NZ, .calc_remanis_ds
|
|
|
|
LD A, H
|
|
CP 1
|
|
JP Z, .d720
|
|
LD HL, 360
|
|
JP .calc_remanis_ds
|
|
.d720:
|
|
LD HL, 720
|
|
|
|
; Disk size - Dir size = Free
|
|
.calc_remanis_ds:
|
|
EX DE, HL
|
|
LD HL, (CPM_VARS.tmp_dir_total)
|
|
LD A, E
|
|
SUB L
|
|
LD E, A
|
|
LD A, D
|
|
SBC A, H
|
|
LD D, A
|
|
CALL ccp_cout_num
|
|
LD C, 'K'
|
|
CALL BIOS.conout_f
|
|
CALL CCP_RAM.ccp_out_crlf
|
|
JP CCP_RAM.ccp_cmdline_back
|
|
|
|
msg_free_space:
|
|
DB "\r\nFREE SPACE ",0
|
|
|
|
ccp_cout_num:
|
|
LD A, D
|
|
AND 11100000b
|
|
JP Z, .less_224
|
|
LD C, '*'
|
|
CALL BIOS.conout_f
|
|
CALL BIOS.conout_f
|
|
CALL BIOS.conout_f
|
|
CALL BIOS.conout_f
|
|
RET
|
|
|
|
.less_224:
|
|
LD HL, 0x0
|
|
; copy number to BC
|
|
LD B, D
|
|
LD C, E
|
|
LD DE, 0x1
|
|
LD A, 13
|
|
|
|
.bc_rra:
|
|
PUSH AF
|
|
PUSH HL
|
|
; BC >> 1
|
|
LD A, B
|
|
RRA
|
|
LD B, A
|
|
LD A, C
|
|
RRA
|
|
LD C, A
|
|
JP NC, .bc_rra_ex
|
|
POP HL
|
|
CALL cpp_daa16
|
|
PUSH HL
|
|
|
|
.bc_rra_ex:
|
|
LD L, E
|
|
LD H, D
|
|
CALL cpp_daa16
|
|
EX DE, HL
|
|
POP HL
|
|
POP AF
|
|
DEC A
|
|
JP NZ, .bc_rra
|
|
LD D, 4
|
|
LD B, 0
|
|
|
|
.next_d:
|
|
LD E, 4
|
|
|
|
.next_e:
|
|
LD A, L
|
|
RLA
|
|
LD L, A
|
|
LD A, H
|
|
RLA
|
|
LD H, A
|
|
LD A, C
|
|
RLA
|
|
LD C, A
|
|
DEC E
|
|
JP NZ, .next_e
|
|
LD A, C
|
|
AND 0xf
|
|
ADD A, '0'
|
|
CP '0'
|
|
JP NZ, .no_zero
|
|
DEC B
|
|
INC B
|
|
JP NZ, .b_no_one
|
|
LD A, D
|
|
DEC A
|
|
JP Z, .d_one
|
|
LD A, ' '
|
|
JP .b_no_one
|
|
|
|
.d_one:
|
|
LD A, '0'
|
|
.no_zero:
|
|
LD B, 0x1
|
|
.b_no_one:
|
|
LD C, A
|
|
CALL BIOS.conout_f
|
|
DEC D
|
|
JP NZ, .next_d
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; ADD with correction HL=HL+DE
|
|
; -------------------------------------------------------
|
|
cpp_daa16:
|
|
LD A, L
|
|
ADD A, E
|
|
DAA
|
|
LD L, A
|
|
LD A, H
|
|
ADC A, D
|
|
DAA
|
|
LD H, A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Call BDOS function 35 (F_SIZE) - Compute file size
|
|
; -------------------------------------------------------
|
|
cpp_bdos_f_size:
|
|
LD C, F_SIZE
|
|
JP jp_bdos_enter
|
|
|
|
; -------------------------------------------------------
|
|
; Read Intel HEX data from serial port
|
|
; -------------------------------------------------------
|
|
ccp_read:
|
|
LD DE, msg_read_hex
|
|
CALL out_dollar_str
|
|
LD HL, 0x0
|
|
LD (CCP_RAM.hex_length), HL
|
|
|
|
; Wait for start of Intel HEX line
|
|
.wait_colon:
|
|
CALL MON.mon_serial_in
|
|
CP ':'
|
|
JP NZ, .wait_colon
|
|
|
|
; Init checksum
|
|
XOR A
|
|
LD D, A
|
|
|
|
CALL ser_read_hexb ; read byte_count
|
|
JP Z, .end_of_file
|
|
LD E, A
|
|
CALL ser_read_hexb ; read address hi
|
|
LD H, A
|
|
CALL ser_read_hexb ; read address lo
|
|
LD L, A ; HL - dst address
|
|
CALL ser_read_hexb ; read rec type
|
|
|
|
; calculate length += byte_count
|
|
PUSH HL
|
|
LD HL, (CCP_RAM.hex_length)
|
|
LD A, L
|
|
ADD A, E
|
|
LD L, A
|
|
LD A, H
|
|
ADC A, 0
|
|
LD H, A
|
|
LD (CCP_RAM.hex_length), HL
|
|
POP HL
|
|
|
|
LD C, E
|
|
|
|
; receive next E=byte_count bytes
|
|
.receive_rec:
|
|
CALL ser_read_hexb
|
|
LD (HL), A
|
|
INC HL
|
|
DEC E
|
|
JP NZ, .receive_rec
|
|
|
|
CALL ser_read_hexb ; receive checksum
|
|
JP NZ, .load_error ; jump if error
|
|
JP .wait_colon ; jump to wait next line
|
|
|
|
.end_of_file:
|
|
; read tail 4 bytes: 00 00 01 ff
|
|
CALL ser_read_hexb
|
|
CALL ser_read_hexb
|
|
CALL ser_read_hexb
|
|
CALL ser_read_hexb
|
|
JP Z, .load_complete
|
|
|
|
.load_error:
|
|
LD DE, .msg_error
|
|
JP out_dollar_str
|
|
|
|
.load_complete:
|
|
; Out message with length of received file
|
|
LD HL, (CCP_RAM.hex_length)
|
|
LD A, H
|
|
CALL MON.mon_hexb
|
|
LD A, L
|
|
CALL MON.mon_hexb
|
|
LD DE, .msg_bytes
|
|
CALL out_dollar_str
|
|
; Calculate number of pages
|
|
LD HL, (CCP_RAM.hex_length)
|
|
LD A, L
|
|
ADD A, 0xff
|
|
LD A, H
|
|
ADC A, 0x0
|
|
RLA
|
|
LD (CCP_RAM.hex_sectors), A
|
|
; Out message with number of pages
|
|
CALL MON.mon_hexb
|
|
LD DE, .msg_pages
|
|
CALL out_dollar_str
|
|
|
|
; Check for file name specified in cmd line
|
|
CALL CCP_RAM.ccp_cv_first_to_fcb
|
|
CALL CCP_RAM.ccp_drive_sel
|
|
LD A, (CCP_RAM.ccp_current_fcb_fn)
|
|
CP ASCII_SP
|
|
JP Z, .warm_boot
|
|
|
|
; Create file
|
|
LD DE, CCP_RAM.ccp_current_fcb
|
|
LD C, F_MAKE
|
|
CALL jp_bdos_enter
|
|
INC A
|
|
JP Z, .load_error
|
|
LD HL, tpa_start
|
|
LD (CCP_RAM.hex_buff), HL
|
|
|
|
.wr_sector:
|
|
; set source buffer address
|
|
LD HL, (CCP_RAM.hex_buff)
|
|
EX DE, HL
|
|
LD C, F_DMAOFF
|
|
CALL jp_bdos_enter
|
|
; write source buffer to disk
|
|
LD DE, CCP_RAM.ccp_current_fcb
|
|
LD C, F_WRITE
|
|
CALL jp_bdos_enter
|
|
; check errors
|
|
OR A
|
|
JP NZ, .load_error
|
|
|
|
; rewind forward to next sector
|
|
LD HL, (CCP_RAM.hex_buff)
|
|
LD DE, 128 ; sector size
|
|
ADD HL, DE
|
|
LD (CCP_RAM.hex_buff), HL
|
|
|
|
; decrement sector count
|
|
LD A, (CCP_RAM.hex_sectors)
|
|
DEC A
|
|
LD (CCP_RAM.hex_sectors), A
|
|
JP NZ, .wr_sector ; jump if remains sectors
|
|
|
|
; close file
|
|
LD DE, CCP_RAM.ccp_current_fcb
|
|
LD C, F_CLOSE
|
|
CALL jp_bdos_enter
|
|
; check errors
|
|
CP 0xff
|
|
JP Z, .load_error
|
|
|
|
.warm_boot:
|
|
LD C, P_TERMCPM
|
|
JP jp_bdos_enter
|
|
|
|
.msg_bytes:
|
|
DB "h bytes ($"
|
|
|
|
.msg_pages:
|
|
DB " pages)\n\r$"
|
|
|
|
.msg_error:
|
|
DB "error!\n\r$"
|
|
|
|
; ---------------------------------------------------
|
|
; Read next two symbols from serial and convert to
|
|
; byte
|
|
; Out: A - byte
|
|
; CF set if error
|
|
; ---------------------------------------------------
|
|
ser_read_hexb:
|
|
PUSH BC
|
|
CALL MON.mon_serial_in
|
|
CALL hex_to_nibble
|
|
RLCA
|
|
RLCA
|
|
RLCA
|
|
RLCA
|
|
LD C, A
|
|
CALL MON.mon_serial_in
|
|
CALL hex_to_nibble
|
|
OR C
|
|
LD C, A
|
|
ADD A, D
|
|
LD D, A
|
|
LD A, C
|
|
POP BC
|
|
RET
|
|
|
|
; ---------------------------------------------------
|
|
; Convert hex symbol to byte
|
|
; Inp: A - '0'..'F'
|
|
; Out: A - 0..15
|
|
; CF set if error
|
|
; ---------------------------------------------------
|
|
hex_to_nibble:
|
|
SUB '0' ; < '0' - error
|
|
RET C
|
|
ADD A, 233 ; F -> 255
|
|
RET C ; > F - error
|
|
ADD A, 6
|
|
JP P, .l1
|
|
ADD A, 7
|
|
RET C
|
|
.l1:
|
|
ADD A, 10
|
|
OR A
|
|
RET
|
|
|
|
; ---------------------------------------------------
|
|
; Out $ ended string
|
|
; Inp: DE -> string$
|
|
; ---------------------------------------------------
|
|
out_dollar_str:
|
|
LD C, C_WRITESTR
|
|
JP jp_bdos_enter
|
|
|
|
msg_read_hex:
|
|
DB "\n\rRead HEX from RS232... $"
|
|
|
|
filler1:
|
|
DS 62, 0
|
|
|
|
; -------------------------------------------------------
|
|
; Out zerro ended string
|
|
; In: HL -> strZ
|
|
; -------------------------------------------------------
|
|
ccp_out_str_z:
|
|
LD A, (HL)
|
|
OR A
|
|
RET Z
|
|
LD C, A
|
|
CALL BIOS.conout_f
|
|
INC HL
|
|
JP ccp_out_str_z
|
|
|
|
; -------------------------------------------------------
|
|
; Delete file and out No Space message
|
|
; -------------------------------------------------------
|
|
ccp_del_f_no_space:
|
|
LD DE, CCP_RAM.ccp_current_fcb
|
|
CALL CCP_RAM.ccp_bdos_era_file
|
|
JP CCP_RAM.ccp_no_space
|
|
|
|
; -------------------------------------------------------
|
|
; Read current file next block
|
|
; Out: A=0 - Ok, 0xFF - HW Error;
|
|
; -------------------------------------------------------
|
|
cpp_read_f_blk:
|
|
LD DE, CPM_VARS.ccp_fcb ; FCB here
|
|
JP CCP_RAM.ccp_bdos_read_f
|
|
|
|
ccp_write:
|
|
CALL CCP_RAM.ccp_cv_first_to_fcb
|
|
CALL CCP_RAM.ccp_drive_sel
|
|
LD HL, CCP_RAM.ccp_current_fcb_fn
|
|
LD A, (HL)
|
|
CP ' '
|
|
JP NZ, .find_f
|
|
LD B, 11
|
|
|
|
.fill_with_wc:
|
|
LD (HL), '?'
|
|
INC HL
|
|
DEC B
|
|
JP NZ, .fill_with_wc
|
|
|
|
.find_f:
|
|
CALL CCP_RAM.ccp_find_first
|
|
JP NZ, .found_f
|
|
CALL CCP_RAM.ccp_out_no_file
|
|
JP CCP_RAM.ccp_cmdline_back
|
|
|
|
.found_f:
|
|
LD E, 0 ; file counter
|
|
|
|
.do_next_f1:
|
|
PUSH DE
|
|
CALL CCP_RAM.ccp_find_first
|
|
POP DE
|
|
PUSH DE
|
|
|
|
.do_next_f2:
|
|
DEC E
|
|
JP M, .do_file
|
|
PUSH DE
|
|
CALL CCP_RAM.ccp_bdos_find_next
|
|
POP DE
|
|
JP Z, .no_more_f
|
|
JP .do_next_f2
|
|
|
|
.do_file:
|
|
POP BC
|
|
PUSH BC
|
|
LD A, C
|
|
OR A
|
|
JP Z, .calc_addr
|
|
LD DE, 1200
|
|
|
|
; Delay with key interrupt check
|
|
.delay_1:
|
|
XOR A
|
|
.delay_2:
|
|
DEC A
|
|
JP NZ, .delay_2
|
|
PUSH DE
|
|
CALL CCP_RAM.ccp_getkey_no_wait
|
|
POP DE
|
|
JP NZ, CCP_RAM.ccp_cmdline_back
|
|
DEC DE
|
|
LD A, D
|
|
OR E
|
|
JP NZ, .delay_1
|
|
|
|
.calc_addr:
|
|
LD A, (CCP_RAM.ccp_bdos_result_code)
|
|
; A=0-3 - for Ok, calc address of DIR entry in DMA buffer
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
AND 01100000b
|
|
LD C, A
|
|
PUSH BC
|
|
CALL CCP_RAM.ccp_out_crlf
|
|
CALL CCP_RAM.ccp_bdos_drv_get
|
|
INC A
|
|
LD (CPM_VARS.ccp_fcb_dr), A ; set drive number
|
|
POP BC
|
|
LD B, 0x0
|
|
LD HL, dma_buffer+1
|
|
ADD HL, BC
|
|
LD DE, CPM_VARS.ccp_fcb_fn
|
|
LD B, 0x1
|
|
|
|
.copy_fn:
|
|
LD A, (HL)
|
|
LD (DE), A
|
|
INC HL
|
|
INC DE
|
|
INC B
|
|
LD A, B
|
|
CP 12
|
|
JP C, .copy_fn
|
|
|
|
.fillz_fn:
|
|
XOR A
|
|
LD (DE), A
|
|
INC DE
|
|
INC B
|
|
LD A, B
|
|
CP 36
|
|
JP C, .fillz_fn
|
|
LD HL, CPM_VARS.ccp_fcb_fn
|
|
CALL ccp_out_str_z
|
|
LD HL, dma_buffer
|
|
|
|
; Empty first 128 bytes of DMA buffer
|
|
LD B, 128
|
|
.clear_buf:
|
|
LD (HL), 0x0
|
|
INC HL
|
|
DEC B
|
|
JP NZ, .clear_buf
|
|
|
|
; Copy file name at buffer start
|
|
LD HL, dma_buffer
|
|
LD DE, CPM_VARS.ccp_fcb_fn
|
|
LD B, 8
|
|
|
|
.find_sp:
|
|
LD A, (DE)
|
|
CP ' '
|
|
JP Z, .sp_rep_dot ; ' ' -> '.'
|
|
LD (HL), A
|
|
INC HL
|
|
INC DE
|
|
JP .find_sp
|
|
.sp_rep_dot:
|
|
LD (HL), '.'
|
|
INC HL
|
|
CALL CCP_RAM.ccp_find_no_space
|
|
|
|
.cont_copy_fn:
|
|
LD A, (DE)
|
|
LD (HL), A
|
|
OR A
|
|
JP Z, .end_copy
|
|
INC HL
|
|
INC DE
|
|
JP .cont_copy_fn
|
|
|
|
.end_copy:
|
|
LD DE, CPM_VARS.ccp_fcb
|
|
CALL CCP_RAM.ccp_bdos_open_f
|
|
LD DE, 0x8000 ; Block ID
|
|
LD HL, dma_buffer
|
|
CALL cpp_pause_tape_wr_blk
|
|
CALL cpp_pause_tape_wr_blk
|
|
LD DE, 0x1
|
|
|
|
; Read file block and write to Tape
|
|
.read_f_write_t:
|
|
PUSH DE
|
|
CALL cpp_read_f_blk
|
|
; a=0xff if error; a=1 - EOF
|
|
DEC A
|
|
JP Z, .eof
|
|
LD A, (CPM_VARS.ccp_fcb_cr)
|
|
AND 0x7f
|
|
CP 0x1
|
|
JP NZ, .write_once
|
|
; Write block to Tape with ID=0 twice
|
|
LD DE, 0x0 ; Block ID=0
|
|
LD HL, dma_buffer
|
|
CALL cpp_pause_tape_wr_blk
|
|
|
|
.write_once:
|
|
CALL CCP_RAM.ccp_getkey_no_wait
|
|
LD HL, dma_buffer
|
|
POP DE
|
|
JP NZ, CCP_RAM.ccp_cmdline_back
|
|
CALL cpp_pause_tape_wr_blk
|
|
; Inc Block ID and continue
|
|
INC DE
|
|
JP .read_f_write_t
|
|
|
|
.eof:
|
|
POP DE
|
|
EX DE, HL
|
|
LD (dma_buffer), HL
|
|
EX DE, HL
|
|
|
|
; Final block ID=0xFFFF
|
|
LD DE, 0xffff
|
|
; Write twice
|
|
CALL cpp_pause_tape_wr_blk
|
|
CALL cpp_pause_tape_wr_blk
|
|
POP DE
|
|
INC E
|
|
JP .do_next_f1
|
|
|
|
.no_more_f:
|
|
POP DE
|
|
CALL CCP_RAM.ccp_out_crlf
|
|
JP CCP_RAM.ccp_cmdline_back
|
|
|
|
; -------------------------------------------------------
|
|
; Write block to tape after pause
|
|
; -------------------------------------------------------
|
|
cpp_pause_tape_wr_blk:
|
|
LD BC, 3036
|
|
.delay:
|
|
DEC BC
|
|
LD A, B
|
|
OR C
|
|
JP NZ, .delay
|
|
JP BIOS.tape_write_f
|
|
|
|
DB 0x4c
|
|
|
|
; -------------------------------------------------------
|
|
; Filler to align blocks in ROM
|
|
; -------------------------------------------------------
|
|
LAST EQU $
|
|
CODE_SIZE EQU LAST-0xDB00
|
|
FILL_SIZE EQU 0x500-CODE_SIZE
|
|
|
|
DISPLAY "| CCP_ROM\t| ",/H,ccp_entry," | ",/H,CODE_SIZE," | ",/H,FILL_SIZE," |"
|
|
|
|
; Check integrity
|
|
ASSERT ccp_dir = 0xdb62
|
|
ASSERT ccp_dir.find_file_e = 0xdb97
|
|
ASSERT ccp_dir.file_out_next = 0xdba6
|
|
ASSERT ccp_dir.file_e_found = 0xdc3e
|
|
ASSERT ccp_dir.calc_remanis_ds = 0xdc72
|
|
ASSERT ccp_dir.no_ram_dsk = 0xdc52
|
|
ASSERT msg_free_space = 0xdc8a
|
|
ASSERT ccp_cout_num = 0xdc9a
|
|
|
|
FILLER
|
|
DS FILL_SIZE-1, 0xff
|
|
DB 0xaa
|
|
|
|
ENDMODULE
|
|
|
|
IFNDEF BUILD_ROM
|
|
OUTEND
|
|
ENDIF
|