Make bank switching refer to Z180 physical memory, with memory and bank sizes up...
authorNick Downing <nick@ndcode.org>
Tue, 5 Mar 2019 15:29:21 +0000 (02:29 +1100)
committerNick Downing <nick@ndcode.org>
Tue, 5 Mar 2019 15:29:21 +0000 (02:29 +1100)
Makefile
roms/z180.asm
roms/z180.bin [new file with mode: 0644]
sim/iosim.cpp
sim/memory.cpp
sim/memory.h
sim/sim0.cpp
sim/simctl.cpp

index ba9416b..7ec727e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,7 @@
 CPPFLAGS=-DCONFDIR=\"conf\" -DDISKSDIR=\"disks\" -DROMSDIR=\"roms\" -I.
 CXXFLAGS=-g
 
-all: fuzix_sim roms/z180.ihx
-#bin
+all: fuzix_sim roms/z180.bin
 
 fuzix_sim: \
 iodevices/unix_terminal.o \
index f1a8dc2..4259c11 100644 (file)
@@ -15,14 +15,18 @@ FDC_SECTOR_HI       = 17
 
 MMU_INIT       = 20
 MMU_BANK_SEL   = 21
-MMU_SEG_SIZE   = 22
+MMU_SEG_SIZE_LO = 22
 MMU_WRITE_PROT = 23
+MMU_BITMAP_LO  = 52
+MMU_BITMAP_HI  = 53
 
+       ; the ROM size has been rounded up to the nearest 0x100 (= 0x100),
+       ; MMU_SEG_SIZE_LO has been set to make RAM visible at this address
        ld      hl,loader
-       ld      de,0x1000
+       ld      de,0x100
        ld      bc,loader_end-loader
        ldir
-       jp      0x1000
+       jp      0x100
 
 loader:
        ; use in0/out0 for internal registers
@@ -30,12 +34,13 @@ loader:
        out0    (IOCR),a                ; remap Z180 internal I/O to c0-ff
 
        ; use in/out for simulation registers (high address not decoded)
-       ;sub    a
-       ;out    (MMU_BANK_SEL),a        ; go to first bank (RAM)
-       ;ld     a,0xc0
-       ;out    (MMU_SEG_SIZE),a        ; 48 kbyte
-       ;ld     a,1
-       ;out    (MMU_INIT),a            ; 1 bank
+       sub     a
+       out     (MMU_BANK_SEL),a        ; go to first bank (RAM)
+       out     (MMU_BITMAP_LO),a       ; unprotect second bank (ROM)
+       ld      a,1
+       out     (MMU_INIT),a            ; delete second bank (ROM)
+       ld      a,0xc0
+       out     (MMU_SEG_SIZE_LO),a     ; bank size 48 kbyte (for new banks)
 
        ; read drive 0 track 0 sector 1 to address 0
        sub     a
@@ -53,7 +58,7 @@ loader:
        jp      z,0
 
        ; read has failed, print message
-       ld      hl,message-loader+0x1000
+       ld      hl,message-loader+0x100
 message_loop:
        ld      a,(hl)
        or      a
diff --git a/roms/z180.bin b/roms/z180.bin
new file mode 100644 (file)
index 0000000..3175f68
Binary files /dev/null and b/roms/z180.bin differ
index 6253ab7..ef52cde 100644 (file)
@@ -243,10 +243,14 @@ static BYTE dmal_in(void);
 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);
