File:  [Previous NeXT emulator] / previous / src / dimension / nd_mem.cpp
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:33:24 2018 UTC (8 years, 3 months ago) by root
Branches: giles, MAIN
CVS tags: branch_softfloat, HEAD
Previous NeXT emulator

#include "main.h"
#include "configuration.h"
#include "m68000.h"
#include "sysdeps.h"
#include "dimension.hpp"
#include "nd_mem.hpp"
#include "log.h"

/* --------- NEXTDIMENSION MEMORY ---------- */

/* NeXTdimension board memory */
#define ND_RAM_START	0xF8000000
#define ND_RAM_SIZE		0x04000000
#define ND_RAM_MASK		0x03FFFFFF

#define ND_VRAM_START	0xFE000000
#define ND_VRAM_SIZE	0x00400000
#define ND_VRAM_MASK	0x003FFFFF

#define ND_EEPROM_START	0xFFF00000
#define ND_EEPROM_SIZE	0x00020000
#define ND_EEPROM_MASK	0x0001FFFF

/* RAM banks */
#define ND_RAM_BANKSIZE 0x01000000
#define ND_RAM_BANKMASK 0x03000000

/* NeXTdimension dither memory */
#define ND_DMEM_START   0xFF000000
#define ND_DMEM_SIZE    0x00000200
#define ND_DMEM_MASK    0x000001FF

/* NeXTdimension board devices */
#define ND_IO_START		0xFF800000
#define ND_IO_SIZE		0x00004000
#define ND_IO_MASK		0x00003FFF

/* NeXTdimension board RAMDAC */
#define ND_RAMDAC_START	0xFF200000
#define ND_RAMDAC_SIZE  0x00001000
#define ND_RAMDAC_MASK  0x00000FFF

/* NeXTdimension board data path */
#define ND_DP_START	0xF0000000
#define ND_DP_SIZE  0x00001000
#define ND_DP_MASK  0x00000FFF

/* NeXTdimension unknown registers */
#define ND_CSR_START 0xFF400000
#define ND_CSR_SIZE  0x00000200
#define ND_CSR_MASK  0x000001FF

/* Function to fix address for ROM access */
static uaecptr nd_rom_addr_fix(uaecptr addr)
{
#if ND_STEP
    addr >>= 2;
#else
    addr &= ~3;
    addr |= (addr>>17)&3;
#endif
    addr &= ND_EEPROM_MASK;
    return addr;
}

/* Memory banks */

/* NeXTdimension RAM */

class ND_RAM : public ND_Addrbank {
    Uint8* base;
    Uint32 mask;
public:
    ND_RAM(NextDimension* nd, int bank) : ND_Addrbank(nd), base(nd->ram), mask(nd->bankmask[bank]) {}
    
    Uint32 lget(Uint32 addr) {
        addr &= mask;
        return do_get_mem_long(base + addr);
    }

    Uint32 wget(Uint32 addr) {
        addr &= mask;
        return do_get_mem_word(base + addr);
    }

    Uint32 bget(Uint32 addr) {
        addr &= mask;
        return base[addr];
    }

     void lput(Uint32 addr, Uint32 l) {
        addr &= mask;
        do_put_mem_long(base + addr, l);
    }

     void wput(Uint32 addr, Uint32 w) {
        addr &= mask;
        do_put_mem_word(base + addr, w);
    }

     void bput(Uint32 addr, Uint32 b) {
        addr &= mask;
        base[addr] = b;
    }
};

class ND_Empty : public ND_Addrbank {
public:
    ND_Empty(NextDimension* nd) : ND_Addrbank(nd) {}
    
    Uint32 lget(Uint32 addr) {
        Log_Printf(LOG_ND_MEM, "[ND] Slot %i: empty memory bank lget at %08X\n", nd->slot,addr);
        return 0;
    }

     Uint32 wget(Uint32 addr) {
        Log_Printf(LOG_ND_MEM, "[ND] Slot %i: empty memory bank wget at %08X\n", nd->slot,addr);
        return 0;
    }

