#include "zx_128mem.h" #include "z80mem.h" #include "z80.h" #include "zx_screen.h" #include #include #define ZX_128MEM_PAGE 0x07 #define ZX_128MEM_SCREEN 0x08 #define ZX_128MEM_ROM 0x10 #define ZX_128MEM_DISPAG 0x20 void zx_128_port_out(int port, int val) { ((zx_128mem*)z80mem::get())->port_out(port, val); } zx_128mem::zx_128mem() { z80mem::singleton = this; } void zx_128mem::port_out(int port, int val) { if (config & ZX_128MEM_DISPAG) return; const bool shadow = config & ZX_128MEM_SCREEN; config = val; if (config & ZX_128MEM_SCREEN) { if (!shadow) zxscreen::setBaseAddresses(0x4000*7, 0x1800+0x4000*7); } else { if (shadow) zxscreen::setBaseAddresses(0x4000*5, 0x1800+0x4000*5); } } uint8_t zx_128mem::readMem(uint16_t address) { const uint8_t bank = address >> 14; const uint16_t disp = address & 0x3fff; switch (bank) { case 0: return rom[disp | ((config & ZX_128MEM_ROM)<<10)]; break; case 1: return memory[disp | 0x14000]; break; case 2: return memory[address]; break; case 3: return memory[disp | (0x4000 * (config&ZX_128MEM_PAGE))]; break; } return 0; } void zx_128mem::writeMem(uint16_t address, uint8_t value) { const uint8_t bank = address >> 14; const uint16_t disp = address & 0x3fff; switch (bank) { case 0: break; case 1: memory[disp | 0x14000] = value; break; case 2: memory[address] = value; break; case 3: memory[disp | (0x4000 * (config&ZX_128MEM_PAGE))] = value; break; } } void zx_128mem::loadMem(uint16_t address, uint16_t len, uint8_t *buffer) { memcpy(&memory[address], buffer, len); } uint8_t zx_128mem::getTag(uint16_t address) { const uint8_t bank = address >> 14; const uint16_t disp = address & 0x3fff; switch (bank) { case 0: return romtags[disp | ((config & ZX_128MEM_ROM)<<10)]; break; case 1: return tags[disp | 0x14000]; break; case 2: return tags[address]; break; case 3: return tags[disp | (0x4000 * (config&ZX_128MEM_PAGE))]; break; } return tags[address]; } void zx_128mem::setTag(uint16_t address, uint8_t value) { const uint8_t bank = address >> 14; const uint16_t disp = address & 0x3fff; switch (bank) { case 0: romtags[disp | ((config & ZX_128MEM_ROM)<<10)] = value; break; case 1: tags[disp | 0x14000] = value; break; case 2: tags[address] = value; break; case 3: tags[disp | (0x4000 * (config&ZX_128MEM_PAGE))] = value; break; } } void zx_128mem::reset() { FILE* f = fopen("128k.rom", "rb"); fread(rom, 1024, 32, f); fclose(f); for (int i=0x0000; i<=0x1FFFF; ++i) memory[i] = 0; for (int i=0; i<131072; ++i) tags[i] = MEMTAG_NONE; z80::connect_port(0x7ffd, nullptr, zx_128_port_out); z80::connect_port(0xfd, nullptr, zx_128_port_out); } void zx_128mem::saveState(FILE *f) { fwrite(&memory[0x0000], 131072, 1, f); } void zx_128mem::loadState(FILE *f) { fread(&memory[0x0000], 131072, 1, f); } uint32_t zx_128mem::getSize() { return 131072; } uint8_t *zx_128mem::rawPtr(uint32_t address) { return &memory[address]; } uint8_t *zx_128mem::rawTagPtr(uint32_t address) { return &tags[address]; }