From ea1ed9972a256d2c3f27ff513cf713c0ba25692d Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Sun, 5 Nov 2017 22:02:18 -0800 Subject: [PATCH] Speedups because direct pc-rel read/write, fix sound a bit --- components/tme-esp32/mipi_lcd.c | 7 +++-- components/tme-esp32/snd.c | 18 ++++++++--- components/tme/component.mk | 12 +++++--- components/tme/emu.c | 54 +++++++++++++++++++++------------ components/tme/m68kconf.h | 46 +++++++++++++++++++++++++--- components/tme/musashi/m68k.h | 2 ++ components/tme/rtc.c | 2 +- components/tme/scc.c | 31 +++++++++++++------ components/tme/scc.h | 2 +- components/tme/sdl/disp.c | 5 ++- components/tme/sdl/main.c | 2 ++ components/tme/sdl/snd.c | 2 +- components/tme/tmeconfig.h | 7 ++--- components/tme/via.c | 24 +++++++++------ 14 files changed, 151 insertions(+), 63 deletions(-) diff --git a/components/tme-esp32/mipi_lcd.c b/components/tme-esp32/mipi_lcd.c index b46b57c..ad4a211 100644 --- a/components/tme-esp32/mipi_lcd.c +++ b/components/tme-esp32/mipi_lcd.c @@ -231,8 +231,11 @@ static void IRAM_ATTR displayTask(void *arg) { //No need for update yend=342; } else { + //Only copy changed bits of data to changebuffer + memcpy(oldImg+(ystart*64), myData+(ystart*64), (yend-ystart)*64); + ystart=(ystart*32)/SCALE_FACT-1; - yend=(yend*32)/SCALE_FACT+1; + yend=(yend*32)/SCALE_FACT+2; if (ystart<0) ystart=0; printf("Changed %d to %d\n", ystart, yend); } @@ -248,7 +251,7 @@ static void IRAM_ATTR displayTask(void *arg) { uint8_t *p=&img[1]; for (int j=ystart; j>8); } diff --git a/components/tme-esp32/snd.c b/components/tme-esp32/snd.c index 2ba2a60..ff62860 100644 --- a/components/tme-esp32/snd.c +++ b/components/tme-esp32/snd.c @@ -48,11 +48,19 @@ void sndTask(void *arg) { int sndPush(uint8_t *data, int volume) { while (!sndDone()) usleep(1000); myVolume=volume; - for (int i=0; i<370; i++) { - buf[wp]=*data; - data+=2; - wp++; - if (wp>=BUFLEN) wp=0; + if (volume) { + for (int i=0; i<370; i++) { + buf[wp]=*data; + data+=2; + wp++; + if (wp>=BUFLEN) wp=0; + } + } else { + //muted + for (int i=0; i<370; i++) { + buf[wp++]=128; + if (wp>=BUFLEN) wp=0; + } } return 1; } diff --git a/components/tme/component.mk b/components/tme/component.mk index b09a9f1..dd9c552 100644 --- a/components/tme/component.mk +++ b/components/tme/component.mk @@ -7,14 +7,15 @@ COMPONENT_SRCDIRS := . musashi MUSASHI_GEN_SRC := musashi/m68kops_pre.c musashi/m68kopac.c musashi/m68kopdm.c musashi/m68kopnz.c MUSASHI_GEN_OBJ := $(MUSASHI_GEN_SRC:%.c=%.o) -COMPONENT_OBJS := musashi/m68kops_pre.o musashi/m68kopac.o musashi/m68kopdm-iram.o musashi/m68kopnz.o musashi/m68kcpu.o emu.o \ +COMPONENT_OBJS := musashi/m68kops_pre.o musashi/m68kopac.o musashi/m68kopdm-iram.o musashi/m68kopnz.o musashi/m68kcpu-iram.o emu.o \ iwm.o via.o rtc.o ncr.o scc.o mouse.o -#nothing in iram: 16% +#nothing in iram: 1240000 #ac nz in iram: 19% -#dm nz in iram: 19% +#dm nz in iram: ng #ac dm in iram: 23% -#dm in iram: 23% +#dm in iram: 1709000 +#cpu in iram: 1278000 #-O3: #nothing: 13% @@ -33,8 +34,9 @@ COMPONENT_EXTRA_CLEAN := $(addprefix $(COMPONENT_PATH)/musashi/,$(MUSASHI_GEN_SR #musashi/m68kops_pre.o: CFLAGS += -O3 #musashi/m68kopac.o: CFLAGS += -O3 -#musashi/m68kopdm.o: CFLAGS += -O3 +musashi/m68kopdm.o: CFLAGS += -O3 #musashi/m68kopnz.o: CFLAGS += -O3 +musashi/m68kcpu.o: CFLAGS += -O3 emu.o: CFLAGS += -O3 diff --git a/components/tme/emu.c b/components/tme/emu.c index 2c2c33c..d974752 100644 --- a/components/tme/emu.c +++ b/components/tme/emu.c @@ -441,6 +441,22 @@ void m68k_write_memory_32(unsigned int address, unsigned int value) { } #endif +unsigned char *m68k_pcbase=NULL; + +void m68k_pc_changed_handler_function(unsigned int address) { +// printf("m68k_pc_changed_handler_function %x\n", address); + const MemmapEnt *mmEnt=getMmmapEnt(address); + if (mmEnt->memAddr) { + uint8_t *p; + p=(uint8_t*)MMAP_RAM_PTR(mmEnt, address); + m68k_pcbase=p-address; + } else { + printf("PC not in mem!\n"); + abort(); + } +} + + //Should be called every second. void printFps() { struct timeval tv; @@ -449,7 +465,7 @@ void printFps() { 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("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; @@ -458,7 +474,7 @@ void printFps() { void tmeStartEmu(void *rom) { int ca1=0, ca2=0; - int x, m=0, frame=0; + int x, frame=0; int cyclesPerSec=0; macRom=rom; ramInit(); @@ -473,6 +489,7 @@ void tmeStartEmu(void *rom) { viaSet(VIA_PORTB, (1<<3)); sccInit(); printf("Initializing m68k...\n"); + m68k_pc_changed_handler_function(0x0); m68k_init(); printf("Setting CPU type and resetting..."); m68k_set_cpu_type(M68K_CPU_TYPE_68000); @@ -484,27 +501,24 @@ void tmeStartEmu(void *rom) { printf("Done! Running.\n"); while(1) { for (x=0; x<8000000/60; x+=1000) { - for (int i=0; i<10; i++) { - m68k_execute(100); - for (int l=0; l<10; l++) { - viaStep(1); //should run at 783.36KHz - sccTick(); - } - } + m68k_execute(1000); + viaStep(100); //should run at 783.36KHz + sccTick(100); + 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; + //Sound handler keeps track of real time, if its buffer is empty we should be done with the video frame. - if (sndDone()) break; + if (x>(8000000/120) && sndDone()) break; } cyclesPerSec+=x; dispDraw(macFb[video_remap?1:0]); sndPush(macSnd[audio_remap?1:0], audio_en?audio_volume:0); - localtalkTick(); +// localtalkTick(); frame++; ca1^=1; viaControlWrite(VIA_CA1, ca1); @@ -513,8 +527,8 @@ void tmeStartEmu(void *rom) { viaControlWrite(VIA_CA2, ca2); rtcTick(); frame=0; - printFps(); - printf("%d Hz\n", cyclesPerSec); +// printFps(); +// printf("%d Hz\n", cyclesPerSec); cyclesPerSec=0; } } @@ -532,17 +546,19 @@ void sccIrq(int req) { void viaCbPortAWrite(unsigned int val) { - int oldRomRemap=rom_remap; + static int writes=0; + if ((writes++)==0) val=0x67; + printf("VIA PORTA WRITE %x\n", val); video_remap=(val&(1<<6))?1:0; rom_remap=(val&(1<<4))?1:0; - regenMemmap(rom_remap); - audio_remap=(val&(1<<3))?0:1; - if (oldRomRemap!=rom_remap) printf("ROM REMAP %d\n", rom_remap); - iwmSetHeadSel(val&(1<<5)); + audio_remap=(val&(1<<3))?1:0; audio_volume=(val&7); + iwmSetHeadSel(val&(1<<5)); + regenMemmap(rom_remap); } void viaCbPortBWrite(unsigned int val) { + printf("VIA PORTB WRITE %x\n", val); int b; b=rtcCom(val&4, val&1, val&2); if (b) viaSet(VIA_PORTB, 1); else viaClear(VIA_PORTB, 1); diff --git a/components/tme/m68kconf.h b/components/tme/m68kconf.h index 4ca9682..6db8232 100644 --- a/components/tme/m68kconf.h +++ b/components/tme/m68kconf.h @@ -73,7 +73,8 @@ * and m68k_read_pcrelative_xx() for PC-relative addressing. * If off, all read requests from the CPU will be redirected to m68k_read_xx() */ -#define M68K_SEPARATE_READS OPT_OFF +#define M68K_SEPARATE_READS OPT_ON + /* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a * predecrement destination EA mode instead of m68k_write_32(). @@ -124,9 +125,9 @@ * large value. This allows host programs to be nicer when it comes to * fetching immediate data and instructions on a banked memory system. */ -#define M68K_MONITOR_PC OPT_OFF -#define M68K_SET_PC_CALLBACK(A) your_pc_changed_handler_function(A) - +#define M68K_MONITOR_PC OPT_SPECIFY_HANDLER +#define M68K_SET_PC_CALLBACK(A) m68k_pc_changed_handler_function(A) +void m68k_pc_changed_handler_function(unsigned int addr); /* If ON, CPU will call the instruction hook callback before every * instruction. @@ -185,4 +186,41 @@ void m68k_instruction(); /* ============================== END OF FILE ============================= */ /* ======================================================================== */ + +#include +#include + +extern unsigned char *m68k_pcbase; + +static inline unsigned int m68k_read_immediate_16(unsigned int address) { + address&=0xFFFFFF; + uint16_t *p=(uint16_t*)(m68k_pcbase+address); + return __bswap_16(*p); +} + +static inline unsigned int m68k_read_immediate_32(unsigned int address) { + address&=0xFFFFFF; + uint32_t *p=(uint32_t*)(m68k_pcbase+address); + return __bswap_32(*p); +} + +static inline unsigned int m68k_read_pcrelative_8(unsigned int address) { + address&=0xFFFFFF; + uint8_t *p=(uint8_t*)(m68k_pcbase+address); + return *p; +} + +static inline unsigned int m68k_read_pcrelative_16(unsigned int address) { + address&=0xFFFFFF; + uint16_t *p=(uint16_t*)(m68k_pcbase+address); + return __bswap_16(*p); +} + +static inline unsigned int m68k_read_pcrelative_32(unsigned int address) { + address&=0xFFFFFF; + uint32_t *p=(uint32_t*)(m68k_pcbase+address); + return __bswap_32(*p); +} + + #endif /* M68KCONF__HEADER */ diff --git a/components/tme/musashi/m68k.h b/components/tme/musashi/m68k.h index e2f0b27..2245790 100755 --- a/components/tme/musashi/m68k.h +++ b/components/tme/musashi/m68k.h @@ -161,6 +161,7 @@ unsigned int m68k_read_memory_8(unsigned int address); unsigned int m68k_read_memory_16(unsigned int address); unsigned int m68k_read_memory_32(unsigned int address); +#if 0 /* Read data immediately following the PC */ unsigned int m68k_read_immediate_16(unsigned int address); unsigned int m68k_read_immediate_32(unsigned int address); @@ -169,6 +170,7 @@ unsigned int m68k_read_immediate_32(unsigned int address); unsigned int m68k_read_pcrelative_8(unsigned int address); unsigned int m68k_read_pcrelative_16(unsigned int address); unsigned int m68k_read_pcrelative_32(unsigned int address); +#endif /* Memory access for the disassembler */ unsigned int m68k_read_disassembler_8 (unsigned int address); diff --git a/components/tme/rtc.c b/components/tme/rtc.c index ed0ce2c..3000378 100644 --- a/components/tme/rtc.c +++ b/components/tme/rtc.c @@ -39,7 +39,7 @@ int rtcCom(int en, int dat, int clk) { } else if (rtc.pos==15) { if ((rtc.cmd&0x8000)==0) { rtc.mem[(rtc.cmd&0x7C00)>>10]=rtc.cmd&0xff; -// saveRtcMem(rtc.mem); + saveRtcMem(rtc.mem); } printf("RTC/PRAM CMD %x\n", rtc.cmd); } diff --git a/components/tme/scc.c b/components/tme/scc.c index 8a0ce97..dbf62ad 100644 --- a/components/tme/scc.c +++ b/components/tme/scc.c @@ -111,10 +111,11 @@ static int rxBytesLeft(int chan) { return scc.chan[chan].rx[scc.chan[chan].rxBufCur].len-scc.chan[chan].rxPos; } -static int rxBufTick(int chan) { +static int rxBufTick(int chan, int noTicks) { if (scc.chan[chan].rx[scc.chan[chan].rxBufCur].delay > 0) { - scc.chan[chan].rx[scc.chan[chan].rxBufCur].delay--; - if (scc.chan[chan].rx[scc.chan[chan].rxBufCur].delay==0) { + scc.chan[chan].rx[scc.chan[chan].rxBufCur].delay-=noTicks; + if (scc.chan[chan].rx[scc.chan[chan].rxBufCur].delay<=0) { + scc.chan[chan].rx[scc.chan[chan].rxBufCur].delay=0; #ifdef SCC_DBG printf("Feeding buffer %d into SCC\n", scc.chan[chan].rxBufCur); #endif @@ -592,30 +593,40 @@ unsigned int sccRead(unsigned int addr) { } //Called at about 800KHz -void sccTick() { +void sccTick(int noTicks) { for (int n=0; n<2; n++) { + int needCheck=0; if (scc.chan[n].txTimer>0) { - scc.chan[n].txTimer--; - if (scc.chan[n].txTimer==0) { + scc.chan[n].txTimer-=noTicks; + if (scc.chan[n].txTimer<=0) { + scc.chan[n].txTimer=0; // printf("Tx buffer empty: Sent data\n"); sccTxFinished(n); + needCheck=1; } } - if (rxBufTick(n)) { + if (rxBufTick(n, noTicks)) { triggerRx(n); + needCheck=1; } if (scc.chan[n].eofDelay>0) { - scc.chan[n].eofDelay--; + scc.chan[n].eofDelay-=noTicks; + if (scc.chan[n].eofDelay<0) scc.chan[n].eofDelay=0; if (scc.chan[n].eofDelay==0 && (scc.chan[n].wr1&0x10)!=0) { //Int mode is recv char or special / special only printf("Raise EOF int for channel %d\n", n); scc.chan[n].eofIntPending=1; scc.intpending|=((n==0)?SCC_RR3_CHA_RX:SCC_RR3_CHB_RX); raiseInt(n); + needCheck=1; } } - if (scc.chan[n].rxAbrtTimer>0) scc.chan[n].rxAbrtTimer--; - checkExtInt(n); + if (scc.chan[n].rxAbrtTimer>0) { + scc.chan[n].rxAbrtTimer-=noTicks; + if (scc.chan[n].rxAbrtTimer<0) scc.chan[n].rxAbrtTimer=0; + needCheck=1; + } + if (needCheck) checkExtInt(n); } } diff --git a/components/tme/scc.h b/components/tme/scc.h index 8b42711..5e05fb3 100644 --- a/components/tme/scc.h +++ b/components/tme/scc.h @@ -6,6 +6,6 @@ void sccWrite(unsigned int addr, unsigned int val); unsigned int sccRead(unsigned int addr); void sccSetDcd(int chan, int val); void sccInit(); -void sccTick(); +void sccTick(int cycles); void sccRecv(int chan, uint8_t *data, int len, int delay); diff --git a/components/tme/sdl/disp.c b/components/tme/sdl/disp.c index 57074a6..85009e6 100644 --- a/components/tme/sdl/disp.c +++ b/components/tme/sdl/disp.c @@ -17,13 +17,16 @@ void sdlDie() { void dispInit() { - if (SDL_Init( SDL_INIT_VIDEO|SDL_INIT_AUDIO ) < 0 ) sdlDie(); win=SDL_CreateWindow( "TME", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN ); if (win==0) sdlDie(); surf=SDL_GetWindowSurface(win); drwsurf=SDL_CreateRGBSurfaceWithFormat(0, SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_PIXELFORMAT_RGBA32); } +void sdlDispAudioInit() { + if (SDL_Init( SDL_INIT_VIDEO|SDL_INIT_AUDIO ) < 0 ) sdlDie(); +} + void handleInput() { static int btn=0; static int oldx, oldy; diff --git a/components/tme/sdl/main.c b/components/tme/sdl/main.c index 5a9d330..5569160 100644 --- a/components/tme/sdl/main.c +++ b/components/tme/sdl/main.c @@ -8,6 +8,7 @@ #include #include "tmeconfig.h" #include "snd.h" +#include "disp.h" static void *loadRom(char *file) { int i; @@ -38,5 +39,6 @@ int main(int argc, char **argv) { rtcInit(data); fclose(f); } + sdlDispAudioInit(); tmeStartEmu(rom); } diff --git a/components/tme/sdl/snd.c b/components/tme/sdl/snd.c index 342f5c1..ec640d0 100644 --- a/components/tme/sdl/snd.c +++ b/components/tme/sdl/snd.c @@ -15,7 +15,7 @@ static int bufLen() { } int sndDone() { - if (!soundEna) return 1; + if (!soundEna) return 0; return (bufLen()<512); } diff --git a/components/tme/tmeconfig.h b/components/tme/tmeconfig.h index 3b9a87e..b1d14a0 100644 --- a/components/tme/tmeconfig.h +++ b/components/tme/tmeconfig.h @@ -29,7 +29,6 @@ #define TME_SCREENBUF 0x3FA700 #define TME_SCREENBUF_ALT 0x3F2700 #define TME_SNDBUF 0x3FFD00 -#define TME_SNDBUF_ALT 0x3FA100 #else @@ -40,9 +39,9 @@ #define TME_SCREENBUF 0x1A700 #define TME_SCREENBUF_ALT 0x12700 #define TME_SNDBUF 0x1FD00 -#define TME_SNDBUF_ALT 0x1A100 +#endif #endif - -#endif \ No newline at end of file +//Source: Guide to the Macintosh family hardware +#define TME_SNDBUF_ALT (TME_SNDBUF-0x5C00) diff --git a/components/tme/via.c b/components/tme/via.c index 5692939..a302a9a 100644 --- a/components/tme/via.c +++ b/components/tme/via.c @@ -30,7 +30,7 @@ typedef struct { uint8_t ddra, ddrb; uint8_t ina, inb; uint8_t outa, outb; - uint16_t timer1, timer2; + int timer1, timer2; uint16_t latch1, latch2; uint8_t ifr, ier; uint8_t pcr, acr; @@ -54,18 +54,19 @@ void viaClear(int no, int mask) { } void viaStep(int clockcycles) { - while(clockcycles--) { - if (via.timer1==1) { + if ((via.timer1!=0) || (via.acr&(1<<6))) { + via.timer1-=clockcycles; + if (via.timer1<=1) { via.ifr|=IFR_T1; - via.timer1=via.latch1; - } - if ((via.timer1!=0) || (via.acr&(1<<6))) via.timer1--; - via.timer2--; - if (via.timer2==0) { - //Actually shouldn't be set when timer2 gets 0 a 2nd time... ahwell. - via.ifr|=IFR_T2; + via.timer1+=via.latch1; } } + via.timer2-=clockcycles; + if (via.timer2<=0) { + //Actually shouldn't be set when timer2 gets 0 a 2nd time... ahwell. + via.ifr|=IFR_T2; + via.timer2+=0x10000; + } } static void viaCheckIrq() { @@ -119,10 +120,12 @@ void viaWrite(unsigned int addr, unsigned int val) { if (addr==0x0) { //ORB viaCbPortBWrite(val); + via.inb=(via.inb&~via.ddrb)|(val&via.ddrb); accessPort(1); } else if (addr==0x1) { //ORA viaCbPortAWrite(val); + via.ina=(via.ina&~via.ddra)|(val&via.ddra); accessPort(0); } else if (addr==0x2) { //DDRB @@ -180,6 +183,7 @@ void viaWrite(unsigned int addr, unsigned int val) { } else if (addr==0xf) { //ORA viaCbPortAWrite(val); + via.ina=(via.ina&~via.ddra)|(val&via.ddra); } // printf("VIA write %s val %x\n", viaRegNames[addr], val); }