     Uint32 bget(Uint32 addr) {
        Log_Printf(LOG_ND_MEM, "[ND] Slot %i: empty memory bank bget at %08X\n", nd->slot,addr);
        return 0;
    }

     void lput(Uint32 addr, Uint32 l) {
        Log_Printf(LOG_ND_MEM, "[ND] Slot %i: empty memory bank lput at %08X\n", nd->slot,addr);
    }

     void wput(Uint32 addr, Uint32 w) {
        Log_Printf(LOG_ND_MEM, "[ND] Slot %i: empty memory bank wput at %08X\n", nd->slot,addr);
    }

     void bput(Uint32 addr, Uint32 b) {
        Log_Printf(LOG_ND_MEM, "[ND] Slot %i: empty memory bank bput at %08X\n",nd->slot,addr);
    }
};

/* NeXTdimension VRAM */
/* stored as ARGB for faster blitting, assuming aligned access for 32 bit */

class ND_VRAM : public ND_Addrbank {
    Uint8* base;
public:
    ND_VRAM(NextDimension* nd) : ND_Addrbank(nd), base(nd->vram) {
        // sanity checks for ARGB mem access
        lput(0, 0x12345678);
        if(lget(0) != 0x12345678) {fprintf(stderr, "ND_VRAM: 32 bit access check failed\n");  goto error;}

        if(bget(0) != 0x12)       {fprintf(stderr, "ND_VRAM: 8 bit access 0 check failed\n"); goto error;}
        if(bget(1) != 0x34)       {fprintf(stderr, "ND_VRAM: 8 bit access 1 check failed\n"); goto error;}
        if(bget(2) != 0x56)       {fprintf(stderr, "ND_VRAM: 8 bit access 2 check failed\n"); goto error;}
        if(bget(3) != 0x78)       {fprintf(stderr, "ND_VRAM: 8 bit access 3 check failed\n"); goto error;}

        if(wget(0) != 0x1234)     {fprintf(stderr, "ND_VRAM: 16 bit access 0 check failed\n"); goto error;}
        if(wget(2) != 0x5678)     {fprintf(stderr, "ND_VRAM: 16 bit access 2 check failed\n"); goto error;}

        wput(0, 0x7654);
        wput(2, 0x3210);
        if(lget(0) != 0x76543210) {fprintf(stderr, "ND_VRAM: 32 bit access check failed (wput)\n");  goto error;}

        bput(0, 0x12);
        bput(1, 0x34);
        bput(2, 0x56);
        bput(3, 0x78);
        if(lget(0) != 0x12345678) {fprintf(stderr, "ND_VRAM: 32 bit access check failed (bput)\n");  goto error;}

        return;
    error:
        exit(1);
    }

    Uint32 lget(Uint32 addr) {
        addr &= ND_VRAM_MASK;
        return
            base[addr+3]         |
            (base[addr+0] << 8)  |
            (base[addr+1] << 16) |
            (base[addr+2] << 24);
    }

    void lput(Uint32 addr, Uint32 l) {
        addr &= ND_VRAM_MASK;
        base[addr+3] = l;
        base[addr+0] = l >> 8;
        base[addr+1] = l >> 16;
        base[addr+2] = l >> 24;
    }

    Uint32 wget(Uint32 addr) {
        addr &= ND_VRAM_MASK;
        return (bget(addr) << 8) | bget(addr+1);
    }

    void wput(Uint32 addr, Uint32 w) {
        addr &= ND_VRAM_MASK;
        bput(addr,   w >> 8);
        bput(addr+1, w);
    }

    Uint32 bget(Uint32 addr) {
        addr &= ND_VRAM_MASK;
        switch(addr&3) {
            case 0: return base[(addr&~3)+2];
            case 1: return base[(addr&~3)+1];
            case 2: return base[(addr&~3)+0];
            case 3: return base[(addr&~3)+3];
        }
        return 0;
    }

