CP/M R7 crc32:b89a7e16 added

This commit is contained in:
Роман Бойков 2026-02-20 13:25:57 +03:00
parent e54099e44a
commit 1f7e4e3ac9
17 changed files with 6866 additions and 0 deletions

View File

@ -0,0 +1,9 @@
{
"recommendations": [
"maziac.asm-code-lens",
"maziac.dezog",
"maziac.hex-hover-converter",
"maziac.z80-instruction-set",
"maziac.sna-fileviewer"
]
}

35
CPM_v2.2_r7_b89a7e16/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,35 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "make CPM (sjasmplus)",
"type": "shell",
"command": "sjasmplus",
"args": [
"--sld=cpm.sld",
"--sym=cpm.labels",
"--lstlab=sort",
"--lst=cpm.lst",
"--raw=cpm.obj",
"--fullpath",
"cpm.asm"
],
"problemMatcher": {
"owner": "sjasmplus",
"fileLocation": "autoDetect",
"pattern": {
"regexp": "^(.*)\\((\\d+)\\):\\s+(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"severity": 3,
"message": 4
}
},
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

Binary file not shown.

View File

@ -0,0 +1,12 @@
# Ocean-240.2 ROM Sources CP/M (V2.2) REL.7 checksum b89a7e16
Source codes of CP/M (V2.2) REL.7 version for Ocean-240.2 with Floppy controller.
In Z80 mnemonics, but limited for i8080 instruction set.
* 64k RAM Drive
## Compile
sjasmplus --sld=cpm.sld --sym=cpm.labels --raw=cpm.obj --fullpath cpm.asm
To compile sources, use [sjasmplus Z80 assembler](https://github.com/z00m128/sjasmplus).

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
; =======================================================
; Ocean-240.2
; CP/M BDOS Entries to build other depended modules
;
; By Romych 2025-09-09
; ======================================================
IFNDEF _BDOS
DEFINE _BDOS
MODULE BDOS
bdos_enter EQU 0xba06
bdos_no_outflag EQU 0xba09
bdos_strtcol EQU 0xba0a
bdos_column EQU 0xba0b
bdos_prnflag EQU 0xba0c
bdos_kbchar EQU 0xba0d
bdos_entrance EQU 0xc811
ENDMODULE
ENDIF

View File

@ -0,0 +1,668 @@
; =======================================================
; Ocean-240.2
;
; CP/M BIOS
;
; Disassembled by Romych 2025-09-09
; =======================================================
INCLUDE "equates.inc"
INCLUDE "ram.inc"
INCLUDE "mon_entries.inc"
IFNDEF BUILD_ROM
OUTPUT bios.bin
ENDIF
MODULE BIOS
ORG 0xD600
; -------------------------------------------------------
; BIOS JUMP TABLE
; -------------------------------------------------------
boot_f:
JP bios_boot
wboot_f:
JP bios_wboot
; -------------------------------------------------------
; console status to reg-a
; -------------------------------------------------------
const_f:
JP MON.mon_con_status
; -------------------------------------------------------
; console character to reg-a
; -------------------------------------------------------
conin_f:
JP MON.mon_con_in
; -------------------------------------------------------
; console character from c to console out
; -------------------------------------------------------
conout_f:
JP MON.mon_con_out
; -------------------------------------------------------
; list device out
; -------------------------------------------------------
list_f:
JP MON.mon_char_print
; -------------------------------------------------------
; punch device out
; -------------------------------------------------------
punch_f:
JP MON.mon_serial_out
; -------------------------------------------------------
; reader character in to reg-a
; -------------------------------------------------------
reader_f:
JP MON.mon_serial_in
; -------------------------------------------------------
; move to home position, treat as track 00 seek
; -------------------------------------------------------
home_f:
JP home
; -------------------------------------------------------
; select disk given by register c
; -------------------------------------------------------
seldsk_f:
JP sel_disk
settrk_f:
JP set_trk
setsec_f:
JP set_sec
; -------------------------------------------------------
; Set DMA address from BC
; -------------------------------------------------------
setdma_f:
JP set_dma
read_f:
JP read
write_f:
JP write
listst_f:
JP list_st
sectran_f:
JP sec_tran
; -------------------------------------------------------
; Reserved
; -------------------------------------------------------
JP warm_boot
JP warm_boot
; -------------------------------------------------------
; Tape read
; -------------------------------------------------------
tape_read_f:
JP MON.mon_tape_read
; -------------------------------------------------------
; Tape write
; -------------------------------------------------------
tape_write_f:
JP MON.mon_tape_write
; -------------------------------------------------------
; Tape wait block
; -------------------------------------------------------
tape_wait_f:
JP MON.mon_tape_wait
; -------------------------------------------------------
; cold start
; -------------------------------------------------------
bios_boot:
LD HL, (bdos_ent_addr) ; 0xba06
LD DE, 0x10000-CCP_RAM.bdos_enter_jump ; 0x45fa
ADD HL, DE ; 0xba06+0x45fa=10000
LD A, H
OR L
JP Z, bios_signon
; Init DMA buffer
LD HL, dma_buffer ; 0x8000
LD B, DMA_BUFF_SIZE ; 0x80
.init_dma_buff:
LD (HL), FILE_DELETED ; 0xE5
INC HL
DEC B
JP NZ, .init_dma_buff
; Init RAM disk
LD HL, dma_buffer
LD DE, 0x0000
LD B, 8
.init_ram_dsk:
PUSH BC
CALL MON.mon_ram_disk_write
POP BC
INC DE
DEC B
JP NZ, .init_ram_dsk
; Init user to 0 and drive to 0
XOR A
LD (cur_user_drv), A
bios_signon:
LD SP, bios_stack
; Print CP/M hello message
LD HL, msg_hello
CALL print_strz
; -------------------------------------------------------
; BIOS Warm start entry
; -------------------------------------------------------
bios_wboot:
LD SP, bios_stack
; Move CPP from 0xC000 to 0xB200
LD HL, CCP_DST_ADDR
LD DE, CCP_SRC_ADDR
LD BC, CCP_SIZE
.move_ccp:
LD A, (DE)
LD (HL), A
INC DE
INC HL
DEC BC
LD A, B
OR C
JP NZ, .move_ccp
; Init variables with zeroes
LD HL, CPM_VARS.cpm_vars_start
LD BC, CPM_VARS.ccp_vars_size ; 213
.clr_cpm_vars:
LD (HL), 0x0
INC HL
DEC BC
LD A, B
OR C
JP NZ, .clr_cpm_vars
LD A, FILE_DELETED
LD (CPM_VARS.bdos_efcb), A ; mark empty FCB
LD A, low dma_buffer ; 0x80
LD (CPM_VARS.bdos_dmaad), A ; 0x0080
; Move DPH + DPB to RAM
LD HL, CPM_VARS.DPH_RAM
LD DE, DPH_A
LD BC, DPB_END-DPH_A ; 78
.move_dph:
LD A, (DE)
LD (HL), A
INC HL
INC DE
DEC BC
LD A, B
OR C
JP NZ, .move_dph
LD BC, dma_buffer ; DMA default buffer addr
CALL setdma_f
; Setup JP to Warm boot after CPU reset
LD A, JP_OPCODE
LD (warm_boot), A
LD HL, wboot_f
LD (warm_boot_addr), HL
; Setup JP to BDOS entrance
LD (jp_bdos_enter), A
LD HL, CCP_RAM.bdos_enter_jump
LD (bdos_ent_addr), HL
XOR A
LD (CPM_VARS.slicer_has_data), A
LD (CPM_VARS.slicer_uninited_count), A
LD A, (cur_user_drv)
LD C, A
; go to CCP
JP CCP_DST_ADDR
list_st:
XOR A
RET
; -------------------------------------------------------
; Select disk
; Inp: C - disk,
; E - active drive flag
; Out: HL -> DPH
; -------------------------------------------------------
sel_disk:
LD A, C
LD (CPM_VARS.cur_disk), A
OR A
JP Z, .get_dph_addr ; skip next for disk 0 - RAM disk
LD A, E ; selected disk map
AND 0x1 ; bit 0 is set if disk already selected
JP NZ, .get_dph_addr
; Reset disk
LD (CPM_VARS.slicer_has_data), A
LD (CPM_VARS.slicer_uninited_count), A
; calc DPH address of new drive
.get_dph_addr:
LD L, C
LD H, 0x0
ADD HL, HL ; *2
ADD HL, HL ; *4
ADD HL, HL ; *8
ADD HL, HL ; *16 (size of DBH)
LD DE, CPM_VARS.DPH_RAM
ADD HL, DE
RET
; -------------------------------------------------------
; move to track 00
; -------------------------------------------------------
home:
LD A, (CPM_VARS.cur_disk)
OR A
JP Z, .is_default
LD A, (CPM_VARS.slicer_need_save)
OR A
JP NZ, .is_default
LD (CPM_VARS.slicer_has_data), A ; set to 0, no data
.is_default:
LD C, 0 ; set track to 0
; -------------------------------------------------------
; set track address (0..76) for subsequent read/write
; -------------------------------------------------------
set_trk:
LD HL, CPM_VARS.curr_track
LD (HL), C
RET
; -------------------------------------------------------
; set sector address (1,..., 26) for subsequent read/write
; -------------------------------------------------------
set_sec:
LD HL, CPM_VARS.curr_sec
LD (HL), C
RET
; -------------------------------------------------------
; set subsequent dma address (initially 80h)
; -------------------------------------------------------
set_dma:
LD L, C
LD H, B
LD (CPM_VARS.dma_addr), HL
RET
sec_tran:
LD L, C
LD H, B
RET
; -------------------------------------------------------
; read track/sector to preset dma address
; -------------------------------------------------------
read:
LD A, (CPM_VARS.cur_disk)
OR A
JP NZ,read_phys ; for physical disk use special routine
CALL ram_disk_calc_addr
CALL MON.mon_ram_disk_read
XOR A
RET
; -------------------------------------------------------
; write track/sector from preset dma address
; -------------------------------------------------------
write:
LD A, (CPM_VARS.cur_disk)
OR A
JP NZ,write_phys
CALL ram_disk_calc_addr
CALL MON.mon_ram_disk_write
XOR A
RET
; -------------------------------------------------------
; Calculate address for current sector and track
; -------------------------------------------------------
ram_disk_calc_addr:
LD HL, CPM_VARS.curr_track
; HL = cur_track * 16
LD L, (HL)
LD H, 0x0
ADD HL, HL
ADD HL, HL
ADD HL, HL
ADD HL, HL
; DE = HL + cur_sec
EX DE, HL
LD HL, CPM_VARS.curr_sec
LD L, (HL)
LD H, 0x0
ADD HL, DE
EX DE, HL
; store address
LD HL, (CPM_VARS.dma_addr)
RET
read_phys:
CALL read_phys_op
RET
write_phys:
CALL write_phys_op
RET
read_phys_op:
XOR A
; reset counter
LD (CPM_VARS.slicer_uninited_count), A
LD A, 0x1
LD (CPM_VARS.tmp_slicer_operation), A ; 0 - write; 1 - read
LD (CPM_VARS.tmp_slicer_can_read), A ; enable read fron disk
LD A, 0x2
LD (CPM_VARS.tmp_slicer_flush), A ; disable flush data to disk
JP base_read_write
write_phys_op:
XOR A
LD (CPM_VARS.tmp_slicer_operation), A
LD A, C
LD (CPM_VARS.tmp_slicer_flush), A
CP 0x2
JP NZ, .mode_ne_2
LD A, 0x10 ; 2048/128
LD (CPM_VARS.slicer_uninited_count), A
LD A, (CPM_VARS.cur_disk)
LD (CPM_VARS.slicer_uninited_disk), A
LD A, (CPM_VARS.curr_track)
LD (CPM_VARS.slicer_uninited_track), A
LD A, (CPM_VARS.curr_sec)
LD (CPM_VARS.slicer_uninited_sector_128), A
.mode_ne_2:
LD A, (CPM_VARS.slicer_uninited_count)
OR A
JP Z, slicer_read_write
DEC A
LD (CPM_VARS.slicer_uninited_count), A
LD A, (CPM_VARS.cur_disk)
LD HL, CPM_VARS.slicer_uninited_disk
CP (HL)
JP NZ, slicer_read_write
LD A, (CPM_VARS.curr_track)
LD HL, CPM_VARS.slicer_uninited_track
CP (HL)
JP NZ, slicer_read_write
LD A, (CPM_VARS.curr_sec)
LD HL, CPM_VARS.slicer_uninited_sector_128
CP (HL)
JP NZ, slicer_read_write
INC (HL)
LD A, (HL)
CP 36 ; Sectors per track
JP C, .no_inc_track
LD (HL), 0x0
LD A, (CPM_VARS.slicer_uninited_track)
INC A
LD (CPM_VARS.slicer_uninited_track), A
.no_inc_track:
XOR A
LD (CPM_VARS.tmp_slicer_can_read), A
JP base_read_write
slicer_read_write:
XOR A
LD (CPM_VARS.slicer_uninited_count), A
INC A
LD (CPM_VARS.tmp_slicer_can_read), A
base_read_write:
XOR A
LD (CPM_VARS.tmp_slicer_result), A
LD A, (CPM_VARS.curr_sec)
OR A
RRA
OR A
RRA
LD (CPM_VARS.tmp_slicer_real_sector), A
LD HL, CPM_VARS.slicer_has_data
LD A, (HL)
LD (HL), 0x1
OR A
JP Z, .no_data
LD A, (CPM_VARS.cur_disk)
LD HL, CPM_VARS.slicer_disk
CP (HL)
JP NZ, .pos_diff
LD A, (CPM_VARS.curr_track)
LD HL, CPM_VARS.slicer_track
CP (HL)
JP NZ, .pos_diff
LD A, (CPM_VARS.tmp_slicer_real_sector)
LD HL, CPM_VARS.slicer_real_sector
CP (HL)
JP Z,calc_sec_addr_in_bfr
.pos_diff:
LD A, (CPM_VARS.slicer_need_save)
OR A
CALL NZ, slicer_save_buffer ; save buffer if needed
.no_data:
LD A, (CPM_VARS.cur_disk)
LD (CPM_VARS.slicer_disk), A
LD A, (CPM_VARS.curr_track)
LD (CPM_VARS.slicer_track), A
LD A, (CPM_VARS.tmp_slicer_real_sector)
LD (CPM_VARS.slicer_real_sector), A
LD A, (CPM_VARS.tmp_slicer_can_read)
OR A
CALL NZ,slicer_read_buffer
XOR A
LD (CPM_VARS.slicer_need_save), A
calc_sec_addr_in_bfr:
LD A, (CPM_VARS.curr_sec)
AND 0x3
LD L, A
LD H, 0x0
ADD HL, HL
ADD HL, HL
ADD HL, HL
ADD HL, HL
ADD HL, HL
ADD HL, HL
ADD HL, HL ; *128
LD DE, CPM_VARS.slicer_buffer
ADD HL, DE
EX DE, HL
LD HL, (CPM_VARS.dma_addr)
LD C, 0x80
LD A, (CPM_VARS.tmp_slicer_operation)
OR A
JP NZ, .no_save
LD A, 0x1
LD (CPM_VARS.slicer_need_save), A
EX DE, HL
.no_save:
LD A, (DE)
INC DE
LD (HL), A
INC HL
DEC C
JP NZ, .no_save
LD A, (CPM_VARS.tmp_slicer_flush)
CP 0x1
LD A, (CPM_VARS.tmp_slicer_result)
RET NZ
OR A
RET NZ
XOR A
LD (CPM_VARS.slicer_need_save), A
CALL slicer_save_buffer
LD A, (CPM_VARS.tmp_slicer_result)
RET
slicer_save_buffer:
CALL slicer_get_floppy_args
LD C, 0xA4 ; VG93 CMD
CALL MON.mon_write_floppy
LD (CPM_VARS.tmp_slicer_result), A
RET
slicer_read_buffer:
CALL slicer_get_floppy_args
LD C, 0x84 ; VG93 CMD
CALL MON.mon_read_floppy
LD (CPM_VARS.tmp_slicer_result), A
RET
slicer_get_floppy_args:
LD HL, sector_128_interleave_b ; = 1h
LD A, (CPM_VARS.slicer_real_sector)
ADD A, L
LD L, A
LD E, (HL)
LD A, (CPM_VARS.slicer_track)
LD D, A
LD HL, CPM_VARS.slicer_buffer
LD A, (CPM_VARS.slicer_disk)
RET
sector_128_interleave_b:
DB 1, 8, 6, 4, 2, 9, 7, 5, 3
; -------------------------------------------------------
; Print zerro ended string
; Inp: HL -> string
; -------------------------------------------------------
print_strz:
LD A, (HL)
OR A
RET Z
LD C, A
PUSH HL
CALL conout_f
POP HL
INC HL
JP print_strz
msg_hello:
DB ASCII_ESC, "60" ; Режим 32x18 <ESC>60
DB ASCII_ESC, "8", 2 ; Выбор палтитры <ESC>82
DB ASCII_ESC, "42" ; Выбор цвета <ESC>42
DB "48K CP/M (V2.2) REL.7/2D\r\n64K RAM DISK (A:)\r\n180K FD (B:)\r\n", 0
; --------------------------------------------------
; Disk parameters headers in ROM
; --------------------------------------------------
; Disk A RAM
DPH_A:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
DW CPM_VARS.DIRBUFF ; Directory buffer pointer
DW CPM_VARS.DPB64K_RAM ; DPB Pointer
DW CPM_VARS.CHK_VEC_A ; Check Vector pointer
DW CPM_VARS.AL_MAP_A ; Allocation map pointer
; Disk B Floppy
DPH_B:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
DW CPM_VARS.DIRBUFF ; Directory buffer pointer
DW CPM_VARS.DPB360K_RAM ; DPB Pointer
DW CPM_VARS.CHK_VEC_B ; Check Vector pointer
DW CPM_VARS.AL_MAP_B ; Allocation map pointer
; Disk C Floppy
DPH_C:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
DW CPM_VARS.DIRBUFF ; Directory buffer pointer
DW CPM_VARS.DPB360K_RAM ; DPB Pointer
DW CPM_VARS.CHK_VEC_C ; Check Vector pointer
DW CPM_VARS.AL_MAP_C ; Allocation map pointer
; --------------------------------------------------
; Disk parameters blocks in ROM (DPBs)
; Tables of memory that describe the characteristics
; of discs on our system. There is one DPB for each
; disc type
; ----------------------------------------
; Block size | No of sectors | BSH | BLM |
; ----------------------------------------
; 1K | 8 | 3 | 7 |
; 2K | 16 | 4 | 15 |
; 4K | 32 | 5 | 31 |
; 8K | 64 | 6 | 63 |
; 16K | 128 | 7 | 127 |
; ----------------------------------------
; -------------------------------------
; Block size| Extent mask (EXM) |
; | Small disk | Large disk |
; -------------------------------------
; 2K | 1 | 0 |
; 4K | 3 | 1 |
; 8K | 7 | 3 |
; 16K | 15 | 7 |
; -------------------------------------
; CKS - number of dir sectors to check before write, 0 for HDD
; For RAM-Disk 128k
DPB_64K:
DW 0010h ; SPT Sector (128b) per track (16d)
DB 03h ; BSH 1k
DB 07h ; BLM 1k; Allocation block size = (BLM + 1) * 128 = 1k
DB 00h ; EXM extent mask
DW 003Fh ; DSM Disk size blocks - 1 (63d)
DW 001Fh ; DRM Dir elements - 1 (31d)
DB 10000000b ; AL0 Dir map byte 1
DB 00000000b ; AL1 Dir map byte 2
DW 0008h ; CKS checksum vector size (8 sectors=1k)
DW 0000h ; OFF (tracks reserved for system)
; For FLOPPY 360k
DPB_360K:
DW 0024h ; SPT Sector (128b) per track 36 * 128 = 18KB
DB 04h ; BSH 2k
DB 0Fh ; BLM 2k; Allocation block size = (BLM + 1) * 128 = 2k
DB 01h ; EXM extent mask
DW 00B3h ; DSM Disk size blocks - 1 (179d)
DW 003Fh ; DRM Directory entries - 1 (63d)
DB 10000000b ; AL0 Dir map byte 1
DB 00000000b ; AL1 Dir map byte 2
DW 0010h ; CKS checksum vector size (16 sectors = 2k)
DW 0000h ; OFF (No of tracks reserved for system)
DPB_END:
DB 4h ; reserved
; -------------------------------------------------------
; Filler to align blocks in ROM
; -------------------------------------------------------
LAST EQU $
CODE_SIZE EQU LAST-0xD600
FILL_SIZE EQU 0x400-CODE_SIZE
DISPLAY "| BIOS\t| ",/H,boot_f," | ",/H,CODE_SIZE," | ",/H,FILL_SIZE," |"
FILLER
DS FILL_SIZE, 0x00
ENDMODULE
IFNDEF BUILD_ROM
OUTEND
ENDIF

View File

@ -0,0 +1,39 @@
; =======================================================
; Ocean-240.2
; Definition of CPM BIOS entries to compile depended
; modules
;
; By Romych 2025-09-09
; ======================================================
IFNDEF _BIOS
DEFINE _BIOS
MODULE BIOS
boot_f EQU 0xD600
wboot_f EQU 0xD603
const_f EQU 0xD606
conin_f EQU 0xD609
conout_f EQU 0xD60C
list_f EQU 0xD60F
punch_f EQU 0xD612
reader_f EQU 0xD615
home_f EQU 0xD618
seldsk_f EQU 0xD61B
settrk_f EQU 0xD61E
setsec_f EQU 0xD621
setdma_f EQU 0xD624
read_f EQU 0xD627
write_f EQU 0xD62A
sectran_f EQU 0xD630
reserved_f1 EQU 0xD633
reserved_f2 EQU 0xD636
tape_read_f EQU 0xD639
tape_write_f EQU 0xD63C
tape_wait_f EQU 0xD63F
ENDMODULE
ENDIF

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,875 @@
; =======================================================
; 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 "DIR "
DB "READ "
DB "WRITE"
DB "EXIT "
; -------------------------------------------------------
; 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_COMMANDS_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_exit1
DW ccp_ret
ccp_ret:
LD HL, (CPM_VARS.saved_stack_ptr)
LD SP, HL
JP CCP_RAM.ccp_unk_cmd
ccp_exit1:
JP MON.mon_cold_start
; --------------------------------------------------
; 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_dsk_a3
LD DE, DEF_DISK_A_SIZE ; 63 blk
JP .calc_remanis_ds
.no_dsk_a3:
LD DE, DEF_DISK_B_SIZE ; 360 blk * 2k = 720k
; Disk size - Dir size = Free
.calc_remanis_ds:
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, 0x4
LD B, 0x0
.next_d:
LD E, 0x4
.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, 35
JP jp_bdos_enter
; -------------------------------------------------------
; Read data from Tape
; -------------------------------------------------------
ccp_read:
CALL BIOS.const_f
OR A
JP Z, .no_key ; chk key pressed
CALL BIOS.conin_f
JP ccp_read
.no_key:
CALL CCP_RAM.ccp_bdos_drv_allreset
CALL CCP_RAM.ccp_out_crlf
; wait tape block header
LD A, 100
CALL BIOS.tape_wait_f
OR A
JP NZ, key_pressed1
; try to load header 8 times
LD E, 8
.load8_cont:
LD HL, dma_buffer
CALL BIOS.tape_read_f
CP 0x4
JP Z, key_pressed1
OR A
JP Z, .hdr_id_chk
DEC E
JP NZ, .load8_cont
JP cp_load_err_what
; Check blk ID, will be 0x8000
.hdr_id_chk:
LD A, B
CP 0x80
JP NZ, .load8_cont
LD A, C
OR A
JP NZ, .load8_cont
; set end of file name strZ
XOR A
LD (dma_buffer+12), A
LD DE, dma_buffer
LD HL, CCP_RAM.ccp_inp_line ;= 2020h
LD (CCP_RAM.ccp_inp_line_addr), HL ;= B208h
.cp_name_char:
LD A, (DE)
OR A
JP Z, .name_copied
LD (HL), A ;= 2020h
INC HL
INC DE
JP .cp_name_char
.name_copied:
LD (HL), 0x0 ; mark end of strZ
CALL CCP_RAM.ccp_cv_first_to_fcb
JP NZ, CCP_RAM.print_syn_err
; Output file name to screen
LD HL, CCP_RAM.ccp_current_fcb_fn
LD B, 11
.name_output:
LD A, (HL)
AND 01111111b ; 7bit ASCII
LD C, A
CALL BIOS.conout_f
INC HL
DEC B
JP NZ, .name_output
; Out ' '
LD C, ' '
CALL BIOS.conout_f
CALL BIOS.conout_f
CALL BIOS.conout_f
CALL CCP_RAM.ccp_open_cur_fcb
JP Z, .recreate_f
LD HL,MSG_EX ;= "*EX* "
CALL ccp_out_str_z
LD HL, CCP_RAM.ccp_current_fcb_fn+8
; '$$$' at the end of buffer
LD A, '$'
LD (HL), A
INC HL
LD (HL), A
INC HL
LD (HL), A
; delete file if exists and create new
.recreate_f:
LD DE, CCP_RAM.ccp_current_fcb
PUSH DE
CALL CCP_RAM.ccp_bdos_era_file
POP DE
CALL CCP_RAM.ccp_bdos_make_f
JP Z, CCP_RAM.ccp_no_space ; out NO SPACE if err
XOR A
LD (CCP_RAM.ccp_current_fcb_fn+31), A
; Load block with ID=1
LD DE, 1
.fin_load:
LD HL, dma_buffer
PUSH DE
.blk_ld_rep:
CALL BIOS.tape_read_f
CP 4
JP Z, key_pressed2
OR A
JP Z, .blk_id_chk
LD A, (CCP_RAM.ccp_current_fcb_fn+31)
AND 0x7f
JP NZ, cp_read_cs
.blk_id_chk:
LD A, C
OR B
JP Z, .blk_ld_rep
; Check id for 0xFFFF - last blk
LD A, C
AND B
CP 0xff
JP Z, blk_id_last
; Check ID for DE
LD A, C
CP E
JP NZ, blk_ne_id
LD A, B
CP D
JP NZ, blk_ne_id
; Ok, write blk to disk
LD DE, dma_buffer
CALL CCP_RAM.ccp_bdos_dma_set
LD DE, CCP_RAM.ccp_current_fcb
CALL CCP_RAM.ccp_bdos_f_write
POP DE
JP NZ,ccp_del_f_no_space
INC DE
JP .fin_load
cp_load_err_what:
LD HL,msg_what ;= "WHAT?\a"
CALL ccp_out_str_z
JP load_restart
cp_read_cs:
POP BC
LD HL, msg_cs ;= "<CS "
CALL ccp_out_str_z
CALL ccp_cout_num
JP out_clos
blk_ne_id:
POP BC
LD HL, msg_sq ;= "<SQ "
CALL ccp_out_str_z
CALL ccp_cout_num
out_clos:
LD HL, msg_clos ;= ">\a"
CALL ccp_out_str_z
; cleanup partial file and load again
load_restart:
LD DE, CCP_RAM.ccp_current_fcb
CALL CCP_RAM.ccp_bdos_era_file
CALL CCP_RAM.cpp_set_disk_buff_addr
JP ccp_read
blk_id_last:
LD DE, CCP_RAM.ccp_current_fcb
CALL CCP_RAM.ccp_bdos_close_f
INC A
JP Z,ccp_del_f_no_space ; If no success, may be no disk space
CALL CCP_RAM.cpp_set_disk_buff_addr ; reset DMA buff
JP ccp_read ; and read next file
key_pressed2:
POP DE
PUSH BC
LD DE, CCP_RAM.ccp_current_fcb
CALL CCP_RAM.ccp_bdos_era_file
POP BC
LD A, C
AND 0x7f
CP CTRL_C
JP Z, ctrl_c_or_esc
CP ASCII_ESC
JP Z, ctrl_c_or_esc
LD HL, msg_break ;= "*BREAK*"
CALL ccp_out_str_z
JP ccp_read
key_pressed1:
LD A, C
AND 0x7f
CP CTRL_C
JP Z, ctrl_c
CP ASCII_ESC
JP NZ, ccp_read
ctrl_c:
CALL CCP_RAM.cpp_set_disk_buff_addr
JP CCP_RAM.ccp_cmdline_back
ctrl_c_or_esc:
CALL CCP_RAM.ccp_out_crlf
JP ctrl_c
msg_what:
DB "WHAT?\a",0
msg_cs:
DB "<CS ", 0
msg_sq:
DB "<SQ ", 0
msg_break:
DB "*BREAK*", 0
MSG_EX:
DB "*EX* ", 0
msg_clos:
DB ">\a", 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, 1500
.delay:
DEC BC
LD A, B
OR C
JP NZ, .delay
JP BIOS.tape_write_f
RET NC
; -------------------------------------------------------
; 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," |"
FILLER
DS FILL_SIZE, 0xFF
ENDMODULE
IFNDEF BUILD_ROM
OUTEND
ENDIF

View File

@ -0,0 +1,40 @@
; ======================================================
; Ocean-240.2
; CP/M Combine file. Includes all sources to build
; ROM 0xC000
;
; Disassembled by Romych 2025-09-09
; ======================================================
DEFINE BUILD_ROM
DEVICE NOSLOT64K
;
; |-----------|---------------|-----------|--------------------------------------|
; | OFFSET | SIZE | Module | Memory Address |
; |-----------|---------------|-----------|--------------------------------------|
; | 0x0000 | 2048 (0x800) | CCP_RAM | 0xC000..0xC7FF -> RAM 0xB200..0xB5FF |
; | 0x0800 | 3584 (0xE00) | BDOS | 0xC800.. |
; | 0x1600 | 1024 (0x400) | BIOS | 0xD600..D9FF |
; | 0x1B00 | 1280 (0x500) | CCP_ROM | 0xDB00..DFFF |
; |-----------|---------------|-----------|--------------------------------------|
;
DISPLAY "| Module | Offset | Size | Free |"
DISPLAY "|-------------|---------|--------|--------|"
OUTPUT cpm-C000.bin
INCLUDE "ccp_ram.asm"
INCLUDE "bdos.asm"
INCLUDE "bios.asm"
INCLUDE "cpm_fill_1.asm"
INCLUDE "ccp_rom.asm"
OUTEND
INCLUDE "cpm_vars.inc"
END

View File

@ -0,0 +1,24 @@
; =======================================================
; Ocean-240.2
;
; CPM filler, between BIOS and CCP_ROM
;
; By Romych 2025-09-09
; =======================================================
IFNDEF BUILD_ROM
OUTPUT ccp_fill_1.bin
ENDIF
MODULE CPM_FILL_1
ORG 0xda00
FILL1 DS 107, 0
FILL2 DB 0x7b
FILL3 DS 148, 0xff
ENDMODULE
IFNDEF BUILD_ROM
OUTEND
ENDIF

View File

@ -0,0 +1,228 @@
; =======================================================
; Ocean-240.2
; Module CPM - BIOS/BDOS/CPP variables
; RAM Range: 0xba09-0xbf00
;
; Disassembled by Romych 2025-09-09
; =======================================================
IFNDEF _CPM_VARS
DEFINE _CPM_VARS
MODULE CPM_VARS
ORG 0xba09
cpm_vars_start EQU $
; Filled by zeroes by BIOS at cold boot
; until ccp_vars_end
; Output disabel if non zero
bdos_no_outflag DS 1
bdos_strtcol DS 1
bdos_column DS 1
; Copy output to printer in non zero
bdos_prnflag DS 1
bdos_kbchar DS 1
; Stored user stack pointer on enter bdos fn
bdos_usersp DS 2 ; 0xba0e
; BDOS Stack
DS 48
bdos_stack EQU $
; -------------------------------------------------------
; Common values shared between bdosi and bdos
; -------------------------------------------------------
; current user number 0..15
bdos_userno DS 1 ; 0xba40
; current disk number
bdos_curdsk DS 1
; reg DE (pointer) value to call BDOS fn
bdos_info DS 2 ; 0xba42
; Address value to return
bdos_aret DS 2 ; 0xba44
; Empty FCB
bdos_efcb DS 1 ; 0xba46 = 0xE5 at init
; Read-only disks flag
bdos_rodsk DS 2 ; 0xba47
; Drive login vector
bdos_dlog DS 2 ; 0xba49
; Address of DMA buffer
bdos_dmaad DS 2 ; 0xba4b = 0x80 at init
bdos_cdrmax DS 2 ; 0xba4d
; Current track
bdos_curtrk DS 2 ; 0xba4f
; Current record (sector)
bdos_currec DS 2 ; 0xba51
; Address of user buffer
bdos_buffa DS 2 ; 0xba53
; Address of cur disk DPB
bdos_dpbaddr DS 2 ; 0xba55
; Calculated checksum
bdos_cksum DS 2 ; 0xba57
; Address of cur disk allocation map
bdos_alloca DS 2 ; 0xba59
; Sectors per track
dbos_sectpt DS 2 ; 0xba5b
bdos_blkshf DS 1 ; 0xba5d
bdos_blmsk DS 1 ; 0xba5e
bdos_extmsk DS 1 ; 0xba5f
; Max allocation number (disk size)
bdos_maxall DS 2 ; 0xba60
bdos_dirmax DS 2 ; 0xba62
; Size of directory
bdos_dirblk DS 2 ; 0xba64
bdos_alloc1 DS 2 ; 0xba66
; First track offset
bdos_offset DS 2 ; 0xba68
; Disk traslation vector address
bdos_tranv DS 2 ; 0xba6a
; Open and closed flag 0xff - closed
bdos_fcb_closed DS 1 ; 0xba6c
; Read file modified flag. 0xff - not allow read unwritten
bdos_rfm DS 1 ; 0xba6d
bdos_dirloc DS 1 ; 0xba6e
; File access mode (0=random, 1=sequential, 2=special)
bdos_seqio DS 1 ; 0xba6f
; Reg E value to call BDOS fn
bdos_linfo DS 1 ; 0xba70
bdos_dminx DS 1 ; 0xba71
; Length in bytes to match when search
bdos_searchl DS 1 ; 0xba72
; Address of buffer where to search
bdos_searcha DS 2 ; 0xba73
DS 2
; 0 - big disk (>255 blk), 0xff - small disk
bdos_small_disk DS 1 ; 0xba77
; Drive selected (0xff) by user specified FCB flag
bdos_resel DS 1 ; 0xba78
bdos_olddsk DS 1 ; 0xba79
; Saved disk of user FCB
bdos_fcbdsk DS 1 ; 0xba7a
; Number of records in extent
bdos_rcount DS 1 ; 0xba7b
bdos_extval DS 1 ; 0xba7c
; Record number to read
bdos_vrecord DS 2 ; 0xba7d
; Record to access
bdos_arecord DS 2 ; 0xba7f
bdos_arecord1 DS 2 ; 0xba81
bdos_dptr DS 1 ; 0xba83
bdos_dcnt DS 2 ; 0xba84
;bdos_dcnt_hi DS 1 ; 0xba85
bdos_drec DS 20 ; 0xba86
tmp_dir_total DS 2 ; 0xba9a
; Save pointer at ccp entry, restore on exit
saved_stack_ptr DS 2 ; 0xba9c
DS 22
ccp_safe_stack
DS 2 ; 0xbab4
; --------------------------------------------------
; FCB
; --------------------------------------------------
ccp_FCB
ccp_FCB_DR DS 1 ; 0xbab6 drive letter to write file
ccp_FCB_FN DS 8 ; 0xbab7 file name
ccp_FCB_FT DS 3 ; file type
cpp_FCB_EXT DS 1 ; extent
cpp_FCB_S1 DS 1
cpp_FCB_S2 DS 1 ; extent hi bits
cpp_FCB_RC DS 1
cpp_FCB_AL DS 16 ; Second half of FCB
ccp_FCB_CR DS 1 ; Current record
ccp_FCB_Rn DS 1 ; Random access record number
DS 2
DS 2
DS 2
ccp_vars_end EQU $
; --------------------------------------------------
; Disk parameters headers/blocks in RAM
; --------------------------------------------------
DPH_RAM DS 16, 0 ; 0xbade
DPH1_RAM DS 16, 0
DPH2_RAM DS 16, 0
DPB64K_RAM DS 15, 0 ; 0xbb0e
DPB360K_RAM DS 15, 0 ; 0xbb1d
; --------------------------------------------------
cur_disk DS 1 ; 0xbb2c
dma_addr DS 2 ; 0xbb2d
curr_track DS 1 ; 0xbb2f
curr_sec DS 1 ; 0xbb30
slicer_disk DS 1 ; 0xbb31
slicer_track DS 1 ; 0xbb32
slicer_real_sector
DS 1 ; 0xbb33
tmp_slicer_real_sector
DS 1 ; 0xbb34
slicer_has_data DS 1 ; 0xbb35
slicer_need_save
DS 1 ; 0xbb36
slicer_uninited_count
DS 1 ; 0xbb37
slicer_uninited_disk
DS 1 ; 0xbb38
slicer_uninited_track
DS 1 ; 0xbb39
slicer_uninited_sector_128
DS 1 ; 0xbb3a
tmp_slicer_result
DS 1 ; 0xbb3b
tmp_slicer_can_read
DS 1 ; 0xbb3c
tmp_slicer_operation
DS 1 ; 0xbb3d
tmp_slicer_flush
DS 1 ; 0xbb3e
; The directory buffer is an area used by the BDOS for directory operations.
; There is only one of these for the entire system.
DIRBUFF DS DIR_BUFF_SIZE ; 0xbb3f
; Allocation map for drive A (Mark used allocation blocks)
AL_MAP_A DS 31 ; 248 bit
; Check vector for drive A (Checksumm of dir entries, used to detect disk change)
CHK_VEC_A DS 16 ; 0xbbde
; Allocation map for drive B
AL_MAP_B DS 23 ; 184 bit
; Check vector for drive B
CHK_VEC_B DS 16 ; 0xbc05
; Allocation map for drive C
AL_MAP_C DS 23 ; 184 bit
; Check vector for drive C
CHK_VEC_C DS 16 ; 0xbc2c
DS 196
slicer_buffer DS 512 ; 0xbd00
cpm_vars_end EQU $
ccp_vars_size EQU ccp_vars_end-cpm_vars_start
cpm_vars_size EQU cpm_vars_end-cpm_vars_start
; check integrity of original ROM
ASSERT tmp_dir_total = 0xba9a
ASSERT saved_stack_ptr = 0xba9c
ASSERT ccp_FCB_FN = 0xbab7
ASSERT DPH_RAM = 0xbade
ASSERT slicer_uninited_count = 0xbb37
ASSERT slicer_buffer = 0xbd00
DISPLAY "| CCP_VARS\t| ",/H,cpm_vars_start," | ",/H,cpm_vars_size," |\t |"
ENDMODULE
ENDIF

View File

@ -0,0 +1,142 @@
; ======================================================
; Ocean-240.2
; Equates for all assembly sources
;
; By Romych 2025-09-09
; ======================================================
IFNDEF _EQUATES
DEFINE _EQUATES
ADDLIST EQU 0x08
ASCII_BS EQU 0x08
ASCII_TAB EQU 0x09
ASCII_LF EQU 0x0A
ASCII_FF EQU 0x0C
ASCII_CR EQU 0x0D
ASCII_CAN EQU 0x18
ASCII_EM EQU 0x19
ASCII_SUB EQU 0x1A ; CTRL-Z - end of text file marker
ASCII_ESC EQU 0x1B
ASCII_US EQU 0x1F
ASCII_SP EQU 0x20
; ------------------------------------------------------
BDOS_CTLC EQU 0x03
BDOS_NFUNCS EQU 0x29
BELL_CHAR EQU 0x07
BELL_PIN EQU 0x08
; ------------------------------------------------------
CCP_COMMAND_SIZE EQU 0x05
CCP_COMMANDS_COUNT EQU 0x04
CCP_COMMAND_CNT EQU 6
CCP_COMMAND_LEN EQU 4
CCP_SRC_ADDR EQU 0xc000
CCP_DST_ADDR EQU 0xb200
CCP_SIZE EQU 0x809
CPM_VERSION EQU 0x22 ; Version of CP/M as byte nibbles '2.2'
CTRL EQU 0x5E ; ^
CTRL_C EQU 0x03 ; Warm boot
CTRL_H EQU 0x08 ; Backspace
CTRL_E EQU 0x05 ; Move to beginning of new line (Physical EOL)
CTRL_J EQU 0x0A ; LF - Line Feed
CTRL_M EQU 0x0D ; CR - Carriage Return
CTRL_P EQU 0x10 ; turn on/off printer
CTRL_R EQU 0x12 ; Repeat current cmd line
CTRL_S EQU 0x13 ; Temporary stop display data to console (aka DC3)
CTRL_U EQU 0x15 ; Cancel (erase) current cmd line
CTRL_X EQU 0x18 ; Cancel (erase) current cmd line
; ------------------------------------------------------
DBPLIST EQU 0x0F
DEF_DISK_A_SIZE EQU 0x3F
DEF_DISK_B_SIZE EQU 0x0168
DSK_MAP EQU 0x10
DSK_MSK EQU 0x03
DSK_SHF EQU 0x02
DMA_BUFF_SIZE EQU 0x80
; ------------------------------------------------------
ENDDIR EQU 0xFFFF
ESC_CMD_END EQU 0x1A
;EXT_NUM EQU 12 ; Extent byte offset
; ------------------------------------------------------
FALSE EQU 0x00
FDC_DD80RB EQU 0x21
FDC_NOT_READY EQU 0x80
FDC_RESTORE_L EQU 0x08
FDC_SEEK_LV EQU 0x1C
FILE_DELETED EQU 0xE5
FWF_MASK EQU 0x80 ; File Write Flag mask
; ---------------------------------------------------
; FCB Offsets
; ---------------------------------------------------
FCB_LEN EQU 32 ; length of FCB
FCB_SHF EQU 5
FN_LEN EQU 12 ; Length of filename in FCB
FCB_DR EQU 0 ; Drive. 0 for default, 1-16 for A-P
FCB_FN EQU 1 ; Fn - Filename, 7-bit ASCII. The top bits - attributes
FCB_FT EQU 9 ; Filetype, 7-bit ASCII.
; T1' to T3' have the following
; T1' - Read-Only
; T2' - System (hidden)
; T3' - Archive
FCB_EXT EQU 12 ; EX - Set this to 0 when opening a file and then leave it to
; CP/M. You can rewind a file by setting EX, RC, S2 and CR to 0.
FCB_S1 EQU 13 ; S1 - Reserved.
FCB_S2 EQU 14 ; S2 - Reserved. Bit 7 - wile write flag, [6:0] module number (Extent hi bits)
FCB_RC EQU 15 ; RC - Set this to 0 when opening a file and then leave it to CP/M.
FCB_AL EQU 16 ; AL - Image of the second half of the directory entry,
; containing the file's allocation (which disc blocks it owns).
FCB_CR EQU 32 ; CR - Current record within extent. It is usually best to set
; this to 0 immediately after a file has been opened and
; then ignore it.
FCB_RN EQU 33 ; Rn - Random access record number. A 16-bit (with R2 used for overflow)
; ------------------------------------------------------
JP_OPCODE EQU 0xC3
; ------------------------------------------------------
KBD_ACK EQU 0x10
KBD_IRQ EQU 0x02
KEY_ALF EQU 0x0D
KEY_FIX EQU 0x15
; ------------------------------------------------------
LST_REC EQU 0x7F
; ------------------------------------------------------
MAX_EXT EQU 0x1F
MAX_MOD EQU 0x0F
;MOD_NUM EQU 0x0E
; ------------------------------------------------------
FCB_INFO_LEN EQU 15 ; length of FCB info bytes to match
;NXT_REC EQU 0x20
; ------------------------------------------------------
PIC_POLL_MODE EQU 0x0A
PORT_C4 EQU 0x10
PRINTER_ACK EQU 0x10
PRINTER_IRQ EQU 0x08
; ------------------------------------------------------
;RAN_REC EQU 0x21
;FCB_RC EQU 0x0F
DIR_BUFF_SIZE EQU 128
RO_FILE EQU 0x09
DEL_KEY EQU 0x7F
RX_READY EQU 0x02
; ------------------------------------------------------
TAPE_D EQU 0x08
TAPE_P EQU 0x04
TIMER_IRQ EQU 0x10
TL_HIGH EQU 0x05
TL_LOW EQU 0x03
TL_MID EQU 0x04
TMR0_SQWAVE EQU 0x36
TRUE EQU 0xFF
TX_READY EQU 0x01
; ------------------------------------------------------
;U_BYTES EQU 0x0D
ENDIF

132
CPM_v2.2_r7_b89a7e16/io.inc Normal file
View File

@ -0,0 +1,132 @@
; =======================================================
; Ocean-240.2
; Computer with FDC variant.
; IO Ports definitions
;
; By Romych 2025-09-09
; =======================================================
IFNDEF _IO_PORTS
DEFINE _IO_PORTS
; -------------------------------------------------------
; КР580ВВ55 DD79
; -------------------------------------------------------
; Port A - User port A
USR_DD79PA EQU 0x00
; Port B - User port B
USR_DD79PB EQU 0x01
; Port C - User port C
USR_DD79PC EQU 0x02
; Config: [1][ma1,ma0][0-aO|1-aI],[0-chO,1-chI],[mb],[0-bO|1-bI],[0-clO,1-clI]
; Set bit: [0][xxx][bbb][0|1]
USR_DD79CTR EQU 0x03
; -------------------------------------------------------
; КР1818ВГ93
; -------------------------------------------------------
; CMD
FDC_CMD EQU 0x20
; TRACK
FDC_TRACK EQU 0x21
; SECTOR
FDC_SECT EQU 0x22
; DATA
FDC_DATA EQU 0x23
;
FDC_WAIT EQU 0x24
; Controller port
FLOPPY EQU 0x25
; -------------------------------------------------------
; КР580ВВ55 DD78
; -------------------------------------------------------
; Port A - Keyboard Data
KBD_DD78PA EQU 0x40
; Port B - JST3,SHFT,CTRL,ACK,TAPE5,TAPE4,GK,GC
KBD_DD78PB EQU 0x41
; Port C - [PC7..0]
KBD_DD78PC EQU 0x42
; Сonfig: [1][ma1,ma0][0-aO|1-aI],[0-chO,1-chI],[mb],[0-bO|1-bI],[0-clO,1-clI]
; Set bit: [0][xxx][bbb][0|1];
KBD_DD78CTR EQU 0x43
; -------------------------------------------------------
; КР580ВИ53 DD70
; -------------------------------------------------------
; Counter 1
TMR_DD70C1 EQU 0x60
; Counter 2
TMR_DD70C2 EQU 0x61
; Counter 3
TMR_DD70C3 EQU 0x62
; Config: [sc1,sc0][rl1,rl0][m2,m1,m0][bcd]
; sc - timer, rl=01-LSB, 10-MSB, 11-LSB+MSB
; mode 000 - int on fin,
; 001 - one shot,
; x10 - rate gen,
; x11-sq wave
TMR_DD70CTR EQU 0x63
; Programable Interrupt controller PIC KR580VV59
PIC_DD75RS EQU 0x80
PIC_DD75RM EQU 0x81
; -------------------------------------------------------
; КР580ВВ51 DD72
; -------------------------------------------------------
; Data
UART_DD72RD EQU 0xA0
; [RST,RQ_RX,RST_ERR,PAUSE,RX_EN,RX_RDY,TX_RDY]
UART_DD72RR EQU 0xA1
; -------------------------------------------------------
; КР580ВВ55 DD17
; -------------------------------------------------------
; Port A - VShift[8..1]
SYS_DD17PA EQU 0xC0
; Port B - [ROM14,13][REST][ENROM-][A18,17,16][32k]
SYS_DD17PB EQU 0xC1
; Port C - HShift[HS5..1,SB3..1]
SYS_DD17PC EQU 0xC2
; Сonfig: [1][ma1,ma0][0-aO|1-aI],[0-chO,1-chI],[mb],[0-bO|1-bI],[0-clO,1-clI]
; Set bit: [0][xxx][bbb][0|1];
SYS_DD17CTR EQU 0xC3
; -------------------------------------------------------
; КР580ВВ55 DD67
; -------------------------------------------------------
; Port A - LPT Data
LPT_DD67PA EQU 0xE0
; Port B - [VSU,C/M,FL3..1,COL3..1]
VID_DD67PB EQU 0xE1
; Port C - [USER3..1,STB-LP,BELL,TAPE3..1]
DD67PC EQU 0xE2
; Сonfig: [1][ma1,ma0][0-aO|1-aI],[0-chO,1-chI],[mb],[0-bO|1-bI],[0-clO,1-clI]
; Set bit: [0][xxx][bbb][0|1];
DD67CTR EQU 0xE3
ENDIF

View File

@ -0,0 +1,35 @@
; ======================================================
; Ocean-240.2
;
; Monitor entries to compile CP/M modules
;
; By Romych 2025-09-09
; ======================================================
IFNDEF _MON_ENTRY
DEFINE _MON_ENTRY
MODULE MON
mon_init EQU 0xe000
mon_cold_start EQU 0xe003
mon_con_status EQU 0xe006
mon_con_in EQU 0xe009
mon_con_out EQU 0xe00c
mon_serial_in EQU 0xe00f
mon_serial_out EQU 0xe012
mon_char_print EQU 0xe015
mon_tape_read EQU 0xe018
mon_tape_write EQU 0xe01b
mon_ram_disk_read EQU 0xe01e
mon_ram_disk_write EQU 0xe021
mon_res_f1 EQU 0xe024
mon_res_f2 EQU 0xe027
mon_tape_wait EQU 0xe02a
mon_tape_detect EQU 0xe02d
mon_read_floppy EQU 0xe030
mon_write_floppy EQU 0xe033
ENDMODULE
ENDIF

View File

@ -0,0 +1,38 @@
; =======================================================
; Ocean-240.2
;
; RAM area at address: 0x0000 - 0x0100, used by CP/M and
; HW-Monitor
; By Romych 2026-02-03
; =======================================================
IFNDEF _RAM
DEFINE _RAM
MODULE RAM
@warm_boot EQU 0x0000 ; Jump warm_boot (Restart)
@warm_boot_addr EQU 0x0001 ; address of warm boot entry point
@iobyte EQU 0x0003 ; Input/Output mapping
@cur_user_drv EQU 0x0004 ; [7:4] - curent user, [3:0] - current drive
@jp_bdos_enter EQU 0x0005 ; Jump bdos (CALL 5 to make CP/M requests)
@bdos_ent_addr EQU 0x0006 ; addres of BDOS entry point
@bios_var1 EQU 0x0041
@bios_var2 EQU 0x0042
@bios_var3 EQU 0x0043
@fcb1 EQU 0x005c ; Default FCB, 16 bytes
@fcb2 EQU 0x006c
@dma_buffer EQU 0x0080 ; Default "DMA" 128 bytes buffer
@p_cmd_line_len EQU 0x0080 ; command line character count
@p_cmd_line EQU 0x0081 ; command line buffer
@fcb_ra_record_num EQU 0x00a1
@bios_stack EQU 0x0100
@tpa_start EQU 0x0100 ; start of program
@video_ram EQU 0x4000
ENDMODULE
ENDIF