3 CP/M, 3/MON, 1/Test source codes

This commit is contained in:
Роман Бойков 2026-02-16 16:08:13 +03:00
parent a9f138f77b
commit 97ca74577a
100 changed files with 47344 additions and 0 deletions

10
CPM_v2.2_r8_099942fc/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
*.labels
*.obj
*.OBJ
*.bin
*.tmp
tmp/
build/
*.lst
*.sld

View File

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

36
CPM_v2.2_r8_099942fc/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,36 @@
{
"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,11 @@
# Ocean-240.2 ROM Sources CP/M (V2.2) REL.8 checksum 099942fc
Source codes of CP/M (V2.2) REL.8 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,823 @@
; =======================================================
; 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.non_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
JP warm_boot ; r8
disk_a_size DW 0x0040 ; 64 disk A size
disk_b_size DW 0x02d0 ; 720 disk B size
disk_c_size DW 0x02d0 ; 720 disk C size
bios_var04 DB 0x50
bios_var05 DB 0x50
; -------------------------------------------------------
; 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
; >> r8
LD HL, (bios_var0) ; if bios_var0 = 0xaaaa (initialized)
LD DE, 0x5556
ADD HL, DE ; 0xaaaa+0x5556=0x10000 if initialized
LD A, H
OR L
JP Z, bios_signon ; if initialized, go to logon, skip init
; <<
; 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.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
; init bios variables
CALL bios_init_ilv ; r8
bios_signon:
LD SP, bios_stack
; Print CP/M hello message
LD HL, msg_hello
CALL print_strz
JP bios_wboot
;bios_wboot:
; LD SP, bios_stack
; r8 >>
bios_init_ilv:
LD HL, bios_var0
LD DE, bios_ini_vals
LD C, 13
CALL mov_dlhe_c
LD A, (bios_var05) ; 0x50
LD (bios_var2), A
RET
; <<
; -------------------------------------------------------
; BIOS Warm start entry
; -------------------------------------------------------
bios_wboot: ; r8
LD HL, (bios_var0)
LD DE, 0x5556 ; 0xaaaa + 0x5556 = 0x10000
ADD HL, DE
LD A, H
OR L
CALL NZ, bios_init_ilv ; init if not initialized before
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_disk_a
LD BC, DPB_END-dph_disk_a ; 0x39 -> 57d
.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
LD HL, CPM_VARS.DPB_A_RAM
LD C, 0xf
LD DE, dpb_ram
LD A, (disk_a_size+1)
OR A
JP Z, set_curr_dpb
LD DE, dpb_empty
set_curr_dpb:
CALL mov_dlhe_c
LD HL, CPM_VARS.DPB_B_RAM
LD C, 0xf
LD DE, dpb_flop_360k
LD A, (disk_b_size+1)
CP 0x1
JP Z, .l1
LD DE, dpb_flop_720k
.l1
CALL mov_dlhe_c
LD HL, CPM_VARS.DPB_C_RAM
LD C, 0xf
LD A, (disk_c_size+1)
CP 0x2
JP Z, .l2
LD DE, dpb_flop_360k
LD A, (bios_var3)
OR A
JP NZ, .l3
LD DE, dpb_flop_720k
JP .l3
.l2
LD DE, dpb_flop_720k
LD A, (bios_var3)
OR A
JP NZ, .l3
LD DE, dpb_flop_360k
.l3
CALL mov_dlhe_c
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
; -------------------------------------------------------
; Move C bytes from [DE] to [HL]
; -------------------------------------------------------
mov_dlhe_c:
LD A,(DE) ; [DE]->[HL]
LD (HL),A
INC HL
INC DE
DEC C
JP NZ, mov_dlhe_c
RET
list_st:
XOR A
RET
; -------------------------------------------------------
; Select disk
; Inp: C - disk,
; E - active drive flag
; Out: HL -> DPH
; -------------------------------------------------------
sel_disk:
LD HL, 0x00
LD A, C
CP CTRL_C
RET NC
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.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.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, 0xA6 ; VG93 CMD
CALL MON.write_floppy
LD (CPM_VARS.tmp_slicer_result), A
RET
; --------------------------------------------------
slicer_read_buffer:
CALL slicer_get_floppy_args
LD C, 0x86 ; VG93 CMD
CALL MON.read_floppy
LD (CPM_VARS.tmp_slicer_result), A
RET
; --------------------------------------------------
slicer_get_floppy_args:
LD HL, CPM_VARS.tmp_buff9
LD A, (CPM_VARS.slicer_disk)
DEC A
JP Z, .non_interleave
LD HL, interleave_0
.non_interleave
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
; -------------------------------------------------------
; 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, "83"
DB ASCII_ESC, "5!%"
DB ASCII_ESC, "41"
DB ASCII_ESC, "1", 0x16, 0xe2, 0xe2, 0xfc, 0x01
DB ASCII_ESC, "40"
DB ASCII_ESC, "1", 0x1e, 0xe6, 0xdb, 0xf8, 0x01
DB ASCII_ESC, "43"
DB "OKEAH-240 CP/M (V2.2) REL.8 \r\n\n"
DB ASCII_ESC, "42", 0
; --------------------------------------------------
; 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 64k
dpb_ram:
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)
dpb_empty:
DS 15, 0xff
; For FLOPPY 720k
dpb_flop_720k:
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 00h ; EXM extent mask
DW 359 ; DSM Disk size blocks - 1 (359d)
DW 127 ; DRM Directory entries - 1 (127d)
DB 11000000b ; AL0 Dir map byte 1 (2 dir blk)
DB 00000000b ; AL1 Dir map byte 2
DW 32 ; CKS checksum vector size (32 sectors = 2k)
DW 0000h ; OFF (No of tracks reserved for system)
; For FLOPPY 360k
dpb_flop_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 179 ; DSM Disk size blocks - 1 (179d)
DW 127 ; DRM Directory entries - 1 (127d)
DB 11000000b ; AL0 Dir map byte 1 (2 dir blk)
DB 00000000b ; AL1 Dir map byte 2
DW 32 ; CKS checksum vector size (32 sectors = 2k)
DW 0000h ; OFF (No of tracks reserved for system)
bios_ini_vals:
DB 0xaa, 0xaa, 0, 0xff, 1, 8, 6, 4, 2, 9, 7, 5, 3
; --------------------------------------------------
; Disk parameters headers in ROM
; --------------------------------------------------
; Disk A RAM
dph_disk_a:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
; 0xda00
DW CPM_VARS.dir_buffer ; Directory buffer pointer
DW CPM_VARS.DPB_A_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_disk_b:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
DW CPM_VARS.dir_buffer ; Directory buffer pointer
DW CPM_VARS.DPB_B_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_disk_c:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
DW CPM_VARS.dir_buffer ; Directory buffer pointer
DW CPM_VARS.DPB_C_RAM ; DPB Pointer
DW CPM_VARS.CHK_VEC_C ; Check Vector pointer
DW CPM_VARS.AL_MAP_C ; Allocation map pointer
res_data: ; 0xda28
DB 1,8,6,4,2,9,7,5,3
DPB_END EQU $
DB 0x0e, 3
; -------------------------------------------------------
; Filler to align blocks in ROM
; -------------------------------------------------------
LAST EQU $
CODE_SIZE EQU LAST-0xD600
FILL_SIZE EQU 0x500-CODE_SIZE
DISPLAY "| BIOS\t| ",/H,boot_f," | ",/H,CODE_SIZE," | ",/H,FILL_SIZE," |"
; Check integrity
ASSERT bios_wboot = 0xd6a8
ASSERT set_curr_dpb = 0xd722
ASSERT sel_disk = 0xd781
ASSERT home = 0xd7a7
ASSERT ram_disk_calc_addr = 0xd7eb
ASSERT write_phys_op = 0xd81e
ASSERT base_read_write = 0xd88a
ASSERT calc_sec_addr_in_bfr = 0xd8e4
ASSERT slicer_save_buffer = 0xd928
ASSERT print_strz = 0xd95e
ASSERT msg_hello = 0xd96b
ASSERT dpb_ram = 0xd9af
ASSERT dph_disk_a = 0xd9f8
ASSERT res_data = 0xda28
FILLER:
DS FILL_SIZE, 0xff
ENDMODULE
IFNDEF BUILD_ROM
OUTEND
ENDIF

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,901 @@
; =======================================================
; 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_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_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, (bios_var3)
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, 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, 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

View File

@ -0,0 +1,44 @@
; ======================================================
; 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
;LABELSLIST "cpm.labels"
;CSPECTMAP "cpm.map"
INCLUDE "ccp_ram.asm"
INCLUDE "bdos.asm"
INCLUDE "bios.asm"
INCLUDE "ccp_rom.asm"
OUTEND
OUTPUT variables.bin
INCLUDE "cpm_vars.inc"
OUTEND
END

View File

@ -0,0 +1,219 @@
; =======================================================
; Ocean-240.2
; Module CPM_VARS - 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 DB 0
bdos_strtcol DB 0
bdos_column DB 0
; Copy output to printer in non zero
bdos_prnflag DB 0
bdos_kbchar DB 0
; Stored user stack pointer on enter bdos fn
bdos_usersp DW 0 ; 0xba0e
; BDOS Stack
DS 48, 0
bdos_stack EQU $
; -------------------------------------------------------
; Common values shared between bdosi and bdos
; -------------------------------------------------------
; current user number 0..15
bdos_userno DB 0x00 ; 0xba40
; current disk number
bdos_curdsk DB 0x00
; reg DE (pointer) value to call BDOS fn
bdos_info DW 0x0000 ; 0xba42
; Address value to return
bdos_aret DW 0x0000 ; 0xba44
; Empty FCB
bdos_efcb DB 0x00 ; 0xba46 = 0xE5 at init
; Read-only disks flag
bdos_rodsk DW 0x0000 ; 0xba47
; Drive login vector
bdos_dlog DW 0x0000 ; 0xba49
; Address of DMA buffer
bdos_dmaad DW 0x0000 ; 0xba4b = 0x80 at init
bdos_cdrmax DW 0x0000 ; 0xba4d
; Current track
bdos_curtrk DW 0x0000 ; 0xba4f
; Current record (sector)
bdos_currec DW 0x0000 ; 0xba51
; Address of user buffer
bdos_buffa DW 0x0000 ; 0xba53
; Address of cur disk DPB
bdos_dpbaddr DW 0x0000 ; 0xba55
; Calculated checksum
bdos_cksum DW 0x0000 ; 0xba57
; Address of cur disk allocation map
bdos_alloca DW 0x0000 ; 0xba59
; Sectors per track
dbos_sectpt DW 0x0000 ; 0xba5b
bdos_blkshf DB 0x00 ; 0xba5d
bdos_blmsk DB 0x00 ; 0xba5e
bdos_extmsk DB 0x00 ; 0xba5f
; Max allocation number (disk size)
bdos_maxall DW 0x0000 ; 0xba60
bdos_dirmax DW 0x0000 ; 0xba62
; Size of directory
bdos_dirblk DW 0x0000 ; 0xba64
bdos_alloc1 DW 0x0000 ; 0xba66
; First track offset
bdos_offset DW 0x0000 ; 0xba68
; Disk traslation vector address
bdos_tranv DW 0x0000 ; 0xba6a
; Open and closed flag 0xff - closed
bdos_fcb_closed DB 0x00 ; 0xba6c
; Read file modified flag. 0xff - not allow read unwritten
bdos_rfm DB 0x00 ; 0xba6d
bdos_dirloc DB 0x00 ; 0xba6e
; File access mode (0=random, 1=sequential, 2=special)
bdos_seqio DB 0x00 ; 0xba6f
; Reg E value to call BDOS fn
bdos_linfo DB 0x00 ; 0xba70
bdos_dminx DB 0x00 ; 0xba71
; Length in bytes to match when search
bdos_searchl DB 0x00 ; 0xba72
; Address of buffer where to search
bdos_searcha DW 0x0000 ; 0xba73
DW 0x0000
; 0 - big disk (>255 blk), 0xff - small disk
bdos_small_disk DB 0x00 ; 0xba77
; Drive selected (0xff) by user specified FCB flag
bdos_resel DB 0x00 ; 0xba78
bdos_olddsk DB 0x00 ; 0xba79
; Saved disk of user FCB
bdos_fcbdsk DB 0x00 ; 0xba7a
; Number of records in extent
bdos_rcount DB 0x00 ; 0xba7b
bdos_extval DB 0x00 ; 0xba7c
; Record number to read
bdos_vrecord DW 0x0000 ; 0xba7d
; Record to access
bdos_arecord DW 0x0000 ; 0xba7f
bdos_arecord1 DW 0x0000 ; 0xba81
bdos_dptr DB 0x00 ; 0xba83
bdos_dcnt DW 0x00 ; 0xba84
bdos_drec DS 20, 0x00 ; 0xba86
tmp_dir_total DW 0x0000 ; 0xba9a
; Save pointer at ccp entry, restore on exit
saved_stack_ptr DW 0x0000 ; 0xba9c
DS 22, 0
ccp_safe_stack
DW 0x0000 ; 0xbab4
; --------------------------------------------------
; FCB
; --------------------------------------------------
ccp_fcb
ccp_fcb_dr DB 0 ; 0xbab6 drive letter to write file
ccp_fcb_fn DS 8,0 ; 0xbab7 file name
ccp_fcb_ft DS 3,0 ; file type
ccp_fcb_ext DB 0 ; extent
ccp_fcb_s1 DB 0
ccp_fcb_s2 DB 0 ; extent hi bits
ccp_fcb_rc DB 0
ccp_fcb_al DS 16, 0 ; Second half of FCB
ccp_fcb_cr DB 0x00 ; Current record
ccp_fcb_rn DB 0x00 ; Random access record number
DW 0x00
DW 0x00
DW 0x00
ccp_vars_end EQU $
; --------------------------------------------------
; Disk parameters headers/blocks in RAM
; --------------------------------------------------
DPH_RAM DS 16, 0 ; 0xbade
DPH1_RAM DS 16, 0 ; 0xbaee
DPH2_RAM DS 16, 0 ; 0xbafe
tmp_buff9 DS 9, 0
DPB_A_RAM DS 15, 0 ; 0xbb17
DPB_B_RAM DS 15, 0 ; 0xbb26
DPB_C_RAM DS 15, 0 ; 0xbb35
; --------------------------------------------------
cur_disk DB 0x00 ; 0xbb44
dma_addr DW 0x0000 ; 0xbb46
curr_track DB 0x00 ; 0xbb47
curr_sec DB 0x00 ; 0xbb48
slicer_disk DB 0x00 ; 0xbb49
slicer_track DB 0x00 ; 0xbb4a
slicer_real_sector DB 0x00 ; 0xbb4b
tmp_slicer_real_sector DB 0x00 ; 0xbb4c
slicer_has_data DB 0x00 ; 0xbb4d
slicer_need_save DB 0x00 ; 0xbb4e
slicer_uninited_count DB 0x00 ; 0xbb4f
slicer_uninited_disk DB 0x00 ; 0xbb42
slicer_uninited_track DB 0x00 ; 0xbb43
slicer_uninited_sector_128 DB 0x00 ; 0xbb44
tmp_slicer_result DB 0x00 ; 0xbb45
tmp_slicer_can_read DB 0x00 ; 0xbb46
tmp_slicer_operation DB 0x00 ; 0xbb47
tmp_slicer_flush DB 0x00 ; 0xbb48
; Directory buffer used by BDOS for directory operations
dir_buffer DS DIR_BUFF_SIZE, 0 ; 0xbb49
; Allocation map for drive A (Mark used allocation blocks)
AL_MAP_A DS 31, 0 ; 248 bit
; Check vector for drive A (Checksumm of dir entries, used to detect disk change)
CHK_VEC_A DS 16, 0 ; 0xbbf6
; Allocation map for drive B
AL_MAP_B DS 45, 0 ; 184 bit
; Check vector for drive B
CHK_VEC_B DS 32, 0 ; 0xbc33
; Allocation map for drive C
AL_MAP_C DS 45, 0 ; 184 bit
; Check vector for drive C
CHK_VEC_C DS 32, 0 ; 0xbc80
DS 96, 0
slicer_buffer DS 512, 0 ; 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 cur_disk = 0xbb44
ASSERT slicer_uninited_count = 0xbb4f
ASSERT slicer_buffer = 0xbd00
DISPLAY "| CCP_VARS\t| ",/H,cpm_vars_start," | ",/H,cpm_vars_size," |\t |"
DISPLAY "cur_disk:",/H,cur_disk
ENDMODULE
ENDIF

View File

@ -0,0 +1,149 @@
; ======================================================
; Ocean-240.2
; Equates for all assembly sources
;
; By Romych 2025-09-09
; ======================================================
IFNDEF _EQUATES
DEFINE _EQUATES
ADDLIST EQU 0x08
ASCII_BELL EQU 0x07 ; Make Beep
ASCII_BS EQU 0x08 ; Move cursor left (Back Space)
ASCII_TAB EQU 0x09 ; Move cursor right +8 pos
ASCII_LF EQU 0x0A ; Move cursor down (Line Feed)
ASCII_FF EQU 0x0C ; Move cursor to home (Form Feed)
ASCII_CR EQU 0x0D ; Move gursor to 1st pos (Cariage Return)
ASCII_CAN EQU 0x18 ; Move cursor right
ASCII_EM EQU 0x19 ; Move cursor up
ASCII_SUB EQU 0x1A ; CTRL-Z - end of text file marker
ASCII_ESC EQU 0x1B ;
ASCII_US EQU 0x1F ; Clear screen
ASCII_SP EQU 0x20
ASCII_DEL EQU 0x7F
; ------------------------------------------------------
BDOS_NFUNCS EQU 41
BELL_PIN EQU 0x08 ; DD67 Pin PC3 - "BELL"
; ------------------------------------------------------
CCP_COMMAND_SIZE EQU 5 ; max length of CCP command
CCP_COMMAND_COUNT EQU 3 ; Count of CCP commands
CCP_COMMAND_CNT EQU 6
CCP_COMMAND_LEN EQU 4
CCP_SRC_ADDR EQU 0xc000 ; Address of CCP resident part in ROM
CCP_DST_ADDR EQU 0xb200 ; Address of CCP resident part in RAM
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
DIR_BUFF_SIZE EQU 128
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
FDC_RESTORE_UH_NV EQU 0x03 ; Restore Unload Head, No Verify, 15ms Rate
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
; ------------------------------------------------------
IRQ_0 EQU 0x01
IRQ_1 EQU 0x02
IRQ_2 EQU 0x04
;LP_IRQ EQU 0x08
KBD_IRQ EQU 0x02
KBD_ACK EQU 0x10
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
RO_FILE EQU 0x09
ROM_CHIP_SIZE EQU 8192 ; ROM Size, used to limit monitor code size
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
; ------------------------------------------------------
ENDIF