    void bput(Uint32 addr, Uint32 b) {
        addr &= ND_VRAM_MASK;
        switch(addr&3) {
            case 0: base[(addr&~3)+2] = b; break;
            case 1: base[(addr&~3)+1] = b; break;
            case 2: base[(addr&~3)+0] = b; break;
            case 3: base[(addr&~3)+3] = b; break;
        }
    }
};

/* NeXTdimension ROM */

class ND_ROM : public ND_Addrbank {
public:
    ND_ROM(NextDimension* nd) : ND_Addrbank(nd) {}

    Uint32 lget(Uint32 addr) {
        addr = nd_rom_addr_fix(addr);
        return (nd->rom_read(addr) << 24); /* byte lane at msb */
    }

    Uint32 wget(Uint32 addr) {
        addr = nd_rom_addr_fix(addr);
        return (nd->rom_read(addr) << 8); /* byte lane at msb */
    }

    Uint32 bget(Uint32 addr) {
        addr = nd_rom_addr_fix(addr);
        return nd->rom_read(addr);
    }

    Uint32 cs8get(Uint32 addr) {
        addr &= ND_EEPROM_MASK;
        return nd->rom[addr];
    }

    void lput(Uint32 addr, Uint32 l) {
        addr = nd_rom_addr_fix(addr);
        nd->rom_write(addr, l >> 24);
    }

    void wput(Uint32 addr, Uint32 w) {
        addr = nd_rom_addr_fix(addr);
        nd->rom_write(addr, w >> 8);
    }

    void bput(Uint32 addr, Uint32 b) {
        addr = nd_rom_addr_fix(addr);
        nd->rom_write(addr, b);
    }
};

/* Unknown register access functions (memory controller step 1) */
#if ND_STEP

class ND_CSR : public ND_Addrbank {
public:
    ND_CSR(NextDimension* nd) : ND_Addrbank(nd) {}

     Uint32 lget(Uint32 addr) {
        Log_Printf(LOG_ND_MEM, "[ND] Slot %i: Board CSR lget at %08X\n", nd->slot,addr);
        return 0;
    }

     Uint32 wget(Uint32 addr) {
        Log_Printf(LOG_ND_MEM, "[ND] Slot %i: Board CSR wget at %08X\n",nd->slot,addr);
        return 0;
    }

     Uint32 bget(Uint32 addr) {
        Log_Printf(LOG_ND_MEM, "[ND] Slot %i: Board CSR bget at %08X\n",nd->slot,addr);
        return 0;
    }

     void lput(Uint32 addr, Uint32 l) {
        Log_Printf(LOG_ND_MEM, "[ND] Slot %i: Board CSR lput at %08X: %08X\n",nd->slot,addr,l);
    }

     void wput(Uint32 addr, Uint32 w) {
        Log_Printf(LOG_ND_MEM, "[ND] Slot %i: Board CSR wput at %08X: %04X\n",nd->slot,addr,w);
    }

     void bput(Uint32 addr, Uint32 b) {
        Log_Printf(LOG_ND_MEM, "[ND] Slot %i: Board CSR bput at %08X: %02X\n",nd->slot,addr,b);
    }
};
#endif

/* NeXTdimension dither memory & datapath */

class ND_DMEM : public ND_Addrbank {
public:
    ND_DMEM(NextDimension* nd) : ND_Addrbank(nd) {}

     Uint32 lget(Uint32 addr) {
        addr &= ND_DP_MASK;
        return addr < ND_DMEM_SIZE ? do_get_mem_long(nd->dmem + addr) : nd->dp.lget(addr);
    }

     Uint32 wget(Uint32 addr) {
        addr &= ND_DP_MASK;
        return addr < ND_DMEM_SIZE ? do_get_mem_word(nd->dmem + addr) : nd->dp.lget(addr);
    }

     Uint32 bget(Uint32 addr) {
        addr &= ND_DP_MASK;
        return addr < ND_DMEM_SIZE ? do_get_mem_byte(nd->dmem + addr) : nd->dp.lget(addr);
    }

