]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - avr/cmd_loadcpm3.c
Get common_base from cpm3.sys file. Update default environment (BOOTCMD)
[z180-stamp.git] / avr / cmd_loadcpm3.c
index 3f1bbe10e9a0868f3a4440251fc36231588c7009..f24ee19352d2722cc62181c8c2f5aedff40ac2ef 100644 (file)
@@ -1,7 +1,11 @@
 /*
  * (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de>
  *
- * SPDX-License-Identifier:    GPL-2.0+
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+/*
+ * See CP/M 3 System Manual, Appendix D: CPM3.SYS File Format
  */
 
 #include "common.h"
@@ -20,6 +24,8 @@
 
 #define RS             128             /* CP/M record size */
 
+#define FSIZE_t DWORD
+
 /*
  *     Load Routine
  *
@@ -27,7 +33,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 */
@@ -63,12 +69,12 @@ command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
        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;
        FIL File;
-       /* TODO: put CONFIG_PATH_CPM3SYS in flash */
-       char default_fname[] = CONFIG_PATH_CPM3SYS;
+       char default_fname[] = CONFIG_CPM3_SYSFILE;
        unsigned int br;                                        /* bytes read */
        uint8_t buffer[RS];
        int res;
@@ -76,15 +82,20 @@ 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 = strtoul(argv[3], NULL, 16);
+       if (argc > 2)
+               common_base = strtoul(argv[2], NULL, 16);
 
-       if (argc > 2) {
-               fname = argv[2];
+       fname = getenv_char(PSTR(ENV_CPM3_SYSFILE));
+       if (argc > 1) {
+               fname = argv[1];
        }
-
        if (fname == NULL || *fname == '\0')
                fname = default_fname;
 
@@ -105,7 +116,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);
@@ -118,14 +129,28 @@ 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);
+       }
        /* 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);
@@ -134,16 +159,31 @@ out:
                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"));