132
CPM_v2.2_r8_099942fc/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
DEFINE _MON
MODULE MON
mon_init EQU 0xe000
mon_cold_start EQU 0xe003
non_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
ram_disk_read EQU 0xe01e
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
read_floppy EQU 0xe030
write_floppy EQU 0xe033
ENDMODULE
ENDIF

View File

@ -0,0 +1,49 @@
; =======================================================
; 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
@RST1 EQU 0x0008
@RST1_handler_addr EQU 0x0009
;RST2 EQU 0x0010
;RST3 EQU 0x0018
;RST4 EQU 0x0020
;RST5 EQU 0x0028
;RST6 EQU 0x0030
;RST7 EQU 0x0038
;reserve1 EQU 0x003b
@bios_var0 EQU 0x0040 ; 0xaa - bios init r8
@bios_var1 EQU 0x0041 ; 0xaa - bios init r8
@bios_var2 EQU 0x0042 ; 0x00 - bios init r8
@bios_var3 EQU 0x0043 ; 0xff - bios init r8
@interleave_0 EQU 0x0044
;reserve2 EQU 0x0050
@fcb1 EQU 0x005c ; Default FCB, 16 bytes
@fcb2 EQU 0x006c
;NMI_ISR EQU 0x0066
@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

10
CPM_v2.2_r8_2e4a7b71/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
*.labels
*.obj
*.OBJ
*.bin
*.tmp
tmp/
build/
*.lst
*.sld

View File

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

36
CPM_v2.2_r8_2e4a7b71/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,36 @@
{
"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,11 @@
# Ocean-240.2 ROM Sources CP/M (V2.2) REL.8' checksum 2e4a7b71
Source codes of CP/M (V2.2) REL.8' version for Ocean-240.2 with Floppy controller.
In Z80 mnemonics, but limited for i8080 instruction set.
* 192k 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,823 @@
; =======================================================
; 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.non_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
JP warm_boot ; r8
disk_a_size DW 0x00C0 ; 192k disk A size
disk_b_size DW 0x02d0 ; 720 disk B size
disk_c_size DW 0x02d0 ; 720 disk C size
bios_var04 DB 0x50
bios_var05 DB 0x50
; -------------------------------------------------------
; 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
; >> r8
LD HL, (bios_var0) ; if bios_var0 = 0xaaaa (initialized)
LD DE, 0x5556
ADD HL, DE ; 0xaaaa+0x5556=0x10000 if initialized
LD A, H
OR L
JP Z, bios_signon ; if initialized, go to logon, skip init
; <<
; 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.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
; init bios variables
CALL bios_init_ilv ; r8
bios_signon:
LD SP, bios_stack
; Print CP/M hello message
LD HL, msg_hello
CALL print_strz
JP bios_wboot
;bios_wboot:
; LD SP, bios_stack
; r8 >>
bios_init_ilv:
LD HL, bios_var0
LD DE, bios_ini_vals
LD C, 13
CALL mov_dlhe_c
LD A, (bios_var05) ; 0x50
LD (bios_var2), A
RET
; <<
; -------------------------------------------------------
; BIOS Warm start entry
; -------------------------------------------------------
bios_wboot: ; r8
LD HL, (bios_var0)
LD DE, 0x5556 ; 0xaaaa + 0x5556 = 0x10000
ADD HL, DE
LD A, H
OR L
CALL NZ, bios_init_ilv ; init if not initialized before
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_disk_a
LD BC, DPB_END-dph_disk_a ; 0x39 -> 57d
.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
LD HL, CPM_VARS.DPB_A_RAM
LD C, 0xf
LD DE, dpb_ram
LD A, (disk_a_size+1)
OR A
JP Z, set_curr_dpb
LD DE, dpb_empty
set_curr_dpb:
CALL mov_dlhe_c
LD HL, CPM_VARS.DPB_B_RAM
LD C, 0xf
LD DE, dpb_flop_360k
LD A, (disk_b_size+1)
CP 0x1
JP Z, .l1
LD DE, dpb_flop_720k
.l1
CALL mov_dlhe_c
LD HL, CPM_VARS.DPB_C_RAM
LD C, 0xf
LD A, (disk_c_size+1)
CP 0x2
JP Z, .l2
LD DE, dpb_flop_360k
LD A, (bios_var3)
OR A
JP NZ, .l3
LD DE, dpb_flop_720k
JP .l3
.l2
LD DE, dpb_flop_720k
LD A, (bios_var3)
OR A
JP NZ, .l3
LD DE, dpb_flop_360k
.l3
CALL mov_dlhe_c
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
; -------------------------------------------------------
; Move C bytes from [DE] to [HL]
; -------------------------------------------------------
mov_dlhe_c:
LD A,(DE) ; [DE]->[HL]
LD (HL),A
INC HL
INC DE
DEC C
JP NZ, mov_dlhe_c
RET
list_st:
XOR A
RET
; -------------------------------------------------------
; Select disk
; Inp: C - disk,
; E - active drive flag
; Out: HL -> DPH
; -------------------------------------------------------
sel_disk:
LD HL, 0x00
LD A, C
CP CTRL_C
RET NC
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.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.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, 0xA6 ; VG93 CMD
CALL MON.write_floppy
LD (CPM_VARS.tmp_slicer_result), A
RET
; --------------------------------------------------
slicer_read_buffer:
CALL slicer_get_floppy_args
LD C, 0x86 ; VG93 CMD
CALL MON.read_floppy
LD (CPM_VARS.tmp_slicer_result), A
RET
; --------------------------------------------------
slicer_get_floppy_args:
LD HL, CPM_VARS.tmp_buff9
LD A, (CPM_VARS.slicer_disk)
DEC A
JP Z, .non_interleave
LD HL, interleave_0
.non_interleave
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
; -------------------------------------------------------
; 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, "83"
DB ASCII_ESC, "5!%"
DB ASCII_ESC, "41"
DB ASCII_ESC, "1", 0x16, 0xe2, 0xe2, 0xfc, 0x01
DB ASCII_ESC, "40"
DB ASCII_ESC, "1", 0x1e, 0xe6, 0xdb, 0xf8, 0x01
DB ASCII_ESC, "43"
DB "OKEAH-240 CP/M (V2.2) REL.8'\r\n\n"
DB ASCII_ESC, "42", 0
; --------------------------------------------------
; 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_ram:
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 191 ; DSM Disk size blocks - 1
DW 31 ; DRM Dir elements - 1
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)
dpb_empty:
DS 15, 0xff
; For FLOPPY 720k
dpb_flop_720k:
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 00h ; EXM extent mask
DW 359 ; DSM Disk size blocks - 1 (359d)
DW 127 ; DRM Directory entries - 1 (127d)
DB 11000000b ; AL0 Dir map byte 1 (2 dir blk)
DB 00000000b ; AL1 Dir map byte 2
DW 32 ; CKS checksum vector size (32 sectors = 2k)
DW 0000h ; OFF (No of tracks reserved for system)
; For FLOPPY 360k
dpb_flop_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 179 ; DSM Disk size blocks - 1 (179d)
DW 127 ; DRM Directory entries - 1 (127d)
DB 11000000b ; AL0 Dir map byte 1 (2 dir blk)
DB 00000000b ; AL1 Dir map byte 2
DW 32 ; CKS checksum vector size (32 sectors = 2k)
DW 0000h ; OFF (No of tracks reserved for system)
bios_ini_vals:
DB 0xaa, 0xaa, 0, 0xff, 1, 8, 6, 4, 2, 9, 7, 5, 3
; --------------------------------------------------
; Disk parameters headers in ROM
; --------------------------------------------------
; Disk A RAM
dph_disk_a:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
; 0xda00
DW CPM_VARS.dir_buffer ; Directory buffer pointer
DW CPM_VARS.DPB_A_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_disk_b:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
DW CPM_VARS.dir_buffer ; Directory buffer pointer
DW CPM_VARS.DPB_B_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_disk_c:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
DW CPM_VARS.dir_buffer ; Directory buffer pointer
DW CPM_VARS.DPB_C_RAM ; DPB Pointer
DW CPM_VARS.CHK_VEC_C ; Check Vector pointer
DW CPM_VARS.AL_MAP_C ; Allocation map pointer
res_data: ; 0xda28
DB 1,8,6,4,2,9,7,5,3
DPB_END EQU $
DB 0x0e, 3
; -------------------------------------------------------
; Filler to align blocks in ROM
; -------------------------------------------------------
LAST EQU $
CODE_SIZE EQU LAST-0xD600
FILL_SIZE EQU 0x500-CODE_SIZE
DISPLAY "| BIOS\t| ",/H,boot_f," | ",/H,CODE_SIZE," | ",/H,FILL_SIZE," |"
; Check integrity
ASSERT bios_wboot = 0xd6a8
ASSERT set_curr_dpb = 0xd722
ASSERT sel_disk = 0xd781
ASSERT home = 0xd7a7
ASSERT ram_disk_calc_addr = 0xd7eb
ASSERT write_phys_op = 0xd81e
ASSERT base_read_write = 0xd88a
ASSERT calc_sec_addr_in_bfr = 0xd8e4
ASSERT slicer_save_buffer = 0xd928
ASSERT print_strz = 0xd95e
ASSERT msg_hello = 0xd96b
ASSERT dpb_ram = 0xd9af
ASSERT dph_disk_a = 0xd9f8
ASSERT res_data = 0xda28
FILLER:
DS FILL_SIZE, 0xff
ENDMODULE
IFNDEF BUILD_ROM
OUTEND
ENDIF

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,901 @@
; =======================================================
; 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_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_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, (bios_var3)
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, 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, 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

View File

@ -0,0 +1,44 @@
; ======================================================
; Ocean-240.2
; CP/M Combine file. Includes all sources to build
; ROM 0xC000
;
; Disassembled by Romych 2025-02-12
; ======================================================
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
;LABELSLIST "cpm.labels"
;CSPECTMAP "cpm.map"
INCLUDE "ccp_ram.asm"
INCLUDE "bdos.asm"
INCLUDE "bios.asm"
INCLUDE "ccp_rom.asm"
OUTEND
OUTPUT variables.bin
INCLUDE "cpm_vars.inc"
OUTEND
END

View File

@ -0,0 +1,219 @@
; =======================================================
; Ocean-240.2
; Module CPM_VARS - 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 DB 0
bdos_strtcol DB 0
bdos_column DB 0
; Copy output to printer in non zero
bdos_prnflag DB 0
bdos_kbchar DB 0
; Stored user stack pointer on enter bdos fn
bdos_usersp DW 0 ; 0xba0e
; BDOS Stack
DS 48, 0
bdos_stack EQU $
; -------------------------------------------------------
; Common values shared between bdosi and bdos
; -------------------------------------------------------
; current user number 0..15
bdos_userno DB 0x00 ; 0xba40
; current disk number
bdos_curdsk DB 0x00
; reg DE (pointer) value to call BDOS fn
bdos_info DW 0x0000 ; 0xba42
; Address value to return
bdos_aret DW 0x0000 ; 0xba44
; Empty FCB
bdos_efcb DB 0x00 ; 0xba46 = 0xE5 at init
; Read-only disks flag
bdos_rodsk DW 0x0000 ; 0xba47
; Drive login vector
bdos_dlog DW 0x0000 ; 0xba49
; Address of DMA buffer
bdos_dmaad DW 0x0000 ; 0xba4b = 0x80 at init
bdos_cdrmax DW 0x0000 ; 0xba4d
; Current track
bdos_curtrk DW 0x0000 ; 0xba4f
; Current record (sector)
bdos_currec DW 0x0000 ; 0xba51
; Address of user buffer
bdos_buffa DW 0x0000 ; 0xba53
; Address of cur disk DPB
bdos_dpbaddr DW 0x0000 ; 0xba55
; Calculated checksum
bdos_cksum DW 0x0000 ; 0xba57
; Address of cur disk allocation map
bdos_alloca DW 0x0000 ; 0xba59
; Sectors per track
dbos_sectpt DW 0x0000 ; 0xba5b
bdos_blkshf DB 0x00 ; 0xba5d
bdos_blmsk DB 0x00 ; 0xba5e
bdos_extmsk DB 0x00 ; 0xba5f
; Max allocation number (disk size)
bdos_maxall DW 0x0000 ; 0xba60
bdos_dirmax DW 0x0000 ; 0xba62
; Size of directory
bdos_dirblk DW 0x0000 ; 0xba64
bdos_alloc1 DW 0x0000 ; 0xba66
; First track offset
bdos_offset DW 0x0000 ; 0xba68
; Disk traslation vector address
bdos_tranv DW 0x0000 ; 0xba6a
; Open and closed flag 0xff - closed
bdos_fcb_closed DB 0x00 ; 0xba6c
; Read file modified flag. 0xff - not allow read unwritten
bdos_rfm DB 0x00 ; 0xba6d
bdos_dirloc DB 0x00 ; 0xba6e
; File access mode (0=random, 1=sequential, 2=special)
bdos_seqio DB 0x00 ; 0xba6f
; Reg E value to call BDOS fn
bdos_linfo DB 0x00 ; 0xba70
bdos_dminx DB 0x00 ; 0xba71
; Length in bytes to match when search
bdos_searchl DB 0x00 ; 0xba72
; Address of buffer where to search
bdos_searcha DW 0x0000 ; 0xba73
DW 0x0000
; 0 - big disk (>255 blk), 0xff - small disk
bdos_small_disk DB 0x00 ; 0xba77
; Drive selected (0xff) by user specified FCB flag
bdos_resel DB 0x00 ; 0xba78
bdos_olddsk DB 0x00 ; 0xba79
; Saved disk of user FCB
bdos_fcbdsk DB 0x00 ; 0xba7a
; Number of records in extent
bdos_rcount DB 0x00 ; 0xba7b
bdos_extval DB 0x00 ; 0xba7c
; Record number to read
bdos_vrecord DW 0x0000 ; 0xba7d
; Record to access
bdos_arecord DW 0x0000 ; 0xba7f
bdos_arecord1 DW 0x0000 ; 0xba81
bdos_dptr DB 0x00 ; 0xba83
bdos_dcnt DW 0x00 ; 0xba84
bdos_drec DS 20, 0x00 ; 0xba86
tmp_dir_total DW 0x0000 ; 0xba9a
; Save pointer at ccp entry, restore on exit
saved_stack_ptr DW 0x0000 ; 0xba9c
DS 22, 0
ccp_safe_stack
DW 0x0000 ; 0xbab4
; --------------------------------------------------
; FCB
; --------------------------------------------------
ccp_fcb
ccp_fcb_dr DB 0 ; 0xbab6 drive letter to write file
ccp_fcb_fn DS 8,0 ; 0xbab7 file name
ccp_fcb_ft DS 3,0 ; file type
ccp_fcb_ext DB 0 ; extent
ccp_fcb_s1 DB 0
ccp_fcb_s2 DB 0 ; extent hi bits
ccp_fcb_rc DB 0
ccp_fcb_al DS 16, 0 ; Second half of FCB
ccp_fcb_cr DB 0x00 ; Current record
ccp_fcb_rn DB 0x00 ; Random access record number
DW 0x00
DW 0x00
DW 0x00
ccp_vars_end EQU $
; --------------------------------------------------
; Disk parameters headers/blocks in RAM
; --------------------------------------------------
DPH_RAM DS 16, 0 ; 0xbade
DPH1_RAM DS 16, 0 ; 0xbaee
DPH2_RAM DS 16, 0 ; 0xbafe
tmp_buff9 DS 9, 0
DPB_A_RAM DS 15, 0 ; 0xbb17
DPB_B_RAM DS 15, 0 ; 0xbb26
DPB_C_RAM DS 15, 0 ; 0xbb35
; --------------------------------------------------
cur_disk DB 0x00 ; 0xbb44
dma_addr DW 0x0000 ; 0xbb46
curr_track DB 0x00 ; 0xbb47
curr_sec DB 0x00 ; 0xbb48
slicer_disk DB 0x00 ; 0xbb49
slicer_track DB 0x00 ; 0xbb4a
slicer_real_sector DB 0x00 ; 0xbb4b
tmp_slicer_real_sector DB 0x00 ; 0xbb4c
slicer_has_data DB 0x00 ; 0xbb4d
slicer_need_save DB 0x00 ; 0xbb4e
slicer_uninited_count DB 0x00 ; 0xbb4f
slicer_uninited_disk DB 0x00 ; 0xbb42
slicer_uninited_track DB 0x00 ; 0xbb43
slicer_uninited_sector_128 DB 0x00 ; 0xbb44
tmp_slicer_result DB 0x00 ; 0xbb45
tmp_slicer_can_read DB 0x00 ; 0xbb46
tmp_slicer_operation DB 0x00 ; 0xbb47
tmp_slicer_flush DB 0x00 ; 0xbb48
; Directory buffer used by BDOS for directory operations
dir_buffer DS DIR_BUFF_SIZE, 0 ; 0xbb49
; Allocation map for drive A (Mark used allocation blocks)
AL_MAP_A DS 31, 0 ; 248 bit
; Check vector for drive A (Checksumm of dir entries, used to detect disk change)
CHK_VEC_A DS 16, 0 ; 0xbbf6
; Allocation map for drive B
AL_MAP_B DS 45, 0 ; 184 bit
; Check vector for drive B
CHK_VEC_B DS 32, 0 ; 0xbc33
; Allocation map for drive C
AL_MAP_C DS 45, 0 ; 184 bit
; Check vector for drive C
CHK_VEC_C DS 32, 0 ; 0xbc80
DS 96, 0
slicer_buffer DS 512, 0 ; 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 cur_disk = 0xbb44
ASSERT slicer_uninited_count = 0xbb4f
ASSERT slicer_buffer = 0xbd00
DISPLAY "| CCP_VARS\t| ",/H,cpm_vars_start," | ",/H,cpm_vars_size," |\t |"
DISPLAY "cur_disk:",/H,cur_disk
ENDMODULE
ENDIF

