#include #include #include "emu.h" #include #include #include #include #include #include "tmeconfig.h" #include "m68k.h" #include "disp.h" #include "iwm.h" #include "via.h" #include "scc.h" #include "rtc.h" #include "ncr.h" #include "hd.h" #include "mouse.h" #include #include "esp_heap_caps.h" #include unsigned char *macRom; unsigned char *macRam; int rom_remap, video_remap=0, audio_remap=0; void m68k_instruction() { unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC); printf("Mon: %x\n", pc); int ok=0; if (pc < 0x400000) { if (rom_remap) { ok=1; } } else if (pc >= 0x400000 && pc<0x500000) { ok=1; } if (!ok) return; pc&=0x1FFFF; if (pc==0x7DCC) printf("Mon: SCSIReadSectors\n"); if (pc==0x7E4C) printf("Mon: SCSIReadSectors exit OK\n"); if (pc==0x7E56) printf("Mon: SCSIReadSectors exit FAIL\n"); } typedef uint8_t (*PeripAccessCb)(unsigned int address, int data, int isWrite); uint8_t unhandledAccessCb(unsigned int address, int data, int isWrite) { unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC); printf("Unhandled %s @ 0x%X! PC=0x%X\n", isWrite?"write":"read", address, pc); return 0xff; } uint8_t bogusReadCb(unsigned int address, int data, int isWrite) { if (isWrite) return 0; return address^(address>>8)^(address>>16); } uint8_t ncrAccessCb(unsigned int address, int data, int isWrite) { if (isWrite) { ncrWrite((address>>4)&0x7, (address>>9)&1, data); return 0; } else { return ncrRead((address>>4)&0x7, (address>>9)&1); } } uint8_t sscAccessCb(unsigned int address, int data, int isWrite) { if (isWrite) { sccWrite(address, data); return 0; } else { return sccRead(address); } } uint8_t iwmAccessCb(unsigned int address, int data, int isWrite) { if (isWrite) { iwmWrite((address>>9)&0xf, data); return 0; } else { return iwmRead((address>>9)&0xf);; } } uint8_t viaAccessCb(unsigned int address, int data, int isWrite) { if (isWrite) { viaWrite((address>>9)&0xf, data); return 0; } else { return viaRead((address>>9)&0xf); } } #define FLAG_RO (1<<0); typedef struct { uint8_t *memAddr; union { PeripAccessCb cb; int flags; }; } MemmapEnt; #define MEMMAP_ES 0x20000 //entry size #define MEMMAP_MAX_ADDR 0x1000000 //Memmap describing 128 128K blocks of memory, from 0 to 0x1000000 (16MiB). MemmapEnt memmap[128]; static void regenMemmap(int remapRom) { int i; //Default handler for (i=0; i<128; i++) { memmap[i].memAddr=0; memmap[i].cb=unhandledAccessCb; } //0-0x400000 is RAM, or ROM when remapped if (remapRom) { memmap[0].memAddr=macRom; memmap[0].flags=FLAG_RO; for (i=1; i<0x400000/MEMMAP_ES; i++) { //Do not point at ROM again, but at... something else. Abuse RAM here. //If pointed at ROM again, ROM will think this machine does not have SCSI. memmap[i].memAddr=NULL; memmap[i].cb=bogusReadCb; } } else { for (i=0; i<0x400000/MEMMAP_ES; i++) { memmap[i].memAddr=&macRam[(i*MEMMAP_ES)&(TME_RAMSIZE-1)]; memmap[i].flags=0; } } //0x40000-0x50000 is ROM memmap[0x400000/MEMMAP_ES].memAddr=macRom; memmap[0x400000/MEMMAP_ES].flags=FLAG_RO; for (i=0x400000/MEMMAP_ES+1; i<0x500000/MEMMAP_ES; i++) { //Again, point to crap or SCSI won't work. memmap[i].memAddr=0; memmap[i].cb=bogusReadCb; } //0x580000-0x600000 is SCSI controller for (i=0x580000/MEMMAP_ES; i<0x600000/MEMMAP_ES; i++) { memmap[i].memAddr=NULL; memmap[i].cb=ncrAccessCb; } //0x600000-0x700000 is RAM for (i=0x600000/MEMMAP_ES; i<0x700000/MEMMAP_ES; i++) { memmap[i].memAddr=&macRam[(i*MEMMAP_ES)&(TME_RAMSIZE-1)]; memmap[i].flags=0; } //0x800000-0xC00000 is SSC for (i=0x800000/MEMMAP_ES; i<0xC00000/MEMMAP_ES; i++) { memmap[i].memAddr=NULL; memmap[i].cb=sscAccessCb; } //0xC00000-0xE00000 is IWM for (i=0xc00000/MEMMAP_ES; i<0xe00000/MEMMAP_ES; i++) { memmap[i].memAddr=NULL; memmap[i].cb=iwmAccessCb; } //0xE80000-0xF00000 is VIA for (i=0xE80000/MEMMAP_ES; i<0xF00000/MEMMAP_ES; i++) { memmap[i].memAddr=NULL; memmap[i].cb=viaAccessCb; } } const inline static MemmapEnt *getMmmapEnt(const unsigned int address) { if (address>=MEMMAP_MAX_ADDR) return &memmap[127]; return &memmap[address/MEMMAP_ES]; } unsigned int m68k_read_memory_8(unsigned int address) { const MemmapEnt *mmEnt=getMmmapEnt(address); if (mmEnt->memAddr) { uint8_t *p; p=&mmEnt->memAddr[address&(MEMMAP_ES-1)]; return *p; } else { return mmEnt->cb(address, 0, 0); } } unsigned int m68k_read_memory_16(unsigned int address) { const MemmapEnt *mmEnt=getMmmapEnt(address); if (mmEnt->memAddr) { uint16_t *p; p=&mmEnt->memAddr[address&(MEMMAP_ES-1)]; return __bswap_16(*p); } else { unsigned int ret; ret=mmEnt->cb(address, 0, 0)<<8; ret|=mmEnt->cb(address+1, 0, 0); return ret; } } unsigned int m68k_read_memory_32(unsigned int address) { const MemmapEnt *mmEnt=getMmmapEnt(address); if (mmEnt->memAddr) { uint32_t *p; p=&mmEnt->memAddr[address&(MEMMAP_ES-1)]; return __bswap_32(*p); } else { unsigned int ret; ret=mmEnt->cb(address, 0, 0)<<24; ret|=mmEnt->cb(address+1, 0, 0)<<16; ret|=mmEnt->cb(address+2, 0, 0)<<8; ret|=mmEnt->cb(address+3, 0, 0)<<0; return ret; } } void m68k_write_memory_8(unsigned int address, unsigned int value) { const MemmapEnt *mmEnt=getMmmapEnt(address); if (mmEnt->memAddr) { uint8_t *p; p=&mmEnt->memAddr[address&(MEMMAP_ES-1)]; *p=value; } else { mmEnt->cb(address, value, 1); } } void m68k_write_memory_16(unsigned int address, unsigned int value) { const MemmapEnt *mmEnt=getMmmapEnt(address); if (mmEnt->memAddr) { uint16_t *p; p=&mmEnt->memAddr[address&(MEMMAP_ES-1)]; *p=__bswap_16(value); } else { mmEnt->cb(address, (value>>8)&0xff, 1); mmEnt->cb(address+1, (value>>0)&0xff, 1); } } void m68k_write_memory_32(unsigned int address, unsigned int value) { const MemmapEnt *mmEnt=getMmmapEnt(address); if (mmEnt->memAddr) { uint32_t *p; p=&mmEnt->memAddr[address&(MEMMAP_ES-1)]; *p=__bswap_32(value); } else { mmEnt->cb(address, (value>>24)&0xff, 1); mmEnt->cb(address+1, (value>>16)&0xff, 1); mmEnt->cb(address+2, (value>>8)&0xff, 1); mmEnt->cb(address+3, (value>>0)&0xff, 1); } } //Should be called every second. void printFps() { struct timeval tv; static struct timeval oldtv; gettimeofday(&tv, NULL); if (oldtv.tv_sec!=0) { long msec=(tv.tv_sec-oldtv.tv_sec)*1000; msec+=(tv.tv_usec-oldtv.tv_usec)/1000; printf("Speed: %d%%\n", (int)(100000/msec)); // printf("Mem free: %dKiB 8-bit, %dKiB 32-bit\n", xPortGetFreeHeapSizeCaps(MALLOC_CAP_8BIT)/1024, xPortGetFreeHeapSizeCaps(MALLOC_CAP_32BIT)/1024); } oldtv.tv_sec=tv.tv_sec; oldtv.tv_usec=tv.tv_usec; } void tmeStartEmu(void *ram, void *rom) { int ca1=0, ca2=0; int x, m=0, frame=0; macRom=rom; macRam=ram; printf("Clearing ram...\n"); for (int x=0; x=1000) { int r=mouseTick(); if (r&MOUSE_BTN) viaClear(VIA_PORTB, (1<<3)); else viaSet(VIA_PORTB, (1<<3)); if (r&MOUSE_QXB) viaClear(VIA_PORTB, (1<<4)); else viaSet(VIA_PORTB, (1<<4)); if (r&MOUSE_QYB) viaClear(VIA_PORTB, (1<<5)); else viaSet(VIA_PORTB, (1<<5)); sccSetDcd(SCC_CHANA, r&MOUSE_QXA); sccSetDcd(SCC_CHANB, r&MOUSE_QYA); m=0; } } dispDraw(&macRam[video_remap?TME_SCREENBUF_ALT:TME_SCREENBUF]); frame++; ca1^=1; viaControlWrite(VIA_CA1, ca1); if (frame>=60) { ca2^=1; viaControlWrite(VIA_CA2, ca2); rtcTick(); frame=0; printFps(); } } } void viaIrq(int req) { // printf("IRQ %d\n", req); m68k_set_irq(req?1:0); } void sccIrq(int req) { // printf("IRQ %d\n", req); m68k_set_irq(req?2:0); } void viaCbPortAWrite(unsigned int val) { int oldRomRemap=rom_remap; video_remap=(val&(1<<6))?1:0; rom_remap=(val&(1<<4))?1:0; regenMemmap(rom_remap); audio_remap=(val&(1<<3))?1:0; if (oldRomRemap!=rom_remap) printf("ROM REMAP %d\n", rom_remap); iwmSetHeadSel(val&(1<<5)); } void viaCbPortBWrite(unsigned int val) { int b; b=rtcCom(val&4, val&1, val&2); if (b) viaSet(VIA_PORTB, 1); else viaClear(VIA_PORTB, 1); }