static void dmal_out(BYTE);
static BYTE dmah_in(void);
static void dmah_out(BYTE);
-static BYTE mmui_in(void), mmus_in(void), mmuc_in(void);
-static void mmui_out(BYTE), mmus_out(BYTE), mmuc_out(BYTE);
+static BYTE mmui_in(void), mmus_in(void), mmussl_in(void), mmussh_in(void);
+static void mmui_out(BYTE), mmus_out(BYTE), mmussl_out(BYTE), mmussh_out(BYTE);
static BYTE mmup_in(void);
static void mmup_out(BYTE);
+static BYTE mmupbml_in(void);
+static void mmupbml_out(BYTE);
+static BYTE mmupbmh_in(void);
+static void mmupbmh_out(BYTE);
static BYTE clkc_in(void), clkd_in(void);
static void clkc_out(BYTE), clkd_out(BYTE);
static BYTE time_in(void);
io_trap_in, /* port 19 */
mmui_in, /* port 20 */
mmus_in, /* port 21 */
- mmuc_in, /* port 22 */
+ mmussl_in, /* port 22 */
mmup_in, /* port 23 */
- io_trap_in, /* port 24 */
+ mmussh_in, /* port 24 */
clkc_in, /* port 25 */
clkd_in, /* port 26 */
time_in, /* port 27 */
io_trap_in, /* port 49 */
nets1_in, /* port 50 */
netd1_in, /* port 51 */
- io_trap_in, /* port 52 */
- io_trap_in, /* port 53 */
+ mmupbml_in, /* port 52 */
+ mmupbmh_in, /* port 53 */
io_trap_in, /* port 54 */
io_trap_in, /* port 55 */
io_trap_in, /* port 56 */
io_trap_out, /* port 19 */
mmui_out, /* port 20 */
mmus_out, /* port 21 */
- mmuc_out, /* port 22 */
+ mmussl_out, /* port 22 */
mmup_out, /* port 23 */
- io_trap_out, /* port 24 */
+ mmussh_out, /* port 24 */
clkc_out, /* port 25 */
clkd_out, /* port 26 */
time_out, /* port 27 */
io_trap_out, /* port 49 */
nets1_out, /* port 50 */
netd1_out, /* port 51 */
- io_trap_out, /* port 52 */
- io_trap_out, /* port 53 */
+ mmupbml_out, /* port 52 */
+ mmupbmh_out, /* port 53 */
io_trap_out, /* port 54 */
io_trap_out, /* port 55 */
io_trap_out, /* port 56 */
void init_io(void)
{
register int i;
+#if defined(DISKSDIR) || defined(PIPES)
struct stat sbuf;
+#endif
#if defined(NETWORKING) && defined(TCPASYNC)
static struct sigaction newact;
#endif
if (diskdir != NULL) {
strcpy(fn, diskd);
} else {
+#ifdef DISKSDIR
/* if not first try ./disks */
if ((stat("./disks", &sbuf) == 0) &&
S_ISDIR(sbuf.st_mode)) {
} else {
strcpy(fn, DISKSDIR);
}
+#else
+ strcpy(fn, "./disks");
+#endif
}
strcat(fn, "/");
/* reset hardware */
time_out(0); /* stop timer */
- for (i = 1; i < MAXSEG; i++) { /* reset MMU */
- if (memory[i] != NULL) {
- free(memory[i]);
- memory[i] = NULL;
- }
+ for (i = 1; i < maxbnk; i++) { /* reset MMU */
+ free(memory[i]);
+ memory[i] = NULL;
}
+ maxbnk = 1;
selbnk = 0;
segsize = SEGSIZ;
*/
static void mmui_out(BYTE data)
{
+ int new_maxbnk;
register int i;
- /* do nothing if MMU initialised already */
- if (memory[1] != NULL)
- return;
-
- if (data > MAXSEG) {
- printf("Try to init %d banks, available %d banks\r\n",
- data, MAXSEG);
+ new_maxbnk = data;
+ if (new_maxbnk <= selbnk || new_maxbnk > MAXSEG) {
+ printf("Try to init %d banks, must be %d to %d inclusive\r\n",
+ new_maxbnk, selbnk + 1, MAXSEG);
#if 1
assert(false);
#else
#endif
return;
}
-
- for (i = 1; i < data; i++) {
- if ((memory[i] = (BYTE *)malloc(segsize)) == NULL) {
- printf("can't allocate memory for bank %d\r\n", i);
+ if (new_maxbnk >= maxbnk)
+ for (i = maxbnk; i < new_maxbnk; i++) {
+ if ((memory[i] = (BYTE *)malloc(segsize)) == NULL && segsize) {
+ printf("can't allocate memory for bank %d\r\n", i);
#if 1
assert(false);
#else
- cpu_error = IOERROR;
- cpu_state = STOPPED;
+ cpu_error = IOERROR;
+ cpu_state = STOPPED;
#endif
- return;
+ return;
+ }
+ memset(memory[i], 0, segsize);
}
- }
-
- maxbnk = data;
+ else
+ for (i = new_maxbnk; i < maxbnk; i++) {
+ free(memory[i]);
+ memory[i] = NULL;
+ }
+ maxbnk = new_maxbnk;
}
/*
*/
static void mmus_out(BYTE data)
{
- if (data > maxbnk - 1) {
+ if (data >= maxbnk) {
#if 1
printf("try to select unallocated bank %d\r\n", data);
assert(false);
/*
* I/O handler for read MMU segment size configuration:
- * returns size of the bank segments in pages a 256 bytes
+ * returns lower byte, size of the bank segments in pages a 256 bytes
*/
-static BYTE mmuc_in(void)
+static BYTE mmussl_in(void)
{
return((BYTE) (segsize >> 8));
}
/*
* I/O handler for write MMU segment size configuration:
- * set the size of the bank segments in pages a 256 bytes
+ * sets lower byte, size of the bank segments in pages a 256 bytes
+ * must be done before any banks are allocated
+ */
+static void mmussl_out(BYTE data)
+{
+ if (maxbnk > 1) {
+ printf("Not possible to resize already allocated segments\r\n");
+#if 1
+ assert(false);
+#else
+ cpu_error = IOERROR;
+ cpu_state = STOPPED;
+#endif
+ return;
+ }
+ segsize = (segsize & 0xff0000) | (data << 8);
+}
+
+/*
+ * I/O handler for read MMU segment size configuration:
+ * returns upper byte, size of the bank segments in pages a 256 bytes
+ */
+static BYTE mmussh_in(void)
+{
+ return((BYTE) (segsize >> 16));
+}
+
+/*
+ * I/O handler for write MMU segment size configuration:
+ * sets lower byte, size of the bank segments in pages a 256 bytes
* must be done before any banks are allocated
*/
-static void mmuc_out(BYTE data)
+static void mmussh_out(BYTE data)
{
- if (memory[1] != NULL) {
+ if (maxbnk > 1) {
printf("Not possible to resize already allocated segments\r\n");
#if 1
assert(false);
#endif
return;
}
- segsize = data << 8;
+ segsize = (segsize & 0xff00) | (data << 16);
}
/*
wp_common = data;
}
+/*
+ * I/O handler for MMU protect/unprotect individual banks
+ * return lower byte of the protection bitmap
+ */
+static BYTE mmupbml_in(void)
+{
+ return((BYTE) wp_bitmap);
+}
+
+/*
+ * I/O handler for MMU protect/unprotect individual banks
+ * set higher byte of the protection bitmap
+ */
+static void mmupbml_out(BYTE data)
+{
+ wp_bitmap = (wp_bitmap & 0xff00) | data;
+}
+
+/*
+ * I/O handler for MMU protect/unprotect individual banks
+ * return higher byte of current protection bitmap
+ */
+static BYTE mmupbmh_in(void)
+{
+ return((BYTE) (wp_bitmap >> 8));
+}
+
+/*
+ * I/O handler for MMU protect/unprotect individual banks
+ * set higher byte of the protection bitmap
+ */
+static void mmupbmh_out(BYTE data)
+{
+ wp_bitmap = (wp_bitmap & 0xff) | (data << 8);
+}
+
/*
* I/O handler for read clock command:
* return last clock command
extern void init_memory(void), init_rom(void);
extern BYTE *memory[];
-extern int selbnk, maxbnk, segsize, wp_common;
+extern int selbnk, maxbnk, segsize, wp_common, wp_bitmap;
/*
* memory access for the CPU cores
*/
-static inline void memwrt(WORD addr, BYTE data)
+static inline void memwrt(uint32_t addr, BYTE data)
{
- if ((addr >= segsize) && (wp_common != 0))
- return;
-
- if (selbnk == 0) {
- *(memory[0] + addr) = data;
- } else {
- if (addr >= segsize)
- *(memory[0] + addr) = data;
- else
- *(memory[selbnk] + addr) = data;
+ if (addr >= segsize) {
+ assert(addr < 0x100000);
+ if (wp_common == 0)
+ memory[0][addr] = data;
}
+ else if ((wp_bitmap & (1 << selbnk)) == 0)
+ memory[selbnk][addr] = data;
}
-static inline BYTE memrdr(WORD addr)
+static inline BYTE memrdr(uint32_t addr)
{
- if (selbnk == 0)
- return(*(memory[0] + addr));
-
- if (addr >= segsize)
- return(*(memory[0] + addr));
- else
- return(*(memory[selbnk] + addr));
+ if (addr >= segsize) {
+ assert(addr < 0x100000);
+ return(memory[0][addr]);
+ }
+ return(memory[selbnk][addr]);
}
/*
/*
* Load boot code from a saved core image, a boot file or from
- * first sector of disk drive A:
+ * a simulated ROM (usually reads first sector of disk drive A:)
*/
int boot(void)
{
register int fd;
+#ifdef ROMSDIR //DISKSDIR
struct stat sbuf;
+#endif
static char fn[4096];
static char err[256];
+#if 1
+ ssize_t count;
+#endif
puts("\r\nBooting...\r\n");
return(load_file(xfn));
}
+#if 1
+ assert(maxbnk == 1);
+
+ /* allocate the second 1 Mbyte bank, it will be shrunk later */
+ if ((memory[1] = (BYTE *)malloc(0x100000)) == NULL) {
+ printf("can't allocate memory for bank 1\r\n");
+ return(1);
+ }
+ memset(memory[1], 0, 0x100000);
+
+#ifdef ROMSDIR
+ /* if not first try ./roms */
+ if ((stat("./roms", &sbuf) == 0) && S_ISDIR(sbuf.st_mode)) {
+ strcpy(fn, "./roms");
+ /* nope, then ROMSDIR as set in Makefile */
+ } else {
+ strcpy(fn, ROMSDIR);
+ }
+#else
+ strcpy(fn, "./roms");
+#endif
+ strcat(fn, "/z180.bin");
+
+ strcpy(err, "file ");
+ strcat(err, fn);
+
+ if ((fd = open(fn, O_RDONLY)) == -1) {
+ perror(err);
+ puts("\r\n");
+ close(fd);
+ return(1);
+ }
+ if ((count = read(fd, memory[1], 0x100000)) == (ssize_t)-1) {
+ perror(err);
+ puts("\r\n");
+ close(fd);
+ return(1);
+ }
+ close(fd);
+
+ segsize = (count + 0xff) & 0xffff00;
+ memory[1] = (BYTE *)realloc(memory[1], segsize);
+
+ selbnk = 1;
+ maxbnk = 2;
+ wp_bitmap = 2;
+#if 1
+ static_cast<z180_device *>(cpu_dev)->m_PC.w.l = 0;
+#else
+ PC = 0;
+#endif
+#else
/* if option -d is used disks are there */
if (diskdir != NULL) {
strcpy(fn, diskd);
} else {
+#ifdef DISKSDIR
/* if not first try ./disks */
if ((stat("./disks", &sbuf) == 0) && S_ISDIR(sbuf.st_mode)) {
strcpy(fn, "./disks");
} else {
strcpy(fn, DISKSDIR);
}
+#else
+ strcpy(fn, "./disks");
+#endif
}
strcat(fn, "/");
return(1);
}
close(fd);
+#endif
return(0);
}