View File

@ -0,0 +1,149 @@
; ======================================================
; Ocean-240.2
; Equates for all assembly sources
;
; By Romych 2025-09-09
; ======================================================
IFNDEF _EQUATES
DEFINE _EQUATES
ADDLIST EQU 0x08
ASCII_BELL EQU 0x07 ; Make Beep
ASCII_BS EQU 0x08 ; Move cursor left (Back Space)
ASCII_TAB EQU 0x09 ; Move cursor right +8 pos
ASCII_LF EQU 0x0A ; Move cursor down (Line Feed)
ASCII_FF EQU 0x0C ; Move cursor to home (Form Feed)
ASCII_CR EQU 0x0D ; Move gursor to 1st pos (Cariage Return)
ASCII_CAN EQU 0x18 ; Move cursor right
ASCII_EM EQU 0x19 ; Move cursor up
ASCII_SUB EQU 0x1A ; CTRL-Z - end of text file marker
ASCII_ESC EQU 0x1B ;
ASCII_US EQU 0x1F ; Clear screen
ASCII_SP EQU 0x20
ASCII_DEL EQU 0x7F
; ------------------------------------------------------
BDOS_NFUNCS EQU 41
BELL_PIN EQU 0x08 ; DD67 Pin PC3 - "BELL"
; ------------------------------------------------------
CCP_COMMAND_SIZE EQU 5 ; max length of CCP command
CCP_COMMAND_COUNT EQU 3 ; Count of CCP commands
CCP_COMMAND_CNT EQU 6
CCP_COMMAND_LEN EQU 4
CCP_SRC_ADDR EQU 0xc000 ; Address of CCP resident part in ROM
CCP_DST_ADDR EQU 0xb200 ; Address of CCP resident part in RAM
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
DIR_BUFF_SIZE EQU 128
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
FDC_RESTORE_UH_NV EQU 0x03 ; Restore Unload Head, No Verify, 15ms Rate
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
; ------------------------------------------------------
IRQ_0 EQU 0x01
IRQ_1 EQU 0x02
IRQ_2 EQU 0x04
;LP_IRQ EQU 0x08
KBD_IRQ EQU 0x02
KBD_ACK EQU 0x10
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
RO_FILE EQU 0x09
ROM_CHIP_SIZE EQU 8192 ; ROM Size, used to limit monitor code size
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
; ------------------------------------------------------
ENDIF

132
CPM_v2.2_r8_2e4a7b71/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
DEFINE _MON
MODULE MON
mon_init EQU 0xe000
mon_cold_start EQU 0xe003
non_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
ram_disk_read EQU 0xe01e
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
read_floppy EQU 0xe030
write_floppy EQU 0xe033
ENDMODULE
ENDIF

View File

@ -0,0 +1,49 @@
; =======================================================
; 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
@RST1 EQU 0x0008
@RST1_handler_addr EQU 0x0009
;RST2 EQU 0x0010
;RST3 EQU 0x0018
;RST4 EQU 0x0020
;RST5 EQU 0x0028
;RST6 EQU 0x0030
;RST7 EQU 0x0038
;reserve1 EQU 0x003b
@bios_var0 EQU 0x0040 ; 0xaa - bios init r8
@bios_var1 EQU 0x0041 ; 0xaa - bios init r8
@bios_var2 EQU 0x0042 ; 0x00 - bios init r8
@bios_var3 EQU 0x0043 ; 0xff - bios init r8
@interleave_0 EQU 0x0044
;reserve2 EQU 0x0050
@fcb1 EQU 0x005c ; Default FCB, 16 bytes
@fcb2 EQU 0x006c
;NMI_ISR EQU 0x0066
@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

10
CPM_v2.2_r8_bc0695e4/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
*.labels
*.obj
*.OBJ
*.bin
*.tmp
tmp/
build/
*.lst
*.sld

View File

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

36
CPM_v2.2_r8_bc0695e4/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,36 @@
{
"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,38 @@
# Ocean-240.2 ROM Sources CP/M (V2.2) REL.8 checksum bc0695e4
Source codes of CP/M (V2.2) REL.8 version for Ocean-240.2 with Floppy controller.
In Z80 mnemonics, but limited for i8080 instruction set.
* READ command replaced with Intel HEX loader by **tnt23**
* 192k 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).
## Convert binary file to Intel HEX
srec_cat file_name.COM -binary -offset 0x100 -output file_name.hex -Intel
## Send HEX from Linux console
It is assumed that there is a USB-RS232 (USB-TTL) adapter on the /dev/ttyUSB0.
1) At Ocean's CP/M command line:
A>READ
2) At Linux terminal, configure tty for 4800,8N2:
stty -F /dev/ttyUSB0 4800 cs8 -cstopb
3) At Linux terminal, send file:
cat okeah.hex > /dev/ttyUSB0
srec_cat - Utility from **srecord** package - collection of tools for manipulating EPROM load files.
[Forum topic](https://zx-pk.ru/threads/35390-zagruzka-hex-fajlov-direktivoj-l-monitora.html)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
; =======================================================
; Ocean-240.2
; CP/M v2.2. Equates to call BDOS functions
;
; Created by Romych 2026-02-16
; =======================================================
IFNDEF _BDOS_INC
DEFINE _BDOS_INC
P_TERMCPM EQU 0 ; System Reset
C_READ EQU 1 ; Console input
C_WRITE EQU 2 ; Console output
A_READ EQU 3 ; Auxiliary (Reader) input
A_WRITE EQU 4 ; Auxiliary (Punch) output
L_WRITE EQU 5 ; Printer output
C_RAWIO EQU 6 ; Direct console I/O
A_STATIN EQU 7 ; Auxiliary Input status
A_STATOUT EQU 8 ; Auxiliary Output status
C_WRITESTR EQU 9 ; Output string
C_READSTR EQU 10 ; Buffered console input
C_STAT EQU 11 ; Console status
S_BDOSVER EQU 12 ; Return version number
DRV_ALLRESET EQU 13 ; Reset discs
DRV_SET EQU 14 ; Select disc
F_OPEN EQU 15 ; Open file
F_CLOSE EQU 16 ; Close file
F_SFIRST EQU 17 ; search for first
F_SNEXT EQU 18 ; search for next
F_DELETE EQU 19 ; delete file
F_READ EQU 20 ; read next record
F_WRITE EQU 21 ; write next record
F_MAKE EQU 22 ; create file
F_RENAME EQU 23 ; Rename file
DRV_LOGINVEC EQU 24 ; Return bitmap of logged-in drives
DRV_GET EQU 25 ; Return current drive
F_DMAOFF EQU 26 ; Set DMA address
DRV_ALLOCVEC EQU 27 ; Return address of allocation map
DRV_SETRO EQU 28 ; Software write-protect current disc
DRV_ROVEC EQU 29 ; Return bitmap of read-only drives
F_ATTRIB EQU 30 ; set file attributes
DRV_DPB EQU 31 ; get DPB address
F_USERNUM EQU 32 ; get/set user number
F_READRAND EQU 33 ; Random access read record
F_WRITERAND EQU 34 ; Random access write record
F_SIZE EQU 35 ; Compute file size
F_RANDREC EQU 36 ; Update random access pointer
DRV_RESET EQU 37 ; Selectively reset disc drives
DRV_ACCESS EQU 38 ; Access drives
DRV_FREE EQU 39 ; Free drive
F_WRITEZF EQU 40 ; Write random with zero fill
ENDIF

View File

@ -0,0 +1,823 @@
; =======================================================
; 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.non_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
JP warm_boot ; r8
disk_a_size DW 0x00C0 ; 192k disk A size
disk_b_size DW 0x02d0 ; 720 disk B size
disk_c_size DW 0x02d0 ; 720 disk C size
bios_var04 DB 0x50
bios_var05 DB 0x50
; -------------------------------------------------------
; 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
; >> r8
LD HL, (bios_var0) ; if bios_var0 = 0xaaaa (initialized)
LD DE, 0x5556
ADD HL, DE ; 0xaaaa+0x5556=0x10000 if initialized
LD A, H
OR L
JP Z, bios_signon ; if initialized, go to logon, skip init
; <<
; 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.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
; init bios variables
CALL bios_init_ilv ; r8
bios_signon:
LD SP, bios_stack
; Print CP/M hello message
LD HL, msg_hello
CALL print_strz
JP bios_wboot
;bios_wboot:
; LD SP, bios_stack
; r8 >>
bios_init_ilv:
LD HL, bios_var0
LD DE, bios_ini_vals
LD C, 13
CALL mov_dlhe_c
LD A, (bios_var05) ; 0x50
LD (bios_var2), A
RET
; <<
; -------------------------------------------------------
; BIOS Warm start entry
; -------------------------------------------------------
bios_wboot: ; r8
LD HL, (bios_var0)
LD DE, 0x5556 ; 0xaaaa + 0x5556 = 0x10000
ADD HL, DE
LD A, H
OR L
CALL NZ, bios_init_ilv ; init if not initialized before
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_disk_a
LD BC, DPB_END-dph_disk_a ; 0x39 -> 57d
.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
LD HL, CPM_VARS.DPB_A_RAM
LD C, 0xf
LD DE, dpb_ram
LD A, (disk_a_size+1)
OR A
JP Z, set_curr_dpb
LD DE, dpb_empty
set_curr_dpb:
CALL mov_dlhe_c
LD HL, CPM_VARS.DPB_B_RAM
LD C, 0xf
LD DE, dpb_flop_360k
LD A, (disk_b_size+1)
CP 0x1
JP Z, .l1
LD DE, dpb_flop_720k
.l1
CALL mov_dlhe_c
LD HL, CPM_VARS.DPB_C_RAM
LD C, 0xf
LD A, (disk_c_size+1)
CP 0x2
JP Z, .l2
LD DE, dpb_flop_360k
LD A, (bios_var3)
OR A
JP NZ, .l3
LD DE, dpb_flop_720k
JP .l3
.l2
LD DE, dpb_flop_720k
LD A, (bios_var3)
OR A
JP NZ, .l3
LD DE, dpb_flop_360k
.l3
CALL mov_dlhe_c
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
; -------------------------------------------------------
; Move C bytes from [DE] to [HL]
; -------------------------------------------------------
mov_dlhe_c:
LD A,(DE) ; [DE]->[HL]
LD (HL),A
INC HL
INC DE
DEC C
JP NZ, mov_dlhe_c
RET
list_st:
XOR A
RET
; -------------------------------------------------------
; Select disk
; Inp: C - disk,
; E - active drive flag
; Out: HL -> DPH
; -------------------------------------------------------
sel_disk:
LD HL, 0x00
LD A, C
CP CTRL_C
RET NC
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.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.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, 0xA6 ; VG93 CMD
CALL MON.write_floppy
LD (CPM_VARS.tmp_slicer_result), A
RET
; --------------------------------------------------
slicer_read_buffer:
CALL slicer_get_floppy_args
LD C, 0x86 ; VG93 CMD
CALL MON.read_floppy
LD (CPM_VARS.tmp_slicer_result), A
RET
; --------------------------------------------------
slicer_get_floppy_args:
LD HL, CPM_VARS.tmp_buff9
LD A, (CPM_VARS.slicer_disk)
DEC A
JP Z, .non_interleave
LD HL, interleave_0
.non_interleave
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
; -------------------------------------------------------
; 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, "83"
DB ASCII_ESC, "5!%"
DB ASCII_ESC, "41"
DB ASCII_ESC, "1", 0x16, 0xe2, 0xe2, 0xfc, 0x01
DB ASCII_ESC, "40"
DB ASCII_ESC, "1", 0x1e, 0xe6, 0xdb, 0xf8, 0x01
DB ASCII_ESC, "43"
DB "OKEAH-240 CP/M (V2.2) REL.8'\r\n\n"
DB ASCII_ESC, "42", 0
; --------------------------------------------------
; 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_ram:
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 191 ; DSM Disk size blocks - 1
DW 31 ; DRM Dir elements - 1
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)
dpb_empty:
DS 15, 0xff
; For FLOPPY 720k
dpb_flop_720k:
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 00h ; EXM extent mask
DW 359 ; DSM Disk size blocks - 1 (359d)
DW 127 ; DRM Directory entries - 1 (127d)
DB 11000000b ; AL0 Dir map byte 1 (2 dir blk)
DB 00000000b ; AL1 Dir map byte 2
DW 32 ; CKS checksum vector size (32 sectors = 2k)
DW 0000h ; OFF (No of tracks reserved for system)
; For FLOPPY 360k
dpb_flop_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 179 ; DSM Disk size blocks - 1 (179d)
DW 127 ; DRM Directory entries - 1 (127d)
DB 11000000b ; AL0 Dir map byte 1 (2 dir blk)
DB 00000000b ; AL1 Dir map byte 2
DW 32 ; CKS checksum vector size (32 sectors = 2k)
DW 0000h ; OFF (No of tracks reserved for system)
bios_ini_vals:
DB 0xaa, 0xaa, 0, 0xff, 1, 8, 6, 4, 2, 9, 7, 5, 3
; --------------------------------------------------
; Disk parameters headers in ROM
; --------------------------------------------------
; Disk A RAM
dph_disk_a:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
; 0xda00
DW CPM_VARS.dir_buffer ; Directory buffer pointer
DW CPM_VARS.DPB_A_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_disk_b:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
DW CPM_VARS.dir_buffer ; Directory buffer pointer
DW CPM_VARS.DPB_B_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_disk_c:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
DW CPM_VARS.dir_buffer ; Directory buffer pointer
DW CPM_VARS.DPB_C_RAM ; DPB Pointer
DW CPM_VARS.CHK_VEC_C ; Check Vector pointer
DW CPM_VARS.AL_MAP_C ; Allocation map pointer
res_data: ; 0xda28
DB 1,8,6,4,2,9,7,5,3
DPB_END EQU $
DB 0x0e, 3
; -------------------------------------------------------
; Filler to align blocks in ROM
; -------------------------------------------------------
LAST EQU $
CODE_SIZE EQU LAST-0xD600
FILL_SIZE EQU 0x500-CODE_SIZE
DISPLAY "| BIOS\t| ",/H,boot_f," | ",/H,CODE_SIZE," | ",/H,FILL_SIZE," |"
; Check integrity
ASSERT bios_wboot = 0xd6a8
ASSERT set_curr_dpb = 0xd722
ASSERT sel_disk = 0xd781
ASSERT home = 0xd7a7
ASSERT ram_disk_calc_addr = 0xd7eb
ASSERT write_phys_op = 0xd81e
ASSERT base_read_write = 0xd88a
ASSERT calc_sec_addr_in_bfr = 0xd8e4
ASSERT slicer_save_buffer = 0xd928
ASSERT print_strz = 0xd95e
ASSERT msg_hello = 0xd96b
ASSERT dpb_ram = 0xd9af
ASSERT dph_disk_a = 0xd9f8
ASSERT res_data = 0xda28
FILLER:
DS FILL_SIZE, 0xff
ENDMODULE
IFNDEF BUILD_ROM
OUTEND
ENDIF

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,882 @@
; =======================================================
; 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, (bios_var3)
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

View File

@ -0,0 +1,46 @@
; ======================================================
; Ocean-240.2
; CP/M Combine file. Includes all sources to build
; ROM 0xC000
;
; Disassembled by Romych 2025-02-12
; ======================================================
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
;LABELSLIST "cpm.labels"
;CSPECTMAP "cpm.map"
INCLUDE "equates.inc"
INCLUDE "bdos.inc"
INCLUDE "ccp_ram.asm"
INCLUDE "bdos.asm"
INCLUDE "bios.asm"
INCLUDE "ccp_rom.asm"
OUTEND
OUTPUT variables.bin
INCLUDE "cpm_vars.inc"
OUTEND
END

View File

