From 437c16a8f1d73b28d7262819654b88b207231154 Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Thu, 24 May 2012 19:08:14 +0000 Subject: [PATCH] Minor tweaks to Makefiles, added command line switches for most options. --- Makefile | 24 ++- jaguarcore.mak | 36 ++-- res/help.html | 2 +- src/dac.cpp | 368 +---------------------------------------- src/dac.h | 11 +- src/dsp.cpp | 4 + src/file.cpp | 85 ++++++++-- src/file.h | 4 +- src/gui/app.cpp | 265 ++++++++++++++++++++++++----- src/gui/filepicker.cpp | 2 +- src/gui/filethread.cpp | 2 +- src/gui/mainwin.cpp | 131 ++++++++++++--- src/gui/mainwin.h | 7 +- src/jaguar.cpp | 14 +- src/log.cpp | 7 +- src/m68000/Makefile | 18 +- src/virtualjaguar.cpp | 2 +- 17 files changed, 491 insertions(+), 491 deletions(-) diff --git a/Makefile b/Makefile index 03de51b..4dfadf4 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,20 @@ ifeq "$(findstring Darwin,$(OSTYPE))" "Darwin" QMAKE_EXTRA := -spec macx-g++ endif +# Eh? +CFLAGS ?= "" +CPPFLAGS ?= "" +CXXFLAGS ?= "" +LDFLAGS ?= "" + +QMAKE_EXTRA += "QMAKE_CFLAGS_RELEASE=$(CFLAGS)" +QMAKE_EXTRA += "QMAKE_CXXFLAGS_RELEASE=$(CXXFLAGS)" +QMAKE_EXTRA += "QMAKE_LFLAGS_RELEASE=$(LDFLAGS)" + +QMAKE_EXTRA += "QMAKE_CFLAGS_DEBUG=$(CFLAGS)" +QMAKE_EXTRA += "QMAKE_CXXFLAGS_DEBUG=$(CXXFLAGS)" +QMAKE_EXTRA += "QMAKE_LFLAGS_DEBUG=$(LDFLAGS)" + all: prepare virtualjaguar @echo -e "\033[01;33m***\033[00;32m Success!\033[00m" @@ -26,10 +40,10 @@ obj: prepare: obj @echo -e "\033[01;33m***\033[00;32m Preparing to compile Virtual Jaguar...\033[00m" -# @echo "#define VJ_RELEASE_VERSION \"v2.0.3\"" > src/version.h +# @echo "#define VJ_RELEASE_VERSION \"v2.1.0\"" > src/version.h # @echo "#define VJ_RELEASE_SUBVERSION \"Final\"" >> src/version.h @echo "#define VJ_RELEASE_VERSION \"SVN `svn info | grep -i revision`\"" > src/version.h - @echo "#define VJ_RELEASE_SUBVERSION \"2.0.3 Prerelease\"" >> src/version.h + @echo "#define VJ_RELEASE_SUBVERSION \"2.1.0 Prerelease\"" >> src/version.h virtualjaguar: sources libs makefile-qt @echo -e "\033[01;33m***\033[00;32m Making Virtual Jaguar GUI...\033[00m" @@ -45,7 +59,8 @@ libs: obj/libm68k.a obj/libjaguarcore.a obj/libm68k.a: src/m68000/Makefile sources @echo -e "\033[01;33m***\033[00;32m Making Customized UAE 68K Core...\033[00m" - @$(MAKE) -C src/m68000 +# @$(MAKE) -C src/m68000 + @$(MAKE) -C src/m68000 CFLAGS="$(CFLAGS)" @cp src/m68000/obj/libm68k.a obj/ obj/libmusashi.a: musashi.mak sources @@ -54,7 +69,8 @@ obj/libmusashi.a: musashi.mak sources obj/libjaguarcore.a: jaguarcore.mak sources @echo -e "\033[01;33m***\033[00;32m Making Virtual Jaguar core...\033[00m" - $(MAKE) -f jaguarcore.mak +# $(MAKE) -f jaguarcore.mak + $(MAKE) -f jaguarcore.mak CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" sources: src/*.h src/*.cpp src/*.c src/m68000/*.c src/m68000/*.h diff --git a/jaguarcore.mak b/jaguarcore.mak index 16e0b1e..1bcafe0 100644 --- a/jaguarcore.mak +++ b/jaguarcore.mak @@ -11,22 +11,26 @@ OSTYPE := $(shell uname -a) -ifeq "$(findstring Msys,$(OSTYPE))" "Msys" # Win32 +# Win32 +ifeq "$(findstring Msys,$(OSTYPE))" "Msys" SYSTYPE := __GCCWIN32__ SDLLIBTYPE := --libs -else ifeq "$(findstring Darwin,$(OSTYPE))" "Darwin" # Should catch both 'darwin' and 'darwin7.0' +# Apple. Should catch both 'darwin' and 'darwin7.0' +else ifeq "$(findstring Darwin,$(OSTYPE))" "Darwin" SYSTYPE := __GCCUNIX__ -D__THINK_STUPID__ SDLLIBTYPE := --static-libs -else ifeq "$(findstring Linux,$(OSTYPE))" "Linux" # Linux +# Linux +else ifeq "$(findstring Linux,$(OSTYPE))" "Linux" SYSTYPE := __GCCUNIX__ SDLLIBTYPE := --libs -else # ??? +# ??? Throw error, unknown OS +else $(error OS TYPE UNDETECTED) @@ -41,14 +45,20 @@ HAVECDIO := CDIOLIB := endif -CC := gcc -LD := gcc -AR := ar -ARFLAGS := -rs +CC := gcc +LD := gcc +AR := ar +ARFLAGS := -rs # Note that we use optimization level 2 instead of 3--3 doesn't seem to gain much over 2 -CFLAGS := -MMD -O2 -ffast-math -fomit-frame-pointer `sdl-config --cflags` -D$(SYSTYPE) -CXXFLAGS := -MMD -O2 -ffast-math -fomit-frame-pointer `sdl-config --cflags` -D$(SYSTYPE) +#CFLAGS := -MMD -O2 -ffast-math -fomit-frame-pointer `sdl-config --cflags` -D$(SYSTYPE) +#CXXFLAGS := -MMD -O2 -ffast-math -fomit-frame-pointer `sdl-config --cflags` -D$(SYSTYPE) +CFLAGS ?= -O2 -ffast-math -fomit-frame-pointer +CXXFLAGS ?= -O2 -ffast-math -fomit-frame-pointer + +SDL_CFLAGS = `sdl-config --cflags` +DEFINES = -D$(SYSTYPE) +GCC_DEPS = "-MMD" INCS := -I./src @@ -101,10 +111,12 @@ obj/libjaguarcore.a: $(OBJS) obj/%.o: src/%.c @echo -e "\033[01;33m***\033[00;32m Compiling $<...\033[00m" - @$(CC) $(CFLAGS) $(INCS) -c $< -o $@ +# @$(CC) $(CFLAGS) $(INCS) -c $< -o $@ + @$(CC) $(GCC_DEPS) $(CFLAGS) $(SDL_CFLAGS) $(DEFINES) $(INCS) -c $< -o $@ obj/%.o: src/%.cpp @echo -e "\033[01;33m***\033[00;32m Compiling $<...\033[00m" - @$(CC) $(CXXFLAGS) $(INCS) -c $< -o $@ +# @$(CC) $(CXXFLAGS) $(INCS) -c $< -o $@ + @$(CC) $(GCC_DEPS) $(CXXFLAGS) $(SDL_CFLAGS) $(DEFINES) $(INCS) -c $< -o $@ -include obj/*.d diff --git a/res/help.html b/res/help.html index 7a6fc00..86daf51 100644 --- a/res/help.html +++ b/res/help.html @@ -244,7 +244,7 @@

