First Commit of my working state
[simh.git] / AltairZ80 / flashwriter2.c
CommitLineData
196ba1fc
PH
1/*************************************************************************\r
2 * *\r
3 * $Id: flashwriter2.c 1753 2008-01-02 16:36:47Z Hharte $ *\r
4 * *\r
5 * Copyright (c) 2007-2008 Howard M. Harte. *\r
6 * http:/*www.hartetec.com *\r
7 * *\r
8 * Permission is hereby granted, free of charge, to any person obtaining *\r
9 * a copy of this software and associated documentation files (the *\r
10 * "Software"), to deal in the Software without restriction, including *\r
11 * without limitation the rights to use, copy, modify, merge, publish, *\r
12 * distribute, sublicense, and/or sell copies of the Software, and to *\r
13 * permit persons to whom the Software is furnished to do so, subject to *\r
14 * the following conditions: *\r
15 * *\r
16 * The above copyright notice and this permission notice shall be *\r
17 * included in all copies or substantial portions of the Software. *\r
18 * *\r
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *\r
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *\r
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *\r
22 * NONINFRINGEMENT. IN NO EVENT SHALL HOWARD M. HARTE BE LIABLE FOR ANY *\r
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *\r
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *\r
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *\r
26 * *\r
27 * Except as contained in this notice, the name of Howard M. Harte shall *\r
28 * not be used in advertising or otherwise to promote the sale, use or *\r
29 * other dealings in this Software without prior written authorization *\r
30 * Howard M. Harte. *\r
31 * *\r
32 * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. *\r
33 * *\r
34 * Module Description: *\r
35 * Vector Graphic, Inc. FlashWriter II module for SIMH *\r
36 * *\r
37 * Environment: *\r
38 * User mode only *\r
39 * *\r
40 *************************************************************************/\r
41\r
42/*#define DBG_MSG*/\r
43\r
44#include "altairz80_defs.h"\r
45\r
46#if defined (_WIN32)\r
47#include <windows.h>\r
48#else\r
49#include "sim_sock.h"\r
50#endif\r
51\r
52#include "sim_tmxr.h"\r
53\r
54#ifdef DBG_MSG\r
55#define DBG_PRINT(args) printf args\r
56#else\r
57#define DBG_PRINT(args)\r
58#endif\r
59\r
60\r
61extern int32 sio0s(const int32 port, const int32 io, const int32 data);\r
62extern int32 sio0d(const int32 port, const int32 io, const int32 data);\r
63extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,\r
64 int32 (*routine)(const int32, const int32, const int32), uint8 unmap);\r
65\r
66static char ansibuf[10];\r
67\r
68#define FW2_MAX_BOARDS 4\r
69#define UNIT_V_FW2_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */\r
70#define UNIT_FW2_VERBOSE (1 << UNIT_V_FW2_VERBOSE)\r
71#define FW2_CAPACITY (2048) /* FlashWriter II Memory Size */\r
72\r
73typedef struct {\r
74 UNIT *uptr; /* UNIT pointer */\r
75 uint8 cur_FL_Row; /* Current Flashwriter Row */\r
76 uint8 cur_FL_Col; /* Current Flashwriter Column */\r
77 uint8 FL_Row;\r
78 uint8 FL_Col;\r
79 uint8 reversevideo; /* Flag set if reverse video is currently on */\r
80 uint8 M[FW2_CAPACITY]; /* FlashWriter 2K Video Memory */\r
81} FW2_INFO;\r
82\r
83static FW2_INFO *fw2_info[4];\r
84static uint8 port_map[4] = { 0x11, 0x15, 0x17, 0x19 };\r
85\r
86static int32 fw2dev(const int32 Addr, const int32 rw, const int32 data);\r
87static t_stat fw2_reset(DEVICE *dptr);\r
88static t_stat fw2_attach(UNIT *uptr, char *cptr);\r
89static t_stat fw2_detach(UNIT *uptr);\r
90static uint8 FW2_Read(const uint32 Addr);\r
91static uint8 FW2_Write(const uint32 Addr, uint8 cData);\r
92static t_stat get_base_address(char *cptr, uint32 *baseaddr);\r
93\r
94static int32 FWIITrace = FALSE;\r
95\r
96static UNIT fw2_unit[] = {\r
97 { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) },\r
98 { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) },\r
99 { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) },\r
100 { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) }\r
101};\r
102\r
103static REG fw2_reg[] = {\r
104 { DRDATA (FWIITRACE, FWIITrace, 8), },\r
105 { NULL }\r
106};\r
107\r
108static MTAB fw2_mod[] = {\r
109 /* quiet, no warning messages */\r
110 { UNIT_FW2_VERBOSE, 0, "QUIET", "QUIET", NULL },\r
111 /* verbose, show warning messages */\r
112 { UNIT_FW2_VERBOSE, UNIT_FW2_VERBOSE, "VERBOSE", "VERBOSE", NULL },\r
113 { 0 }\r
114};\r
115\r
116DEVICE fw2_dev = {\r
117 "FWII", fw2_unit, fw2_reg, fw2_mod,\r
118 FW2_MAX_BOARDS, 10, 31, 1, FW2_MAX_BOARDS, FW2_MAX_BOARDS,\r
119 NULL, NULL, &fw2_reset,\r
120 NULL, &fw2_attach, &fw2_detach,\r
121 NULL, 0, 0,\r
122 NULL, NULL, NULL\r
123};\r
124\r
125/* Reset routine */\r
126static t_stat fw2_reset(DEVICE *dptr)\r
127{\r
128 return SCPE_OK;\r
129}\r
130\r
131/* Attach routine */\r
132static t_stat fw2_attach(UNIT *uptr, char *cptr)\r
133{\r
134 t_stat r;\r
135 unsigned int i = 0;\r
136 uint32 baseaddr;\r
137 char *tptr;\r
138\r
139 r = get_base_address(cptr, &baseaddr);\r
140 if(r != SCPE_OK) /* error?*/\r
141 return r;\r
142\r
143 DBG_PRINT(("%s\n", __FUNCTION__));\r
144\r
145 for(i = 0; i < FW2_MAX_BOARDS; i++) {\r
146 if(&fw2_dev.units[i] == uptr) {\r
147 if(uptr->flags & UNIT_FW2_VERBOSE) {\r
148 printf("Attaching unit %d\n at %04x", i, baseaddr);\r
149 }\r
150 break;\r
151 }\r
152 }\r
153\r
154 fw2_info[i] = calloc(1, sizeof(FW2_INFO));\r
155 fw2_info[i]->uptr = uptr;\r
156 fw2_info[i]->uptr->u3 = baseaddr;\r
157\r
158 if(sim_map_resource(baseaddr, FW2_CAPACITY, RESOURCE_TYPE_MEMORY, &fw2dev, FALSE) != 0) {\r
159 printf("%s: error mapping MEM resource at 0x%04x\n", __FUNCTION__, baseaddr);\r
160 return SCPE_ARG;\r
161 }\r
162\r
163 if(sim_map_resource(0x00, 1, RESOURCE_TYPE_IO, &sio0s, FALSE) != 0) {\r
164 printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, 0x00);\r
165 return SCPE_ARG;\r
166 }\r
167\r
168 if(sim_map_resource(0x01, 1, RESOURCE_TYPE_IO, &sio0d, FALSE) != 0) {\r
169 printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, 0x01);\r
170 return SCPE_ARG;\r
171 }\r
172\r
173 tptr = (char *) malloc (strlen (cptr) + 3); /* get string buf */\r
174 if (tptr == NULL) return SCPE_MEM; /* no more mem? */\r
175 sprintf(tptr, "0x%04x", baseaddr); /* copy base address */\r
176 uptr->filename = tptr; /* save */\r
177 uptr->flags = uptr->flags | UNIT_ATT;\r
178 return SCPE_OK;\r
179}\r
180\r
181\r
182/* Detach routine */\r
183static t_stat fw2_detach(UNIT *uptr)\r
184{\r
185 uint8 i;\r
186\r
187 DBG_PRINT(("%s\n", __FUNCTION__));\r
188\r
189 for(i = 0; i < FW2_MAX_BOARDS; i++) {\r
190 if(&fw2_dev.units[i] == uptr) {\r
191 break;\r
192 }\r
193 }\r
194\r
195 if (i >= FW2_MAX_BOARDS) return SCPE_ARG;\r
196\r
197 /* Disconnect FlashWriter2: unmap memory and I/O resources */\r
198 sim_map_resource(fw2_info[i]->uptr->u3, FW2_CAPACITY, RESOURCE_TYPE_MEMORY, &fw2dev, TRUE);\r
199 sim_map_resource(0x00, 1, RESOURCE_TYPE_IO, &sio0s, TRUE);\r
200 sim_map_resource(0x01, 1, RESOURCE_TYPE_IO, &sio0d, TRUE);\r
201\r
202 if(fw2_info[i]) {\r
203 free(fw2_info[1]);\r
204 }\r
205\r
206 free (uptr->filename); /* free base address string */\r
207 uptr->filename = NULL;\r
208 uptr->flags = uptr->flags & ~UNIT_ATT; /* not attached */\r
209 return SCPE_OK;\r
210}\r
211\r
212static t_stat get_base_address(char *cptr, uint32 *baseaddr) {\r
213 uint32 b;\r
214 sscanf(cptr, "%x", &b);\r
215 if(b & (FW2_CAPACITY-1)) {\r
216 printf("FWII must be on a %d-byte boundary.\n", FW2_CAPACITY);\r
217 return SCPE_ARG;\r
218 }\r
219 *baseaddr = b & ~(FW2_CAPACITY-1);\r
220 return SCPE_OK;\r
221}\r
222\r
223extern int32 getBankSelect(void);\r
224\r
225/* This is the main entry point into the Flashwriter2 emulation. */\r
226static int32 fw2dev(const int32 Addr, const int32 rw, const int32 data)\r
227{\r
228 int32 bank = getBankSelect();\r
229 if(bank == 0) {\r
230 if(rw == 0) { /* Read */\r
231 return(FW2_Read(Addr));\r
232 } else { /* Write */\r
233 return(FW2_Write(Addr, data));\r
234 }\r
235 } else return 0xff;\r
236}\r
237\r
238\r
239static uint8 FW2_Write(const uint32 Addr, uint8 Value)\r
240{\r
241 FW2_INFO *fw2 = NULL;\r
242 uint8 FL_Row;\r
243 uint8 FL_Col;\r
244 uint32 baseaddr = 0;\r
245 uint8 i;\r
246 uint8 outchar;\r
247 uint8 port;\r
248\r
249 for(i = 0; i < FW2_MAX_BOARDS; i++) {\r
250 if(fw2_info[i] != NULL) {\r
251 baseaddr = fw2_info[i]->uptr->u3;\r
252 if((Addr >= baseaddr) && (Addr < (baseaddr + FW2_CAPACITY))) {\r
253 break;\r
254 }\r
255 }\r
256 }\r
257\r
258 if(i == FW2_MAX_BOARDS) {\r
259 return 0;\r
260 }\r
261\r
262 fw2 = fw2_info[i];\r
263 port = port_map[i];\r
264\r
265 fw2->M[Addr - baseaddr] = Value;\r
266\r
267 /* Only print if it is in the visible part of the Flashwriter memory */\r
268 if((Addr >= baseaddr) && (Addr < (baseaddr + (80 * 24)))) {\r
269 FL_Col = ((Addr-baseaddr) % 80) + 1;\r
270 FL_Row = ((Addr-baseaddr) / 80) + 1;\r
271\r
272 if(Value & 0x80) { /* reverse video */\r
273 if(fw2->reversevideo == 0) {\r
274 fw2->reversevideo = 1;\r
275 sprintf(ansibuf, "\x1b[07m");\r
276 for(i=0;i<strlen(ansibuf);i++) {\r
277 sio0d(port, 1, ansibuf[i]);\r
278 }\r
279 }\r
280 } else {\r
281 if(fw2->reversevideo == 1) {\r
282 fw2->reversevideo = 0;\r
283 sprintf(ansibuf, "\x1b[00m");\r
284 for(i=0;i<strlen(ansibuf);i++) {\r
285 sio0d(port, 1, ansibuf[i]);\r
286 }\r
287 }\r
288 }\r
289\r
290 outchar = Value & 0x7F;\r
291 if(outchar < ' ') {\r
292 outchar = 'O';\r
293 }\r
294 if(outchar == 0x7F) { /* this is supposed to be a square Block character on FW2 */\r
295 outchar = 'X';\r
296 }\r
297\r
298 if((fw2->cur_FL_Row == FL_Row) && (FL_Col == fw2->cur_FL_Col + 1)) {\r
299 sio0d(port, 1, outchar);\r
300 } else {\r
301 /* ESC[#;#H */\r
302 sprintf(ansibuf, "\x1b[%d;%dH%c", FL_Row, FL_Col, outchar);\r
303 for(i=0;i<strlen(ansibuf);i++) {\r
304 sio0d(port, 1, ansibuf[i]);\r
305 }\r
306 }\r
307 fw2->cur_FL_Col = FL_Col;\r
308 fw2->cur_FL_Row = FL_Row;\r
309 }\r
310\r
311 return(1);\r
312}\r
313\r
314\r
315static uint8 FW2_Read(const uint32 Addr)\r
316{\r
317 uint32 baseaddr = 0;\r
318 uint8 i;\r
319\r
320 for(i = 0; i < FW2_MAX_BOARDS; i++) {\r
321 if(fw2_info[i] != NULL) {\r
322 baseaddr = fw2_info[i]->uptr->u3;\r
323 if((Addr >= baseaddr) && (Addr < (baseaddr + FW2_CAPACITY))) {\r
324 break;\r
325 }\r
326 }\r
327 }\r
328\r
329 if(i == FW2_MAX_BOARDS) {\r
330 return 0xFF;\r
331 }\r
332\r
333 return(fw2_info[i]->M[Addr - baseaddr]);\r
334}\r