@ -0,0 +1,219 @@
; =======================================================
; Ocean-240.2
; Module CPM_VARS - 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 DB 0
bdos_strtcol DB 0
bdos_column DB 0
; Copy output to printer in non zero
bdos_prnflag DB 0
bdos_kbchar DB 0
; Stored user stack pointer on enter bdos fn
bdos_usersp DW 0 ; 0xba0e
; BDOS Stack
DS 48, 0
bdos_stack EQU $
; -------------------------------------------------------
; Common values shared between bdosi and bdos
; -------------------------------------------------------
; current user number 0..15
bdos_userno DB 0x00 ; 0xba40
; current disk number
bdos_curdsk DB 0x00
; reg DE (pointer) value to call BDOS fn
bdos_info DW 0x0000 ; 0xba42
; Address value to return
bdos_aret DW 0x0000 ; 0xba44
; Empty FCB
bdos_efcb DB 0x00 ; 0xba46 = 0xE5 at init
; Read-only disks flag
bdos_rodsk DW 0x0000 ; 0xba47
; Drive login vector
bdos_dlog DW 0x0000 ; 0xba49
; Address of DMA buffer
bdos_dmaad DW 0x0000 ; 0xba4b = 0x80 at init
bdos_cdrmax DW 0x0000 ; 0xba4d
; Current track
bdos_curtrk DW 0x0000 ; 0xba4f
; Current record (sector)
bdos_currec DW 0x0000 ; 0xba51
; Address of user buffer
bdos_buffa DW 0x0000 ; 0xba53
; Address of cur disk DPB
bdos_dpbaddr DW 0x0000 ; 0xba55
; Calculated checksum
bdos_cksum DW 0x0000 ; 0xba57
; Address of cur disk allocation map
bdos_alloca DW 0x0000 ; 0xba59
; Sectors per track
bdos_sectpt DW 0x0000 ; 0xba5b
bdos_blkshf DB 0x00 ; 0xba5d
bdos_blmsk DB 0x00 ; 0xba5e
bdos_extmsk DB 0x00 ; 0xba5f
; Max allocation number (disk size)
bdos_maxall DW 0x0000 ; 0xba60
bdos_dirmax DW 0x0000 ; 0xba62
; Size of directory
bdos_dirblk DW 0x0000 ; 0xba64
bdos_alloc1 DW 0x0000 ; 0xba66
; First track offset
bdos_offset DW 0x0000 ; 0xba68
; Disk traslation vector address
bdos_tranv DW 0x0000 ; 0xba6a
; Open and closed flag 0xff - closed
bdos_fcb_closed DB 0x00 ; 0xba6c
; Read file modified flag. 0xff - not allow read unwritten
bdos_rfm DB 0x00 ; 0xba6d
bdos_dirloc DB 0x00 ; 0xba6e
; File access mode (0=random, 1=sequential, 2=special)
bdos_seqio DB 0x00 ; 0xba6f
; Reg E value to call BDOS fn
bdos_linfo DB 0x00 ; 0xba70
bdos_dminx DB 0x00 ; 0xba71
; Length in bytes to match when search
bdos_searchl DB 0x00 ; 0xba72
; Address of buffer where to search
bdos_searcha DW 0x0000 ; 0xba73
DW 0x0000
; 0 - big disk (>255 blk), 0xff - small disk
bdos_small_disk DB 0x00 ; 0xba77
; Drive selected (0xff) by user specified FCB flag
bdos_resel DB 0x00 ; 0xba78
bdos_olddsk DB 0x00 ; 0xba79
; Saved disk of user FCB
bdos_fcbdsk DB 0x00 ; 0xba7a
; Number of records in extent
bdos_rcount DB 0x00 ; 0xba7b
bdos_extval DB 0x00 ; 0xba7c
; Record number to read
bdos_vrecord DW 0x0000 ; 0xba7d
; Record to access
bdos_arecord DW 0x0000 ; 0xba7f
bdos_arecord1 DW 0x0000 ; 0xba81
bdos_dptr DB 0x00 ; 0xba83
bdos_dcnt DW 0x00 ; 0xba84
bdos_drec DS 20, 0x00 ; 0xba86
tmp_dir_total DW 0x0000 ; 0xba9a
; Save pointer at ccp entry, restore on exit
saved_stack_ptr DW 0x0000 ; 0xba9c
DS 22, 0
ccp_safe_stack
DW 0x0000 ; 0xbab4
; --------------------------------------------------
; FCB
; --------------------------------------------------
ccp_fcb
ccp_fcb_dr DB 0 ; 0xbab6 drive letter to write file
ccp_fcb_fn DS 8,0 ; 0xbab7 file name
ccp_fcb_ft DS 3,0 ; file type
ccp_fcb_ext DB 0 ; extent
ccp_fcb_s1 DB 0
ccp_fcb_s2 DB 0 ; extent hi bits
ccp_fcb_rc DB 0
ccp_fcb_al DS 16, 0 ; Second half of FCB
ccp_fcb_cr DB 0x00 ; Current record
ccp_fcb_rn DB 0x00 ; Random access record number
DW 0x00
DW 0x00
DW 0x00
ccp_vars_end EQU $
; --------------------------------------------------
; Disk parameters headers/blocks in RAM
; --------------------------------------------------
DPH_RAM DS 16, 0 ; 0xbade
DPH1_RAM DS 16, 0 ; 0xbaee
DPH2_RAM DS 16, 0 ; 0xbafe
tmp_buff9 DS 9, 0
DPB_A_RAM DS 15, 0 ; 0xbb17
DPB_B_RAM DS 15, 0 ; 0xbb26
DPB_C_RAM DS 15, 0 ; 0xbb35
; --------------------------------------------------
cur_disk DB 0x00 ; 0xbb44
dma_addr DW 0x0000 ; 0xbb46
curr_track DB 0x00 ; 0xbb47
curr_sec DB 0x00 ; 0xbb48
slicer_disk DB 0x00 ; 0xbb49
slicer_track DB 0x00 ; 0xbb4a
slicer_real_sector DB 0x00 ; 0xbb4b
tmp_slicer_real_sector DB 0x00 ; 0xbb4c
slicer_has_data DB 0x00 ; 0xbb4d
slicer_need_save DB 0x00 ; 0xbb4e
slicer_uninited_count DB 0x00 ; 0xbb4f
slicer_uninited_disk DB 0x00 ; 0xbb42
slicer_uninited_track DB 0x00 ; 0xbb43
slicer_uninited_sector_128 DB 0x00 ; 0xbb44
tmp_slicer_result DB 0x00 ; 0xbb45
tmp_slicer_can_read DB 0x00 ; 0xbb46
tmp_slicer_operation DB 0x00 ; 0xbb47
tmp_slicer_flush DB 0x00 ; 0xbb48
; Directory buffer used by BDOS for directory operations
dir_buffer DS DIR_BUFF_SIZE, 0 ; 0xbb49
; Allocation map for drive A (Mark used allocation blocks)
AL_MAP_A DS 31, 0 ; 248 bit
; Check vector for drive A (Checksumm of dir entries, used to detect disk change)
CHK_VEC_A DS 16, 0 ; 0xbbf6
; Allocation map for drive B
AL_MAP_B DS 45, 0 ; 184 bit
; Check vector for drive B
CHK_VEC_B DS 32, 0 ; 0xbc33
; Allocation map for drive C
AL_MAP_C DS 45, 0 ; 184 bit
; Check vector for drive C
CHK_VEC_C DS 32, 0 ; 0xbc80
DS 96, 0
slicer_buffer DS 512, 0 ; 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 cur_disk = 0xbb44
ASSERT slicer_uninited_count = 0xbb4f
ASSERT slicer_buffer = 0xbd00
DISPLAY "| CCP_VARS\t| ",/H,cpm_vars_start," | ",/H,cpm_vars_size," |\t |"
;DISPLAY "cur_disk:",/H,cur_disk
ENDMODULE
ENDIF

View File

@ -0,0 +1,149 @@
; ======================================================
; Ocean-240.2
; Equates for all assembly sources
;
; By Romych 2025-09-09
; ======================================================
IFNDEF _EQUATES
DEFINE _EQUATES
ADDLIST EQU 0x08
ASCII_BELL EQU 0x07 ; Make Beep
ASCII_BS EQU 0x08 ; Move cursor left (Back Space)
ASCII_TAB EQU 0x09 ; Move cursor right +8 pos
ASCII_LF EQU 0x0A ; Move cursor down (Line Feed)
ASCII_FF EQU 0x0C ; Move cursor to home (Form Feed)
ASCII_CR EQU 0x0D ; Move gursor to 1st pos (Cariage Return)
ASCII_CAN EQU 0x18 ; Move cursor right
ASCII_EM EQU 0x19 ; Move cursor up
ASCII_SUB EQU 0x1A ; CTRL-Z - end of text file marker
ASCII_ESC EQU 0x1B ;
ASCII_US EQU 0x1F ; Clear screen
ASCII_SP EQU 0x20
ASCII_DEL EQU 0x7F
; ------------------------------------------------------
BDOS_NFUNCS EQU 41
BELL_PIN EQU 0x08 ; DD67 Pin PC3 - "BELL"
; ------------------------------------------------------
CCP_COMMAND_SIZE EQU 5 ; max length of CCP command
CCP_COMMAND_COUNT EQU 3 ; Count of CCP commands
CCP_COMMAND_CNT EQU 6
CCP_COMMAND_LEN EQU 4
CCP_SRC_ADDR EQU 0xc000 ; Address of CCP resident part in ROM
CCP_DST_ADDR EQU 0xb200 ; Address of CCP resident part in RAM
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
DIR_BUFF_SIZE EQU 128
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
FDC_RESTORE_UH_NV EQU 0x03 ; Restore Unload Head, No Verify, 15ms Rate
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
; ------------------------------------------------------
IRQ_0 EQU 0x01
IRQ_1 EQU 0x02
IRQ_2 EQU 0x04
;LP_IRQ EQU 0x08
KBD_IRQ EQU 0x02
KBD_ACK EQU 0x10
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
RO_FILE EQU 0x09
ROM_CHIP_SIZE EQU 8192 ; ROM Size, used to limit monitor code size
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
; ------------------------------------------------------
ENDIF

132
CPM_v2.2_r8_bc0695e4/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
DEFINE _MON
MODULE MON
mon_init EQU 0xe000
mon_hexb EQU 0xe003
non_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
ram_disk_read EQU 0xe01e
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
read_floppy EQU 0xe030
write_floppy EQU 0xe033
ENDMODULE
ENDIF

View File

@ -0,0 +1,49 @@
; =======================================================
; 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
;@RST1 EQU 0x0008
;@RST1_handler_addr EQU 0x0009
;RST2 EQU 0x0010
;RST3 EQU 0x0018
;RST4 EQU 0x0020
;RST5 EQU 0x0028
;RST6 EQU 0x0030
;RST7 EQU 0x0038
;reserve1 EQU 0x003b
@bios_var0 EQU 0x0040 ; 0xaa - bios init r8
@bios_var1 EQU 0x0041 ; 0xaa - bios init r8
@bios_var2 EQU 0x0042 ; 0x00 - bios init r8
@bios_var3 EQU 0x0043 ; 0xff - bios init r8
@interleave_0 EQU 0x0044
;reserve2 EQU 0x0050
@fcb1 EQU 0x005c ; Default FCB, 16 bytes
@fcb2 EQU 0x006c
;NMI_ISR EQU 0x0066
@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

10
CPM_v2.2_r8_ddd05ed7/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
*.labels
*.obj
*.OBJ
*.bin
*.tmp
tmp/
build/
*.lst
*.sld

View File

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

36
CPM_v2.2_r8_ddd05ed7/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,36 @@
{
"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,11 @@
# Ocean-240.2 ROM Sources CP/M (V2.2) REL.8 checksum ddd05ed7
Source codes of CP/M (V2.2) REL.8 version for Ocean-240.2 with Floppy controller.
In Z80 mnemonics, but limited for i8080 instruction set.
* 64k RAM Disk
## 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,824 @@
; =======================================================
; 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.non_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
JP warm_boot ;
disk_a_size DW 0x0040 ; 64k disk A size
disk_b_size DW 0x02d0 ; 720k disk B size
disk_c_size DW 0x02d0 ; 720k disk C size
bios_var04 DB 0x50
bios_var05 DB 0x50
; -------------------------------------------------------
; 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
; >> r8
LD HL, (bios_var0) ; if bios_var0 = 0xaaaa (initialized)
LD DE, 0x5556
ADD HL, DE ; 0xaaaa+0x5556=0x10000 if initialized
LD A, H
OR L
JP Z, bios_signon ; if initialized, go to logon, skip init
; <<
; 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.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
; init bios variables
CALL bios_init_ilv ; r8
bios_signon:
LD SP, bios_stack
; Print CP/M hello message
LD HL, msg_hello
CALL print_strz
JP bios_wboot
;bios_wboot:
; LD SP, bios_stack
; r8 >>
bios_init_ilv:
LD HL, bios_var0
LD DE, bios_ini_vals
LD C, 13
CALL mov_dlhe_c
LD A, (bios_var05) ; 0x50
LD (bios_var2), A
RET
; <<
; -------------------------------------------------------
; BIOS Warm start entry
; -------------------------------------------------------
bios_wboot: ; r8
LD HL, (bios_var0)
LD DE, 0x5556 ; 0xaaaa + 0x5556 = 0x10000
ADD HL, DE
LD A, H
OR L
CALL NZ, bios_init_ilv ; init if not initialized before
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_disk_a
LD BC, DPB_END-dph_disk_a ; 0x39 -> 57d
.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
LD HL, CPM_VARS.DPB_A_RAM
LD C, 0xf
LD DE, dpb_ram
LD A, (disk_a_size+1)
OR A
JP Z, set_curr_dpb
LD DE, dpb_empty
set_curr_dpb:
CALL mov_dlhe_c
LD HL, CPM_VARS.DPB_B_RAM
LD C, 0xf
LD DE, dpb_flop_360k
LD A, (disk_b_size+1)
CP 0x1
JP Z, .l1
LD DE, dpb_flop_720k
.l1
CALL mov_dlhe_c
LD HL, CPM_VARS.DPB_C_RAM
LD C, 0xf
LD A, (disk_c_size+1)
CP 0x2
JP Z, .l2
LD DE, dpb_flop_360k
LD A, (bios_var3)
OR A
JP NZ, .l3
LD DE, dpb_flop_720k
JP .l3
.l2
LD DE, dpb_flop_720k
LD A, (bios_var3)
OR A
JP NZ, .l3
LD DE, dpb_flop_360k
.l3
CALL mov_dlhe_c
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
; -------------------------------------------------------
; Move C bytes from [DE] to [HL]
; -------------------------------------------------------
mov_dlhe_c:
LD A,(DE) ; [DE]->[HL]
LD (HL),A
INC HL
INC DE
DEC C
JP NZ, mov_dlhe_c
RET
list_st:
XOR A
RET
; -------------------------------------------------------
; Select disk
; Inp: C - disk,
; E - active drive flag
; Out: HL -> DPH
; -------------------------------------------------------
sel_disk:
LD HL, 0x00
LD A, C
CP CTRL_C
RET NC
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.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.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, 0xA6 ; VG93 CMD
CALL MON.write_floppy
LD (CPM_VARS.tmp_slicer_result), A
RET
; --------------------------------------------------
slicer_read_buffer:
CALL slicer_get_floppy_args
LD C, 0x86 ; VG93 CMD
CALL MON.read_floppy
LD (CPM_VARS.tmp_slicer_result), A
RET
; --------------------------------------------------
slicer_get_floppy_args:
LD HL, CPM_VARS.tmp_buff9
LD A, (CPM_VARS.slicer_disk)
DEC A
JP Z, .non_interleave
LD HL, interleave_0
.non_interleave
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
; -------------------------------------------------------
; 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, "6", "0" ; Режим 32x25 <ESC>60
DB ASCII_ESC, "8", 3
DB ASCII_ESC, "5% "
DB ASCII_ESC, "4", "2"
DB ASCII_ESC, "1", 6, 0xE1, 0xF6, 0xFE, 0x01
DB ASCII_ESC, "40"
DB ASCII_ESC, "1", 10, 0xE5, 0xF2, 0xF9, 0x01
DB ASCII_ESC, "4", "1"
DB ASCII_ESC, "5", 0x21, 0x27
DB "OKEAH-240 CP/M (V2.2) REL.8\r\n\n", 0
; --------------------------------------------------
; 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 64k
dpb_ram:
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 63 ; DSM Disk size blocks - 1
DW 31 ; DRM Dir elements - 1
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)
dpb_empty:
DS 15, 0xff
; For FLOPPY 720k
dpb_flop_720k:
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 00h ; EXM extent mask
DW 359 ; DSM Disk size blocks - 1 (359d)
DW 127 ; DRM Directory entries - 1 (127d)
DB 11000000b ; AL0 Dir map byte 1 (2 dir blk)
DB 00000000b ; AL1 Dir map byte 2
DW 32 ; CKS checksum vector size (32 sectors = 2k)
DW 0000h ; OFF (No of tracks reserved for system)
; For FLOPPY 360k
dpb_flop_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 179 ; DSM Disk size blocks - 1 (179d)
DW 127 ; DRM Directory entries - 1 (127d)
DB 11000000b ; AL0 Dir map byte 1 (2 dir blk)
DB 00000000b ; AL1 Dir map byte 2
DW 32 ; CKS checksum vector size (32 sectors = 2k)
DW 0000h ; OFF (No of tracks reserved for system)
bios_ini_vals:
DB 0xaa, 0xaa, 0, 0xff, 1, 8, 6, 4, 2, 9, 7, 5, 3
; --------------------------------------------------
; Disk parameters headers in ROM
; --------------------------------------------------
; Disk A RAM
dph_disk_a:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
; 0xda00
DW CPM_VARS.dir_buffer ; Directory buffer pointer
DW CPM_VARS.DPB_A_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_disk_b:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
DW CPM_VARS.dir_buffer ; Directory buffer pointer
DW CPM_VARS.DPB_B_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_disk_c:
DW 00h ; Sector translate table pointer
DW 00h, 00h, 00h ; Scratchpad area
DW CPM_VARS.dir_buffer ; Directory buffer pointer
DW CPM_VARS.DPB_C_RAM ; DPB Pointer
DW CPM_VARS.CHK_VEC_C ; Check Vector pointer
DW CPM_VARS.AL_MAP_C ; Allocation map pointer
res_data: ; 0xda28
DB 1,8,6,4,2,9,7,5,3
DPB_END EQU $
DB 0x0e, 3
; -------------------------------------------------------
; Filler to align blocks in ROM
; -------------------------------------------------------
LAST EQU $
CODE_SIZE EQU LAST-0xD600
FILL_SIZE EQU 0x500-CODE_SIZE
DISPLAY "| BIOS\t| ",/H,boot_f," | ",/H,CODE_SIZE," | ",/H,FILL_SIZE," |"
; Check integrity
ASSERT bios_wboot = 0xd6a8
ASSERT set_curr_dpb = 0xd722
ASSERT sel_disk = 0xd781
ASSERT home = 0xd7a7
ASSERT ram_disk_calc_addr = 0xd7eb
ASSERT write_phys_op = 0xd81e
ASSERT base_read_write = 0xd88a
ASSERT calc_sec_addr_in_bfr = 0xd8e4
ASSERT slicer_save_buffer = 0xd928
ASSERT print_strz = 0xd95e
ASSERT msg_hello = 0xd96b
ASSERT dpb_ram = 0xd9af
ASSERT dph_disk_a = 0xd9f8
ASSERT res_data = 0xda28
FILLER:
DS FILL_SIZE, 0xff
ENDMODULE
IFNDEF BUILD_ROM
OUTEND
ENDIF

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,901 @@
; =======================================================
; 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_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_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, (bios_var3)
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, 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 ; DIFF
.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, 0xff
;DB 0xaa
ENDMODULE
IFNDEF BUILD_ROM
OUTEND
ENDIF

View File

@ -0,0 +1,44 @@
; ======================================================
; Ocean-240.2
; CP/M Combine file. Includes all sources to build
; ROM 0xC000
;
; Disassembled by Romych 2025-02-12
; ======================================================
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
;LABELSLIST "cpm.labels"
;CSPECTMAP "cpm.map"
INCLUDE "ccp_ram.asm"
INCLUDE "bdos.asm"
INCLUDE "bios.asm"
INCLUDE "ccp_rom.asm"
OUTEND
OUTPUT variables.bin
INCLUDE "cpm_vars.inc"
OUTEND
END

View File

