]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/cmd_loadcpm3.c
clean up includes
[z180-stamp.git] / avr / cmd_loadcpm3.c
CommitLineData
c0abd68b 1/*
5e8ac5e0 2 * (C) Copyright 2015,2016,2018 Leo C. <erbl259-lmu@yahoo.de>
c0abd68b 3 *
b51d2360
L
4 * SPDX-License-Identifier: GPL-2.0
5 */
6
7/*
8 * See CP/M 3 System Manual, Appendix D: CPM3.SYS File Format
c0abd68b
L
9 */
10
7eecbdac 11#include "cmd_loadcpm3.h"
c0abd68b 12
c0abd68b
L
13#include "env.h"
14#include "ff.h"
2d914b45 15#include "eval_arg.h"
c0abd68b
L
16#include "con-utils.h"
17#include "z80-if.h"
18#include "debug.h"
19
20
21#define RS 128 /* CP/M record size */
22
b51d2360
L
23#define FSIZE_t DWORD
24
5e8ac5e0
L
25static FRESULT read_record(FIL *fp, uint8_t *buffer)
26{
27 unsigned int br; /* bytes read */
28
29 FRESULT res = f_read(fp, buffer, RS, &br);
30 if (br != RS)
31 return EEOF;
32 return res;
33}
34
c0abd68b
L
35/*
36 * Load Routine
37 *
38 * Input: addr = Page Address of load top
39 * len = Length in pages of module to read
40 *
41 */
5e8ac5e0 42ERRNUM load(FIL *File, uint32_t addr, uint8_t len)
c0abd68b
L
43{
44 uint8_t buffer[RS];
c0abd68b
L
45
46 len *= 2; /* length in records of module */
47 //debug("## load: addr: 0x%.4X, records: 0x%.4X, (%u)\n", addr, len, len);
48
49 for (; len; len--) {
50 addr -= RS;
5e8ac5e0
L
51 FRESULT res = read_record(File, buffer);
52 if (res)
53 return res;
c0abd68b 54
5e8ac5e0
L
55 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED))
56 return EBUSTO;
c0abd68b
L
57 z80_write_block(buffer, addr, RS);
58 z80_bus_cmd(Release);
59 //debug("## written: 0x%.4X\n", addr);
60 }
61
5e8ac5e0 62 return ESUCCESS;
c0abd68b
L
63}
64
ad9bc17c 65#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
c0abd68b 66
5e8ac5e0 67command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
c0abd68b
L
68{
69 uint16_t mem_top;
70 uint8_t res_len;
71 uint16_t bank_top;
72 uint8_t bank_len;
057817cb 73 uint16_t osentry_addr = 0;
b51d2360
L
74 uint32_t common_base = 0;
75 uint32_t banked_base;
c0abd68b 76 char *fname;
c0abd68b 77 FIL File;
209025e8 78 char default_fname[strlen_P(PSTR(CONFIG_CPM3_SYSFILE)) + 1];
c0abd68b 79 uint8_t buffer[RS];
5e8ac5e0 80 FRESULT res;
c0abd68b
L
81
82
b51d2360
L
83 //common_base = getenv_ulong(PSTR(ENV_CPM3_COMMON_BASE), 16,
84 // CONFIG_CPM3_COMMON_BASE);
057817cb
L
85 banked_base = getenv_ulong(PSTR(ENV_CPM3_BANKED_BASE), 16,
86 CONFIG_CPM3_BANKED_BASE);
c0abd68b 87
057817cb 88 if (argc > 3)
2d914b45 89 banked_base = eval_arg(argv[3], NULL);
057817cb 90 if (argc > 2)
2d914b45 91 common_base = eval_arg(argv[2], NULL);
c0abd68b 92
bddc7e77 93 fname = getenv_str(PSTR(ENV_CPM3_SYSFILE));
209025e8
L
94 if (fname == NULL || *fname == '\0') {
95 strcpy_P(default_fname, PSTR(CONFIG_CPM3_SYSFILE));
96 fname = default_fname;
97 }
98aac4d0
L
98 if (argc > 1) {
99 fname = argv[1];
c0abd68b 100 }
c0abd68b 101
bbd45c46 102 res = f_open(&File, fname, FA_READ );
5e8ac5e0
L
103 if (res)
104 goto out;
c0abd68b
L
105
106 printf_P(PSTR("Loading: '%s'...\n"), fname);
107
108 /* read the load record */
5e8ac5e0
L
109 res = read_record(&File, buffer);
110 if (res)
c0abd68b
L
111 goto out;
112
113 mem_top = buffer[0] << 8;
114 res_len = buffer[1];
115 bank_top = buffer[2] << 8;
116 bank_len = buffer[3];
057817cb 117 osentry_addr = buffer[4] + (buffer[5] << 8);
c0abd68b
L
118
119 /* read display info */
5e8ac5e0
L
120 res = read_record(&File, buffer);
121 if (res)
c0abd68b
L
122 goto out;
123
124 /* print the info */
125 buffer[RS-1] = '$';
126 uint8_t *p = memchr(buffer, '$', RS);
127 *p = '\0';
128 my_puts((char *)buffer);
129
b51d2360
L
130 if (common_base == 0) {
131 /* read common base
132 * http://www.seasip.info/Cpm/scb.html
133 */
134 FSIZE_t common_base_ofs = ((res_len - 6) << 8) + 2*RS + RS-7;
135 FSIZE_t cur_pos = f_tell(&File);
5e8ac5e0 136 unsigned int br; /* bytes read */
b51d2360
L
137 if ((res = f_lseek(&File, common_base_ofs)) ||
138 (res = f_read(&File, buffer, 2, &br)) ||
b51d2360
L
139 (res = f_lseek(&File, cur_pos)))
140 goto out;
5e8ac5e0
L
141 if (br != 2) {
142 res = EEOF;
143 goto out;
144 }
b51d2360
L
145 common_base = (uint16_t) buffer[0] + (buffer[1] << 8);
146 setenv_hex(PSTR(ENV_CPM3_COMMON_BASE), common_base);
147 }
2b3aff48
L
148
149 setenv_hex(PSTR(ENV_CPM3_SCB), mem_top - ((res_len - (6 - 1)) << 8) + common_base);
150
c0abd68b
L
151 /* Main System Load */
152
153 /* Load Common Portion of System */
057817cb 154 if ((res = load(&File, common_base + mem_top, res_len)) != 0)
c0abd68b
L
155 goto out;
156
157 /* Load Banked Portion of System */
057817cb 158 res = load(&File, banked_base + bank_top, bank_len);
c0abd68b
L
159
160out:
161 f_close(&File);
c0abd68b 162
5e8ac5e0
L
163 if (res)
164 cmd_error(CMD_RET_FAILURE, res, PSTR("%s"), fname);
165
166 if (res_len != 0) {
167 if (osentry_addr + common_base > 0xffff) {
168 z80_bus_cmd(Request);
169 if (z80_read(osentry_addr + common_base) == 0xc3) {
170 osentry_addr = z80_read(osentry_addr+common_base+1) +
171 (z80_read(osentry_addr + common_base+2) << 8);
057817cb 172 }
5e8ac5e0
L
173 z80_bus_cmd(Release);
174 if (banked_base + osentry_addr > 0xffff)
175 osentry_addr = 0;
057817cb 176 }
5e8ac5e0 177 setenv_hex(PSTR(ENV_STARTADDRESS), osentry_addr);
c0abd68b 178 }
5e8ac5e0
L
179 printf_P(PSTR("Loaded: Resident: "));
180 if (res_len != 0)
181 printf_P(PSTR("%.5lX-%.5lX, "),
182 (common_base + mem_top) - res_len*256,
183 (common_base + mem_top) - 1);
184 else
185 printf_P(PSTR(" - "));
186 printf_P(PSTR("Banked: "));
187 if (bank_len != 0)
188 printf_P(PSTR("%.5lX-%.5lX\n"),
189 (banked_base + bank_top) - bank_len*256,
190 (banked_base + bank_top) - 1);
191 else
192 printf_P(PSTR(" - \n"));
193
194 return CMD_RET_SUCCESS;
c0abd68b 195}