ref: 9861f1a92b373a16939fd6f3c167e5dad9f253d3
dir: /sys/src/games/c64/mem.c/
#include <u.h> #include <libc.h> #include <thread.h> #include "../eui.h" #include "dat.h" #include "fns.h" u8int pla; u8int ram[65536], krom[8192], brom[8192], crom[4096], cart[16384], cram[1024]; u8int reg[47]; u16int vicbank; u8int cia[32]; u16int timer[4], timrel[4]; enum { TIMEREN = 1, TIMERUND = 2, TIMERSTOP = 8, TIMERASRC = 0x20, TIMERBSRC = 0x60, TIMERBSYS = 0, TIMERBA = 0x40, }; u8int ciaread(int n, u8int a) { u8int r; int i; switch(a){ case 0: return (cia[0] | ~cia[2]) & (~joys >> 5 | 0xe0); case 1: if(!n){ r = 0; for(i = 0; i < 8; i++) if((cia[0] & 1<<i) == 0) r |= keys >> 8 * i; return (cia[1] | ~cia[3]) & ~r & (~joys | 0xe0); } break; case 4: return timer[n*2]; case 5: return timer[n*2] >> 8; case 6: return timer[n*2+1]; case 7: return timer[n*2+1] >> 8; case 13: if(n){ r = nmi >> 4 & 0x1f | ((nmi & nmien & 0x1f0) != 0) << 7; nmi &= ~0x1f0; return r; }else{ r = irq >> 4 & 0x1f | ((irq & irqen & 0x1f0) != 0) << 7; irq &= ~0x1f0; return r; } } return cia[n * 16 + a]; } void ciawrite(int n, u8int a, u8int v) { switch(a){ case 0: if(n) vicbank = (~v & 3) << 14; break; case 4: timrel[n*2] = v | timrel[n*2] & 0xff00; break; case 5: timrel[n*2] = v << 8 | timrel[n*2] & 0xff; break; case 6: timrel[n*2+1] = v | timrel[n*2+1] & 0xff00; break; case 7: timrel[n*2+1] = v << 8 | timrel[n*2+1] & 0xff; break; case 13: if(n) if((v & 0x80) != 0) nmien |= v << 4 & 0x1f0; else nmien &= ~(v << 4 & 0x1f0); else if((v & 0x80) != 0) irqen |= v << 4 & 0x1f0; else irqen &= ~(v << 4 & 0x1f0); break; case 14: case 15: if((v & 0x10) != 0){ timer[n * 2 + (a & 1)] = timrel[n * 2 + (a & 1)]; v &= ~0x10; } break; } cia[n * 16 + a] = v; } u8int mioread(u16int a) { u8int b, v; switch(a & 0xc00){ case 0: b = a & 63; switch(b){ case CTRL1: return reg[b] & 0x7f | ppuy >> 1 & 0x80; case RASTER: return ppuy; case IRQLATCH: return irq & 0xf | (irq & irqen & 0xf) + 0x7f & 0x80; case IRQEN: return irqen & 0xf; case SPRSPR: case SPRBG: v = reg[b]; reg[b] = 0; return v; } if(b >= 0x20) return reg[b] | 0xf0; if(b >= 47) return 0xff; return reg[b]; case 0x800: return cram[a & 0x3ff]; case 0xc00: if((a & 0x200) == 0) return ciaread(a >> 8 & 1, a & 0xf); default: return 0xff; } } void miowrite(u16int a, u8int v) { u8int b; switch(a & 0xc00){ case 0: b = a & 63; if(b >= 0x20) v &= 0xf; switch(b){ case CTRL2: v |= 0xc0; break; case IRQLATCH: v |= 0xf0; irq &= ~(v & 0xf); break; case IRQEN: irqen = irqen & ~0xf | v & 0xf; v |= 0xf0; break; } if(b < 47) reg[b] = v; if(b == CTRL1 || b == CTRL2) bordset(); return; case 0x800: cram[a & 0x3ff] = v & 0xf; return; case 0xc00: if((a & 0x200) == 0) ciawrite(a >> 8 & 1, a & 0xf, v); return; } } void tapestep(void) { static int tapectr; static int idx; if((ram[1] & 1<<5) != 0) return; if(tapectr == 0){ if(idx >= tapelen){ progress(0, 0); tapeplay = 0; idx = 0; return; } tapectr = tape[idx++] << 3; if(tapever == 1 && tapectr == 0){ tapectr = tape[idx++]; tapectr |= tape[idx++] << 8; tapectr |= tape[idx++] << 16; } progress(idx, tapelen); }else{ tapectr--; if(tapectr == 0) irq |= IRQFLAG; } } void timerstep(void) { int i, at; u8int a, b; u16int *t; for(i = 0; i < 2; i++){ a = cia[i * 16 + 14]; b = cia[i * 16 + 15]; at = 0; t = &timer[2 * i]; if((a & (TIMEREN|TIMERASRC)) == TIMEREN){ t[0]--; if(t[0] == 0){ at = 1; if(i) nmi |= IRQTIMERA; else irq |= IRQTIMERA; if((a & TIMERSTOP) != 0) cia[i * 16 + 14] &= ~TIMEREN; t[0] = timrel[2 * i]; } } if((b & TIMEREN) != 0 && ((b & TIMERBSRC) == TIMERBSYS || (b & TIMERBSRC) == TIMERBA && at)){ t[1]--; if(t[1] == 0){ if(i) nmi |= IRQTIMERB; else irq |= IRQTIMERB; if((b & TIMERSTOP) == 0) cia[i * 16 + 15] &= ~TIMEREN; t[1] = timrel[2 * i + 1]; } } } if(tapeplay) tapestep(); } void io(void) { vicstep(); timerstep(); } u8int memread(u16int a) { io(); if(a == 1) return ram[1] & ~(1<<4) | (tapeplay ^ 1) << 4; switch(a >> 12){ case 8: case 9: if((pla & (EXROM|GAME)) == EXROM || (pla & (EXROM|HIRAM|LORAM)) == (HIRAM|LORAM)) return cart[a & 0x1fff]; goto def; case 10: case 11: if((pla & (GAME|HIRAM|LORAM)) == (GAME|HIRAM|LORAM)) return brom[a & 0x1fff]; if((pla & (EXROM|GAME|HIRAM)) == HIRAM) return cart[8192 + (a & 0x1fff)]; goto def; case 13: if((pla & (HIRAM|LORAM)) == 0 || pla == 1) goto def; if((pla & CHAREN) == 0 && (pla & (EXROM|GAME)) != EXROM) return crom[a & 0xfff]; return mioread(a & 0xfff); case 14: case 15: if((pla & (EXROM|GAME)) == EXROM) return cart[8192 + (a & 0x1fff)]; if((pla & HIRAM) == HIRAM) return krom[a & 0x1fff]; def: default: return ram[a]; } } void memwrite(u16int a, u8int v) { if(a >> 12 == 13 && !((pla & (HIRAM|LORAM)) == 0 || pla == 1 || (pla & CHAREN) == 0 && (pla & (EXROM|GAME)) != EXROM)){ miowrite(a & 0xfff, v); io(); return; } ram[a] = v; if(a == 1) pla = pla & ~7 | v & 7; io(); } u8int vmemread(u16int a) { a |= vicbank; if((a & 0x7000) == 0x1000) return crom[a & 0xfff]; return ram[a]; } void memreset(void) { pla = 0x1f; }