Trademarks used in Virtual Jaguar and/or this documentation are the property of their respective owners. The user(s) of Virtual Jaguar assumes all risk associated with using the software; the authors are not responsible for anything the user(s) does with said software or what happens to the user(s) as a result of using this software.

-

Virtual Jaguar is Free (as in Libre) software and is licensed under the GPL version 3. You should have recieved a copy of the license with this software; if you did not, you may view a copy at http://www.gnu.org/licenses. A copy of the source code is available at http://icculus.org/virtualjaguar.

+

Virtual Jaguar is Free (as in Libre) software and is licensed under the GPL version 3. You should have received a copy of the license with this software; if you did not, you may view a copy at http://www.gnu.org/licenses. A copy of the source code is available at http://icculus.org/virtualjaguar.

Downfall is © 2011 Reboot, All Rights Reserved. Distribution of Downfall with Virtual Jaguar has been graciously authorized by Reboot, and may not be distributed as part of any other package.

diff --git a/src/dac.cpp b/src/dac.cpp index be6c3ae..d005518 100644 --- a/src/dac.cpp +++ b/src/dac.cpp @@ -11,6 +11,7 @@ // Who When What // --- ---------- ------------------------------------------------------------- // JLH 01/16/2010 Created this log ;-) +// JLH 04/30/2012 Changed SDL audio handler to run JERRY // // Need to set up defaults that the BIOS sets for the SSI here in DACInit()... !!! FIX !!! @@ -22,10 +23,6 @@ // that is the current spinlock implementation. Since the DSP is a separate // entity, could we get away with running it in the sound IRQ? -// ALSO: It may be a good idea to physically separate the left and right buffers -// to prevent things like the DSP filling only one side and such. Do such -// mono modes exist on the Jag? Seems to according to Super Burnout. - // After testing on a real Jaguar, it seems clear that the I2S interrupt drives // the audio subsystem. So while you can drive the audio at a *slower* rate than // set by SCLK, you can't drive it any *faster*. Also note, that if the I2S @@ -77,25 +74,19 @@ // Global variables +// These are defined in memory.h/cpp //uint16 lrxd, rrxd; // I2S ports (into Jaguar) // Local variables -static uint32 LeftFIFOHeadPtr, LeftFIFOTailPtr, RightFIFOHeadPtr, RightFIFOTailPtr; static SDL_AudioSpec desired; static bool SDLSoundInitialized; - -// We can get away with using native endian here because we can tell SDL to use the native -// endian when looking at the sample buffer, i.e., no need to worry about it. - -static uint16 DACBuffer[BUFFER_SIZE]; static uint8 SCLKFrequencyDivider = 19; // Default is roughly 22 KHz (20774 Hz in NTSC mode) /*static*/ uint16 serialMode = 0; // Private function prototypes void SDLSoundCallback(void * userdata, Uint8 * buffer, int length); -void SDLSoundCallbackNew(void * userdata, Uint8 * buffer, int length); void DSPSampleCallback(void); @@ -112,31 +103,19 @@ void DACInit(void) return; } -#ifdef NEW_DAC_CODE desired.freq = DAC_AUDIO_RATE; desired.format = AUDIO_S16SYS; desired.channels = 2; - desired.samples = 2048; - desired.callback = SDLSoundCallbackNew; -#else -// memory_malloc_secure((void **)&DACBuffer, BUFFER_SIZE * sizeof(uint16), "DAC buffer"); -// DACBuffer = (uint16 *)memory_malloc(BUFFER_SIZE * sizeof(uint16), "DAC buffer"); - - desired.freq = GetCalculatedFrequency(); // SDL will do conversion on the fly, if it can't get the exact rate. Nice! - desired.format = AUDIO_S16SYS; // This uses the native endian (for portability)... - desired.channels = 2; -// desired.samples = 4096; // Let's try a 4K buffer (can always go lower) - desired.samples = 2048; // Let's try a 2K buffer (can always go lower) + desired.samples = 2048; // 2K buffer = audio delay of 42.67 ms (@ 48 KHz) desired.callback = SDLSoundCallback; -#endif - if (SDL_OpenAudio(&desired, NULL) < 0) // NULL means SDL guarantees what we want + if (SDL_OpenAudio(&desired, NULL) < 0) // NULL means SDL guarantees what we want WriteLog("DAC: Failed to initialize SDL sound...\n"); else { SDLSoundInitialized = true; DACReset(); - SDL_PauseAudio(false); // Start playback! + SDL_PauseAudio(false); // Start playback! WriteLog("DAC: Successfully initialized. Sample rate: %u\n", desired.freq); } @@ -153,7 +132,7 @@ void DACInit(void) // void DACReset(void) { - LeftFIFOHeadPtr = LeftFIFOTailPtr = 0, RightFIFOHeadPtr = RightFIFOTailPtr = 1; +// LeftFIFOHeadPtr = LeftFIFOTailPtr = 0, RightFIFOHeadPtr = RightFIFOTailPtr = 1; ltxd = lrxd = desired.silence; } @@ -169,7 +148,6 @@ void DACDone(void) SDL_CloseAudio(); } -// memory_free(DACBuffer); WriteLog("DAC: Done.\n"); } @@ -189,12 +167,11 @@ void DACDone(void) // Note: The samples are packed in the buffer in 16 bit left/16 bit right pairs. // Also, length is the length of the buffer in BYTES // -//static double timePerSample = 0; static Uint8 * sampleBuffer; static int bufferIndex = 0; static int numberOfSamples = 0; static bool bufferDone = false; -void SDLSoundCallbackNew(void * userdata, Uint8 * buffer, int length) +void SDLSoundCallback(void * userdata, Uint8 * buffer, int length) { // 1st, check to see if the DSP is running. If not, fill the buffer with L/RXTD and exit. @@ -218,29 +195,6 @@ void SDLSoundCallbackNew(void * userdata, Uint8 * buffer, int length) // Now, run the DSP for that length of time for each sample we need to make -#if 0 - for(int i=0; i<(length/2); i+=2) - { -//This stuff is from the old Jaguar execute loop. New stuff is timer based... -//which means we need to figure that crap out, and how to make it work here. -//Seems like we need two separate timing queues. Tho not sure how to make that work here... -//Maybe like the "frameDone" in JaguarExecuteNew() in jaguar.cpp? -// JERRYExecPIT(cyclesPerSample); -// JERRYI2SExec(cyclesPerSample); -// BUTCHExec(cyclesPerSample); - - if (vjs.DSPEnabled) - { - if (vjs.usePipelinedDSP) - DSPExecP2(cyclesPerSample); - else - DSPExec(cyclesPerSample); - } - - ((uint16_t *)buffer)[i + 0] = ltxd; - ((uint16_t *)buffer)[i + 1] = rtxd; - } -#else bufferIndex = 0; sampleBuffer = buffer; numberOfSamples = length / 2; @@ -264,10 +218,6 @@ void SDLSoundCallbackNew(void * userdata, Uint8 * buffer, int length) HandleNextEvent(EVENT_JERRY); } while (!bufferDone); - - // We do this to prevent problems with trying to write past the end of the buffer... -// RemoveCallback(DSPSampleCallback); -#endif } @@ -285,98 +235,9 @@ void DSPSampleCallback(void) SetCallbackTime(DSPSampleCallback, 1000000.0 / (double)DAC_AUDIO_RATE, EVENT_JERRY); } -#if 0 - frameDone = false; - - do - { - double timeToNextEvent = GetTimeToNextEvent(); -//WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent)); - - m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent)); - - if (vjs.GPUEnabled) - GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); - -#ifndef NEW_DAC_CODE - if (vjs.DSPEnabled) - { - if (vjs.usePipelinedDSP) - DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Pipelined DSP execution (3 stage)... - else - DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Ordinary non-pipelined DSP - } -#endif - - HandleNextEvent(); - } - while (!frameDone); -#endif - - -// -// SDL callback routine to fill audio buffer -// -// Note: The samples are packed in the buffer in 16 bit left/16 bit right pairs. -// Also, length is the length of the buffer in BYTES -// -void SDLSoundCallback(void * userdata, Uint8 * buffer, int length) -{ - // Clear the buffer to silence, in case the DAC buffer is empty (or short) -//This causes choppy sound... Ick. - memset(buffer, desired.silence, length); -//WriteLog("DAC: Inside callback...\n"); - if (LeftFIFOHeadPtr != LeftFIFOTailPtr) - { -//WriteLog("DAC: About to write some data!\n"); - int numLeftSamplesReady - = (LeftFIFOTailPtr + (LeftFIFOTailPtr < LeftFIFOHeadPtr ? BUFFER_SIZE : 0)) - - LeftFIFOHeadPtr; - int numRightSamplesReady - = (RightFIFOTailPtr + (RightFIFOTailPtr < RightFIFOHeadPtr ? BUFFER_SIZE : 0)) - - RightFIFOHeadPtr; -//This waits for the slower side to catch up. If writing only one side, then this -//causes the buffer not to drain... - int numSamplesReady - = (numLeftSamplesReady < numRightSamplesReady - ? numLeftSamplesReady : numRightSamplesReady);//Hmm. * 2; - -//Kludge, until I can figure out WTF is going on WRT Super Burnout. -if (numLeftSamplesReady == 0 || numRightSamplesReady == 0) - numSamplesReady = numLeftSamplesReady + numRightSamplesReady; - -//The numbers look good--it's just that the DSP can't get enough samples in the DAC buffer! -//WriteLog("DAC: Left/RightFIFOHeadPtr: %u/%u, Left/RightFIFOTailPtr: %u/%u\n", LeftFIFOHeadPtr, RightFIFOHeadPtr, LeftFIFOTailPtr, RightFIFOTailPtr); -//WriteLog(" numLeft/RightSamplesReady: %i/%i, numSamplesReady: %i, length of buffer: %i\n", numLeftSamplesReady, numRightSamplesReady, numSamplesReady, length); - -/* if (numSamplesReady > length) - numSamplesReady = length;//*/ - if (numSamplesReady > length / 2) // length / 2 because we're comparing 16-bit lengths - numSamplesReady = length / 2; -//else -// WriteLog(" Not enough samples to fill the buffer (short by %u L/R samples)...\n", (length / 2) - numSamplesReady); -//WriteLog("DAC: %u samples ready.\n", numSamplesReady); - - // Actually, it's a bit more involved than this, but this is the general idea: -// memcpy(buffer, DACBuffer, length); - for(int i=0; i Left/RightFIFOHeadPtr: %04X/%04X, Left/RightFIFOTailPtr: %04X/%04X\n", LeftFIFOHeadPtr, RightFIFOHeadPtr, LeftFIFOTailPtr, RightFIFOTailPtr); - } -//Hmm. Seems that the SDL buffer isn't being starved by the DAC buffer... -// else -// WriteLog("DAC: Silence...!\n"); -} +#if 0 // // Calculate the frequency of SCLK * 32 using the divider // @@ -388,48 +249,7 @@ int GetCalculatedFrequency(void) // 16 bits of left data + 16 bits of right data = 32 bits, 1 SCLK = 1 bit transferred). return systemClockFrequency / (32 * (2 * (SCLKFrequencyDivider + 1))); } - - -static int oldFreq = 0; - -void DACSetNewFrequency(int freq) -{ -#ifdef NEW_DAC_CODE -#else - if (freq == oldFreq) - return; - - oldFreq = freq; - - // Should do some sanity checking on the frequency... - - if (SDLSoundInitialized) - SDL_CloseAudio(); - - desired.freq = freq;// SDL will do conversion on the fly, if it can't get the exact rate. Nice! - WriteLog("DAC: Changing sample rate to %u Hz!\n", desired.freq); - - if (SDLSoundInitialized) - { - if (SDL_OpenAudio(&desired, NULL) < 0) // NULL means SDL guarantees what we want - { -// This is bad, Bad, BAD !!! DON'T ABORT BECAUSE WE DIDN'T GET OUR FREQ! !!! FIX !!! -#warning !!! FIX !!! Aborting because of SDL audio problem is bad! - WriteLog("DAC: Failed to initialize SDL sound: %s.\nDesired freq: %u\nShutting down!\n", SDL_GetError(), desired.freq); -// LogDone(); -// exit(1); -#warning "Reimplement GUICrashGracefully!" -// GUICrashGracefully("Failed to initialize SDL sound!"); - return; - } - } - - DACReset(); - - if (SDLSoundInitialized) - SDL_PauseAudio(false); // Start playback! #endif -} // @@ -447,188 +267,18 @@ void DACWriteWord(uint32 offset, uint16 data, uint32 who/*= UNKNOWN*/) { if (offset == LTXD + 2) { - if (!SDLSoundInitialized) - return; - -#ifdef NEW_DAC_CODE ltxd = data; -#else - // Spin until buffer has been drained (for too fast processors!)... -//Small problem--if Head == 0 and Tail == buffer end, then this will fail... !!! FIX !!! -//[DONE] - // Also, we're taking advantage of the fact that the buffer is a multiple of two - // in this check... -uint32 spin = 0; - while (((LeftFIFOTailPtr + 2) & (BUFFER_SIZE - 1)) == LeftFIFOHeadPtr)//; - { -spin++; -//if ((spin & 0x0FFFFFFF) == 0) -// WriteLog("Tail=%X, Head=%X, BUFFER_SIZE-1=%X\n", RightFIFOTailPtr, RightFIFOHeadPtr, BUFFER_SIZE - 1); - -if (spin == 0xFFFF0000) -{ -uint32 ltail = LeftFIFOTailPtr, lhead = LeftFIFOHeadPtr; -WriteLog("Tail=%X, Head=%X", ltail, lhead); - - WriteLog("\nStuck in left DAC spinlock! Aborting!\n"); - WriteLog("LTail=%X, LHead=%X, BUFFER_SIZE-1=%X\n", LeftFIFOTailPtr, LeftFIFOHeadPtr, BUFFER_SIZE - 1); - WriteLog("RTail=%X, RHead=%X, BUFFER_SIZE-1=%X\n", RightFIFOTailPtr, RightFIFOHeadPtr, BUFFER_SIZE - 1); - WriteLog("From while: Tail=%X, Head=%X", (LeftFIFOTailPtr + 2) & (BUFFER_SIZE - 1), LeftFIFOHeadPtr); -// LogDone(); -// exit(0); -#warning "Reimplement GUICrashGracefully!" -// GUICrashGracefully("Stuck in left DAC spinlock!"); - return; -} - }//*/ - - SDL_LockAudio(); // Is it necessary to do this? Mebbe. - // We use a circular buffer 'cause it's easy. Note that the callback function - // takes care of dumping audio to the soundcard...! Also note that we're writing - // the samples in the buffer in an interleaved L/R format. - LeftFIFOTailPtr = (LeftFIFOTailPtr + 2) % BUFFER_SIZE; - DACBuffer[LeftFIFOTailPtr] = data; - SDL_UnlockAudio(); -#endif } else if (offset == RTXD + 2) { - if (!SDLSoundInitialized) - return; -/* -Here's what's happening now: - -Stuck in right DAC spinlock! -Aborting! - -Tail=681, Head=681, BUFFER_SIZE-1=FFFF -From while: Tail=683, Head=681 - -????? What the FUCK ????? - -& when I uncomment the lines below spin++; it *doesn't* lock here... WTF????? - -I think it was missing parentheses causing the fuckup... Seems to work now... - -Except for Super Burnout now...! Aarrrgggghhhhh! - -Tail=AC, Head=AE -Stuck in left DAC spinlock! Aborting! -Tail=AC, Head=AE, BUFFER_SIZE-1=FFFF -From while: Tail=AE, Head=AE - -So it's *really* stuck here in the left FIFO. Figure out why!!! - -Prolly 'cause it doesn't set the sample rate right away--betcha it works with the BIOS... -It gets farther, but then locks here (weird!): - -Tail=2564, Head=2566 -Stuck in left DAC spinlock! Aborting! -Tail=2564, Head=2566, BUFFER_SIZE-1=FFFF -From while: Tail=2566, Head=2566 - -Weird--recompile with more WriteLog() entries and it *doesn't* lock... -Yeah, because there was no DSP running. Duh! - -Tail=AC, Head=AE -Stuck in left DAC spinlock! Aborting! -LTail=AC, LHead=AE, BUFFER_SIZE-1=FFFF -RTail=AF, RHead=AF, BUFFER_SIZE-1=FFFF -From while: Tail=AE, Head=AE - -Odd: The right FIFO is empty, but the left FIFO is full! -And this is what is causing the lockup--the DAC callback waits for the side with -less samples ready and in this case it's the right channel (that never fills up) -that it's waiting for...! - -Okay, with the kludge in place for the right channel not being filled, we select -a track and then it locks here: - -Tail=60D8, Head=60DA -Stuck in left DAC spinlock! Aborting! -LTail=60D8, LHead=60D8, BUFFER_SIZE-1=FFFF -RTail=DB, RHead=60D9, BUFFER_SIZE-1=FFFF -From while: Tail=60DA, Head=60D8 -*/ -#ifdef NEW_DAC_CODE rtxd = data; -#else -#warning Spinlock problem--!!! FIX !!! -#warning Odd: The right FIFO is empty, but the left FIFO is full! - // Spin until buffer has been drained (for too fast processors!)... -uint32 spin = 0; - while (((RightFIFOTailPtr + 2) & (BUFFER_SIZE - 1)) == RightFIFOHeadPtr)//; - { -spin++; -//if ((spin & 0x0FFFFFFF) == 0) -// WriteLog("Tail=%X, Head=%X, BUFFER_SIZE-1=%X\n", RightFIFOTailPtr, RightFIFOHeadPtr, BUFFER_SIZE - 1); - -if (spin == 0xFFFF0000) -{ -uint32 rtail = RightFIFOTailPtr, rhead = RightFIFOHeadPtr; -WriteLog("Tail=%X, Head=%X", rtail, rhead); - - WriteLog("\nStuck in right DAC spinlock! Aborting!\n"); - WriteLog("LTail=%X, LHead=%X, BUFFER_SIZE-1=%X\n", LeftFIFOTailPtr, LeftFIFOHeadPtr, BUFFER_SIZE - 1); - WriteLog("RTail=%X, RHead=%X, BUFFER_SIZE-1=%X\n", RightFIFOTailPtr, RightFIFOHeadPtr, BUFFER_SIZE - 1); - WriteLog("From while: Tail=%X, Head=%X", (RightFIFOTailPtr + 2) & (BUFFER_SIZE - 1), RightFIFOHeadPtr); -// LogDone(); -// exit(0); -#warning "Reimplement GUICrashGracefully!" -// GUICrashGracefully("Stuck in right DAC spinlock!"); - return; -} - }//*/ - - SDL_LockAudio(); - RightFIFOTailPtr = (RightFIFOTailPtr + 2) % BUFFER_SIZE; - DACBuffer[RightFIFOTailPtr] = data; - SDL_UnlockAudio(); -/*#ifdef DEBUG_DAC - else - WriteLog("DAC: Ran into FIFO's right tail pointer!\n"); -#endif*/ -#endif } else if (offset == SCLK + 2) // Sample rate { WriteLog("DAC: Writing %u to SCLK...\n", data); + if ((uint8)data != SCLKFrequencyDivider) - { SCLKFrequencyDivider = (uint8)data; -#ifdef NEW_DAC_CODE -#else -//Of course a better way would be to query the hardware to find the upper limit... - if (data > 7) // Anything less than 8 is too high! - { - if (SDLSoundInitialized) - SDL_CloseAudio(); - - desired.freq = GetCalculatedFrequency();// SDL will do conversion on the fly, if it can't get the exact rate. Nice! - WriteLog("DAC: Changing sample rate to %u Hz!\n", desired.freq); - - if (SDLSoundInitialized) - { - if (SDL_OpenAudio(&desired, NULL) < 0) // NULL means SDL guarantees what we want - { -// This is bad, Bad, BAD !!! DON'T ABORT BECAUSE WE DIDN'T GET OUR FREQ! !!! FIX !!! -#warning !!! FIX !!! Aborting because of SDL audio problem is bad! - WriteLog("DAC: Failed to initialize SDL sound: %s.\nDesired freq: %u\nShutting down!\n", SDL_GetError(), desired.freq); -// LogDone(); -// exit(1); -#warning "Reimplement GUICrashGracefully!" -// GUICrashGracefully("Failed to initialize SDL sound!"); - return; - } - } - - DACReset(); - - if (SDLSoundInitialized) - SDL_PauseAudio(false); // Start playback! - } -#endif - } } else if (offset == SMODE + 2) { diff --git a/src/dac.h b/src/dac.h index ef30549..d0c5720 100644 --- a/src/dac.h +++ b/src/dac.h @@ -5,17 +5,12 @@ #ifndef __DAC_H__ #define __DAC_H__ -//this is here, because we have to compensate in more than just dac.cpp... -#define NEW_DAC_CODE // New code paths! - -//#include "types.h" #include "memory.h" void DACInit(void); void DACReset(void); void DACDone(void); -int GetCalculatedFrequency(void); -void DACSetNewFrequency(int); +//int GetCalculatedFrequency(void); // DAC memory access @@ -24,8 +19,4 @@ void DACWriteWord(uint32 offset, uint16 data, uint32 who = UNKNOWN); uint8 DACReadByte(uint32 offset, uint32 who = UNKNOWN); uint16 DACReadWord(uint32 offset, uint32 who = UNKNOWN); -// Global variables - -//extern uint16 lrxd, rrxd; // I2S ports (into Jaguar) - #endif // __DAC_H__ diff --git a/src/dsp.cpp b/src/dsp.cpp index d321d47..4704aa3 100644 --- a/src/dsp.cpp +++ b/src/dsp.cpp @@ -814,6 +814,9 @@ SET32(ram2, offset, data); // IRQs on J_INT ($F10020), you don't have to run an I2S interrupt on the DSP. Also, // It seems that it's only stable for values of SCLK <= 9. +// All of the preceeding is moot now; we run the DSP in the host audio IRQ. This means +// that we don't actually need this stuff anymore. :-D +#if 0 if (data & INT_ENA1) // I2S interrupt { int freq = GetCalculatedFrequency(); @@ -828,6 +831,7 @@ SET32(ram2, offset, data); // WriteLog("DSP: Setting audio freqency to %u Hz...\n", freq); DACSetNewFrequency(freq); } +#endif /* if (IMASKCleared) // If IMASK was cleared, #ifdef DSP_DEBUG_IRQ diff --git a/src/file.cpp b/src/file.cpp index acf90d6..691f3a2 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -125,7 +125,7 @@ bool JaguarLoadFile(char * path) // directory, copy the one from the ZIP file, if it exists. EepromInit(); jaguarRunAddress = 0x802000; // For non-BIOS runs, this is true - int fileType = ParseFileType(buffer[0], buffer[1], jaguarROMSize); + int fileType = ParseFileType(buffer, jaguarROMSize); jaguarCartInserted = false; if (fileType == JST_ROM) @@ -171,13 +171,71 @@ bool JaguarLoadFile(char * path) jaguarRunAddress = runAddress; return true; } + // NB: This is *wrong* + /* + Basically, if there is no "JAG" at position $1C, then the long there is the load/start + address in LITTLE ENDIAN. + If "JAG" is present, the the next character ("R" or "L") determines the size of the + JagServer command (2 bytes vs. 4). Following that are the commands themselves; + typically it will either be 2 (load) or 3 (load & run). Command headers go like so: + 2: + Load address (long) + Length (long) + payload + 3: + Load address (long) + Length (long) + Run address (long) + payload + 5: (Reset) + [command only] + 7: (Run at address) + Run address (long) + [no payload] + 9: (Clear memory) + Start address (long) + End address (long) + [no payload] + 10: (Poll for commands) + [command only] + 12: (Load & run user program) + filname, terminated with NULL + [no payload] + $FFFF: (Halt) + [no payload] + */ else if (fileType == JST_JAGSERVER) { - uint32 loadAddress = GET32(buffer, 0x22), runAddress = GET32(buffer, 0x2A); - WriteLog("FILE: Setting up homebrew (Jag Server)... Run address: %08X, length: %08X\n", runAddress, jaguarROMSize - 0x2E); - memcpy(jagMemSpace + loadAddress, buffer + 0x2E, jaguarROMSize - 0x2E); + // This kind of shiaut should be in the detection code below... + // (and now it is! :-) +// if (buffer[0x1C] == 'J' && buffer[0x1D] == 'A' && buffer[0x1E] == 'G') +// { + // Still need to do some checking here for type 2 vs. type 3. This assumes 3 + // Also, JAGR vs. JAGL (word command size vs. long command size) + uint32 loadAddress = GET32(buffer, 0x22), runAddress = GET32(buffer, 0x2A); + WriteLog("FILE: Setting up homebrew (Jag Server)... Run address: $%X, length: $%X\n", runAddress, jaguarROMSize - 0x2E); + memcpy(jagMemSpace + loadAddress, buffer + 0x2E, jaguarROMSize - 0x2E); + delete[] buffer; + jaguarRunAddress = runAddress; + return true; +// } +// else // Special WTFOMGBBQ type here... +// { +// uint32_t loadAddress = (buffer[0x1F] << 24) | (buffer[0x1E] << 16) | (buffer[0x1D] << 8) | buffer[0x1C]; +// WriteLog("FILE: Setting up homebrew (GEMDOS WTFOMGBBQ type)... Run address: $%X, length: $%X\n", loadAddress, jaguarROMSize - 0x20); +// memcpy(jagMemSpace + loadAddress, buffer + 0x20, jaguarROMSize - 0x20); +// delete[] buffer; +// jaguarRunAddress = loadAddress; +// return true; +// } + } + else if (fileType == JST_WTFOMGBBQ) + { + uint32_t loadAddress = (buffer[0x1F] << 24) | (buffer[0x1E] << 16) | (buffer[0x1D] << 8) | buffer[0x1C]; + WriteLog("FILE: Setting up homebrew (GEMDOS WTFOMGBBQ type)... Run address: $%X, length: $%X\n", loadAddress, jaguarROMSize - 0x20); + memcpy(jagMemSpace + loadAddress, buffer + 0x20, jaguarROMSize - 0x20); delete[] buffer; - jaguarRunAddress = runAddress; + jaguarRunAddress = loadAddress; return true; } @@ -352,21 +410,26 @@ uint32 GetFileFromZIP(const char * zipFile, FileType type, uint8 * &buffer) // // Parse the file type based upon file size and/or headers. // -uint32 ParseFileType(uint8 header1, uint8 header2, uint32 size) +uint32 ParseFileType(uint8_t * buffer, uint32 size) { // Check headers first... // ABS/COFF type 1 - if (header1 == 0x60 && header2 == 0x1B) + if (buffer[0] == 0x60 && buffer[1] == 0x1B) return JST_ABS_TYPE1; // ABS/COFF type 2 - if (header1 == 0x01 && header2 == 0x50) + if (buffer[0] == 0x01 && buffer[1] == 0x50) return JST_ABS_TYPE2; - // Jag Server - if (header1 == 0x60 && header2 == 0x1A) - return JST_JAGSERVER; + // Jag Server & other old shite + if (buffer[0] == 0x60 && buffer[1] == 0x1A) + { + if (buffer[0x1C] == 'J' && buffer[0x1D] == 'A' && buffer[0x1E] == 'G') + return JST_JAGSERVER; + else + return JST_WTFOMGBBQ; + } // And if that fails, try file sizes... diff --git a/src/file.h b/src/file.h index a7342fc..b9855bc 100644 --- a/src/file.h +++ b/src/file.h @@ -15,13 +15,13 @@ extern "C" { enum FileType { FT_SOFTWARE=0, FT_EEPROM, FT_LABEL, FT_BOXART, FT_OVERLAY }; // JST = Jaguar Software Type -enum { JST_NONE = 0, JST_ROM, JST_ALPINE, JST_ABS_TYPE1, JST_ABS_TYPE2, JST_JAGSERVER }; +enum { JST_NONE = 0, JST_ROM, JST_ALPINE, JST_ABS_TYPE1, JST_ABS_TYPE2, JST_JAGSERVER, JST_WTFOMGBBQ }; uint32 JaguarLoadROM(uint8 * &rom, char * path); bool JaguarLoadFile(char * path); bool AlpineLoadFile(char * path); uint32 GetFileFromZIP(const char * zipFile, FileType type, uint8 * &buffer); -uint32 ParseFileType(uint8 header1, uint8 header2, uint32 size); +uint32 ParseFileType(uint8_t * buffer, uint32 size); bool HasUniversalHeader(uint8 * rom, uint32 romSize); #ifdef __cplusplus diff --git a/src/gui/app.cpp b/src/gui/app.cpp index 7a905a9..10df86c 100644 --- a/src/gui/app.cpp +++ b/src/gui/app.cpp @@ -11,6 +11,7 @@ // JLH 12/23/2009 Created this file // JLH 01/21/2011 Added SDL initialization // JLH 06/26/2011 Added fix to keep SDL from hijacking main() on win32 +// JLH 05/24/2012 Added option switches // #include "app.h" @@ -21,16 +22,24 @@ #include "mainwin.h" #include "settings.h" #include "types.h" +#include "version.h" + -#ifdef __GCCWIN32__ // Apparently on win32, SDL is hijacking main from Qt. So let's do this: +#ifdef __GCCWIN32__ #undef main #endif +// Function prototypes... +static bool ParseCommandLine(int argc, char * argv[]); +static void ParseOptions(int argc, char * argv[]); + + //hm. :-/ // This is stuff we pass into the mainWindow... bool noUntunedTankPlease = false; bool loadAndGo = false; +bool useLogfile = true; QString filename; // Here's the main application loop--short and simple... @@ -41,55 +50,25 @@ int main(int argc, char * argv[]) // This is stuff we pass into the mainWindow... // noUntunedTankPlease = false; - if (argc > 1) - { - if ((strcmp(argv[1], "--help") == 0) || (strcmp(argv[1], "-h") == 0) - || (strcmp(argv[1], "-?") == 0)) - { - printf("Virtual Jaguar 2.0.0 help\n"); - printf("\n"); - printf("Command line interface is mostly non-functional ATM, but may return if\n" - "there is enough demand for it. :-)\n"); - return 0; - } - - if (strcmp(argv[1], "--yarrr") == 0) - { - printf("\n"); - printf("Shiver me timbers!\n"); - printf("\n"); - return 0; - } - - if ((strcmp(argv[1], "--alpine") == 0) || (strcmp(argv[1], "-a") == 0)) - { - printf("Alpine Mode enabled.\n"); - vjs.hardwareTypeAlpine = true; - } - - if (strcmp(argv[1], "--please-dont-kill-my-computer") == 0) - { - noUntunedTankPlease = true; - } - - // Check for filename - if (argv[1][0] != '-') - { - loadAndGo = true; - filename = argv[1]; - } - } + // Check for options that must be in place be constructing the App object + if (!ParseCommandLine(argc, argv)) + return 0; Q_INIT_RESOURCE(virtualjaguar); // This must the same name as the exe filename //or is it the .qrc filename??? // This is so we can pass this stuff using signal/slot mechanism... +//this is left here to remind me not to try doing this again :-P //ick int id = qRegisterMetaType(); - bool success = (bool)LogInit("virtualjaguar.log"); // Init logfile int retVal = -1; // Default is failure - if (!success) - printf("Failed to open virtualjaguar.log for writing!\n"); + if (useLogfile) + { + bool success = (bool)LogInit("./virtualjaguar.log"); // Init logfile + + if (!success) + printf("Failed to open virtualjaguar.log for writing!\n"); + } // Set up SDL library if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0) @@ -111,11 +90,207 @@ int main(int argc, char * argv[]) return retVal; } -// Main app constructor--we stick globally accessible stuff here... - +// +// Main app constructor--we stick globally accessible stuff here... (?) +// App::App(int argc, char * argv[]): QApplication(argc, argv) { - mainWindow = new MainWin(filename); + bool loadAndGo = !filename.isEmpty(); + + mainWindow = new MainWin(loadAndGo); mainWindow->plzDontKillMyComputer = noUntunedTankPlease; + ParseOptions(argc, argv); // Override defaults with command line (if any) + mainWindow->SyncUI(); + + if (loadAndGo) + mainWindow->LoadFile(filename); + mainWindow->show(); } + + +// +// Here we parse out stuff that needs to be looked at *before* we construct the +// App object. +// +bool ParseCommandLine(int argc, char * argv[]) +{ + for(int i=1; i] [switches]\n" + "\n" + " Option Description\n" + " ---------------- -----------------------------------\n" + " Name of file to autoload\n" + " --alpine -a Put Virtual Jaguar into Alpine mode\n" + " --pal -p PAL mode\n" + " --ntsc -n NTSC mode\n" + " --bios -b Boot using Jagaur BIOS\n" + " --no-bios Do not use Jaguar BIOS\n" + " --gpu -g Enable GPU\n" + " --no-gpu Disable GPU\n" + " --dsp -d Enable DSP\n" + " --no-dsp Disable DSP\n" + " --fullscreen -f Start in full screen mode\n" + " --blur -B Enable GL bilinear filter\n" + " --no-blur Disable GL bilinear filtering\n" + " --log -l Create and use log file\n" + " --no-log Do not use log file\n" + " --help -h Show this message\n" + "\n" + "Invoking Virtual Jagaur with no filename will cause it to boot up\n" + "with the VJ GUI.\n" + "\n"); + return false; + } + + if (strcmp(argv[i], "--yarrr") == 0) + { + printf("\n"); + printf("Shiver me timbers!\n"); + printf("\n"); + return false; + } + + if ((strcmp(argv[i], "--alpine") == 0) || (strcmp(argv[i], "-a") == 0)) + { + printf("Alpine Mode enabled.\n"); + vjs.hardwareTypeAlpine = true; + } + + if (strcmp(argv[i], "--please-dont-kill-my-computer") == 0) + { + noUntunedTankPlease = true; + } + + if ((strcmp(argv[i], "--log") == 0) || (strcmp(argv[i], "-l") == 0)) + { + useLogfile = true; + } + + if (strcmp(argv[i], "--no-log") == 0) + { + useLogfile = false; + } + + // Check for filename + if (argv[i][0] != '-') + { + loadAndGo = true; + filename = argv[i]; + } + } + + return true; +} + + +// +// This is to override settings loaded from the config file. +// Note that settings set here will become the new defaults! +// +void ParseOptions(int argc, char * argv[]) +{ + for(int i=1; i -#endif +//#endif // The way BSNES controls things is by setting a timer with a zero // timeout, sleeping if not emulating anything. Seems there has to be a @@ -71,11 +72,16 @@ // We'll make the VJ core modular so that it doesn't matter what GUI is in // use, we can drop it in anywhere and use it as-is. -MainWin::MainWin(QString filenameToRun): running(true), powerButtonOn(false), +//MainWin::MainWin(QString filenameToRun): running(true), powerButtonOn(false), +MainWin::MainWin(bool autoRun): running(true), powerButtonOn(false), showUntunedTankCircuit(true), cartridgeLoaded(false), CDActive(false), //, alpineLoadSuccessful(false), - pauseForFileSelector(false), loadAndGo(false), plzDontKillMyComputer(false) +// pauseForFileSelector(false), loadAndGo(false), plzDontKillMyComputer(false) + pauseForFileSelector(false), loadAndGo(autoRun), plzDontKillMyComputer(false) { + for(int i=0; i<8; i++) + keyHeld[i] = false; + videoWidget = new GLWidget(this); setCentralWidget(videoWidget); setWindowIcon(QIcon(":/res/vj-icon.png")); @@ -230,16 +236,6 @@ MainWin::MainWin(QString filenameToRun): running(true), powerButtonOn(false), ReadSettings(); - // Set toolbar buttons/menus based on settings read in (sync the UI)... - blurAct->setChecked(vjs.glFilter); - x1Act->setChecked(zoomLevel == 1); - x2Act->setChecked(zoomLevel == 2); - x3Act->setChecked(zoomLevel == 3); -// running = powerAct->isChecked(); - ntscAct->setChecked(vjs.hardwareTypeNTSC); - palAct->setChecked(!vjs.hardwareTypeNTSC); - powerAct->setIcon(vjs.hardwareTypeNTSC ? powerRed : powerGreen); - // Do this in case original size isn't correct (mostly for the first-run case) ResizeMainWindow(); @@ -263,13 +259,14 @@ MainWin::MainWin(QString filenameToRun): running(true), powerButtonOn(false), memcpy(jagMemSpace + 0xE00000, jaguarBootROM, 0x20000); // Use the stock BIOS // Check for filename passed in on the command line... - if (!filenameToRun.isEmpty()) +// if (!filenameToRun.isEmpty()) + if (autoRun) { - loadAndGo = true; +// loadAndGo = true; // Attempt to load/run the file the user passed in... - LoadSoftware(filenameToRun); -// memcpy(jagMemSpace + 0xE00000, jaguarBootROM, 0x20000); // Use the stock BIOS - // Prevent the scanner from running... +// LoadSoftware(filenameToRun); +//// memcpy(jagMemSpace + 0xE00000, jaguarBootROM, 0x20000); // Use the stock BIOS + // Prevent the file scanner from running... return; } @@ -302,13 +299,37 @@ MainWin::MainWin(QString filenameToRun): running(true), powerButtonOn(false), filePickWin->ScanSoftwareFolder(allowUnknownSoftware); } + +void MainWin::LoadFile(QString file) +{ + LoadSoftware(file); +} + + +void MainWin::SyncUI(void) +{ + // Set toolbar buttons/menus based on settings read in (sync the UI)... + blurAct->setChecked(vjs.glFilter); + x1Act->setChecked(zoomLevel == 1); + x2Act->setChecked(zoomLevel == 2); + x3Act->setChecked(zoomLevel == 3); +// running = powerAct->isChecked(); + ntscAct->setChecked(vjs.hardwareTypeNTSC); + palAct->setChecked(!vjs.hardwareTypeNTSC); + powerAct->setIcon(vjs.hardwareTypeNTSC ? powerRed : powerGreen); +} + + void MainWin::closeEvent(QCloseEvent * event) { JaguarDone(); - WriteSettings(); +// This should only be done by the config dialog +// WriteSettings(); + WriteUISettings(); event->accept(); // ignore() if can't close for some reason } + void MainWin::keyPressEvent(QKeyEvent * e) { // We ignore the Alt key for now, since it causes problems with the GUI @@ -321,6 +342,7 @@ void MainWin::keyPressEvent(QKeyEvent * e) HandleKeys(e, true); } + void MainWin::keyReleaseEvent(QKeyEvent * e) { // We ignore the Alt key for now, since it causes problems with the GUI @@ -333,12 +355,18 @@ void MainWin::keyReleaseEvent(QKeyEvent * e) HandleKeys(e, false); } + void MainWin::HandleKeys(QKeyEvent * e, bool state) { + enum { P1LEFT = 0, P1RIGHT, P1UP, P1DOWN, P2LEFT, P2RIGHT, P2UP, P2DOWN }; // We kill bad key combos here, before they can get to the emulator... // This also kills the illegal instruction problem that cropped up in Rayman! // May want to do this by killing the old one instead of ignoring the new one... // Seems to work better that way... + +// The problem with this approach is that it causes bad results because it doesn't do +// any checking of previous states. Need to come up with something better because this +// causes problems where the keyboard acts as if it were unresponsive. :-P #if 0 if ((e->key() == vjs.p1KeyBindings[BUTTON_L] && joypad_0_buttons[BUTTON_R]) || (e->key() == vjs.p1KeyBindings[BUTTON_R] && joypad_0_buttons[BUTTON_L]) @@ -346,6 +374,7 @@ void MainWin::HandleKeys(QKeyEvent * e, bool state) || (e->key() == vjs.p1KeyBindings[BUTTON_D] && joypad_0_buttons[BUTTON_U])) return; #else +#if 0 if (e->key() == (int)vjs.p1KeyBindings[BUTTON_L] && joypad_0_buttons[BUTTON_R]) joypad_0_buttons[BUTTON_R] = 0; if (e->key() == (int)vjs.p1KeyBindings[BUTTON_R] && joypad_0_buttons[BUTTON_L]) @@ -363,6 +392,33 @@ void MainWin::HandleKeys(QKeyEvent * e, bool state) joypad_1_buttons[BUTTON_D] = 0; if (e->key() == (int)vjs.p2KeyBindings[BUTTON_D] && joypad_1_buttons[BUTTON_U]) joypad_1_buttons[BUTTON_U] = 0; +#else +//hrm, this still has sticky state problems... Ugh! + // First, settle key states... + if (e->key() == (int)vjs.p1KeyBindings[BUTTON_L]) + keyHeld[P1LEFT] = state; + else if (e->key() == (int)vjs.p1KeyBindings[BUTTON_R]) + keyHeld[P1RIGHT] = state; + else if (e->key() == (int)vjs.p1KeyBindings[BUTTON_U]) + keyHeld[P1UP] = state; + else if (e->key() == (int)vjs.p1KeyBindings[BUTTON_D]) + keyHeld[P1DOWN] = state; + else if (e->key() == (int)vjs.p2KeyBindings[BUTTON_L]) + keyHeld[P2LEFT] = state; + else if (e->key() == (int)vjs.p2KeyBindings[BUTTON_R]) + keyHeld[P2RIGHT] = state; + else if (e->key() == (int)vjs.p2KeyBindings[BUTTON_U]) + keyHeld[P2UP] = state; + else if (e->key() == (int)vjs.p2KeyBindings[BUTTON_D]) + keyHeld[P2DOWN] = state; + + // Next, check for conflicts and bail out if there are any... + if ((keyHeld[P1LEFT] && keyHeld[P1RIGHT]) + || (keyHeld[P1UP] && keyHeld[P1DOWN]) + || (keyHeld[P2LEFT] && keyHeld[P2RIGHT]) + || (keyHeld[P2UP] && keyHeld[P2DOWN])) + return; +#endif #endif // No bad combos exist, let's stuff the emulator key buffers...! @@ -380,10 +436,12 @@ void MainWin::HandleKeys(QKeyEvent * e, bool state) } } + void MainWin::Open(void) { } + void MainWin::Configure(void) { // Call the configuration dialog and update settings @@ -450,6 +508,7 @@ void MainWin::Configure(void) WriteSettings(); } + // // Here's the main emulator loop // @@ -484,6 +543,7 @@ void MainWin::Timer(void) videoWidget->updateGL(); } + void MainWin::TogglePowerState(void) { powerButtonOn = !powerButtonOn; @@ -528,6 +588,7 @@ void MainWin::TogglePowerState(void) } } + void MainWin::ToggleRunState(void) { running = !running; @@ -546,55 +607,67 @@ void MainWin::ToggleRunState(void) } } + void MainWin::SetZoom100(void) { zoomLevel = 1; ResizeMainWindow(); } + void MainWin::SetZoom200(void) { zoomLevel = 2; ResizeMainWindow(); } + void MainWin::SetZoom300(void) { zoomLevel = 3; ResizeMainWindow(); } + void MainWin::SetNTSC(void) { powerAct->setIcon(powerRed); timer->setInterval(16); vjs.hardwareTypeNTSC = true; ResizeMainWindow(); + WriteSettings(); } + void MainWin::SetPAL(void) { powerAct->setIcon(powerGreen); timer->setInterval(20); vjs.hardwareTypeNTSC = false; ResizeMainWindow(); + WriteSettings(); } + void MainWin::ToggleBlur(void) { vjs.glFilter = !vjs.glFilter; + WriteSettings(); } + void MainWin::ShowAboutWin(void) { aboutWin->show(); } + void MainWin::ShowHelpWin(void) { helpWin->show(); } + void MainWin::InsertCart(void) { // If the emulator is running, we pause it here and unpause it later @@ -608,6 +681,7 @@ void MainWin::InsertCart(void) filePickWin->show(); } + void MainWin::Unpause(void) { // Here we unpause the emulator if it was paused when we went into the file selector @@ -621,6 +695,7 @@ void MainWin::Unpause(void) } } + void MainWin::LoadSoftware(QString file) { running = false; // Prevent bad things(TM) from happening... @@ -648,6 +723,7 @@ void MainWin::LoadSoftware(QString file) } } + void MainWin::ToggleCDUsage(void) { CDActive = !CDActive; @@ -670,6 +746,7 @@ void MainWin::ToggleCDUsage(void) #endif } + void MainWin::FrameAdvance(void) { //printf("Frame Advance...\n"); @@ -678,6 +755,7 @@ void MainWin::FrameAdvance(void) videoWidget->updateGL(); } + void MainWin::ResizeMainWindow(void) { videoWidget->setFixedSize(zoomLevel * 320, zoomLevel * (vjs.hardwareTypeNTSC ? 240 : 256)); @@ -691,6 +769,7 @@ void MainWin::ResizeMainWindow(void) } } + #warning "!!! Need to check the window geometry to see if the positions are legal !!!" // i.e., someone could drag it to another screen, close it, then disconnect that screen void MainWin::ReadSettings(void) @@ -781,6 +860,7 @@ WriteLog("Pipelined DSP = %s\n", (vjs.usePipelinedDSP ? "ON" : "off")); vjs.p2KeyBindings[BUTTON_s] = settings.value("p2k_star", Qt::Key_Asterisk).toInt(); } + void MainWin::WriteSettings(void) { QSettings settings("Underground Software", "Virtual Jaguar"); @@ -856,3 +936,14 @@ void MainWin::WriteSettings(void) settings.setValue("p2k_pound", vjs.p2KeyBindings[BUTTON_d]); settings.setValue("p2k_star", vjs.p2KeyBindings[BUTTON_s]); } + + +void MainWin::WriteUISettings(void) +{ + QSettings settings("Underground Software", "Virtual Jaguar"); + settings.setValue("pos", pos()); + settings.setValue("size", size()); + settings.setValue("cartLoadPos", filePickWin->pos()); + + settings.setValue("zoom", zoomLevel); +} diff --git a/src/gui/mainwin.h b/src/gui/mainwin.h index d9d0447..ece5324 100644 --- a/src/gui/mainwin.h +++ b/src/gui/mainwin.h @@ -23,7 +23,10 @@ class MainWin: public QMainWindow Q_OBJECT public: - MainWin(QString); +// MainWin(QString); + MainWin(bool); + void LoadFile(QString); + void SyncUI(void); protected: void closeEvent(QCloseEvent *); @@ -55,6 +58,7 @@ class MainWin: public QMainWindow void ResizeMainWindow(void); void ReadSettings(void); void WriteSettings(void); + void WriteUISettings(void); // public: GLWidget * videoWidget; @@ -72,6 +76,7 @@ class MainWin: public QMainWindow // bool alpineLoadSuccessful; bool pauseForFileSelector; bool loadAndGo; + bool keyHeld[8]; public: bool plzDontKillMyComputer; private: diff --git a/src/jaguar.cpp b/src/jaguar.cpp index a943768..de5b5a8 100644 --- a/src/jaguar.cpp +++ b/src/jaguar.cpp @@ -1900,8 +1900,8 @@ void JaguarDone(void) JaguarDasm(0x802000, 6000); WriteLog("\n");//*/ #endif -/* WriteLog("\n\nM68000 disassembly at $4000...\n"); - JaguarDasm(0x4000, 10000); +/* WriteLog("\n\nM68000 disassembly at $6004...\n"); + JaguarDasm(0x6004, 10000); WriteLog("\n");//*/ // WriteLog("\n\nM68000 disassembly at $802000...\n"); // JaguarDasm(0x802000, 0x1000); @@ -1951,16 +1951,6 @@ void JaguarExecuteNew(void) if (vjs.GPUEnabled) GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); -#ifndef NEW_DAC_CODE - if (vjs.DSPEnabled) - { - if (vjs.usePipelinedDSP) - DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Pipelined DSP execution (3 stage)... - else - DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Ordinary non-pipelined DSP - } -#endif - HandleNextEvent(); } while (!frameDone); diff --git a/src/log.cpp b/src/log.cpp index d21ea68..2782c93 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -29,7 +29,7 @@ static uint32 logSize = 0; int LogInit(const char * path) { - log_stream = fopen(path, "wrt"); + log_stream = fopen(path, "w"); if (log_stream == NULL) return 0; @@ -67,12 +67,11 @@ void WriteLog(const char * text, ...) if (logSize > MAX_LOG_SIZE) { + // Instead of dumping out, we just close the file and ignore any more output. fflush(log_stream); fclose(log_stream); - // Instead of dumping out, we just close the file and ignore any more output. log_stream = NULL; -// exit(1); - }//*/ + } va_end(arg); fflush(log_stream); // Make sure that text is written! diff --git a/src/m68000/Makefile b/src/m68000/Makefile index fd771ae..eac45ba 100644 --- a/src/m68000/Makefile +++ b/src/m68000/Makefile @@ -13,7 +13,9 @@ AR := ar ARFLAGS := -rs # Note that we use optimization level 2 instead of 3--3 doesn't seem to gain much over 2 -CFLAGS := -MMD -O2 -ffast-math -fomit-frame-pointer -g +#CFLAGS := -MMD -O2 -ffast-math -fomit-frame-pointer -g +CFLAGS ?= -O2 -ffast-math -fomit-frame-pointer -g +GCC_DEPS = -MMD INCS := -I. -I./obj `sdl-config --cflags` @@ -26,8 +28,6 @@ OBJS = \ obj/m68kinterface.o \ obj/m68kdasm.o -# obj/newcpu.o \ - # Targets for convenience sake, not "real" targets .PHONY: clean @@ -45,11 +45,13 @@ obj: obj/%.o: %.c @echo -e "\033[01;33m***\033[00;32m Compiling $<...\033[00m" - @$(CC) $(CFLAGS) $(INCS) -c $< -o $@ +# @$(CC) $(CFLAGS) $(INCS) -c $< -o $@ + @$(CC) $(GCC_DEPS) $(CFLAGS) $(INCS) -c $< -o $@ obj/%.o: obj/%.c @echo -e "\033[01;33m***\033[00;32m Compiling $<...\033[00m" - @$(CC) $(CFLAGS) $(INCS) -c $< -o $@ +# @$(CC) $(CFLAGS) $(INCS) -c $< -o $@ + @$(CC) $(GCC_DEPS) $(CFLAGS) $(INCS) -c $< -o $@ # Generated code @@ -60,7 +62,8 @@ obj/cpustbl.c: obj/gencpu obj/gencpu: obj/cpudefs.c @echo -e "\033[01;33m***\033[00;32m Generating gencpu...\033[00m" - @$(CC) $(CFLAGS) gencpu.c readcpu.c obj/cpudefs.c -o obj/gencpu -I. -I./obj +# @$(CC) $(CFLAGS) gencpu.c readcpu.c obj/cpudefs.c -o obj/gencpu -I. -I./obj + @$(CC) $(GCC_DEPS) $(CFLAGS) gencpu.c readcpu.c obj/cpudefs.c -o obj/gencpu -I. -I./obj obj/cpudefs.c: obj/build68k @echo -e "\033[01;33m***\033[00;32m Generating cpudefs.c...\033[00m" @@ -68,7 +71,8 @@ obj/cpudefs.c: obj/build68k obj/build68k: build68k.c @echo -e "\033[01;33m***\033[00;32m Compiling build68k.c...\033[00m" - @$(CC) $(CFLAGS) build68k.c -o obj/build68k +# @$(CC) $(CFLAGS) build68k.c -o obj/build68k + @$(CC) $(GCC_DEPS) $(CFLAGS) build68k.c -o obj/build68k clean: @echo -ne "\033[01;33m***\033[00;32m Cleaning out the garbage...\033[00m" diff --git a/src/virtualjaguar.cpp b/src/virtualjaguar.cpp index 8700c35..95e81c3 100644 --- a/src/virtualjaguar.cpp +++ b/src/virtualjaguar.cpp @@ -146,7 +146,7 @@ int main_old(int argc, char * argv[]) printf(" -ntsc : Force VJ to NTSC mode \n"); printf("\nInvoking Virtual Jagaur with no ROM file will cause it to boot up\n"); printf("with the VJ GUI.\n"); - return 1; + return 1; } } -- 2.37.2