Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
emu_rom_interface.c
Go to the documentation of this file.
1 /* Minimalistic Enterprise-128 emulator with focus on "exotic" hardware
2  Part of the Xemu project, please visit: https://github.com/lgblgblgb/xemu
3  Copyright (C)2015-2016,2020-2021 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18 
19 #include "xemu/emutools.h"
20 #include "xemu/emutools_config.h"
21 #include "enterprise128.h"
22 #include "emu_rom_interface.h"
23 #include "xemu/../rom/ep128/xep_rom_syms.h"
24 #include "xemu/z80.h"
25 #include "cpu.h"
26 #include "roms.h"
27 #include "emu_monitor.h"
28 #include "fileio.h"
29 #include "configdb.h"
30 
31 #include <unistd.h>
32 #include <time.h>
33 
34 #define XEPSYM_ADDR(sym) (xep_rom_addr + (sym) - 0xC000)
35 #define XEPSYM_P(sym) (memory + XEPSYM_ADDR(sym))
36 #define COBUF ((char*)XEPSYM_P(xepsym_cobuf))
37 #define SET_XEPSYM_BYTE(sym, value) *XEPSYM_P(sym) = (value)
38 #define SET_XEPSYM_WORD(sym, value) do { \
39  SET_XEPSYM_BYTE(sym, (value) & 0xFF); \
40  SET_XEPSYM_BYTE((sym) + 1, (value) >> 8); \
41 } while(0)
42 #define BIN2BCD(bin) ((((bin) / 10) << 4) | ((bin) % 10))
43 
44 static const char EXOS_NEWLINE[] = "\r\n";
47 
48 #define EXOS_ADDR(n) (0x3FC000 | ((n) & 0x3FFF))
49 #define EXOS_BYTE(n) memory[EXOS_ADDR(n)]
50 #define EXOS_GET_WORD(n) (EXOS_BYTE(n) | (EXOS_BYTE((n) + 1) << 8))
51 
52 
53 
54 void exos_get_status_line ( char *buffer )
55 {
56  Uint8 *s = memory + EXOS_ADDR(EXOS_GET_WORD(0xBFF6));
57  int a = 40;
58  while (a--)
59  *(buffer++) = *(s++) & 0x7F;
60  *buffer = '\0';
61 }
62 
63 
64 void xep_set_error ( const char *msg )
65 {
66  int l = strlen(msg);
67  if (l > 63)
68  l = 63;
69  SET_XEPSYM_BYTE(xepsym_error_message_buffer, l);
70  memcpy(XEPSYM_P(xepsym_error_message_buffer + 1), msg, l);
71  DEBUG("XEP: error msg set len=%d len_stored=%d \"%s\"" NL, l, *XEPSYM_P(xepsym_error_message_buffer), msg);
72 }
73 
74 
75 void xep_set_time_consts ( char *descbuffer )
76 {
77  struct tm *t = localtime(&unix_time);
78  SET_XEPSYM_BYTE(xepsym_settime_hour, BIN2BCD(t->tm_hour));
79  SET_XEPSYM_WORD(xepsym_settime_minsec, (BIN2BCD(t->tm_min) << 8) | BIN2BCD(t->tm_sec));
80  SET_XEPSYM_BYTE(xepsym_setdate_year, BIN2BCD(t->tm_year - 80));
81  SET_XEPSYM_WORD(xepsym_setdate_monday, (BIN2BCD(t->tm_mon + 1) << 8) | BIN2BCD(t->tm_mday));
82  if (descbuffer)
83  sprintf(descbuffer, "%04d-%02d-%02d %02d:%02d:%02d",
84  t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
85  t->tm_hour, t->tm_min, t->tm_sec
86  );
87  SET_XEPSYM_WORD(xepsym_jump_on_rom_entry, xepsym_set_time);
88 }
89 
90 
91 
92 /* Sets XEP ROM jump to the code fragment to utilize EXOS 19 call
93  to set default device name provided, with also storing the given
94  name */
95 void xep_set_default_device_name ( const char *name )
96 {
97  int l;
98  if (!name)
99  name = configdb.ddn;
100  if (!name)
101  name = "";
102  l = strlen(name);
103  if (l < 16) {
104  if (l)
105  memcpy(XEPSYM_P(xepsym_default_device_name_string + 1), name, l);
106  SET_XEPSYM_BYTE(xepsym_default_device_name_string, l);
107  SET_XEPSYM_WORD(xepsym_jump_on_rom_entry, xepsym_set_default_device_name);
108  SET_XEPSYM_BYTE(xepsym_set_default_device_name_is_file_handler, strncasecmp(name, "TAPE", 4) ? 1 : 0);
109  } else
110  ERROR_WINDOW("Too long default device name is tried to be set, ignoring!");
111 }
112 
113 
114 
115 static int exos_cmd_name_match ( const char *that, Uint16 addr )
116 {
117  if (strlen(that) != Z80_B) return 0;
118  while (*that)
119  if (*(that++) != read_cpu_byte(addr++))
120  return 0;
121  return 1;
122 }
123 
124 
125 
126 static void xep_exos_command_trap ( void )
127 {
128  Uint8 c = Z80_C, b = Z80_B;
129  Uint16 de = Z80_DE;
130  int size;
131  *COBUF = 0; // no ans by def
132  DEBUG("XEP: COMMAND TRAP: C=%02Xh, B=%02Xh, DE=%04Xh" NL, c, b, de);
133  /* restore exos command handler jump address */
134  SET_XEPSYM_WORD(xepsym_jump_on_rom_entry, xepsym_print_xep_buffer);
135  switch (c) {
136  case 2: // EXOS command
137  if (exos_cmd_name_match("XEP", de + 1)) {
138  char buffer[256];
139  char *p = buffer;
140  b = read_cpu_byte(de) - 3;
141  de += 4;
142  while (b--)
143  *(p++) = read_cpu_byte(de++);
144  *p = '\0';
146  buffer, // input buffer
147  1, // source system (XEP ROM)
148  COBUF, // output buffer (directly into the co-buffer area!)
149  xepsym_cobuf_size - 1, // max allowed output size
150  EXOS_NEWLINE // newline delimiter requested (for EXOS we use this fixed value! unlike with console/monitor where it's host-OS dependent!)
151  );
152  Z80_A = 0;
153  Z80_C = 0;
154  }
155  break;
156  case 3: // EXOS help
157  if (!b) {
158  // eg on :HELP (ROM list) we patch the request as ROMNAME monitor command ...
159  monitor_execute("ROMNAME", 1, COBUF, xepsym_cobuf_size - 1, EXOS_NEWLINE);
160  Z80_A = 0;
161  } else if (exos_cmd_name_match("XEP", de + 1)) {
162  monitor_execute("HELP", 1, COBUF, xepsym_cobuf_size - 1, EXOS_NEWLINE);
163  Z80_A = 0;
164  Z80_C = 0;
165  }
166  break;
167  case 8: // Initialization
168  // Tell XEP ROM to set EXOS date/time with setting we will provide here
169  xep_set_time_consts(NULL);
170  SET_XEPSYM_WORD(xepsym_jump_on_rom_entry, xepsym_system_init);
171  break;
172  case 1: // Cold reset (app program can take control here) after the copyright msg ...
173  SET_XEPSYM_WORD(xepsym_jump_on_rom_entry, xepsym_cold_reset);
174  break;
175  case 5: // explain error code ...
176  DEBUG("XEP: explain error code of %02Xh our=%d" NL, Z80_B, Z80_B == XEP_ERROR_CODE);
177  if (Z80_B == XEP_ERROR_CODE) {
178  Z80_B = xep_rom_seg;
179  Z80_DE = xepsym_error_message_buffer;
180  Z80_C = 0; // signal that we recognized the error code
181  }
182  break;
183  }
184  size = strlen(COBUF);
185  if (size)
186  DEBUG("XEP: ANSWER: [%d bytes] = \"%s\"" NL, size, COBUF);
187  // just a sanity check, monitor_execute() would not allow - in theory ... - to store more data than specified (by MPRINTF)
188  if (size > xepsym_cobuf_size - 1)
189  FATAL("FATAL: XEP ROM answer is too large, %d bytes.", size);
190  SET_XEPSYM_WORD(xepsym_print_size, size); // set print-out size (0 = no print)
191 }
192 
193 
194 
195 void xep_rom_trap ( Uint16 pc, Uint8 opcode )
196 {
197  xep_rom_write_support(0); // to be safe, let's switch writable XEP ROM off (maybe it was enabled by previous trap?)
198  DEBUG("XEP: ROM trap at PC=%04Xh OPC=%02Xh" NL, pc, opcode);
199  if (opcode != xepsym_ed_trap_opcode)
200  FATAL("FATAL: Unknown ED-trap opcode in XEP ROM: PC=%04Xh ED_OP=%02Xh", pc, opcode);
201  switch (pc) {
202  case xepsym_trap_enable_rom_write:
203  DEBUG("XEP: write access to XEP ROM was requested" NL);
204  xep_rom_write_support(1); // special ROM request to enable ROM write ... Danger Will Robinson!!
205  break;
206  case xepsym_trap_exos_command:
207  xep_exos_command_trap();
208  break;
209  case xepsym_trap_on_system_init:
210  exos_version = Z80_B; // store EXOS version number we got ...
211  memcpy(exos_info, memory + ((xepsym_exos_info_struct & 0x3FFF) | (xep_rom_seg << 14)), 8);
212  if (configdb.skiplogo) {
213  DEBUG("XEP: skiplogo option requested logo skip, etting EXOS variable 0xBFEF to 1 on system init ROM call" NL);
214  EXOS_BYTE(0xBFEF) = 1; // use this, to skip Enterprise logo when it arrives :-)
215  }
216  break;
217  default:
218  FATAL("FATAL: Unknown ED-trap location in XEP ROM: PC=%04Xh (ED_OP=%02Xh)", pc, opcode);
219  break;
220  //
221  /* ---- FILEIO RELATED TRAPS ---- */
222  //
223  case xepsym_trap_set_default_device_name_feedback:
224  // TODO: handle this :)
225  break;
226  case xepsym_fileio_open_channel_remember:
228  break;
229  case xepsym_fileio_no_used_call:
231  break;
232  case xepsym_fileio_open_channel:
234  break;
235  case xepsym_fileio_create_channel:
237  break;
238  case xepsym_fileio_close_channel:
240  break;
241  case xepsym_fileio_destroy_channel:
243  break;
244  case xepsym_fileio_read_character:
246  break;
247  case xepsym_fileio_read_block:
249  break;
250  case xepsym_fileio_write_character:
252  break;
253  case xepsym_fileio_write_block:
255  break;
256  case xepsym_fileio_channel_read_status:
258  break;
259  case xepsym_fileio_set_channel_status:
261  break;
262  case xepsym_fileio_special_function:
264  break;
265  case xepsym_fileio_init:
267  break;
268  case xepsym_fileio_buffer_moved:
270  break;
271  }
272 }
Z80_DE
#define Z80_DE
Definition: z80ex.h:85
fileio_func_write_character
void fileio_func_write_character(void)
Definition: fileio.c:394
xep_rom_seg
int xep_rom_seg
Definition: roms.c:33
fileio_func_open_channel_remember
void fileio_func_open_channel_remember(void)
Definition: fileio.c:176
xep_set_time_consts
void xep_set_time_consts(char *descbuffer)
Definition: emu_rom_interface.c:75
read_cpu_byte
Uint8 read_cpu_byte(Uint16 addr)
Definition: cpu.c:258
unix_time
time_t unix_time
Definition: enterprise128.c:59
fileio_func_not_used_call
void fileio_func_not_used_call(void)
Definition: fileio.c:497
xep_rom_write_support
void xep_rom_write_support(int towrite)
Definition: cpu.c:66
Z80_A
#define Z80_A
Definition: z80ex.h:75
pc
Uint16 pc
Definition: z8k1.c:127
emutools.h
emu_monitor.h
XEPSYM_P
#define XEPSYM_P(sym)
Definition: emu_rom_interface.c:35
fileio_func_destroy_channel
void fileio_func_destroy_channel(void)
Definition: fileio.c:488
SET_XEPSYM_WORD
#define SET_XEPSYM_WORD(sym, value)
Definition: emu_rom_interface.c:38
fileio_func_write_block
void fileio_func_write_block(void)
Definition: fileio.c:356
emu_rom_interface.h
addr
int addr
Definition: dma65.c:81
fileio_func_special_function
void fileio_func_special_function(void)
Definition: fileio.c:461
BIN2BCD
#define BIN2BCD(bin)
Definition: emu_rom_interface.c:42
fileio_func_read_character
void fileio_func_read_character(void)
Definition: fileio.c:331
fileio.h
EXOS_ADDR
#define EXOS_ADDR(n)
Definition: emu_rom_interface.c:48
configdb_st::skiplogo
int skiplogo
Definition: configdb.h:36
Uint8
uint8_t Uint8
Definition: fat32.c:51
exos_get_status_line
void exos_get_status_line(char *buffer)
Definition: emu_rom_interface.c:54
exos_version
Uint8 exos_version
Definition: emu_rom_interface.c:45
z80.h
fileio_func_buffer_moved
void fileio_func_buffer_moved(void)
Definition: fileio.c:481
roms.h
fileio_func_open_or_create_channel
void fileio_func_open_or_create_channel(int create)
Definition: fileio.c:183
xep_set_default_device_name
void xep_set_default_device_name(const char *name)
Definition: emu_rom_interface.c:95
fileio_func_set_channel_status
void fileio_func_set_channel_status(void)
Definition: fileio.c:425
configdb_st::ddn
char * ddn
Definition: configdb.h:47
fileio_func_init
void fileio_func_init(void)
Definition: fileio.c:468
ERROR_WINDOW
#define ERROR_WINDOW(...)
Definition: xep128.h:116
monitor_execute
void monitor_execute(char *in_input_buffer, int in_source, char *in_output_buffer, int in_output_max_size, const char *in_output_nl)
Definition: emu_monitor.c:730
cpu.h
NL
#define NL
Definition: fat32.c:37
emutools_config.h
configdb
struct configdb_st configdb
Definition: configdb.c:34
XEP_ERROR_CODE
#define XEP_ERROR_CODE
Definition: emu_rom_interface.h:22
configdb.h
memory
Uint8 memory[0x100000]
Definition: commodore_65.c:43
COBUF
#define COBUF
Definition: emu_rom_interface.c:36
xep_set_error
void xep_set_error(const char *msg)
Definition: emu_rom_interface.c:64
Z80_C
#define Z80_C
Definition: z80ex.h:80
size
int size
Definition: inject.c:37
EXOS_BYTE
#define EXOS_BYTE(n)
Definition: emu_rom_interface.c:49
SET_XEPSYM_BYTE
#define SET_XEPSYM_BYTE(sym, value)
Definition: emu_rom_interface.c:37
Z80_B
#define Z80_B
Definition: z80ex.h:79
fileio_func_channel_read_status
void fileio_func_channel_read_status(void)
Definition: fileio.c:418
EXOS_GET_WORD
#define EXOS_GET_WORD(n)
Definition: emu_rom_interface.c:50
Uint16
uint16_t Uint16
Definition: fat32.c:50
fileio_func_close_channel
void fileio_func_close_channel(void)
Definition: fileio.c:235
xep_rom_trap
void xep_rom_trap(Uint16 pc, Uint8 opcode)
Definition: emu_rom_interface.c:195
name
const char * name
Definition: joystick.c:46
enterprise128.h
DEBUG
#define DEBUG(...)
Definition: emutools_basicdefs.h:167
FATAL
#define FATAL(...)
Definition: xep128.h:117
fileio_func_read_block
void fileio_func_read_block(void)
Definition: fileio.c:288
exos_info
Uint8 exos_info[8]
Definition: emu_rom_interface.c:46