@@ -309,9 +313,9 @@ static BYTE (*port_in[256]) (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 */
@@ -339,8 +343,8 @@ static BYTE (*port_in[256]) (void) = {
        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 */
@@ -572,9 +576,9 @@ static void (*port_out[256]) (BYTE) = {
        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 */
@@ -602,8 +606,8 @@ static void (*port_out[256]) (BYTE) = {
        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 */
@@ -824,7 +828,9 @@ static void (*port_out[256]) (BYTE) = {
 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
@@ -835,6 +841,7 @@ void init_io(void)
                if (diskdir != NULL) {
                        strcpy(fn, diskd);
                } else {
+#ifdef DISKSDIR
                        /* if not first try ./disks */
                        if ((stat("./disks", &sbuf) == 0) && 
                            S_ISDIR(sbuf.st_mode)) {
@@ -843,6 +850,9 @@ void init_io(void)
                        } else {
                                strcpy(fn, DISKSDIR);
                        }
+#else
+                       strcpy(fn, "./disks");
+#endif
                }
 
                strcat(fn, "/");
@@ -1079,12 +1089,11 @@ void reset_system(void)
        /* 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;
 
@@ -2369,15 +2378,13 @@ static BYTE mmui_in(void)
  */
 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
@@ -2386,21 +2393,26 @@ static void mmui_out(BYTE data)
 #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;
 }
 
 /*
@@ -2418,7 +2430,7 @@ static BYTE mmus_in(void)
  */
 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);
@@ -2434,21 +2446,50 @@ static void mmus_out(BYTE data)
 
 /*
  *     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);
@@ -2458,7 +2499,7 @@ static void mmuc_out(BYTE data)
 #endif
                return;
        }
-       segsize = data << 8;
+       segsize = (segsize & 0xff00) | (data << 16);
 }
 
 /*
@@ -2477,6 +2518,42 @@ static void mmup_out(BYTE data)
        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
index 0dd5a50..8663e25 100644 (file)
  */
 
 #include <assert.h> // temporary
+#include <fcntl.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include "sim.h"
 #include "simglb.h"
 #include "memory.h"
@@ -39,11 +42,12 @@ int selbnk;                 /* current selected bank */
 int maxbnk;                    /* number of allocated banks */
 int segsize = SEGSIZ;          /* segment size of banks, default 48KB */
 int wp_common;                 /* write protect/unprotect common segment */
+int wp_bitmap;                 /* write protect/unprotect individual banks */
 
 void init_memory(void)
 {
-       /* allocate the first 64KB bank, so that we have some memory */
-       if ((memory[0] = (BYTE *)malloc(65536)) == NULL) {
+       /* allocate the first 1 Mbyte bank, so that we have some memory */
+       if ((memory[0] = (BYTE *)malloc(0x100000)) == NULL) {
                printf("can't allocate memory for bank 0\r\n");
 #if 1
  assert(false);
@@ -53,6 +57,7 @@ void init_memory(void)
 #endif
                return;
        }
+       memset(memory[0], 0, 0x100000);
        maxbnk = 1;
 }
 
index 4b70040..61a39fc 100644 (file)
 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]);
 }
 
 /*
index 1a8a20a..8731e05 100644 (file)
@@ -229,7 +229,9 @@ usage:
                                puts("\t-d = use disks images at diskpath");
                                puts("\t     default path for disk images:");
                                puts("\t     ./disks");
+#ifdef DISKSDIR
                                printf("\t     %s\n", DISKSDIR);
+#endif
 #endif
                                exit(1);
                        }
@@ -272,6 +274,7 @@ puts(" #####    ###     #####    ###            #####    ###   #     #");
 
        /* if the machine has configuration files try to find them */
 #ifdef HAS_CONFIG
+#ifdef CONFDIR
        /* first try ./conf */
        if ((stat("./conf", &sbuf) == 0) && S_ISDIR(sbuf.st_mode)) {
                strcpy(&confdir[0], "./conf");
@@ -279,6 +282,9 @@ puts(" #####    ###     #####    ###            #####    ###   #     #");
        } else {
                strcpy(&confdir[0], CONFDIR);
        }
+#else
+       strcpy(&confdir[0], "./conf");
+#endif
 
        //printf("config = %s\n", &confdir[0]);
 #endif
@@ -339,10 +345,10 @@ static void init_cpu(void)
 
  class sim_memory_address_space : public address_space {
   virtual u8 read_byte(offs_t address) override {
-   return memrdr((WORD)address);
+   return (u8)memrdr((uint32_t)address);
   }
   virtual void write_byte(offs_t address, u8 data) override {
-   memwrt((WORD)address, (BYTE)data);
+   memwrt((uint32_t)address, (BYTE)data);
   }
  };
  z180_dev->m_program = new sim_memory_address_space();
index fc0eb64..0687ee9 100644 (file)
@@ -158,14 +158,19 @@ void mon(void)
 
 /*
  *     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");
 
@@ -177,10 +182,63 @@ int boot(void)
                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");
@@ -188,6 +246,9 @@ int boot(void)
                } else {
                        strcpy(fn, DISKSDIR);
                }
+#else
+               strcpy(fn, "./disks");
+#endif
        }
 
        strcat(fn, "/");
@@ -209,5 +270,6 @@ int boot(void)
                return(1);
        }
        close(fd);
+#endif
        return(0);
 }