X-Git-Url: http://cloudbase.mooo.com/gitweb/z180-stamp.git/blobdiff_plain/c0abd68b350ffd9852923a66f3ee6c315c94813a..228b1c5f79749940e11247bd97626e21df7033bd:/avr/cmd_loadcpm3.c?ds=sidebyside diff --git a/avr/cmd_loadcpm3.c b/avr/cmd_loadcpm3.c index 267cad8..39e3278 100644 --- a/avr/cmd_loadcpm3.c +++ b/avr/cmd_loadcpm3.c @@ -1,18 +1,19 @@ /* - * (C) Copyright 2015 Leo C. + * (C) Copyright 2015,2016 Leo C. * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: GPL-2.0 */ -#include "common.h" -#include +/* + * See CP/M 3 System Manual, Appendix D: CPM3.SYS File Format + */ + +#include "cmd_loadcpm3.h" #include -#include -#include -#include "command.h" #include "env.h" #include "ff.h" +#include "eval_arg.h" #include "con-utils.h" #include "z80-if.h" #include "debug.h" @@ -20,6 +21,8 @@ #define RS 128 /* CP/M record size */ +#define FSIZE_t DWORD + /* * Load Routine * @@ -27,7 +30,7 @@ * len = Length in pages of module to read * */ -int load(FIL *File, uint16_t addr, uint8_t len) +int load(FIL *File, uint32_t addr, uint8_t len) { uint8_t buffer[RS]; unsigned int br; /* bytes read */ @@ -55,19 +58,20 @@ int load(FIL *File, uint16_t addr, uint8_t len) return 0; } +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[]) { uint16_t mem_top; uint8_t res_len; uint16_t bank_top; uint8_t bank_len; - uint16_t osentry_adr = 0; - long offset = 0; + uint16_t osentry_addr = 0; + uint32_t common_base = 0; + uint32_t banked_base; char *fname; - FATFS FatFs; FIL File; - char default_fname[] = CONFIG_PATH_CPM3SYS; + char default_fname[] = CONFIG_CPM3_SYSFILE; unsigned int br; /* bytes read */ uint8_t buffer[RS]; int res; @@ -75,24 +79,26 @@ command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg (void) cmdtp; (void) flag; - if (argc > 1) - offset = strtoul(argv[1], NULL, 16); + //common_base = getenv_ulong(PSTR(ENV_CPM3_COMMON_BASE), 16, + // CONFIG_CPM3_COMMON_BASE); + banked_base = getenv_ulong(PSTR(ENV_CPM3_BANKED_BASE), 16, + CONFIG_CPM3_BANKED_BASE); - fname = getenv(PSTR(ENV_PATH_CPM3SYS)); + if (argc > 3) + banked_base = eval_arg(argv[3], NULL); + if (argc > 2) + common_base = eval_arg(argv[2], NULL); - if (argc > 2) { - fname = argv[2]; + fname = getenv_str(PSTR(ENV_CPM3_SYSFILE)); + if (argc > 1) { + fname = argv[1]; } - if (fname == NULL || *fname == '\0') fname = default_fname; - res = f_mount(&FatFs, fname, 0); - if (!res) - res = f_open(&File, fname, FA_READ ); + res = f_open(&File, fname, FA_READ ); if (res) { printf_P(PSTR("Error: failed to open '%s'\n"), fname); - f_mount(NULL, fname, 0); return CMD_RET_FAILURE; } @@ -107,7 +113,7 @@ command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg res_len = buffer[1]; bank_top = buffer[2] << 8; bank_len = buffer[3]; - osentry_adr = buffer[4] + (buffer[5] << 8); + osentry_addr = buffer[4] + (buffer[5] << 8); /* read display info */ res = f_read(&File, buffer, RS, &br); @@ -120,33 +126,64 @@ command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg *p = '\0'; my_puts((char *)buffer); + if (common_base == 0) { + /* read common base + * http://www.seasip.info/Cpm/scb.html + */ + FSIZE_t common_base_ofs = ((res_len - 6) << 8) + 2*RS + RS-7; + FSIZE_t cur_pos = f_tell(&File); + if ((res = f_lseek(&File, common_base_ofs)) || + (res = f_read(&File, buffer, 2, &br)) || + (br != 2) || + (res = f_lseek(&File, cur_pos))) + goto out; + common_base = (uint16_t) buffer[0] + (buffer[1] << 8); + setenv_hex(PSTR(ENV_CPM3_COMMON_BASE), common_base); + } + + setenv_hex(PSTR(ENV_CPM3_SCB), mem_top - ((res_len - (6 - 1)) << 8) + common_base); + /* Main System Load */ /* Load Common Portion of System */ - if ((res = load(&File, mem_top, res_len)) != 0) + if ((res = load(&File, common_base + mem_top, res_len)) != 0) goto out; /* Load Banked Portion of System */ - res = load(&File, bank_top, bank_len); + res = load(&File, banked_base + bank_top, bank_len); out: f_close(&File); - f_mount(NULL, fname, 0); if (res) { printf_P(PSTR("Error: failed to read '%s'\n"), fname); return CMD_RET_FAILURE; } else { - if (res_len != 0) - setenv_hex(PSTR(ENV_STARTADDRESS), osentry_adr); + if (res_len != 0) { + if (osentry_addr + common_base > 0xffff) { + z80_bus_cmd(Request); + if (z80_read(osentry_addr + common_base) == 0xc3) { + osentry_addr = z80_read(osentry_addr+common_base+1) + + (z80_read(osentry_addr + common_base+2) << 8); + } + z80_bus_cmd(Release); + if (banked_base + osentry_addr > 0xffff) + osentry_addr = 0; + } + setenv_hex(PSTR(ENV_STARTADDRESS), osentry_addr); + } printf_P(PSTR("Loaded: Resident: ")); if (res_len != 0) - printf_P(PSTR("0x%.4X-0x%.4X, "), mem_top-res_len*256, mem_top-1); + printf_P(PSTR("0x%.5lX-0x%.5lX, "), + (common_base + mem_top) - res_len*256, + (common_base + mem_top) - 1); else printf_P(PSTR(" - ")); printf_P(PSTR("Banked: ")); if (bank_len != 0) - printf_P(PSTR("0x%.4X-0x%.4X\n"), bank_top-bank_len*256, bank_top-1); + printf_P(PSTR("0x%.5lX-0x%.5lX\n"), + (banked_base + bank_top) - bank_len*256, + (banked_base + bank_top) - 1); else printf_P(PSTR(" - \n"));