@ -0,0 +1,219 @@
; =======================================================
; Ocean-240.2
; Module CPM_VARS - 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 DB 0
bdos_strtcol DB 0
bdos_column DB 0
; Copy output to printer in non zero
bdos_prnflag DB 0
bdos_kbchar DB 0
; Stored user stack pointer on enter bdos fn
bdos_usersp DW 0 ; 0xba0e
; BDOS Stack
DS 48, 0
bdos_stack EQU $
; -------------------------------------------------------
; Common values shared between bdosi and bdos
; -------------------------------------------------------
; current user number 0..15
bdos_userno DB 0x00 ; 0xba40
; current disk number
bdos_curdsk DB 0x00
; reg DE (pointer) value to call BDOS fn
bdos_info DW 0x0000 ; 0xba42
; Address value to return
bdos_aret DW 0x0000 ; 0xba44
; Empty FCB
bdos_efcb DB 0x00 ; 0xba46 = 0xE5 at init
; Read-only disks flag
bdos_rodsk DW 0x0000 ; 0xba47
; Drive login vector
bdos_dlog DW 0x0000 ; 0xba49
; Address of DMA buffer
bdos_dmaad DW 0x0000 ; 0xba4b = 0x80 at init
bdos_cdrmax DW 0x0000 ; 0xba4d
; Current track
bdos_curtrk DW 0x0000 ; 0xba4f
; Current record (sector)
bdos_currec DW 0x0000 ; 0xba51
; Address of user buffer
bdos_buffa DW 0x0000 ; 0xba53
; Address of cur disk DPB
bdos_dpbaddr DW 0x0000 ; 0xba55
; Calculated checksum
bdos_cksum DW 0x0000 ; 0xba57
; Address of cur disk allocation map
bdos_alloca DW 0x0000 ; 0xba59
; Sectors per track
dbos_sectpt DW 0x0000 ; 0xba5b
bdos_blkshf DB 0x00 ; 0xba5d
bdos_blmsk DB 0x00 ; 0xba5e
bdos_extmsk DB 0x00 ; 0xba5f
; Max allocation number (disk size)
bdos_maxall DW 0x0000 ; 0xba60
bdos_dirmax DW 0x0000 ; 0xba62
; Size of directory
bdos_dirblk DW 0x0000 ; 0xba64
bdos_alloc1 DW 0x0000 ; 0xba66
; First track offset
bdos_offset DW 0x0000 ; 0xba68
; Disk traslation vector address
bdos_tranv DW 0x0000 ; 0xba6a
; Open and closed flag 0xff - closed
bdos_fcb_closed DB 0x00 ; 0xba6c
; Read file modified flag. 0xff - not allow read unwritten
bdos_rfm DB 0x00 ; 0xba6d
bdos_dirloc DB 0x00 ; 0xba6e
; File access mode (0=random, 1=sequential, 2=special)
bdos_seqio DB 0x00 ; 0xba6f
; Reg E value to call BDOS fn
bdos_linfo DB 0x00 ; 0xba70
bdos_dminx DB 0x00 ; 0xba71
; Length in bytes to match when search
bdos_searchl DB 0x00 ; 0xba72
; Address of buffer where to search
bdos_searcha DW 0x0000 ; 0xba73
DW 0x0000
; 0 - big disk (>255 blk), 0xff - small disk
bdos_small_disk DB 0x00 ; 0xba77
; Drive selected (0xff) by user specified FCB flag
bdos_resel DB 0x00 ; 0xba78
bdos_olddsk DB 0x00 ; 0xba79
; Saved disk of user FCB
bdos_fcbdsk DB 0x00 ; 0xba7a
; Number of records in extent
bdos_rcount DB 0x00 ; 0xba7b
bdos_extval DB 0x00 ; 0xba7c
; Record number to read
bdos_vrecord DW 0x0000 ; 0xba7d
; Record to access
bdos_arecord DW 0x0000 ; 0xba7f
bdos_arecord1 DW 0x0000 ; 0xba81
bdos_dptr DB 0x00 ; 0xba83
bdos_dcnt DW 0x00 ; 0xba84
bdos_drec DS 20, 0x00 ; 0xba86
tmp_dir_total DW 0x0000 ; 0xba9a
; Save pointer at ccp entry, restore on exit
saved_stack_ptr DW 0x0000 ; 0xba9c
DS 22, 0
ccp_safe_stack
DW 0x0000 ; 0xbab4
; --------------------------------------------------
; FCB
; --------------------------------------------------
ccp_fcb
ccp_fcb_dr DB 0 ; 0xbab6 drive letter to write file
ccp_fcb_fn DS 8,0 ; 0xbab7 file name
ccp_fcb_ft DS 3,0 ; file type
ccp_fcb_ext DB 0 ; extent
ccp_fcb_s1 DB 0
ccp_fcb_s2 DB 0 ; extent hi bits
ccp_fcb_rc DB 0
ccp_fcb_al DS 16, 0 ; Second half of FCB
ccp_fcb_cr DB 0x00 ; Current record
ccp_fcb_rn DB 0x00 ; Random access record number
DW 0x00
DW 0x00
DW 0x00
ccp_vars_end EQU $
; --------------------------------------------------
; Disk parameters headers/blocks in RAM
; --------------------------------------------------
DPH_RAM DS 16, 0 ; 0xbade
DPH1_RAM DS 16, 0 ; 0xbaee
DPH2_RAM DS 16, 0 ; 0xbafe
tmp_buff9 DS 9, 0
DPB_A_RAM DS 15, 0 ; 0xbb17
DPB_B_RAM DS 15, 0 ; 0xbb26
DPB_C_RAM DS 15, 0 ; 0xbb35
; --------------------------------------------------
cur_disk DB 0x00 ; 0xbb44
dma_addr DW 0x0000 ; 0xbb46
curr_track DB 0x00 ; 0xbb47
curr_sec DB 0x00 ; 0xbb48
slicer_disk DB 0x00 ; 0xbb49
slicer_track DB 0x00 ; 0xbb4a
slicer_real_sector DB 0x00 ; 0xbb4b
tmp_slicer_real_sector DB 0x00 ; 0xbb4c
slicer_has_data DB 0x00 ; 0xbb4d
slicer_need_save DB 0x00 ; 0xbb4e
slicer_uninited_count DB 0x00 ; 0xbb4f
slicer_uninited_disk DB 0x00 ; 0xbb42
slicer_uninited_track DB 0x00 ; 0xbb43
slicer_uninited_sector_128 DB 0x00 ; 0xbb44
tmp_slicer_result DB 0x00 ; 0xbb45
tmp_slicer_can_read DB 0x00 ; 0xbb46
tmp_slicer_operation DB 0x00 ; 0xbb47
tmp_slicer_flush DB 0x00 ; 0xbb48
; Directory buffer used by BDOS for directory operations
dir_buffer DS DIR_BUFF_SIZE, 0 ; 0xbb49
; Allocation map for drive A (Mark used allocation blocks)
AL_MAP_A DS 31, 0 ; 248 bit
; Check vector for drive A (Checksumm of dir entries, used to detect disk change)
CHK_VEC_A DS 16, 0 ; 0xbbf6
; Allocation map for drive B
AL_MAP_B DS 45, 0 ; 184 bit
; Check vector for drive B
CHK_VEC_B DS 32, 0 ; 0xbc33
; Allocation map for drive C
AL_MAP_C DS 45, 0 ; 184 bit
; Check vector for drive C
CHK_VEC_C DS 32, 0 ; 0xbc80
DS 96, 0
slicer_buffer DS 512, 0 ; 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 cur_disk = 0xbb44
ASSERT slicer_uninited_count = 0xbb4f
ASSERT slicer_buffer = 0xbd00
DISPLAY "| CCP_VARS\t| ",/H,cpm_vars_start," | ",/H,cpm_vars_size," |\t |"
DISPLAY "cur_disk:",/H,cur_disk
ENDMODULE
ENDIF

View File

@ -0,0 +1,149 @@
; ======================================================
; Ocean-240.2
; Equates for all assembly sources
;
; By Romych 2025-09-09
; ======================================================
IFNDEF _EQUATES
DEFINE _EQUATES
ADDLIST EQU 0x08
ASCII_BELL EQU 0x07 ; Make Beep
ASCII_BS EQU 0x08 ; Move cursor left (Back Space)
ASCII_TAB EQU 0x09 ; Move cursor right +8 pos
ASCII_LF EQU 0x0A ; Move cursor down (Line Feed)
ASCII_FF EQU 0x0C ; Move cursor to home (Form Feed)
ASCII_CR EQU 0x0D ; Move gursor to 1st pos (Cariage Return)
ASCII_CAN EQU 0x18 ; Move cursor right
ASCII_EM EQU 0x19 ; Move cursor up
ASCII_SUB EQU 0x1A ; CTRL-Z - end of text file marker
ASCII_ESC EQU 0x1B ;
ASCII_US EQU 0x1F ; Clear screen
ASCII_SP EQU 0x20
ASCII_DEL EQU 0x7F
; ------------------------------------------------------
BDOS_NFUNCS EQU 41
BELL_PIN EQU 0x08 ; DD67 Pin PC3 - "BELL"
; ------------------------------------------------------
CCP_COMMAND_SIZE EQU 5 ; max length of CCP command
CCP_COMMAND_COUNT EQU 3 ; Count of CCP commands
CCP_COMMAND_CNT EQU 6
CCP_COMMAND_LEN EQU 4
CCP_SRC_ADDR EQU 0xc000 ; Address of CCP resident part in ROM
CCP_DST_ADDR EQU 0xb200 ; Address of CCP resident part in RAM
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
DIR_BUFF_SIZE EQU 128
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
FDC_RESTORE_UH_NV EQU 0x03 ; Restore Unload Head, No Verify, 15ms Rate
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
; ------------------------------------------------------
IRQ_0 EQU 0x01
IRQ_1 EQU 0x02
IRQ_2 EQU 0x04
;LP_IRQ EQU 0x08
KBD_IRQ EQU 0x02
KBD_ACK EQU 0x10
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
RO_FILE EQU 0x09
ROM_CHIP_SIZE EQU 8192 ; ROM Size, used to limit monitor code size
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
; ------------------------------------------------------
ENDIF

132
CPM_v2.2_r8_ddd05ed7/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
DEFINE _MON
MODULE MON
mon_init EQU 0xe000
mon_cold_start EQU 0xe003
non_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
ram_disk_read EQU 0xe01e
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
read_floppy EQU 0xe030
write_floppy EQU 0xe033
ENDMODULE
ENDIF

View File

@ -0,0 +1,49 @@
; =======================================================
; 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
@RST1 EQU 0x0008
@RST1_handler_addr EQU 0x0009
;RST2 EQU 0x0010
;RST3 EQU 0x0018
;RST4 EQU 0x0020
;RST5 EQU 0x0028
;RST6 EQU 0x0030
;RST7 EQU 0x0038
;reserve1 EQU 0x003b
@bios_var0 EQU 0x0040 ; 0xaa - bios init r8
@bios_var1 EQU 0x0041 ; 0xaa - bios init r8
@bios_var2 EQU 0x0042 ; 0x00 - bios init r8
@bios_var3 EQU 0x0043 ; 0xff - bios init r8
@interleave_0 EQU 0x0044
;reserve2 EQU 0x0050
@fcb1 EQU 0x005c ; Default FCB, 16 bytes
@fcb2 EQU 0x006c
;NMI_ISR EQU 0x0066
@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

10
MON_Turbo/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
*.labels
*.obj
*.OBJ
*.bin
*.tmp
tmp/
build/
*.lst
*.sld

9
MON_Turbo/.vscode/extensions.json vendored Normal file
View File

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

65
MON_Turbo/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,65 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "make MONITOR (sjasmplus)",
"type": "shell",
"command": "sjasmplus",
"args": [
"--sld=turbo_mon.sld",
"--sym=turbo_mon.labels",
"--raw=turbo_mon.obj",
"--fullpath",
"turbo_mon.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
}
},
{
"label": "Optimize MONITOR (MDL)",
"type": "shell",
"command": "/opt/java21/bin/java -jar ~/Soft/MDL/mdl.jar monitor.asm -cpu z80 -so -dialect sjasmplus",
"group": "build",
"problemMatcher": {
"applyTo": "allDocuments",
"fileLocation": [
"autoDetect",
"${workspaceFolder}"
],
"pattern": [
{
"regexp": "^(\\w+): (.+) in (.+)#([0-9]+): (.+)$",
"file": 3,
"line": 4,
"severity": 1,
"message": 5,
"code": 2
}
]
},
"presentation": {
"echo": false,
"focus": false,
"panel": "dedicated",
"showReuseMessage": false,
"clear": true,
"revealProblems": "onProblem"
}
}
]
}

Binary file not shown.

15
MON_Turbo/README.md Normal file
View File

