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