     void lput(Uint32 addr, Uint32 l) {
        addr &= ND_DP_MASK;
        if(addr < ND_DMEM_SIZE)
            do_put_mem_long(nd->dmem + addr, l);
        else
            nd->dp.lput(addr, l);
    }

     void wput(Uint32 addr, Uint32 w) {
        addr &= ND_DP_MASK;
        if(addr < ND_DMEM_SIZE)
            do_put_mem_word(nd->dmem + addr, w);
        else
            nd->dp.lput(addr, w);
    }

     void bput(Uint32 addr, Uint32 b) {
        addr &= ND_DP_MASK;
        if(addr < ND_DMEM_SIZE)
            do_put_mem_byte(nd->dmem + addr, b);
        else
            nd->dp.lput(addr, b);
    }
};

/* Illegal access functions */

ND_Addrbank::ND_Addrbank(NextDimension* nd) : nd(nd) {}

Uint32 ND_Addrbank::lget(Uint32 addr) {
    Log_Printf(LOG_ND_MEM, "[ND] Slot %i: Illegal lget at %08X\n",nd->slot,addr);
    return 0;
}

Uint32 ND_Addrbank::wget(Uint32 addr) {
    Log_Printf(LOG_ND_MEM, "[ND] Slot %i: Illegal wget at %08X\n",nd->slot,addr);
    return 0;
}

Uint32 ND_Addrbank::bget(Uint32 addr) {
    Log_Printf(LOG_ND_MEM, "[ND] Slot %i: Illegal bget at %08X\n",nd->slot,addr);
    return 0;
}

Uint32 ND_Addrbank::cs8get(Uint32 addr) {
    Log_Printf(LOG_ND_MEM, "[ND] Slot %i: Illegal cs8get at %08X\n",nd->slot,addr);
    return 0;
}

void ND_Addrbank::lput(Uint32 addr, Uint32 l) {
    Log_Printf(LOG_ND_MEM, "[ND] Slot %i: Illegal lput at %08X\n",nd->slot,addr);
}

void ND_Addrbank::wput(Uint32 addr, Uint32 w) {
    Log_Printf(LOG_ND_MEM, "[ND] Slot %i: Illegal wput at %08X\n",nd->slot,addr);
}

void ND_Addrbank::bput(Uint32 addr, Uint32 b) {
    Log_Printf(LOG_ND_MEM, "[ND] Slot %i: Illegal bput at %08X\n",nd->slot,addr);
}

/* NeXTdimension device space */

class ND_IO : public ND_Addrbank {
public:
    ND_IO(NextDimension* nd) : ND_Addrbank(nd) {}
    
    Uint32 lget(Uint32 addr) {
        return nd->mc.read(addr);
    }
    
    Uint32 wget(Uint32 addr) {return 0;}
    
    Uint32 bget(Uint32 addr) {return 0;}
    
    void lput(Uint32 addr, Uint32 l) {
        nd->mc.write(addr, l);
    }
    
    void wput(Uint32 addr, Uint32 w) {}
    void bput(Uint32 addr, Uint32 b) {}
};

/* NeXTdimension RAMDAC */

class ND_RAMDAC : public ND_Addrbank {
public:
    ND_RAMDAC(NextDimension* nd) : ND_Addrbank(nd) {}
    
    Uint32 lget(Uint32 addr) {
        return bt463_bget(&nd->ramdac, addr) << 24;
    }
    
    Uint32 wget(Uint32 addr) {
        return bt463_bget(&nd->ramdac, addr) << 8;
    }
    
    Uint32 bget(Uint32 addr) {
        return bt463_bget(&nd->ramdac, addr);
    }
    
    void lput(Uint32 addr, Uint32 l) {
        bt463_bput(&nd->ramdac, addr, l >> 24);
    }
    
    void wput(Uint32 addr, Uint32 w) {
        bt463_bput(&nd->ramdac, addr, w >> 8);
    }
    