@ -0,0 +1,15 @@
# Ocean-240.2 ROM Turbo monitor by Azmaster
**CRC32 checksum**: bcac5ca0
Source codes of Turbo Monitor for Ocean-240.2 with Floppy controller.
In Z80 mnemonics, but limited for i8080 instruction set.
## Compile:
Code is located in memory at address: 0xE000..0xFFFF
sjasmplus --sld=turbo_mon.sld --sym=turbo_mon.labels --raw=turbo_mon.obj --fullpath turbo_mon.asm
To compile sources, use [sjasmplus Z80 assembler](https://github.com/z00m128/sjasmplus).

View File

@ -0,0 +1,41 @@
; =======================================================
; 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
bios_var04 EQU 0xD64B
ENDMODULE
ENDIF

149
MON_Turbo/equates.inc Normal file
View File

@ -0,0 +1,149 @@
; ======================================================
; Ocean-240.2
; Equates for all assembly sources
;
; By Romych 2025-09-09
; ======================================================
IFNDEF _EQUATES
DEFINE _EQUATES
ADDLIST EQU 0x08
ASCII_BELL EQU 0x07 ; Make Beep
ASCII_BS EQU 0x08 ; Move cursor left (Back Space)
ASCII_TAB EQU 0x09 ; Move cursor right +8 pos
ASCII_LF EQU 0x0A ; Move cursor down (Line Feed)
ASCII_FF EQU 0x0C ; Move cursor to home (Form Feed)
ASCII_CR EQU 0x0D ; Move gursor to 1st pos (Cariage Return)
ASCII_CAN EQU 0x18 ; Move cursor right
ASCII_EM EQU 0x19 ; Move cursor up
ASCII_SUB EQU 0x1A ; CTRL-Z - end of text file marker
ASCII_ESC EQU 0x1B ;
ASCII_US EQU 0x1F ; Clear screen
ASCII_SP EQU 0x20
ASCII_DEL EQU 0x7F
; ------------------------------------------------------
BDOS_NFUNCS EQU 41
BELL_PIN EQU 0x08 ; DD67 Pin PC3 - "BELL"
; ------------------------------------------------------
CCP_COMMAND_SIZE EQU 5 ; max length of CCP command
CCP_COMMAND_COUNT EQU 3 ; Count of CCP commands
CCP_COMMAND_CNT EQU 6
CCP_COMMAND_LEN EQU 4
CCP_SRC_ADDR EQU 0xc000 ; Address of CCP resident part in ROM
CCP_DST_ADDR EQU 0xb200 ; Address of CCP resident part in RAM
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
DIR_BUFF_SIZE EQU 128
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
FDC_RESTORE_UH_NV EQU 0x03 ; Restore Unload Head, No Verify, 15ms Rate
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
; ------------------------------------------------------
IRQ_0 EQU 0x01
IRQ_1 EQU 0x02
IRQ_2 EQU 0x04
;LP_IRQ EQU 0x08
KBD_IRQ EQU 0x02
KBD_ACK EQU 0x10
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
RO_FILE EQU 0x09
ROM_CHIP_SIZE EQU 8192 ; ROM Size, used to limit monitor code size
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
; ------------------------------------------------------
ENDIF

132
MON_Turbo/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

35
MON_Turbo/mon_entries.inc Normal file
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_ENTRY
mon_init EQU 0xe000
mon_cold_start EQU 0xe003
non_con_status EQU 0xe006
mon_con_in EQU 0xe009
mon_con_out EQU 0xe00c
mon_serial_in EQU 0xe00f
mpn_serial_out EQU 0xe012
mon_char_print EQU 0xe015
mon_tape_read EQU 0xe018
mon_tape_write EQU 0xe01b
ram_disk_read EQU 0xe01e
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
read_floppy EQU 0xe030
write_floppy EQU 0xe033
ENDMODULE
ENDIF

49
MON_Turbo/ram.inc Normal file
View File

@ -0,0 +1,49 @@
; =======================================================
; 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
@RST1 EQU 0x0008
@RST1_handler_addr EQU 0x0009
;RST2 EQU 0x0010
;RST3 EQU 0x0018
;RST4 EQU 0x0020
;RST5 EQU 0x0028
;RST6 EQU 0x0030
;RST7 EQU 0x0038
;reserve1 EQU 0x003b
@bios_var0 EQU 0x0040 ; 0xaa - bios init r8
@bios_var1 EQU 0x0041 ; 0xaa - bios init r8
@bios_var2 EQU 0x0042 ; 0x00 - bios init r8
@bios_var3 EQU 0x0043 ; 0xff - bios init r8
@interleave_0 EQU 0x0044
;reserve2 EQU 0x0050
@fcb1 EQU 0x005c ; Default FCB, 16 bytes
@fcb2 EQU 0x006c
;NMI_ISR EQU 0x0066
@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

90
MON_Turbo/tm_vars.inc Normal file
View File

@ -0,0 +1,90 @@
; =======================================================
; Ocean-240.2
; Module TM_VARS - Turbo monitor variables
; RAM Range: 0xBA09-0xBFFF
;
; Disassembled by Romych 2025-09-09
; =======================================================
IFNDEF _TM_VARS
DEFINE _TM_VARS
MODULE TM_VARS
ORG 0xbf00
tm_stack ds 80 ; 0xbf00 search text or buffer to search?
tm_ltb ds 32 ; 0xbf50
tm_strt ds 16 ; 0xbf70
tm_track_no ds 1 ; 0xbf80
tm_sector_no ds 1 ; 0xbf81
tm_num_sect ds 1 ; 0xbf82
tm_disk_op ds 1 ; 0xbf83
tm_rw_disk ds 1 ; 0xbf84
tm_drive ds 2 ; 0xbf85
tm_tbu ds 1 ; 0xbf87
; user entered command buffer
tm_hrg ds 48 ; 0xbf88
tm_stack_top ds 2 ; 0xbfb8
tm_stsp ds 6 ; 0xbfba
rst_af_save ds 2 ; 0xbfc0
rst_bc_save ds 2 ; 0xbfc2
rst_de_save ds 2 ; 0xbfc4
rst_hl_save ds 2 ; 0xbfc6
rst_sp_save ds 2 ; 0xbfc8
rst_ret_JP ds 1 ; 0xbfca
rst_ret_addr ds 2 ; 0xbfcb
ds 2 ; 0xbfcd
ds 3 ; 0xbfcf
tm_stack_0 ds 2 ; 0xbfd2
ds 2 ; 0xbfd4
ds 2 ; 0xbfd6
ds 1 ; 0xbfd8
m_esc_mode ds 1 ; 0xbfd9
m_esc_cmd ds 1 ; 0xbfda
m_esc_param_cnt ds 1 ; 0xbfdb
m_esc_param_1 ds 1 ; 0xbfdc
m_esc_param_2 ds 1 ; 0xbfdd
m_esc_param_3 ds 1 ; 0xbfde
m_esc_param_4 ds 1 ; 0xbfdf
m_esc_hex_cmd ds 1 ; 0xbfe0
m_esc_param_6 ds 1 ; 0xbfe1
ds 4 ; 0xbfe2
m_screen_mode ds 1 ; 0xbfe6
m_cursor_row ds 1 ; 0xbfe7
m_cursor_col ds 1 ; 0xbfe8
m_curr_color ds 2 ; 0xbfe9
m_row_shift ds 1 ; 0xbfeb
m_codepage ds 1 ; 0xbfec
m_cur_palette ds 1 ; 0xbfed
m_beep_period ds 2 ; 0xbfee
m_beep_duration ds 2 ; 0xbff0
m_pix_shift ds 1 ; 0xbff2
m_strobe_state ds 1 ; 0xbff3
m_print_pos_x ds 2 ; 0xbff4
ds 2
ds 2
m_last_key ds 1 ; 0xbffa
m_last_shifts ds 1 ; 0xbffb
mc_fix_state ds 1 ; 0xbffc
mc_stored_key ds 1 ; 0xbffd
ASSERT tm_stack_top = 0xbfb8
ASSERT tm_stack = 0xbf00
ASSERT tm_hrg = 0xbf88
ASSERT rst_hl_save = 0xbfc6
ASSERT rst_ret_addr = 0xbfcb
ASSERT tm_stack_0 = 0xbfd2
ASSERT m_esc_mode = 0xbfd9
ASSERT m_screen_mode = 0xbfe6
ASSERT mc_stored_key = 0xbffd
; DISPLAY " m_esc_mode is: ", m_esc_mode
; DISPLAY " m_esc_mode is: ", m_esc_mode
; DISPLAY " rst_ret_addr is: ", rst_ret_addr
; DISPLAY " tm_stack_top is: ", tm_stack_top
; DISPLAY " mc_stored_key is: ", mc_stored_key
ENDMODULE
ENDIF

4787
MON_Turbo/turbo_mon.asm Normal file

File diff suppressed because it is too large Load Diff

10
MON_v8_3edeb015/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
*.labels
*.obj
*.OBJ
*.bin
*.tmp
tmp/
build/
*.lst
*.sld

Binary file not shown.

17
MON_v8_3edeb015/README.md Normal file
View File

@ -0,0 +1,17 @@
# Ocean-240.2 ROM Monitor V8 checksum 3edeb015
Source codes of Monitor v8 for Ocean-240.2 with Floppy controller.
In Z80 mnemonics, but limited for i8080 instruction set.
## Differences:
1) Font. Russian letters б and д;
2) Calculate values for extended ram access in procedures m_ramdisk_read, m_ramdisk_write.
## Compile:
Code is located in memory at address: 0xE000..0xFFFF
sjasmplus --sld=monitor.sld --sym=monitor.labels --raw=monitor.obj --fullpath monitor.asm
To compile sources, use [sjasmplus Z80 assembler](https://github.com/z00m128/sjasmplus).

View File

@ -0,0 +1,41 @@
; =======================================================
; 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
bios_var04 EQU 0xD64B
ENDMODULE
ENDIF

149
MON_v8_3edeb015/equates.inc Normal file
View File

@ -0,0 +1,149 @@
; ======================================================
; Ocean-240.2
; Equates for all assembly sources
;
; By Romych 2025-09-09
; ======================================================
IFNDEF _EQUATES
DEFINE _EQUATES
ADDLIST EQU 0x08
ASCII_BELL EQU 0x07 ; Make Beep
ASCII_BS EQU 0x08 ; Move cursor left (Back Space)
ASCII_TAB EQU 0x09 ; Move cursor right +8 pos
ASCII_LF EQU 0x0A ; Move cursor down (Line Feed)
ASCII_FF EQU 0x0C ; Move cursor to home (Form Feed)
ASCII_CR EQU 0x0D ; Move gursor to 1st pos (Cariage Return)
ASCII_CAN EQU 0x18 ; Move cursor right
ASCII_EM EQU 0x19 ; Move cursor up
ASCII_SUB EQU 0x1A ; CTRL-Z - end of text file marker
ASCII_ESC EQU 0x1B ;
ASCII_US EQU 0x1F ; Clear screen
ASCII_SP EQU 0x20
ASCII_DEL EQU 0x7F
; ------------------------------------------------------
BDOS_NFUNCS EQU 41
BELL_PIN EQU 0x08 ; DD67 Pin PC3 - "BELL"
; ------------------------------------------------------
CCP_COMMAND_SIZE EQU 5 ; max length of CCP command
CCP_COMMAND_COUNT EQU 3 ; Count of CCP commands
CCP_COMMAND_CNT EQU 6
CCP_COMMAND_LEN EQU 4
CCP_SRC_ADDR EQU 0xc000 ; Address of CCP resident part in ROM
CCP_DST_ADDR EQU 0xb200 ; Address of CCP resident part in RAM
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
DIR_BUFF_SIZE EQU 128
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
FDC_RESTORE_UH_NV EQU 0x03 ; Restore Unload Head, No Verify, 15ms Rate
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
; ------------------------------------------------------
IRQ_0 EQU 0x01
IRQ_1 EQU 0x02
IRQ_2 EQU 0x04
;LP_IRQ EQU 0x08
KBD_IRQ EQU 0x02
KBD_ACK EQU 0x10
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
RO_FILE EQU 0x09
ROM_CHIP_SIZE EQU 8192 ; ROM Size, used to limit monitor code size
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
; ------------------------------------------------------
ENDIF

View File

@ -0,0 +1,165 @@
; 96 symbols 6x7, with codes 0x20..0x7f KOI-7 H0
m_font_cp0:
DB 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; ' ' - 0x20
DB 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x04 ; '!' - 0x21
DB 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00 ; '"' - 0x22
DB 0x0a, 0x0a, 0x1f, 0x0a, 0x1f, 0x0a, 0x0a ; '#' - 0x23
DB 0x04, 0x1e, 0x05, 0x0e, 0x14, 0x0f, 0x04 ; '$' - 0x24
DB 0x03, 0x13, 0x08, 0x04, 0x02, 0x19, 0x18 ; '%' - 0x25
DB 0x06, 0x09, 0x05, 0x02, 0x15, 0x09, 0x16 ; '&' - 0x26
DB 0x06, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00 ; ' - 0x27
DB 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08 ; '(' - 0x28
DB 0x02, 0x04, 0x08, 0x08, 0x08, 0x04, 0x02 ; ')' - 0x29
DB 0x00, 0x0a, 0x04, 0x1f, 0x04, 0x0a, 0x00 ; '*' - 0x2a
DB 0x00, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x00 ; '+' - 0x2b
DB 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x02 ; ',' - 0x2c
DB 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00 ; '-' - 0x2d
DB 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06 ; '.' - 0x2e
DB 0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00 ; '/' - 0x2f
DB 0x0e, 0x11, 0x19, 0x15, 0x13, 0x11, 0x0e ; '0' - 0x30
DB 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x0e ; '1' - 0x31
DB 0x0e, 0x11, 0x10, 0x08, 0x04, 0x02, 0x1f ; '2' - 0x32
DB 0x1f, 0x08, 0x04, 0x08, 0x10, 0x11, 0x0e ; '3' - 0x33
DB 0x08, 0x0c, 0x0a, 0x09, 0x1f, 0x08, 0x08 ; '4' - 0x34
DB 0x1f, 0x01, 0x0f, 0x10, 0x10, 0x11, 0x0e ; '5' - 0x35
DB 0x0c, 0x02, 0x01, 0x0f, 0x11, 0x11, 0x0e ; '6' - 0x36
DB 0x1f, 0x10, 0x08, 0x04, 0x02, 0x02, 0x02 ; '7' - 0x37
DB 0x0e, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x0e ; '8' - 0x38
DB 0x0e, 0x11, 0x11, 0x1e, 0x10, 0x08, 0x06 ; '9' - 0x39
DB 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00 ; ':' - 0x3a
DB 0x00, 0x06, 0x06, 0x00, 0x06, 0x04, 0x02 ; ';' - 0x3b
DB 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08 ; '<' - 0x3c
DB 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00 ; '=' - 0x3d
DB 0x02, 0x04, 0x08, 0x10, 0x08, 0x04, 0x02 ; '>' - 0x3e
DB 0x0e, 0x11, 0x10, 0x08, 0x04, 0x00, 0x04 ; '?' - 0x3f
DB 0x0e, 0x11, 0x10, 0x16, 0x15, 0x15, 0x0e ; '@' - 0x40
DB 0x04, 0x0a, 0x11, 0x11, 0x1f, 0x11, 0x11 ; 'A' - 0x41
DB 0x0f, 0x11, 0x11, 0x0f, 0x11, 0x11, 0x0f ; 'B' - 0x42
DB 0x0e, 0x11, 0x01, 0x01, 0x01, 0x11, 0x0e ; 'C' - 0x43
DB 0x07, 0x09, 0x11, 0x11, 0x11, 0x09, 0x07 ; 'D' - 0x44
DB 0x1f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x1f ; 'E' - 0x45
DB 0x1f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x01 ; 'F' - 0x46
DB 0x0e, 0x11, 0x01, 0x1d, 0x11, 0x11, 0x1e ; 'G' - 0x47
DB 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11 ; 'H' - 0x48
DB 0x0e, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0e ; 'I' - 0x49
DB 0x1c, 0x08, 0x08, 0x08, 0x08, 0x09, 0x06 ; 'J' - 0x4a
DB 0x11, 0x09, 0x05, 0x03, 0x05, 0x09, 0x11 ; 'K' - 0x4b
DB 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1f ; 'L' - 0x4c
DB 0x11, 0x1b, 0x15, 0x15, 0x11, 0x11, 0x11 ; 'M' - 0x4d
DB 0x11, 0x11, 0x13, 0x15, 0x19, 0x11, 0x11 ; 'N' - 0x4e
DB 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e ; 'O' - 0x4f
DB 0x0f, 0x11, 0x11, 0x0f, 0x01, 0x01, 0x01 ; 'P' - 0x50
DB 0x0e, 0x11, 0x11, 0x11, 0x15, 0x09, 0x16 ; 'Q' - 0x51
DB 0x0f, 0x11, 0x11, 0x0f, 0x05, 0x09, 0x11 ; 'R' - 0x52
DB 0x1e, 0x01, 0x01, 0x0e, 0x10, 0x10, 0x0f ; 'S' - 0x53
DB 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; 'T' - 0x54
DB 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e ; 'U' - 0x55
DB 0x11, 0x11, 0x11, 0x11, 0x0a, 0x0a, 0x04 ; 'V' - 0x56
DB 0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0x0a ; 'W' - 0x57
DB 0x11, 0x11, 0x0a, 0x04, 0x0a, 0x11, 0x11 ; 'X' - 0x58
DB 0x11, 0x11, 0x11, 0x0a, 0x04, 0x04, 0x04 ; 'Y' - 0x59
DB 0x1f, 0x10, 0x08, 0x04, 0x02, 0x01, 0x1f ; 'Z' - 0x5a
DB 0x0e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0e ; '[' - 0x5b
DB 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00 ; '\' - 0x5c
DB 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e ; ']' - 0x5d
DB 0x0e, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00 ; '^' - 0x5r
DB 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f ; '_' - 0x5f
DB 0x1c, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00 ; '`' - 0x60
DB 0x00, 0x00, 0x0e, 0x10, 0x1e, 0x13, 0x1e ; 'a' - 0x61
DB 0x01, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x0f ; 'b' - 0x62
DB 0x00, 0x00, 0x0e, 0x01, 0x01, 0x01, 0x0e ; 'c' - 0x63
DB 0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x1e ; 'd' - 0x64
DB 0x00, 0x00, 0x0e, 0x11, 0x1f, 0x01, 0x0e ; 'e' - 0x65
DB 0x18, 0x04, 0x04, 0x0e, 0x04, 0x04, 0x04 ; 'f' - 0x66
DB 0x00, 0x0e, 0x11, 0x11, 0x1e, 0x10, 0x0e ; 'g' - 0x67
DB 0x01, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x11 ; 'h' - 0x68
DB 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04 ; 'i' - 0x69
DB 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x06 ; 'j' - 0x6a
DB 0x01, 0x01, 0x09, 0x05, 0x03, 0x05, 0x09 ; 'k' - 0x6b
DB 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08 ; 'l' - 0x6c
DB 0x00, 0x00, 0x0f, 0x15, 0x15, 0x15, 0x15 ; 'm' - 0x6d
DB 0x00, 0x00, 0x09, 0x13, 0x11, 0x11, 0x11 ; 'n' - 0x6e
DB 0x00, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e ; 'o' - 0x6f
DB 0x00, 0x00, 0x0e, 0x11, 0x11, 0x0f, 0x01 ; 'p' - 0x70
DB 0x00, 0x00, 0x0e, 0x11, 0x11, 0x1e, 0x10 ; 'q' - 0x71
DB 0x00, 0x00, 0x0d, 0x13, 0x01, 0x01, 0x01 ; 'r' - 0x72
DB 0x00, 0x00, 0x1e, 0x01, 0x0e, 0x10, 0x0f ; 's' - 0x73
DB 0x04, 0x04, 0x0e, 0x04, 0x04, 0x04, 0x18 ; 't' - 0x74
DB 0x00, 0x00, 0x11, 0x11, 0x11, 0x19, 0x16 ; 'u' - 0x75
DB 0x00, 0x00, 0x11, 0x11, 0x0a, 0x0a, 0x04 ; 'v' - 0x76
DB 0x00, 0x00, 0x11, 0x15, 0x15, 0x15, 0x0a ; 'w' - 0x77
DB 0x00, 0x00, 0x11, 0x0a, 0x04, 0x0a, 0x11 ; 'x' - 0x78
DB 0x00, 0x00, 0x11, 0x11, 0x1e, 0x10, 0x0c ; 'y' - 0x79
DB 0x00, 0x00, 0x1f, 0x08, 0x04, 0x02, 0x1f ; 'z' - 0x7a
DB 0x0c, 0x02, 0x02, 0x01, 0x02, 0x02, 0x0c ; '{' - 0x7b
DB 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; '|' - 0x7c
DB 0x03, 0x04, 0x04, 0x08, 0x04, 0x04, 0x03 ; '}' - 0x7d
DB 0x00, 0x02, 0x15, 0x0a, 0x15, 0x08, 0x00 ; '~' - 0x7e
DB 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15 ; [DEL] - 0x7f
; 64 symbols 6x7, with codes 0x40..0x7f KOI-7 H1
m_font_cp1:
DB 0x00, 0x00, 0x09, 0x15, 0x17, 0x15, 0x09 ; ю - 0x40
DB 0x00, 0x00, 0x06, 0x08, 0x0e, 0x09, 0x16 ; а - 0x41
DB 0x07, 0x02, 0x04, 0x0e, 0x09, 0x09, 0x06 ; б - 0x42 DIFF
DB 0x00, 0x00, 0x09, 0x09, 0x09, 0x1f, 0x10 ; ц - 0x43
DB 0x03, 0x04, 0x08, 0x0e, 0x09, 0x09, 0x06 ; д - 0x44 DIFF
DB 0x00, 0x00, 0x0e, 0x11, 0x1f, 0x01, 0x1e ; е - 0x45
DB 0x00, 0x04, 0x0e, 0x15, 0x15, 0x0e, 0x04 ; ф - 0x46
DB 0x00, 0x00, 0x0f, 0x09, 0x01, 0x01, 0x01 ; г - 0x47
DB 0x00, 0x00, 0x11, 0x0a, 0x04, 0x0a, 0x11 ; х - 0x48
DB 0x00, 0x00, 0x11, 0x19, 0x15, 0x13, 0x11 ; и - 0x49
DB 0x0a, 0x04, 0x11, 0x19, 0x15, 0x13, 0x11 ; й - 0x4a
DB 0x00, 0x00, 0x11, 0x09, 0x07, 0x09, 0x11 ; к - 0x4b
DB 0x00, 0x00, 0x1c, 0x12, 0x12, 0x12, 0x11 ; л - 0x4c
DB 0x00, 0x00, 0x11, 0x1b, 0x15, 0x11, 0x11 ; м - 0x4d
DB 0x00, 0x00, 0x11, 0x11, 0x1f, 0x11, 0x11 ; н - 0x4e
DB 0x00, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e ; о - 0x4f
DB 0x00, 0x00, 0x1f, 0x11, 0x11, 0x11, 0x11 ; п - 0x50
DB 0x00, 0x00, 0x1e, 0x11, 0x1e, 0x14, 0x12 ; я - 0x51
DB 0x00, 0x00, 0x07, 0x09, 0x07, 0x01, 0x01 ; р - 0x52
DB 0x00, 0x00, 0x0e, 0x01, 0x01, 0x01, 0x0e ; с - 0x53
DB 0x00, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04 ; т - 0x54
DB 0x00, 0x00, 0x11, 0x11, 0x1e, 0x10, 0x0e ; у - 0x55
DB 0x00, 0x00, 0x15, 0x15, 0x0e, 0x15, 0x15 ; ж - 0x56
DB 0x00, 0x00, 0x03, 0x05, 0x07, 0x09, 0x07 ; в - 0x57
DB 0x00, 0x00, 0x01, 0x01, 0x07, 0x09, 0x07 ; ь - 0x58
DB 0x00, 0x00, 0x11, 0x11, 0x13, 0x15, 0x13 ; ы - 0x59
DB 0x00, 0x00, 0x0e, 0x11, 0x0c, 0x11, 0x0e ; з - 0x5a
DB 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x1f ; ш - 0x5b
DB 0x00, 0x00, 0x07, 0x08, 0x0e, 0x08, 0x07 ; э - 0x5c
DB 0x00, 0x00, 0x15, 0x15, 0x15, 0x1f, 0x10 ; щ - 0x5d
DB 0x00, 0x00, 0x09, 0x09, 0x0e, 0x08, 0x08 ; ч - 0x5e
DB 0x00, 0x00, 0x06, 0x05, 0x0c, 0x14, 0x0c ; ъ - 0x5f
DB 0x09, 0x15, 0x15, 0x17, 0x15, 0x15, 0x09 ; Ю - 0x60
DB 0x04, 0x0a, 0x11, 0x11, 0x1f, 0x11, 0x11 ; А - 0x61
DB 0x1f, 0x11, 0x01, 0x0f, 0x11, 0x11, 0x1f ; Б - 0x62
DB 0x09, 0x09, 0x09, 0x09, 0x09, 0x1f, 0x10 ; С - 0x63
DB 0x0c, 0x0a, 0x0a, 0x0a, 0x0a, 0x1f, 0x11 ; Д - 0x64
DB 0x1f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x1f ; Е - 0x65
DB 0x04, 0x0e, 0x15, 0x15, 0x15, 0x0e, 0x04 ; Ф - 0x66
DB 0x1f, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01 ; Г - 0x67
DB 0x11, 0x11, 0x0a, 0x04, 0x0a, 0x11, 0x11 ; Х - 0x68
DB 0x11, 0x11, 0x19, 0x15, 0x13, 0x11, 0x11 ; И - 0x69
DB 0x04, 0x15, 0x11, 0x19, 0x15, 0x13, 0x11 ; Й - 0x6a
DB 0x11, 0x09, 0x05, 0x03, 0x05, 0x09, 0x11 ; К - 0x6b
DB 0x1c, 0x12, 0x12, 0x12, 0x12, 0x12, 0x11 ; Л - 0x6c
DB 0x11, 0x1b, 0x15, 0x15, 0x11, 0x11, 0x11 ; М - 0x6d
DB 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11 ; Н - 0x6e
DB 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e ; О - 0x6f
DB 0x1f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 ; П - 0x70
DB 0x1e, 0x11, 0x11, 0x11, 0x1e, 0x12, 0x11 ; Я - 0x71
DB 0x0f, 0x11, 0x11, 0x11, 0x0f, 0x01, 0x01 ; Р - 0x72
DB 0x0e, 0x11, 0x01, 0x01, 0x01, 0x11, 0x0e ; С - 0x73
DB 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; Т - 0x74
DB 0x11, 0x11, 0x11, 0x11, 0x1e, 0x10, 0x0e ; У - 0x75
DB 0x15, 0x15, 0x15, 0x0e, 0x15, 0x15, 0x15 ; Ж - 0x76
DB 0x0f, 0x11, 0x11, 0x0f, 0x11, 0x11, 0x0f ; В - 0x77
DB 0x01, 0x01, 0x01, 0x0f, 0x11, 0x11, 0x0f ; Ь - 0x78
DB 0x11, 0x11, 0x11, 0x13, 0x15, 0x15, 0x13 ; Ы - 0x79
DB 0x0e, 0x11, 0x10, 0x0c, 0x10, 0x11, 0x0e ; З - 0x7a
DB 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x1f ; Ш - 0x7b
DB 0x0e, 0x11, 0x10, 0x1c, 0x10, 0x11, 0x0e ; Э - 0x7c
DB 0x15, 0x15, 0x15, 0x15, 0x15, 0x1f, 0x10 ; Щ - 0x7d
DB 0x11, 0x11, 0x11, 0x1e, 0x10, 0x10, 0x10 ; Ч - 0x7e
DB 0x1f, 0x15, 0x1f, 0x15, 0x1f, 0x15, 0x1f ; [DEL] - 0x7f

132
MON_v8_3edeb015/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

101
MON_v8_3edeb015/m_vars.inc Normal file
View File

@ -0,0 +1,101 @@
; =======================================================
; Ocean-240.2
; Module M_VARS - Monitor variables
; RAM Range: 0xBA09-0xBFFF
;
; Disassembled by Romych 2025-02-05
; =======================================================
IFNDEF _M_VARS
DEFINE _M_VARS
MODULE M_VARS
ORG 0xbf00
buffer DS 128 ; 0xbf00 search text or buffer to search?
DS 36
paint_stack EQU $ ; 0xbfa4
DS 32
stack1: EQU $ ; 0xbfc4
DS 1
paint_var1 DS 1 ; 0xbfc5
paint_var2 DS 1 ; 0xbfc6
paint_var3 DS 1 ; 0xbfc7
paint_var4 DS 1 ; 0xbfc8
paint_var5 DS 1 ; 0xbfc9
paint_y DS 1 ; 0xbfca
paint_var7 DS 1 ; 0xbfcb
cmp_color DS 1 ; 0xbfcc
paint_sp_save DS 2
; Right pixel mask ex: 11111000
pixel_mask_r DS 1 ; 0xbfcf
tmp_color DS 1 ; 0xbfd0
rect_var2 DS 1 ; 0xbfd1
stack_0 EQU $
rect_var3 DS 1 ; 0xbfd2
esc_mode DS 1 ; 0xbfd3
esc_cmd DS 1 ; 0xbfd4
esc_param_cnt DS 1 ; 0xbfd5
esc_param DS 7 ; 0xbfd6
; Left inverse pixel mask ex: 00011111
pixel_mask_l_i DS 1
; Right inverse pixel mask ex: 00011111
pixel_mask_r_i DS 1
; Left pixel mask ex: 11100000
pixel_mask_l DS 1
; Current screen mode, bit 3 - hide/show cursor, bit 4 - only 20 rows
screen_mode DS 1 ; 0xbfe0
cursor_row DS 1 ; 0xbfe1 Cursor Y position
cursor_col DS 1 ; 0xbfe2 Cursor X position
curr_color DS 2 ; 0xbfe3 Current color low and hi bytes
esc_hex_cmd:
row_shift DS 1 ; 0xbfe5
codepage DS 1 ; 0xbfe6
cur_palette DS 1 ; 0xbfe7 00bbbfff - background and foreground colors
beep_period DS 2 ; 0xbfe8
beep_duration DS 2 ; 0xbfea
pix_shift DS 1 ; 0xbfec
strobe_state DS 1 ; 0xbfed
ul_var0 DS 1 ; 0xbfee
ul_A_var1 DS 1 ; 0xbfef
ul_B_var2 DS 1 ; 0xbff0
ul_var3 DS 1 ; 0xbff1
ul_A_var4 DS 1 ; 0xbff2
ul_B_var5 DS 1 ; 0xbff3
ul_var6 DS 1 ; 0xbff4
esc_var0 DS 1 ; 0xbff5
esc_var1 DS 1 ; 0xbff6
esc_var2 DS 1 ; 0xbff7
esc_var3 DS 1 ; 0xbff8
DS 1 ; 0xbff9
DS 1 ; 0xbffa
DS 1 ; 0xbffb
DS 1 ; 0xbffc
DS 1 ; 0xbffd
DS 1 ; 0xbffe
DS 1 ; 0xbfff
ASSERT stack1 = 0xbfc4
ASSERT buffer = 0xbf00
ASSERT paint_var1 = 0xbfc5
ASSERT pixel_mask_r = 0xbfcf
ASSERT stack_0 = 0xbfd2
ASSERT esc_mode = 0xbfd3
ASSERT screen_mode = 0xbfe0
ASSERT cur_palette = 0xbfe7
ASSERT ul_var0 = 0xbfee
ASSERT paint_stack = 0xbfa4
ASSERT esc_var3 = 0xbff8
;DISPLAY "screen_mode: ", /H, screen_mode
;DISPLAY "fn48_var1: ", /H, fn48_var1
ENDMODULE
ENDIF

5594
MON_v8_3edeb015/monitor.asm Normal file

File diff suppressed because it is too large Load Diff

49
MON_v8_3edeb015/ram.inc Normal file
View File

@ -0,0 +1,49 @@
; =======================================================
; 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
@RST1 EQU 0x0008
@RST1_handler_addr EQU 0x0009
;RST2 EQU 0x0010
;RST3 EQU 0x0018
;RST4 EQU 0x0020
;RST5 EQU 0x0028
;RST6 EQU 0x0030
;RST7 EQU 0x0038
;reserve1 EQU 0x003b
@bios_var0 EQU 0x0040 ; 0xaa - bios init r8
@bios_var1 EQU 0x0041 ; 0xaa - bios init r8
@bios_var2 EQU 0x0042 ; 0x00 - bios init r8
@bios_var3 EQU 0x0043 ; 0xff - bios init r8
@interleave_0 EQU 0x0044
;reserve2 EQU 0x0050
@fcb1 EQU 0x005c ; Default FCB, 16 bytes
@fcb2 EQU 0x006c
;NMI_ISR EQU 0x0066
@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

10
MON_v8_c4eec374/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
*.labels
*.obj
*.OBJ
*.bin
*.tmp
tmp/
build/
*.lst
*.sld

View File

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

34
MON_v8_c4eec374/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,34 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "make MONITOR (sjasmplus)",
"type": "shell",
"command": "sjasmplus",
"args": [
"--sld=monitor.sld",
"--sym=monitor.labels",
"--raw=monitor.obj",
"--fullpath",
"monitor.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.

16
MON_v8_c4eec374/README.md Normal file
View File

@ -0,0 +1,16 @@
# Ocean-240.2 ROM Monitor V8 checksum c4eec374
Source codes of Monitor v8 for Ocean-240.2 with Floppy controller.
In Z80 mnemonics, but limited for i8080 instruction set.
## Differences:
Other versions of the code are compared with this one.
## Compile:
Code is located in memory at address: 0xE000..0xFFFF
sjasmplus --sld=monitor.sld --sym=monitor.labels --raw=monitor.obj --fullpath monitor.asm
To compile sources, use [sjasmplus Z80 assembler](https://github.com/z00m128/sjasmplus).

View File

@ -0,0 +1,41 @@
; =======================================================
; 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
bios_var04 EQU 0xD64B
ENDMODULE
ENDIF

149
MON_v8_c4eec374/equates.inc Normal file
View File

@ -0,0 +1,149 @@
; ======================================================
; Ocean-240.2
; Equates for all assembly sources
;
; By Romych 2025-09-09
; ======================================================
IFNDEF _EQUATES
DEFINE _EQUATES
ADDLIST EQU 0x08
ASCII_BELL EQU 0x07 ; Make Beep
ASCII_BS EQU 0x08 ; Move cursor left (Back Space)
ASCII_TAB EQU 0x09 ; Move cursor right +8 pos
ASCII_LF EQU 0x0A ; Move cursor down (Line Feed)
ASCII_FF EQU 0x0C ; Move cursor to home (Form Feed)
ASCII_CR EQU 0x0D ; Move gursor to 1st pos (Cariage Return)
ASCII_CAN EQU 0x18 ; Move cursor right
ASCII_EM EQU 0x19 ; Move cursor up
ASCII_SUB EQU 0x1A ; CTRL-Z - end of text file marker
ASCII_ESC EQU 0x1B ;
ASCII_US EQU 0x1F ; Clear screen
ASCII_SP EQU 0x20
ASCII_DEL EQU 0x7F
; ------------------------------------------------------
BDOS_NFUNCS EQU 41
BELL_PIN EQU 0x08 ; DD67 Pin PC3 - "BELL"
; ------------------------------------------------------
CCP_COMMAND_SIZE EQU 5 ; max length of CCP command
CCP_COMMAND_COUNT EQU 3 ; Count of CCP commands
CCP_COMMAND_CNT EQU 6
CCP_COMMAND_LEN EQU 4
CCP_SRC_ADDR EQU 0xc000 ; Address of CCP resident part in ROM
CCP_DST_ADDR EQU 0xb200 ; Address of CCP resident part in RAM
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
DIR_BUFF_SIZE EQU 128
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
FDC_RESTORE_UH_NV EQU 0x03 ; Restore Unload Head, No Verify, 15ms Rate
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
; ------------------------------------------------------
IRQ_0 EQU 0x01
IRQ_1 EQU 0x02
IRQ_2 EQU 0x04
;LP_IRQ EQU 0x08
KBD_IRQ EQU 0x02
KBD_ACK EQU 0x10
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
RO_FILE EQU 0x09
ROM_CHIP_SIZE EQU 8192 ; ROM Size, used to limit monitor code size
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
; ------------------------------------------------------
ENDIF

View File

@ -0,0 +1,165 @@
; 96 symbols 6x7, with codes 0x20..0x7f KOI-7 H0
m_font_cp0:
DB 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; ' ' - 0x20
DB 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x04 ; '!' - 0x21
DB 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00 ; '"' - 0x22
DB 0x0a, 0x0a, 0x1f, 0x0a, 0x1f, 0x0a, 0x0a ; '#' - 0x23
DB 0x04, 0x1e, 0x05, 0x0e, 0x14, 0x0f, 0x04 ; '$' - 0x24
DB 0x03, 0x13, 0x08, 0x04, 0x02, 0x19, 0x18 ; '%' - 0x25
DB 0x06, 0x09, 0x05, 0x02, 0x15, 0x09, 0x16 ; '&' - 0x26
DB 0x06, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00 ; ' - 0x27
DB 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08 ; '(' - 0x28
DB 0x02, 0x04, 0x08, 0x08, 0x08, 0x04, 0x02 ; ')' - 0x29
DB 0x00, 0x0a, 0x04, 0x1f, 0x04, 0x0a, 0x00 ; '*' - 0x2a
DB 0x00, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x00 ; '+' - 0x2b
DB 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x02 ; ',' - 0x2c
DB 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00 ; '-' - 0x2d
DB 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06 ; '.' - 0x2e
DB 0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00 ; '/' - 0x2f
DB 0x0e, 0x11, 0x19, 0x15, 0x13, 0x11, 0x0e ; '0' - 0x30
DB 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x0e ; '1' - 0x31
DB 0x0e, 0x11, 0x10, 0x08, 0x04, 0x02, 0x1f ; '2' - 0x32
DB 0x1f, 0x08, 0x04, 0x08, 0x10, 0x11, 0x0e ; '3' - 0x33
DB 0x08, 0x0c, 0x0a, 0x09, 0x1f, 0x08, 0x08 ; '4' - 0x34
DB 0x1f, 0x01, 0x0f, 0x10, 0x10, 0x11, 0x0e ; '5' - 0x35
DB 0x0c, 0x02, 0x01, 0x0f, 0x11, 0x11, 0x0e ; '6' - 0x36
DB 0x1f, 0x10, 0x08, 0x04, 0x02, 0x02, 0x02 ; '7' - 0x37
DB 0x0e, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x0e ; '8' - 0x38
DB 0x0e, 0x11, 0x11, 0x1e, 0x10, 0x08, 0x06 ; '9' - 0x39
DB 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00 ; ':' - 0x3a
DB 0x00, 0x06, 0x06, 0x00, 0x06, 0x04, 0x02 ; ';' - 0x3b
DB 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08 ; '<' - 0x3c
DB 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00 ; '=' - 0x3d
DB 0x02, 0x04, 0x08, 0x10, 0x08, 0x04, 0x02 ; '>' - 0x3e
DB 0x0e, 0x11, 0x10, 0x08, 0x04, 0x00, 0x04 ; '?' - 0x3f
DB 0x0e, 0x11, 0x10, 0x16, 0x15, 0x15, 0x0e ; '@' - 0x40
DB 0x04, 0x0a, 0x11, 0x11, 0x1f, 0x11, 0x11 ; 'A' - 0x41
DB 0x0f, 0x11, 0x11, 0x0f, 0x11, 0x11, 0x0f ; 'B' - 0x42
DB 0x0e, 0x11, 0x01, 0x01, 0x01, 0x11, 0x0e ; 'C' - 0x43
DB 0x07, 0x09, 0x11, 0x11, 0x11, 0x09, 0x07 ; 'D' - 0x44
DB 0x1f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x1f ; 'E' - 0x45
DB 0x1f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x01 ; 'F' - 0x46
DB 0x0e, 0x11, 0x01, 0x1d, 0x11, 0x11, 0x1e ; 'G' - 0x47
DB 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11 ; 'H' - 0x48
DB 0x0e, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0e ; 'I' - 0x49
DB 0x1c, 0x08, 0x08, 0x08, 0x08, 0x09, 0x06 ; 'J' - 0x4a
DB 0x11, 0x09, 0x05, 0x03, 0x05, 0x09, 0x11 ; 'K' - 0x4b
DB 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1f ; 'L' - 0x4c
DB 0x11, 0x1b, 0x15, 0x15, 0x11, 0x11, 0x11 ; 'M' - 0x4d
DB 0x11, 0x11, 0x13, 0x15, 0x19, 0x11, 0x11 ; 'N' - 0x4e
DB 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e ; 'O' - 0x4f
DB 0x0f, 0x11, 0x11, 0x0f, 0x01, 0x01, 0x01 ; 'P' - 0x50
DB 0x0e, 0x11, 0x11, 0x11, 0x15, 0x09, 0x16 ; 'Q' - 0x51
DB 0x0f, 0x11, 0x11, 0x0f, 0x05, 0x09, 0x11 ; 'R' - 0x52
DB 0x1e, 0x01, 0x01, 0x0e, 0x10, 0x10, 0x0f ; 'S' - 0x53
DB 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; 'T' - 0x54
DB 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e ; 'U' - 0x55
DB 0x11, 0x11, 0x11, 0x11, 0x0a, 0x0a, 0x04 ; 'V' - 0x56
DB 0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0x0a ; 'W' - 0x57
DB 0x11, 0x11, 0x0a, 0x04, 0x0a, 0x11, 0x11 ; 'X' - 0x58
DB 0x11, 0x11, 0x11, 0x0a, 0x04, 0x04, 0x04 ; 'Y' - 0x59
DB 0x1f, 0x10, 0x08, 0x04, 0x02, 0x01, 0x1f ; 'Z' - 0x5a
DB 0x0e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0e ; '[' - 0x5b
DB 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00 ; '\' - 0x5c
DB 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e ; ']' - 0x5d
DB 0x0e, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00 ; '^' - 0x5r
DB 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f ; '_' - 0x5f
DB 0x1c, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00 ; '`' - 0x60
DB 0x00, 0x00, 0x0e, 0x10, 0x1e, 0x13, 0x1e ; 'a' - 0x61
DB 0x01, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x0f ; 'b' - 0x62
DB 0x00, 0x00, 0x0e, 0x01, 0x01, 0x01, 0x0e ; 'c' - 0x63
DB 0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x1e ; 'd' - 0x64
DB 0x00, 0x00, 0x0e, 0x11, 0x1f, 0x01, 0x0e ; 'e' - 0x65
DB 0x18, 0x04, 0x04, 0x0e, 0x04, 0x04, 0x04 ; 'f' - 0x66
DB 0x00, 0x0e, 0x11, 0x11, 0x1e, 0x10, 0x0e ; 'g' - 0x67
DB 0x01, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x11 ; 'h' - 0x68
DB 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04 ; 'i' - 0x69
DB 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x06 ; 'j' - 0x6a
DB 0x01, 0x01, 0x09, 0x05, 0x03, 0x05, 0x09 ; 'k' - 0x6b
DB 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08 ; 'l' - 0x6c
DB 0x00, 0x00, 0x0f, 0x15, 0x15, 0x15, 0x15 ; 'm' - 0x6d
DB 0x00, 0x00, 0x09, 0x13, 0x11, 0x11, 0x11 ; 'n' - 0x6e
DB 0x00, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e ; 'o' - 0x6f
DB 0x00, 0x00, 0x0e, 0x11, 0x11, 0x0f, 0x01 ; 'p' - 0x70
DB 0x00, 0x00, 0x0e, 0x11, 0x11, 0x1e, 0x10 ; 'q' - 0x71
DB 0x00, 0x00, 0x0d, 0x13, 0x01, 0x01, 0x01 ; 'r' - 0x72
DB 0x00, 0x00, 0x1e, 0x01, 0x0e, 0x10, 0x0f ; 's' - 0x73
DB 0x04, 0x04, 0x0e, 0x04, 0x04, 0x04, 0x18 ; 't' - 0x74
DB 0x00, 0x00, 0x11, 0x11, 0x11, 0x19, 0x16 ; 'u' - 0x75
DB 0x00, 0x00, 0x11, 0x11, 0x0a, 0x0a, 0x04 ; 'v' - 0x76
DB 0x00, 0x00, 0x11, 0x15, 0x15, 0x15, 0x0a ; 'w' - 0x77
DB 0x00, 0x00, 0x11, 0x0a, 0x04, 0x0a, 0x11 ; 'x' - 0x78
DB 0x00, 0x00, 0x11, 0x11, 0x1e, 0x10, 0x0c ; 'y' - 0x79
DB 0x00, 0x00, 0x1f, 0x08, 0x04, 0x02, 0x1f ; 'z' - 0x7a
DB 0x0c, 0x02, 0x02, 0x01, 0x02, 0x02, 0x0c ; '{' - 0x7b
DB 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; '|' - 0x7c
DB 0x03, 0x04, 0x04, 0x08, 0x04, 0x04, 0x03 ; '}' - 0x7d
DB 0x00, 0x02, 0x15, 0x0a, 0x15, 0x08, 0x00 ; '~' - 0x7e
DB 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15 ; [DEL] - 0x7f
; 64 symbols 6x7, with codes 0x40..0x7f KOI-7 H1
m_font_cp1:
DB 0x00, 0x00, 0x09, 0x15, 0x17, 0x15, 0x09 ; ю - 0x40
DB 0x00, 0x00, 0x06, 0x08, 0x0e, 0x09, 0x16 ; а - 0x41
DB 0x07, 0x02, 0x04, 0x0e, 0x09, 0x09, 0x06 ; б - 0x42 DIFF
DB 0x00, 0x00, 0x09, 0x09, 0x09, 0x1f, 0x10 ; ц - 0x43
DB 0x03, 0x04, 0x08, 0x0e, 0x09, 0x09, 0x06 ; д - 0x44 DIFF
DB 0x00, 0x00, 0x0e, 0x11, 0x1f, 0x01, 0x1e ; е - 0x45
DB 0x00, 0x04, 0x0e, 0x15, 0x15, 0x0e, 0x04 ; ф - 0x46
DB 0x00, 0x00, 0x0f, 0x09, 0x01, 0x01, 0x01 ; г - 0x47
DB 0x00, 0x00, 0x11, 0x0a, 0x04, 0x0a, 0x11 ; х - 0x48
DB 0x00, 0x00, 0x11, 0x19, 0x15, 0x13, 0x11 ; и - 0x49
DB 0x0a, 0x04, 0x11, 0x19, 0x15, 0x13, 0x11 ; й - 0x4a
DB 0x00, 0x00, 0x11, 0x09, 0x07, 0x09, 0x11 ; к - 0x4b
DB 0x00, 0x00, 0x1c, 0x12, 0x12, 0x12, 0x11 ; л - 0x4c
DB 0x00, 0x00, 0x11, 0x1b, 0x15, 0x11, 0x11 ; м - 0x4d
DB 0x00, 0x00, 0x11, 0x11, 0x1f, 0x11, 0x11 ; н - 0x4e
DB 0x00, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e ; о - 0x4f
DB 0x00, 0x00, 0x1f, 0x11, 0x11, 0x11, 0x11 ; п - 0x50
DB 0x00, 0x00, 0x1e, 0x11, 0x1e, 0x14, 0x12 ; я - 0x51
DB 0x00, 0x00, 0x07, 0x09, 0x07, 0x01, 0x01 ; р - 0x52
DB 0x00, 0x00, 0x0e, 0x01, 0x01, 0x01, 0x0e ; с - 0x53
DB 0x00, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04 ; т - 0x54
DB 0x00, 0x00, 0x11, 0x11, 0x1e, 0x10, 0x0e ; у - 0x55
DB 0x00, 0x00, 0x15, 0x15, 0x0e, 0x15, 0x15 ; ж - 0x56
DB 0x00, 0x00, 0x03, 0x05, 0x07, 0x09, 0x07 ; в - 0x57
DB 0x00, 0x00, 0x01, 0x01, 0x07, 0x09, 0x07 ; ь - 0x58
DB 0x00, 0x00, 0x11, 0x11, 0x13, 0x15, 0x13 ; ы - 0x59
DB 0x00, 0x00, 0x0e, 0x11, 0x0c, 0x11, 0x0e ; з - 0x5a
DB 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x1f ; ш - 0x5b
DB 0x00, 0x00, 0x07, 0x08, 0x0e, 0x08, 0x07 ; э - 0x5c
DB 0x00, 0x00, 0x15, 0x15, 0x15, 0x1f, 0x10 ; щ - 0x5d
DB 0x00, 0x00, 0x09, 0x09, 0x0e, 0x08, 0x08 ; ч - 0x5e
DB 0x00, 0x00, 0x06, 0x05, 0x0c, 0x14, 0x0c ; ъ - 0x5f
DB 0x09, 0x15, 0x15, 0x17, 0x15, 0x15, 0x09 ; Ю - 0x60
DB 0x04, 0x0a, 0x11, 0x11, 0x1f, 0x11, 0x11 ; А - 0x61
DB 0x1f, 0x11, 0x01, 0x0f, 0x11, 0x11, 0x1f ; Б - 0x62
DB 0x09, 0x09, 0x09, 0x09, 0x09, 0x1f, 0x10 ; С - 0x63
DB 0x0c, 0x0a, 0x0a, 0x0a, 0x0a, 0x1f, 0x11 ; Д - 0x64
DB 0x1f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x1f ; Е - 0x65
DB 0x04, 0x0e, 0x15, 0x15, 0x15, 0x0e, 0x04 ; Ф - 0x66
DB 0x1f, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01 ; Г - 0x67
DB 0x11, 0x11, 0x0a, 0x04, 0x0a, 0x11, 0x11 ; Х - 0x68
DB 0x11, 0x11, 0x19, 0x15, 0x13, 0x11, 0x11 ; И - 0x69
DB 0x04, 0x15, 0x11, 0x19, 0x15, 0x13, 0x11 ; Й - 0x6a
DB 0x11, 0x09, 0x05, 0x03, 0x05, 0x09, 0x11 ; К - 0x6b
DB 0x1c, 0x12, 0x12, 0x12, 0x12, 0x12, 0x11 ; Л - 0x6c
DB 0x11, 0x1b, 0x15, 0x15, 0x11, 0x11, 0x11 ; М - 0x6d
DB 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11 ; Н - 0x6e
DB 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e ; О - 0x6f
DB 0x1f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 ; П - 0x70
DB 0x1e, 0x11, 0x11, 0x11, 0x1e, 0x12, 0x11 ; Я - 0x71
DB 0x0f, 0x11, 0x11, 0x11, 0x0f, 0x01, 0x01 ; Р - 0x72
DB 0x0e, 0x11, 0x01, 0x01, 0x01, 0x11, 0x0e ; С - 0x73
DB 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; Т - 0x74
DB 0x11, 0x11, 0x11, 0x11, 0x1e, 0x10, 0x0e ; У - 0x75
DB 0x15, 0x15, 0x15, 0x0e, 0x15, 0x15, 0x15 ; Ж - 0x76
DB 0x0f, 0x11, 0x11, 0x0f, 0x11, 0x11, 0x0f ; В - 0x77
DB 0x01, 0x01, 0x01, 0x0f, 0x11, 0x11, 0x0f ; Ь - 0x78
DB 0x11, 0x11, 0x11, 0x13, 0x15, 0x15, 0x13 ; Ы - 0x79
DB 0x0e, 0x11, 0x10, 0x0c, 0x10, 0x11, 0x0e ; З - 0x7a
DB 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x1f ; Ш - 0x7b
DB 0x0e, 0x11, 0x10, 0x1c, 0x10, 0x11, 0x0e ; Э - 0x7c
DB 0x15, 0x15, 0x15, 0x15, 0x15, 0x1f, 0x10 ; Щ - 0x7d
DB 0x11, 0x11, 0x11, 0x1e, 0x10, 0x10, 0x10 ; Ч - 0x7e
DB 0x1f, 0x15, 0x1f, 0x15, 0x1f, 0x15, 0x1f ; [DEL] - 0x7f

132
MON_v8_c4eec374/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

101
MON_v8_c4eec374/m_vars.inc Normal file
View File

@ -0,0 +1,101 @@
; =======================================================
; Ocean-240.2
; Module M_VARS - Monitor variables
; RAM Range: 0xBA09-0xBFFF
;
; Disassembled by Romych 2025-02-05
; =======================================================
IFNDEF _M_VARS
DEFINE _M_VARS
MODULE M_VARS
ORG 0xbf00
buffer DS 128 ; 0xbf00 search text or buffer to search?
DS 36
paint_stack EQU $ ; 0xbfa4
DS 32
stack1: EQU $ ; 0xbfc4
DS 1
paint_var1 DS 1 ; 0xbfc5
paint_var2 DS 1 ; 0xbfc6
paint_var3 DS 1 ; 0xbfc7
paint_var4 DS 1 ; 0xbfc8
paint_var5 DS 1 ; 0xbfc9
paint_y DS 1 ; 0xbfca
paint_var7 DS 1 ; 0xbfcb
cmp_color DS 1 ; 0xbfcc
paint_sp_save DS 2
; Right pixel mask ex: 11111000
pixel_mask_r DS 1 ; 0xbfcf
tmp_color DS 1 ; 0xbfd0
rect_var2 DS 1 ; 0xbfd1
stack_0 EQU $
rect_var3 DS 1 ; 0xbfd2
esc_mode DS 1 ; 0xbfd3
esc_cmd DS 1 ; 0xbfd4
esc_param_cnt DS 1 ; 0xbfd5
esc_param DS 7 ; 0xbfd6
; Left inverse pixel mask ex: 00011111
pixel_mask_l_i DS 1
; Right inverse pixel mask ex: 00011111
pixel_mask_r_i DS 1
; Left pixel mask ex: 11100000
pixel_mask_l DS 1
; Current screen mode, bit 3 - hide/show cursor, bit 4 - only 20 rows
screen_mode DS 1 ; 0xbfe0
cursor_row DS 1 ; 0xbfe1 Cursor Y position
cursor_col DS 1 ; 0xbfe2 Cursor X position
curr_color DS 2 ; 0xbfe3 Current color low and hi bytes
esc_hex_cmd:
row_shift DS 1 ; 0xbfe5
codepage DS 1 ; 0xbfe6
cur_palette DS 1 ; 0xbfe7 00bbbfff - background and foreground colors
beep_period DS 2 ; 0xbfe8
beep_duration DS 2 ; 0xbfea
pix_shift DS 1 ; 0xbfec
strobe_state DS 1 ; 0xbfed
ul_var0 DS 1 ; 0xbfee
ul_A_var1 DS 1 ; 0xbfef
ul_B_var2 DS 1 ; 0xbff0
ul_var3 DS 1 ; 0xbff1
ul_A_var4 DS 1 ; 0xbff2
ul_B_var5 DS 1 ; 0xbff3
ul_var6 DS 1 ; 0xbff4
esc_var0 DS 1 ; 0xbff5
esc_var1 DS 1 ; 0xbff6
esc_var2 DS 1 ; 0xbff7
esc_var3 DS 1 ; 0xbff8
DS 1 ; 0xbff9
DS 1 ; 0xbffa
DS 1 ; 0xbffb
DS 1 ; 0xbffc
DS 1 ; 0xbffd
DS 1 ; 0xbffe
DS 1 ; 0xbfff
ASSERT stack1 = 0xbfc4
ASSERT buffer = 0xbf00
ASSERT paint_var1 = 0xbfc5
ASSERT pixel_mask_r = 0xbfcf
ASSERT stack_0 = 0xbfd2
ASSERT esc_mode = 0xbfd3
ASSERT screen_mode = 0xbfe0
ASSERT cur_palette = 0xbfe7
ASSERT ul_var0 = 0xbfee
ASSERT paint_stack = 0xbfa4
ASSERT esc_var3 = 0xbff8
;DISPLAY "screen_mode: ", /H, screen_mode
;DISPLAY "fn48_var1: ", /H, fn48_var1
ENDMODULE
ENDIF

5593
MON_v8_c4eec374/monitor.asm Normal file

File diff suppressed because it is too large Load Diff

49
MON_v8_c4eec374/ram.inc Normal file
View File

@ -0,0 +1,49 @@
; =======================================================
; 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
@RST1 EQU 0x0008
@RST1_handler_addr EQU 0x0009
;RST2 EQU 0x0010
;RST3 EQU 0x0018
;RST4 EQU 0x0020
;RST5 EQU 0x0028
;RST6 EQU 0x0030
;RST7 EQU 0x0038
;reserve1 EQU 0x003b
@bios_var0 EQU 0x0040 ; 0xaa - bios init r8
@bios_var1 EQU 0x0041 ; 0xaa - bios init r8
@bios_var2 EQU 0x0042 ; 0x00 - bios init r8
@bios_var3 EQU 0x0043 ; 0xff - bios init r8
@interleave_0 EQU 0x0044
;reserve2 EQU 0x0050
@fcb1 EQU 0x005c ; Default FCB, 16 bytes
@fcb2 EQU 0x006c
;NMI_ISR EQU 0x0066
@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

9
Test/.vscode/extensions.json vendored Normal file
View File

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

94
Test/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,94 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "dezog",
"request": "launch",
"name": "Internal Simulator",
"remoteType": "zsim",
"zsim": {
"visualMemory": true,
"memoryModel": "CUSTOM",
"customMemory": {
"slots": [
{
"name": "PAGE0",
"range": ["0x0000","0x3FFF"],
"banks": [{"index": [0, 255]}],
"initialBank": 0
},
{
"name": "PAGE1",
"range": ["0x4000","0x7FFF"],
"banks": [{"index": [0, 255]}],
"initialBank": 1
},
{
"name": "PAGE2",
"range": ["0x8000","0xBFFF"],
"banks": [{"index": [0, 255]}],
"initialBank": 2
},
{
"name": "PAGE3",
"range": ["0xC000","0xFFFF"],
"banks": [{"index": [0, 255]}],
"initialBank": 3
}
],
"ioMmu": [
"if (portAddress == 0x82) {",
" bank = portValue;",
" PAGE0 = bank;",
"}",
"if (portAddress == 0xA2) {",
" bank = portValue;",
" PAGE1 = bank;",
"}",
"if (portAddress == 0xC2) {",
" bank = portValue;",
" PAGE2 = bank;",
"}",
"if (portAddress == 0xE2) {",
" bank = portValue;",
" PAGE3 = bank;",
"}"
]
},
"customCode": {
"debug": false,
"jsPath": "sim/ports.js"
//"uiPath": "simulation/ui.html"
},
//"ulaScreen": true,
//"zxBorderWidth": 20,
//"vsyncInterrupt": true,
//"zxKeyboard": true,
//"zxBeeper": true
},
"sjasmplus": [
{
"path": "test_O240.sld"
}
],
"history": {
"reverseDebugInstructionCount": 1000000,
"spotCount": 10,
"codeCoverageEnabled": true
},
"startAutomatically": false,
"commandsAfterLaunch": [],
"rootFolder": "${workspaceFolder}",
"topOfStack": "STACK_TOP",
"loadObjs": [
{
"path": "test_O240.obj",
"start": "0x0000"
}
],
"execAddress": "0x8100",
"smallValuesMaximum": 513,
"tmpDir": ".tmp"
}
]
}

41
Test/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,41 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "make (sjasmplus)",
"type": "shell",
"command": "sjasmplus",
"args": [
"--sld=test_O240.sld",
"--sym=test_O240.labels",
"--raw=test_O240.obj",
"--fullpath",
"test_O240.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
}
},
{
"label": "start mame",
"type": "shell",
"command": "while true; do ./mame spectrum -window -debugger gdbstub -debug -debugger_port 12000 -verbose -resolution 512x384 ; sleep 2 ; done",
"options": {
"cwd": "${config:mame_dir}"
},
"problemMatcher": []
}
]
}

7
Test/README.md Normal file
View File

@ -0,0 +1,7 @@
# Ocean-240.2 Test ROM Sources
Source codes of TEST ROM for Ocean-240.2 computer.
Source codes in Z80 mnemonics, but limited for i8080 instruction set.
To compile sources, use [sjasmplus Z80 assembler](https://github.com/z00m128/sjasmplus).

1249
Test/test_O240.asm Normal file

File diff suppressed because it is too large Load Diff