Skip to content

Commit

Permalink
SDK port for CP/M-65 (#80)
Browse files Browse the repository at this point in the history
* Initial semi-working platform library.

* Add elftocpm65 for converting ELF files to CP/M-65 binaries.

* Add some more ctype functions.

* Flesh out the BDOS API.

* Cleanup some definitions.

* Change most cpm_* return values to return a byte, for slightly smaller
code.

* Put cpm_fcb2 in the right place.

* Generate ELF files with phdrs; use these to remove the libelf
dependency.

* Adjust the system call library to pass parameters in XA rather than
using the C calling convention.

* Move imaginary register definitions out of link.ld so the linker can
discard them if not needed.

* Move the CP/M wrapper functions into their own C file, as we can rely on
LTO to inline them.

* Allow LTO to place variables in zero page.

* Remove the dependency on libfmt and getopt.

* Comment and typo fix.

* Rewrite the linker script completely to be better; use elftocpm65 in
post-link-tool mode.

* Add support for making BIOS calls.

* Add C++ guards.
  • Loading branch information
davidgiven authored Oct 10, 2022
1 parent 79f20a5 commit c158ca9
Show file tree
Hide file tree
Showing 18 changed files with 896 additions and 1 deletion.
1 change: 1 addition & 0 deletions mos-platform/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ add_subdirectory(common)
add_subdirectory(atari8)
add_subdirectory(commodore)
add_subdirectory(c64)
add_subdirectory(cpm65)
add_subdirectory(cx16)
add_subdirectory(mega65)
add_subdirectory(sim)
Expand Down
19 changes: 19 additions & 0 deletions mos-platform/common/c/ctype.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,22 @@ int isprint(int c) {
char ch = (char)c;
return ch >= 0x1f && ch < 0x7f /*DEL*/;
}

int isdigit(int c) {
char ch = (char)c;
return ch >= '0' && ch <= '9';
}

int isalpha(int c) {
char ch = (char)c;
return ((ch >= 'A') && (ch <= 'Z'))
|| ((ch >= 'a') && (ch <= 'z'));
}

int toupper(int c) {
char ch = (char)c;
if ((ch >= 'a') && (ch <= 'z'))
ch &= ~0x20;
return ch;
}

5 changes: 4 additions & 1 deletion mos-platform/common/include/ctype.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
extern "C" {
#endif

int isprint(int c);
extern int isprint(int c);
extern int isdigit(int c);
extern int isalpha(int c);
extern int toupper(int c);

#ifdef __cplusplus
}
Expand Down
37 changes: 37 additions & 0 deletions mos-platform/cpm65/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
platform(cpm65 HOSTED PARENT common)

if(NOT CMAKE_CROSSCOMPILING)
return()
endif()

install(FILES
cpm.h
TYPE INCLUDE)
install(FILES link.ld TYPE LIB)

add_platform_library(cpm65-crt0)
merge_libraries(cpm65-crt0
common-init-stack
common-copy-zp-data
common-zero-bss
)

add_platform_library(cpm65-c
cpm.S
cpm-wrappers.c
bios.S
comhdr.S
pblock.S
putchar.c
stack.S
registers.S
)
merge_libraries(cpm65-c
common-c
)

# abort is preemptively included if LTO is used, which pulls in _exit support
# unneccessarily. It can also be called in an interrupt.
set_property(SOURCE abort.c PROPERTY COMPILE_OPTIONS -fno-lto -fno-static-stack)
target_include_directories(cpm65-c PUBLIC .)

13 changes: 13 additions & 0 deletions mos-platform/cpm65/bios.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.section .init.20, "Rax", @progbits
__do_setup_bios:
ldy #38
jsr BDOS
sta BIOS+1
stx BIOS+2

.text

.global BIOS
BIOS:
jmp 0 ; patched by startup code

4 changes: 4 additions & 0 deletions mos-platform/cpm65/clang.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-D__CPM65__
-Wl,-emit-relocs
-fpost-link-tool=elftocpm65

4 changes: 4 additions & 0 deletions mos-platform/cpm65/comhdr.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.section .comhdr, "aw", @progbits
_comhdr:
.short _pblock /* address of pblock / relocation data */

112 changes: 112 additions & 0 deletions mos-platform/cpm65/cpm-wrappers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#include "cpm.h"

void cpm_printstring(const char* s) /* $-terminated */
{
cpm_printstring_i((uint16_t)s);
}

uint8_t cpm_open_file(FCB* fcb)
{
return cpm_open_file_i((uint16_t)fcb);
}

uint8_t cpm_close_file(FCB* fcb)
{
return cpm_close_file_i((uint16_t)fcb);
}

uint8_t cpm_findfirst(FCB* fcb)
{
return cpm_findfirst_i((uint16_t)fcb);
}

uint8_t cpm_findnext(FCB* fcb)
{
return cpm_findnext_i((uint16_t)fcb);
}

uint8_t cpm_delete_file(FCB* fcb)
{
return cpm_delete_file_i((uint16_t)fcb);
}

uint8_t cpm_read_sequential(FCB* fcb)
{
return cpm_read_sequential_i((uint16_t)fcb);
}

uint8_t cpm_write_sequential(FCB* fcb)
{
return cpm_write_sequential_i((uint16_t)fcb);
}

uint8_t cpm_make_file(FCB* fcb)
{
return cpm_make_file_i((uint16_t)fcb);
}

uint8_t cpm_rename_file(RCB* rcb)
{
return cpm_rename_file_i((uint16_t)rcb);
}

void cpm_set_dma(void* ptr)
{
cpm_set_dma_i((uint16_t)ptr);
}

uint8_t* cpm_get_allocation_vector(void)
{
return (uint8_t*)cpm_get_allocation_vector_i();
}

uint8_t cpm_set_file_attributes(FCB* fcb)
{
return cpm_set_file_attributes_i((uint16_t)fcb);
}

DPB* cpm_get_dpb(void)
{
return (DPB*)cpm_get_dpb_i();
}

uint8_t cpm_read_random(FCB* fcb)
{
return cpm_read_random_i((uint16_t)fcb);
}

uint8_t cpm_write_random(FCB* fcb)
{
return cpm_write_random_i((uint16_t)fcb);
}

void cpm_seek_to_end(FCB* fcb)
{
return cpm_seek_to_end_i((uint16_t)fcb);
}

void cpm_seek_to_seq_pos(FCB* fcb)
{
return cpm_seek_to_seq_pos_i((uint16_t)fcb);
}

uint8_t cpm_write_random_filled(FCB* fcb)
{
return cpm_write_random_filled_i((uint16_t)fcb);
}

DPH* cpm_bios_seldsk(uint8_t drive)
{
return (DPH*) cpm_bios_seldsk_i(drive);
}

void cpm_bios_setdma(void* dma)
{
cpm_bios_setdma_i((uint16_t) dma);
}

void cpm_bios_setsec(uint32_t* sector)
{
cpm_bios_setsec_i((uint16_t) sector);
}

106 changes: 106 additions & 0 deletions mos-platform/cpm65/cpm.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
.macro cpmentry sym:req, num:req, exiter
.section .text.\sym, "ax", @progbits
.global \sym
\sym:
ldy #\num
.ifb \exiter
jmp BDOS
.else
jsr BDOS
jmp \exiter
.endif
.endm

.macro biosentry sym:req, num:req, exiter
.section .text.\sym, "ax", @progbits
.global \sym
\sym:
ldy #\num
.ifb \exiter
jmp BIOS
.else
jsr BDOS
jmp \exiter
.endif
.endm

cpmentry cpm_warmboot, 0
cpmentry cpm_conin, 1
cpmentry cpm_conout, 2
cpmentry cpm_auxin, 3
cpmentry cpm_auxout, 4
cpmentry cpm_lstout, 5
cpmentry cpm_conio, 6
cpmentry cpm_get_iobyte, 7
cpmentry cpm_set_iobyte, 8
cpmentry cpm_printstring_i, 9
cpmentry cpm_readline, 10, __cpmexiter_errno
cpmentry cpm_const, 11
cpmentry cpm_get_version, 12
cpmentry cpm_reset_disk_system, 13
cpmentry cpm_select_drive, 14
cpmentry cpm_open_file_i, 15, __cpmexiter_errno
cpmentry cpm_close_file_i, 16, __cpmexiter_errno
cpmentry cpm_findfirst_i, 17, __cpmexiter_aorerrno
cpmentry cpm_findnext_i, 18, __cpmexiter_aorerrno
cpmentry cpm_delete_file_i, 19, __cpmexiter_errno
cpmentry cpm_read_sequential_i, 20, __cpmexiter_errno
cpmentry cpm_write_sequential_i, 21, __cpmexiter_errno
cpmentry cpm_make_file_i, 22, __cpmexiter_errno
cpmentry cpm_rename_file_i, 23, __cpmexiter_errno
cpmentry cpm_get_login_vector, 24
cpmentry cpm_get_current_drive, 25
cpmentry cpm_set_dma_i, 26
cpmentry cpm_get_allocation_vector_i, 27
cpmentry cpm_write_protect_drive, 28
cpmentry cpm_get_readonly_vector, 29
cpmentry cpm_set_file_attributes_i, 30, __cpmexiter_errno
cpmentry cpm_get_dpb_i, 31
cpmentry cpm_get_set_user, 32
cpmentry cpm_read_random_i, 33, __cpmexiter_errno
cpmentry cpm_write_random_i, 34, __cpmexiter_errno
cpmentry cpm_seek_to_end_i, 35
cpmentry cpm_seek_to_seq_pos_i, 36
cpmentry cpm_reset_drives, 37, __cpmexiter_errno
cpmentry cpm_write_random_filled_i, 40, __cpmexiter_errno

biosentry cpm_bios_const, 0
biosentry cpm_bios_conin, 1
biosentry cpm_bios_conout, 2
biosentry cpm_bios_seldsk_i, 3
biosentry cpm_bios_setsec_i, 4
biosentry cpm_bios_setdma_i, 5
biosentry cpm_bios_read, 6, __cpmexiter_errno
biosentry cpm_bios_write, 7, __cpmexiter_errno
biosentry cpm_bios_relocate, 8
biosentry cpm_bios_gettpa, 9
biosentry cpm_bios_settpa, 10
biosentry cpm_bios_getzp, 11
biosentry cpm_bios_setzp, 12

; On exit from the BDOS (or BIOS), the return value is in A
; and carry is set on error.

.section .text.cpmexiter_errno, "ax", @progbits
__cpmexiter_errno:
sta cpm_errno
lda #0
bcc 1f
lda #$ff
1:
rts
.section .text.cpmexiter_aorerrno, "ax", @progbits
__cpmexiter_aorerrno:
sta cpm_errno
bcc 1f
lda #$ff
1:
rts

.section .bss.cpm_errno
.global cpm_errno
cpm_errno: .fill 1

; vim: ts=4 sw=4 et ft=asm

Loading

0 comments on commit c158ca9

Please sign in to comment.