    void bput(Uint32 addr, Uint32 b) {
        bt463_bput(&nd->ramdac, addr, b);
    }
};

void NextDimension::map_banks (ND_Addrbank *bank, int start, int size) {
    for (int bnr = start; bnr < start + size; bnr++)
        nd_put_mem_bank (bnr << 16, bank);
    return;
}

void NextDimension::init_mem_banks(void) {
    ND_Addrbank* nd_illegal_bank = new ND_Addrbank(this);
    for (int i = 0; i < 65536; i++)
        nd_put_mem_bank(i<<16, nd_illegal_bank);
}

#define write_log printf

void NextDimension::mem_init(void) {
    write_log("[ND] Slot %i: Memory init: Memory size: %iMB\n", slot,
              Configuration_CheckDimensionMemory(ConfigureParams.Dimension.board[ND_NUM(slot)].nMemoryBankSize));

    /* Initialize banks with error memory */
    init_mem_banks();
    
    /* Clear first 4k of memory for m68k ROM polling code */
    memset(ram, 0, 4096 * sizeof(Uint8));
    
    /* Map main memory */
    
    for(int bank = 0; bank < 4; bank++) {
        if (ConfigureParams.Dimension.board[ND_NUM(slot)].nMemoryBankSize[bank]) {
            bankmask[bank] = ND_RAM_BANKMASK|((ConfigureParams.Dimension.board[ND_NUM(slot)].nMemoryBankSize[bank]<<20)-1);
            map_banks(new ND_RAM(this, bank), (ND_RAM_START+(bank*ND_RAM_BANKSIZE))>>16, ND_RAM_BANKSIZE >> 16);
            write_log("[ND] Slot %i: Mapping main memory bank%d at $%08x: %iMB\n", slot, bank,
                      (ND_RAM_START+(bank*ND_RAM_BANKSIZE)), ConfigureParams.Dimension.board[ND_NUM(slot)].nMemoryBankSize[0]);
        } else {
            bankmask[bank] = 0;
            map_banks(new ND_Empty(this), (ND_RAM_START+(bank*ND_RAM_BANKSIZE))>>16, ND_RAM_BANKSIZE >> 16);
            write_log("[ND] Slot %i: Mapping main memory bank%d at $%08x: empty\n", slot, bank,
                      (ND_RAM_START+(bank*ND_RAM_BANKSIZE)));
        }
    }
    
    write_log("[ND] Slot %i: Mapping video memory at $%08x: %iMB\n", slot,
              ND_VRAM_START, ND_VRAM_SIZE/(1024*1024));
    map_banks(new ND_VRAM(this), ND_VRAM_START>>16, (4*ND_VRAM_SIZE)>>16);
    
	write_log("[ND] Slot %i: Mapping ROM at $%08x: %ikB\n", slot,
              ND_EEPROM_START, ND_EEPROM_SIZE/1024);
	map_banks(new ND_ROM(this), ND_EEPROM_START>>16, (ND_EEPROM_SIZE*8)>>16);
    rom_load();
	
    write_log("[ND] Slot %i: Mapping dither memory and data path at $%08x: %ibyte\n", slot,
              ND_DMEM_START, ND_DMEM_SIZE);
    map_banks(new ND_DMEM(this), ND_DMEM_START>>16, 1);

	write_log("[ND] Slot %i: Mapping IO memory at $%08x\n", slot, ND_IO_START);
	map_banks(new ND_IO(this), ND_IO_START>>16, 1);
    
    write_log("[ND] Slot %i: Mapping RAMDAC registers at $%08x\n", slot, ND_RAMDAC_START);
    map_banks(new ND_RAMDAC(this), ND_RAMDAC_START>>16, 1);
#if ND_STEP
    write_log("[ND] Slot %i: Mapping board CSR at $%08x\n", slot, ND_CSR_START);
    map_banks(new ND_CSR(this), ND_CSR_START>>16, 1);
#endif
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.