From: Shamus Hammons Date: Fri, 3 Oct 2003 07:55:30 +0000 (+0000) Subject: Changes for 1.0.7 update X-Git-Tag: 1.0.7~99 X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a1ad40785ac6d954051e4e5882436da9a58cc3a6;p=virtualjaguar Changes for 1.0.7 update --- diff --git a/docs/WHATSNEW b/docs/WHATSNEW index 96f78a2..6ed6f10 100644 --- a/docs/WHATSNEW +++ b/docs/WHATSNEW @@ -1,6 +1,21 @@ +Virtual Jaguar v1.0.7 GCC/SDL +----------------------------- + +* Better GUI support. Most options in the GUI work now, and more are expected + to be functional in the near future. [Shamus] +* Fixed a few lingering blitter bugs (there are more to be found). This fixes + a few glitches in Cybermorph and Alien vs Predator. [Shamus] +* Fixed an Object Processor scaled bitmap bug that caused incorrect + positioning of scaled bitmaps that started outside the line buffer, and + also fixed a problem that caused the OP to hang in certain situations. This + fixes Bubsy, International Sensible Soccer, and probably a few others. + [Shamus] + + Virtual Jaguar v1.0.6 GCC/SDL ----------------------------- + * Added support for gzipped ROM files. [Adam Green] * Added OpenGL support. Because of this, aspect ratios in the various graphic modes should be correct now. Thanks goes to Niels for enlightenment diff --git a/src/blitter.cpp b/src/blitter.cpp index 857c8d2..9a03a25 100644 --- a/src/blitter.cpp +++ b/src/blitter.cpp @@ -1,7 +1,7 @@ // // Blitter core // -// by cal2 +// by Cal2 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS) // Cleanups/fixes by James L. Hammons // @@ -442,9 +442,10 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: // if (dstdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode)) inhibit = 1; } + // This is DEFINITELY WRONG - if (a1_phrase_mode || a2_phrase_mode) - inhibit = !inhibit; +// if (a1_phrase_mode || a2_phrase_mode) +// inhibit = !inhibit; } if (CLIPA1) @@ -593,8 +594,10 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: // if (dstdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode)) inhibit = 1; } - if (a1_phrase_mode || a2_phrase_mode) - inhibit =! inhibit; + +// This is DEFINITELY WRONG +// if (a1_phrase_mode || a2_phrase_mode) +// inhibit = !inhibit; } if (CLIPA1) @@ -693,6 +696,28 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: } } + //New: Phrase mode taken into account! :-p + if (a1_phrase_mode) + { + // Bump the pointer to the next phrase boundary + // Even though it works, this is crappy... Clean it up! + uint32 size = 64 / a1_psize; + uint32 newx = (a1_x >> 16) / size; + uint32 newxrem = (a1_x >> 16) % size; + a1_x &= 0x0000FFFF; + a1_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16; + } + if (a2_phrase_mode) + { + // Bump the pointer to the next phrase boundary + // Even though it works, this is crappy... Clean it up! + uint32 size = 64 / a1_psize; + uint32 newx = (a2_x >> 16) / size; + uint32 newxrem = (a2_x >> 16) % size; + a2_x &= 0x0000FFFF; + a2_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16; + } + a1_x += a1_step_x; a1_y += a1_step_y; a2_x += a2_step_x; @@ -839,7 +864,7 @@ void blitter_blit(uint32 cmd) break; //This really isn't a valid bit combo for A2... Shouldn't this cause the blitter to just say no? case XADDINC: -WriteLog("BLIT: Asked to used invalid bit combo for A2...\n"); +WriteLog("BLIT: Asked to use invalid bit combo (XADDINC) for A2...\n"); // add the contents of the increment register // since there is no register for a2 we just add 1 //Let's do nothing, since it's not listed as a valid bit combo... @@ -1048,6 +1073,104 @@ WriteLog("BLIT: Asked to used invalid bit combo for A2...\n"); } #endif +//NOTE: Pitch is ignored! + +//This *might* be the altimeter blits (they are)... +//On captured screen, x-pos for black (inner) is 259, for pink is 257 +//Black is short by 3, pink is short by 1... +/* +Blit! (00110000 <- 000BF010) count: 9 x 31, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200] + CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: + A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 262/124, A2 x/y: 128/0 +Blit! (00110000 <- 000BF010) count: 5 x 38, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200] + CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: + A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 264/117, A2 x/y: 407/0 + +Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200] + CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: + A1 step values: -10 (X), 1 (Y) + A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 262/132, A2 x/y: 129/0 +Blit! (00110000 <- 000BF010) count: 5 x 27, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200] + CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: + A1 step values: -8 (X), 1 (Y) + A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD + A1 x/y: 264/128, A2 x/y: 336/0 + + 264v vCursor ends up here... + xxxxx...` + 111122223333 + +262v vCursor ends up here... + xxxxxxxxx.' + 1111222233334444 + +Fixed! Now for more: + +; This looks like the ship icon in the upper left corner... + +Blit! (00110000 <- 0010B2A8) count: 11 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609] + CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN + A1 step values: -12 (X), 1 (Y) + A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A1 x/y: 20/24, A2 x/y: 5780/0 + +Also fixed! + +More (not sure this is a blitter problem as much as it's a GPU problem): +All but the "M" are trashed... +This does *NOT* look like a blitter problem, as it's rendering properly... + +; D + +Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609] + CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN + A1 step values: -14 (X), 1 (Y) + A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A1 x/y: 134/144, A2 x/y: 2516/0 +;129,146: +5,-2 + +; E + +Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609] + CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN + A1 step values: -13 (X), 1 (Y) + A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A1 x/y: 147/144, A2 x/y: 2660/0 + +; M + +Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609] + CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN + A1 step values: -12 (X), 1 (Y) + A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A1 x/y: 160/144, A2 x/y: 3764/0 + +; O + +Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609] + CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN + A1 step values: -15 (X), 1 (Y) + A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF] + A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD + A1 x/y: 173/144, A2 x/y: 4052/0 + +*/ extern int blit_start_log; extern int op_start_log; if (blit_start_log) @@ -1080,10 +1203,11 @@ if (blit_start_log) WriteLog("op: %s ", opStr[(cmd >> 21) & 0x0F]); WriteLog("ctrl: %s%s%s%s%s%s\n", (cmd & 0x02000000 ? "CMPDST " : ""), (cmd & 0x04000000 ? "BCOMPEN " : ""), (cmd & 0x08000000 ? "DCOMPEN " : ""), (cmd & 0x10000000 ? "BKGWREN " : ""), (cmd & 0x20000000 ? "BUSHI " : ""), (cmd & 0x40000000 ? "SRCSHADE" : "")); + if (UPDA1) + WriteLog(" A1 step values: %d (X), %d (Y)\n", a1_step_x >> 16, a1_step_y >> 16); + if (UPDA2) - { WriteLog(" A2 step values: %d (X), %d (Y) [mask (%sused): %08X - %08X/%08X]\n", a2_step_x >> 16, a2_step_y >> 16, (a2f & 0x8000 ? "" : "un"), REG(A2_MASK), a2_mask_x, a2_mask_y); - } WriteLog(" A1 -> pitch: %d phrases, depth: %s, z-off: %d, width: %d (%02X), addctl: %s %s %s %s\n", 1 << p1, bppStr[d1], zo1, iw1, w1, ctrlStr[ac1&0x03], (ac1&0x04 ? "YADD1" : "YADD0"), (ac1&0x08 ? "XSIGNSUB" : "XSIGNADD"), (ac1&0x10 ? "YSIGNSUB" : "YSIGNADD")); WriteLog(" A2 -> pitch: %d phrases, depth: %s, z-off: %d, width: %d (%02X), addctl: %s %s %s %s\n", 1 << p2, bppStr[d2], zo2, iw2, w2, ctrlStr[ac2&0x03], (ac2&0x04 ? "YADD1" : "YADD0"), (ac2&0x08 ? "XSIGNSUB" : "XSIGNADD"), (ac2&0x10 ? "YSIGNSUB" : "YSIGNADD")); diff --git a/src/dac.cpp b/src/dac.cpp index 54bc50b..e85d858 100644 --- a/src/dac.cpp +++ b/src/dac.cpp @@ -1,7 +1,7 @@ // // DAC (really, Synchronous Serial Interface) Handler // -// by cal2 +// Original by Cal2 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS) // Rewritten by James L. Hammons // @@ -13,7 +13,7 @@ //#define DEBUG_DAC -#define BUFFER_SIZE 0x8000 // Make the DAC buffers 32K x 16 bits +#define BUFFER_SIZE 0x10000 // Make the DAC buffers 64K x 16 bits // Jaguar memory locations @@ -40,7 +40,7 @@ void SDLSoundCallback(void * userdata, Uint8 * buffer, int length); int GetCalculatedFrequency(void); // -// Initialize the SDL sound system (?) (!) +// Initialize the SDL sound system // void DACInit(void) { @@ -49,7 +49,8 @@ void DACInit(void) 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 = 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.callback = SDLSoundCallback; if (SDL_OpenAudio(&desired, NULL) < 0) // NULL means SDL guarantees what we want @@ -73,7 +74,7 @@ void DACReset(void) } // -// Close down the SDL sound subsystem (?) (!) +// Close down the SDL sound subsystem // void DACDone(void) { @@ -120,15 +121,15 @@ void SDLSoundCallback(void * userdata, Uint8 * buffer, int length) // 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: %u/%u, Left/RightFIFOTailPtr: %u/%u\n", LeftFIFOHeadPtr, RightFIFOHeadPtr, LeftFIFOTailPtr, RightFIFOTailPtr); } //Hmm. Seems that the SDL buffer isn't being starved by the DAC buffer... @@ -141,7 +142,6 @@ void SDLSoundCallback(void * userdata, Uint8 * buffer, int length) // int GetCalculatedFrequency(void) { -// extern bool hardwareTypeNTSC; int systemClockFrequency = (vjs.hardwareTypeNTSC ? RISC_CLOCK_RATE_NTSC : RISC_CLOCK_RATE_PAL); // We divide by 32 here in order to find the frequency of 32 SCLKs in a row (transferring @@ -163,41 +163,47 @@ void DACWriteWord(uint32 offset, uint16 data) { if (offset == LTXD + 2) { - if (LeftFIFOTailPtr + 2 != LeftFIFOHeadPtr) - { - 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; -// Aaron's code does this, but I don't know why... -//Flipping this bit makes the audio MUCH louder. Need to look at the amplitude of the -//waveform to see if any massaging is needed here... -//Looks like a cheap & dirty way to convert signed samples to unsigned... -// DACBuffer[LeftFIFOTailPtr] = data ^ 0x8000; - SDL_UnlockAudio(); - } -#ifdef DEBUG_DAC - else - WriteLog("DAC: Ran into FIFO's left tail pointer!\n"); -#endif + // 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... + while ((LeftFIFOTailPtr + 2) & (BUFFER_SIZE - 1) == LeftFIFOHeadPtr); + + 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(); } else if (offset == RTXD + 2) { - if (RightFIFOTailPtr + 2 != RightFIFOHeadPtr) - { - SDL_LockAudio(); - RightFIFOTailPtr = (RightFIFOTailPtr + 2) % BUFFER_SIZE; - DACBuffer[RightFIFOTailPtr] = data; -// Aaron's code does this, but I don't know why... -// DACBuffer[RightFIFOTailPtr] = data ^ 0x8000; - SDL_UnlockAudio(); - } -#ifdef DEBUG_DAC + // Spin until buffer has been drained (for too fast processors!)... +//uint32 spin = 0; + while ((RightFIFOTailPtr + 2) & (BUFFER_SIZE - 1) == RightFIFOHeadPtr); +/* { +spin++; +if (spin == 0x10000000) +{ + WriteLog("\nStuck in right DAC spinlock! Tail=%u, Head=%u\nAborting!\n", RightFIFOTailPtr, RightFIFOHeadPtr); + log_done(); + exit(0); +} + }*/ + +//This is wrong if (RightFIFOTailPtr + 2 != RightFIFOHeadPtr) +// { + 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 { diff --git a/src/eeprom.cpp b/src/eeprom.cpp index 1e422e4..517a269 100644 --- a/src/eeprom.cpp +++ b/src/eeprom.cpp @@ -39,14 +39,13 @@ uint16 jerry_ee_data = 0; uint16 jerry_ee_data_cnt = 16; uint16 jerry_writes_enabled = 0; uint16 jerry_ee_direct_jump = 0; -FILE * jerry_ee_fp; static char eeprom_filename[MAX_PATH]; static bool foundEEPROM = false; void eeprom_init(void) { sprintf(eeprom_filename, "%s%08X.eep", vjs.EEPROMPath, (unsigned int)jaguar_mainRom_crc32); - jerry_ee_fp = fopen(eeprom_filename, "rb"); + FILE * jerry_ee_fp = fopen(eeprom_filename, "rb"); if (jerry_ee_fp) { fread(eeprom_ram, 1, 128, jerry_ee_fp); @@ -55,12 +54,7 @@ void eeprom_init(void) foundEEPROM = true; } else - { - WriteLog("EEPROM: Creating %s\n", eeprom_filename); - jerry_ee_fp = fopen(eeprom_filename, "wb"); - if (jerry_ee_fp == NULL) - WriteLog("EEPROM: Could not open/create %s!\n", eeprom_filename); - } + WriteLog("EEPROM: Could not open file \"%s\"!\n", eeprom_filename); } void eeprom_reset(void) @@ -71,13 +65,18 @@ void eeprom_reset(void) void eeprom_done(void) { -//Actually, is this necessary now that we write the file immediately upon write to EEPROM? -// EEPROMSave(); } void EEPROMSave(void) { - jerry_ee_fp = fopen(eeprom_filename, "wb"); + FILE * jerry_ee_fp = fopen(eeprom_filename, "wb"); + + if (jerry_ee_fp == NULL) + { + WriteLog("EEPROM: Could not create file \"%s!\"\n", eeprom_filename); + return; + } + fwrite(eeprom_ram, 1, 128, jerry_ee_fp); fclose(jerry_ee_fp); } diff --git a/src/gui.cpp b/src/gui.cpp index 9a96930..e8947dd 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -15,19 +15,33 @@ #include "tom.h" #include "video.h" #include "font1.h" +#include "crc32.h" +#include "zlib.h" +#include "unzip.h" #include "gui.h" using namespace std; // For STL stuff // Private function prototypes +class Window; // Forward declaration... + void DrawTransparentBitmap(int16 * screen, uint32 x, uint32 y, uint16 * bitmap); void DrawStringTrans(int16 * screen, uint32 x, uint32 y, uint16 color, uint8 opacity, const char * text, ...); void DrawStringOpaque(int16 * screen, uint32 x, uint32 y, uint16 color1, uint16 color2, const char * text, ...); -void LoadROM(void); -void RunEmu(void); -void Quit(void); -void About(void); +Window * LoadROM(void); +Window * ResetJaguar(void); +Window * RunEmu(void); +Window * Quit(void); +Window * About(void); + +int gzfilelength(gzFile gd); + +// External variables + +extern uint8 * jaguar_mainRam; +extern uint8 * jaguar_bootRom; +extern uint8 * jaguar_mainRom; // Local global variables @@ -73,12 +87,42 @@ uint16 closeBox[] = { 0x0000,0x0217,0x0217,0x0217,0x0217,0x0217,0x0000 // ..... }; +uint16 upArrowBox[] = { + 8, 8, + + 0x4B5E,0x4B5E,0x4B5E,0x4B5E,0x4B5E,0x4B5E,0x4B5E,0x4B5E, // ++++++++ + 0x4B5E,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0217, // + @@ . + 0x4B5E,0x0000,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x0000,0x0217, // + @@@@ . + 0x4B5E,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x0217, // +@@@@@@. + 0x4B5E,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0217, // + @@ . + 0x4B5E,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0217, // + @@ . + 0x4B5E,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0217, // + @@ . + 0x0217,0x0217,0x0217,0x0217,0x0217,0x0217,0x0217,0x0217 // ........ +}; + +uint16 downArrowBox[] = { + 8, 8, + + 0x4B5E,0x4B5E,0x4B5E,0x4B5E,0x4B5E,0x4B5E,0x4B5E,0x4B5E, // ++++++++ + 0x4B5E,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0217, // + @@ . + 0x4B5E,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0217, // + @@ . + 0x4B5E,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0217, // + @@ . + 0x4B5E,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x0217, // +@@@@@@. + 0x4B5E,0x0000,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x0000,0x0217, // + @@@@ . + 0x4B5E,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0217, // + @@ . + 0x0217,0x0217,0x0217,0x0217,0x0217,0x0217,0x0217,0x0217 // ........ +}; + char separator[] = "--------------------------------------------------------"; +uint16 background[1280 * 240]; + // // Local GUI classes // +enum { WINDOW_CLOSE, MENU_ITEM_CHOSEN }; + class Element { public: @@ -88,6 +132,7 @@ class Element virtual void HandleMouseMove(uint32 x, uint32 y) = 0; virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) = 0; virtual void Draw(uint32, uint32) = 0; + virtual void Notify(Element *) = 0; //Needed? virtual ~Element() = 0; //We're not allocating anything in the base class, so the answer would be NO. bool Inside(uint32 x, uint32 y); @@ -116,24 +161,35 @@ class Button: public Element public: Button(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h), activated(false), clicked(false), inside(false), fgColor(0xFFFF), - bgColor(0x03E0), pic(NULL) {} + bgColor(0x03E0), pic(NULL), elementToTell(NULL) {} Button(uint32 x, uint32 y, uint32 w, uint32 h, uint16 * p): Element(x, y, w, h), activated(false), clicked(false), inside(false), fgColor(0xFFFF), - bgColor(0x03E0), pic(p) {} + bgColor(0x03E0), pic(p), elementToTell(NULL) {} + Button(uint32 x, uint32 y, uint16 * p): Element(x, y, 0, 0), + activated(false), clicked(false), inside(false), fgColor(0xFFFF), + bgColor(0x03E0), pic(p), elementToTell(NULL) + { if (pic) extents.w = pic[0], extents.h = pic[1]; } Button(uint32 x, uint32 y, uint32 w, uint32 h, string s): Element(x, y, w, h), activated(false), clicked(false), inside(false), fgColor(0xFFFF), - bgColor(0x03E0), pic(NULL), text(s) {} + bgColor(0x03E0), pic(NULL), text(s), elementToTell(NULL) {} + Button(uint32 x, uint32 y, string s): Element(x, y, 0, 8), + activated(false), clicked(false), inside(false), fgColor(0xFFFF), + bgColor(0x03E0), pic(NULL), text(s), elementToTell(NULL) + { extents.w = s.length() * 8; } virtual void HandleKey(SDLKey key) {} virtual void HandleMouseMove(uint32 x, uint32 y); virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown); virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0); + virtual void Notify(Element *) {} bool ButtonClicked(void) { return activated; } + void SetNotificationElement(Element * e) { elementToTell = e; } protected: bool activated, clicked, inside; uint16 fgColor, bgColor; uint16 * pic; string text; + Element * elementToTell; }; void Button::HandleMouseMove(uint32 x, uint32 y) @@ -149,7 +205,13 @@ void Button::HandleMouseButton(uint32 x, uint32 y, bool mouseDown) clicked = true; if (clicked && !mouseDown) + { clicked = false, activated = true; + + // Send a message that we're activated (if there's someone to tell, that is) + if (elementToTell) + elementToTell->Notify(this); + } } else clicked = activated = false; @@ -170,42 +232,66 @@ void Button::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/) } } -//WriteLog("Button::Draw [%08X]\n", this); if (pic != NULL) -//{ -//WriteLog("--> Button: About to draw pic [%08X].\n", pic); DrawTransparentBitmap(screenBuffer, extents.x + offsetX, extents.y + offsetY, pic); -//} if (text.length() > 0) -//{ -//WriteLog("--> Button: About to draw string [%s].\n", text.c_str()); DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str()); -//} } class Window: public Element { public: - Window(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h), - /*clicked(false), inside(false),*/ fgColor(0x4FF0), bgColor(0xFE10), - close(w - 8, 1, 7, 7, closeBox) { list.push_back(&close); } - virtual void HandleKey(SDLKey key) {} +/* Window(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h), + fgColor(0x4FF0), bgColor(0xFE10) + { close = new Button(w - 8, 1, closeBox); list.push_back(close); }*/ + Window(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0, + void (* f)(Element *) = NULL): Element(x, y, w, h), + /*clicked(false), inside(false),*/ fgColor(0x4FF0), bgColor(0x1E10), + handler(f) + { close = new Button(w - 8, 1, closeBox); list.push_back(close); + close->SetNotificationElement(this); } + virtual ~Window(); + virtual void HandleKey(SDLKey key); virtual void HandleMouseMove(uint32 x, uint32 y); virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown); virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0); + virtual void Notify(Element * e); void AddElement(Element * e); - bool WindowActive(void) { return !close.ButtonClicked(); } +// bool WindowActive(void) { return true; }//return !close->ButtonClicked(); } protected: // bool clicked, inside; uint16 fgColor, bgColor; - Button close; + void (* handler)(Element *); + Button * close; //We have to use a list of Element *pointers* because we can't make a list that will hold //all the different object types in the same list... vector list; }; +Window::~Window() +{ + for(uint32 i=0; iHandleKey(key); +} + void Window::HandleMouseMove(uint32 x, uint32 y) { // Handle the items this window contains... @@ -246,6 +332,16 @@ void Window::AddElement(Element * e) list.push_back(e); } +void Window::Notify(Element * e) +{ + if (e == close) + { + SDL_Event event; + event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE; + SDL_PushEvent(&event); + } +} + class Text: public Element { public: @@ -257,6 +353,7 @@ class Text: public Element virtual void HandleMouseMove(uint32 x, uint32 y) {} virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {} virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0); + virtual void Notify(Element *) {} protected: uint16 fgColor, bgColor; @@ -269,14 +366,305 @@ void Text::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/) DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str()); } +class ListBox: public Element +//class ListBox: public Window +{ + public: +// ListBox(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h), + ListBox(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0);//: Window(x, y, w, h), +// windowPtr(0), cursor(0), limit(0), charWidth((w / 8) - 1), charHeight(h / 8), +// elementToTell(NULL), upArrow(w - 8, 0, upArrowBox), +// downArrow(w - 8, h - 8, downArrowBox), upArrow2(w - 8, h - 16, upArrowBox) {} + virtual void HandleKey(SDLKey key); + virtual void HandleMouseMove(uint32 x, uint32 y); + virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown); + virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0); + virtual void Notify(Element * e); + void SetNotificationElement(Element * e) { elementToTell = e; } + void AddItem(string s); + string GetSelectedItem(void); + + protected: + uint32 windowPtr, cursor, limit; + uint32 charWidth, charHeight; // Box width/height in characters + Element * elementToTell; + Button upArrow, downArrow, upArrow2; + vector item; +}; + +ListBox::ListBox(uint32 x, uint32 y, uint32 w, uint32 h): Element(x, y, w, h), + windowPtr(0), cursor(0), limit(0), charWidth((w / 8) - 1), charHeight(h / 8), + elementToTell(NULL), upArrow(w - 8, 0, upArrowBox), + downArrow(w - 8, h - 8, downArrowBox), upArrow2(w - 8, h - 16, upArrowBox) +{ + upArrow.SetNotificationElement(this); + downArrow.SetNotificationElement(this); + upArrow2.SetNotificationElement(this); + extents.w -= 8; // Make room for scrollbar... +} + +void ListBox::HandleKey(SDLKey key) +{ + if (key == SDLK_DOWN) + { + if (cursor != limit - 1) // Cursor is within its window + cursor++; + else // Otherwise, scroll the window... + { + if (cursor + windowPtr != item.size() - 1) + windowPtr++; + } + } + else if (key == SDLK_UP) + { + if (cursor != 0) + cursor--; + else + { + if (windowPtr != 0) + windowPtr--; + } + } + else if (key == SDLK_PAGEDOWN) + { + if (cursor != limit - 1) + cursor = limit - 1; + else + { + windowPtr += limit; + if (windowPtr > item.size() - limit) + windowPtr = item.size() - limit; + } + } + else if (key == SDLK_PAGEUP) + { + if (cursor != 0) + cursor = 0; + else + { + if (windowPtr < limit) + windowPtr = 0; + else + windowPtr -= limit; + } + } +//How to handle these??? +/* if (key == SDLK_RETURN) + done = true; + if (key == SDLK_ESCAPE) + { + WriteLog("GUI: Aborting VJ by user request.\n"); + return false; // Bail out! + }*/ + else if (key >= SDLK_a && key <= SDLK_z) + { + // Advance cursor to filename with first letter pressed... + uint8 which = (key - SDLK_a) + 65; // Convert key to A-Z char + + for(uint32 i=0; i windowPtr + limit - 1) + windowPtr = i - limit + 1, + cursor = limit - 1; + if (i < windowPtr) + windowPtr = i, + cursor = 0; + break; + } + } + } +} + +void ListBox::HandleMouseMove(uint32 x, uint32 y) +{ + upArrow.HandleMouseMove(x - extents.x, y - extents.y); + downArrow.HandleMouseMove(x - extents.x, y - extents.y); + upArrow2.HandleMouseMove(x - extents.x, y - extents.y); +} + +void ListBox::HandleMouseButton(uint32 x, uint32 y, bool mouseDown) +{ + if (Inside(x, y) && mouseDown) + { + // Why do we have to do this??? (- extents.y?) + // I guess it's because only the Window class has offsetting implemented... + cursor = (y - extents.y) / 8; + } + + upArrow.HandleMouseButton(x - extents.x, y - extents.y, mouseDown); + downArrow.HandleMouseButton(x - extents.x, y - extents.y, mouseDown); + upArrow2.HandleMouseButton(x - extents.x, y - extents.y, mouseDown); +} + +void ListBox::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/) +{ + for(uint32 i=0; i= thumbStart + (extents.y+offsetY+8) && y < thumbStart + thumb + (extents.y+offsetY+8)) + screenBuffer[x + (y * pitch)] = 0xFFFF; + else + screenBuffer[x + (y * pitch)] = 0x0000; + } + } +} + +void ListBox::Notify(Element * e) +{ + if (e == &upArrow || e == &upArrow2) + { + if (windowPtr != 0) + { + windowPtr--; + + if (cursor < limit - 1) + cursor++; + } + } + else if (e == &downArrow) + { + if (windowPtr < item.size() - limit) + { + windowPtr++; + + if (cursor != 0) + cursor--; + } + } +} + +void ListBox::AddItem(string s) +{ + item.push_back(s); + limit = (item.size() > charHeight ? charHeight : item.size()); +//WriteLog("ListBox: Adding item [%s], limit = %u...\n", s.c_str(), limit); + + //Do this *every* time? + sort(item.begin(), item.end()); +} + +string ListBox::GetSelectedItem(void) +{ + return item[windowPtr + cursor]; +} + +class FileList: public Window +{ + public: + FileList(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0); + virtual ~FileList() {} + virtual void HandleKey(SDLKey key); + virtual void HandleMouseMove(uint32 x, uint32 y) { Window::HandleMouseMove(x, y); } + virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) { Window::HandleMouseButton(x, y, mouseDown); } + virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0) { Window::Draw(offsetX, offsetY); } + virtual void Notify(Element * e); + + protected: + ListBox * files; + Button * load; +}; + +//Need 4 buttons, one scrollbar... +FileList::FileList(uint32 x, uint32 y, uint32 w, uint32 h): Window(x, y, w, h) +{ + files = new ListBox(8, 8, w - 16, h - 32); + AddElement(files); + load = new Button(8, h - 16, " Load "); + AddElement(load); + load->SetNotificationElement(this); + +// DIR * dp = opendir(path); + DIR * dp = opendir(vjs.ROMPath); + dirent * de; + + while ((de = readdir(dp)) != NULL) + { + char * ext = strrchr(de->d_name, '.'); + + if (ext != NULL) + if (stricmp(ext, ".zip") == 0 || stricmp(ext, ".jag") == 0) + files->AddItem(string(de->d_name)); + } + + closedir(dp); +} + +void FileList::HandleKey(SDLKey key) +{ + if (key == SDLK_RETURN) + Notify(load); + else + Window::HandleKey(key); +} + +void FileList::Notify(Element * e) +{ + if (e == load) + { + char filename[MAX_PATH]; + strcpy(filename, vjs.ROMPath); + + if (strlen(filename) > 0) + if (filename[strlen(filename) - 1] != '/') + strcat(filename, "/"); + + strcat(filename, files->GetSelectedItem().c_str()); + + uint32 romSize = JaguarLoadROM(jaguar_mainRom, filename); + + if (romSize == 0) +//We need better error checking here... !!! FIX !!! + WriteLog("VJ: Could not load ROM from file \"%s\"...", files->GetSelectedItem().c_str()); + else + { + jaguar_mainRom_crc32 = crc32_calcCheckSum(jaguar_mainRom, romSize); + WriteLog("CRC: %08X\n", (unsigned int)jaguar_mainRom_crc32); + eeprom_init(); + + SDL_Event event; + event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE; + SDL_PushEvent(&event); + + event.type = SDL_USEREVENT, event.user.code = MENU_ITEM_CHOSEN; + event.user.data1 = (void *)ResetJaguar; + SDL_PushEvent(&event); + } + } + else + Window::Notify(e); +} + + struct NameAction { string name; - void (* action)(void); - bool isWindow; + Window * (* action)(void); + SDLKey hotKey; - NameAction(string n, void (* a)(void) = NULL, bool w = false): name(n), action(a), - isWindow(w) {} + NameAction(string n, Window * (* a)(void) = NULL, SDLKey k = SDLK_UNKNOWN): name(n), + action(a), hotKey(k) {} }; class MenuItems @@ -298,24 +686,18 @@ class Menu: public Element public: Menu(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 8, uint16 fgc = 0x1CFF, uint16 bgc = 0x000F, uint16 fgch = 0x421F, - uint16 bgch = 0x1CFF): Element(x, y, w, h), clicked(false), inside(0), - insidePopup(0), fgColor(fgc), bgColor(bgc), fgColorHL(fgch), bgColorHL(bgch), - menuChosen(-1), menuItemChosen(-1) {} -// { extents.x = x, extents.y = y, extents.w = w, extents.h = h; } + uint16 bgch = 0x1CFF): Element(x, y, w, h), activated(false), clicked(false), + inside(0), insidePopup(0), fgColor(fgc), bgColor(bgc), fgColorHL(fgch), + bgColorHL(bgch), menuChosen(-1), menuItemChosen(-1) {} virtual void HandleKey(SDLKey key); virtual void HandleMouseMove(uint32 x, uint32 y); virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown); virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0); + virtual void Notify(Element *) {} void Add(MenuItems mi); - //This is wrong. !!! FIX !!! - bool ItemChosen(void) { return (clicked && insidePopup); } - //This is bad... !!! FIX !!! - NameAction & GetItem(void) -// { if (ItemChosen()) return itemList[menuChosen].item[menuItemChosen]; return NULL; } - { return itemList[menuChosen].item[menuItemChosen]; } protected: - bool clicked; + bool activated, clicked; uint32 inside, insidePopup; uint16 fgColor, bgColor, fgColorHL, bgColorHL; int menuChosen, menuItemChosen; @@ -324,8 +706,25 @@ class Menu: public Element vector itemList; }; -void Menu::HandleKey(SDLKey Key) +void Menu::HandleKey(SDLKey key) { + for(uint32 i=0; i 32768 entries) //Here we've modified it to have 33 levels of transparency (could have any # we want!) -//because dividing by 32 is faster than dividing by 31! +//because dividing by 32 is faster than dividing by 31...! uint8 invTrans = 32 - trans; uint16 bRed = (eRed * trans + nRed * invTrans) / 32; uint16 bGreen = (eGreen * trans + nGreen * invTrans) / 32; @@ -618,25 +1024,19 @@ bool GUIMain(void) extern int16 * backbuffer; bool done = false; SDL_Event event; + Window * mainWindow = NULL; // Set up the GUI classes... Element::SetScreenAndPitch(backbuffer, GetSDLScreenPitch() / 2); - Button closeButton(45, 90, 16, 16); - Window someWindow(15, 16, 60, 60); - Button button1(50, 15, 9, 9), button2(10, 10, 8, 8), button3(25, 48, 32, 8, " Ok "); - someWindow.AddElement(&button1); - someWindow.AddElement(&button2); - someWindow.AddElement(&button3); - - Menu mainMenu;//(0, 160); + Menu mainMenu; MenuItems mi; mi.title = "File"; mi.item.push_back(NameAction("Load...", LoadROM)); - mi.item.push_back(NameAction("Reset")); - mi.item.push_back(NameAction("Run", RunEmu)); + mi.item.push_back(NameAction("Reset", ResetJaguar)); + mi.item.push_back(NameAction("Run", RunEmu, SDLK_ESCAPE)); mi.item.push_back(NameAction("")); - mi.item.push_back(NameAction("Quit", Quit)); + mi.item.push_back(NameAction("Quit", Quit, SDLK_q)); mainMenu.Add(mi); mi.title = "Settings"; mi.item.clear(); @@ -644,9 +1044,9 @@ bool GUIMain(void) mi.item.push_back(NameAction("Audio...")); mi.item.push_back(NameAction("Misc...")); mainMenu.Add(mi); - mi.title = "Options"; + mi.title = "Info"; mi.item.clear(); - mi.item.push_back(NameAction("About...")); + mi.item.push_back(NameAction("About...", About)); mainMenu.Add(mi); bool showMouse = true; @@ -654,21 +1054,53 @@ bool GUIMain(void) //This is crappy!!! !!! FIX !!! jaguar_reset(); + // Set up our background save... + memset(background, 0x11, tom_getVideoModeWidth() * 240 * 2); + while (!done) { while (SDL_PollEvent(&event)) { - if (event.type == SDL_ACTIVEEVENT) + if (event.type == SDL_USEREVENT) + { + if (event.user.code == WINDOW_CLOSE) + { + delete mainWindow; + mainWindow = NULL; + } + else if (event.user.code == MENU_ITEM_CHOSEN) + { + // Confused? Let me enlighten... What we're doing here is casting + // data1 as a pointer to a function which returns a Window pointer and + // which takes no parameters (the "(Window *(*)(void))" part), then + // derefencing it (the "*" in front of that) in order to call the + // function that it points to. Clear as mud? Yeah, I hate function + // pointers too, but what else are you gonna do? + mainWindow = (*(Window *(*)(void))event.user.data1)(); + + while (SDL_PollEvent(&event)); // Flush the event queue... + event.type = SDL_MOUSEMOTION; + int mx, my; + SDL_GetMouseState(&mx, &my); + event.motion.x = mx, event.motion.y = my; + SDL_PushEvent(&event); // & update mouse position...! + + mouseX = mx, mouseY = my; // This prevents "mouse flash"... + if (vjs.useOpenGL) + mouseX /= 2, mouseY /= 2; + } + } + else if (event.type == SDL_ACTIVEEVENT) { if (event.active.state == SDL_APPMOUSEFOCUS) showMouse = (event.active.gain ? true : false); } - if (event.type == SDL_KEYDOWN) + else if (event.type == SDL_KEYDOWN) { - closeButton.HandleKey(event.key.keysym.sym); - if (someWindow.WindowActive()) - someWindow.HandleKey(event.key.keysym.sym); - mainMenu.HandleKey(event.key.keysym.sym); + if (mainWindow) + mainWindow->HandleKey(event.key.keysym.sym); + else + mainMenu.HandleKey(event.key.keysym.sym); } else if (event.type == SDL_MOUSEMOTION) { @@ -677,10 +1109,10 @@ bool GUIMain(void) if (vjs.useOpenGL) mouseX /= 2, mouseY /= 2; - closeButton.HandleMouseMove(mouseX, mouseY); - if (someWindow.WindowActive()) - someWindow.HandleMouseMove(mouseX, mouseY); - mainMenu.HandleMouseMove(mouseX, mouseY); + if (mainWindow) + mainWindow->HandleMouseMove(mouseX, mouseY); + else + mainMenu.HandleMouseMove(mouseX, mouseY); } else if (event.type == SDL_MOUSEBUTTONDOWN) { @@ -689,10 +1121,10 @@ bool GUIMain(void) if (vjs.useOpenGL) mx /= 2, my /= 2; - closeButton.HandleMouseButton(mx, my, true); - if (someWindow.WindowActive()) - someWindow.HandleMouseButton(mx, my, true); - mainMenu.HandleMouseButton(mx, my, true); + if (mainWindow) + mainWindow->HandleMouseButton(mx, my, true); + else + mainMenu.HandleMouseButton(mx, my, true); } else if (event.type == SDL_MOUSEBUTTONUP) { @@ -701,22 +1133,22 @@ bool GUIMain(void) if (vjs.useOpenGL) mx /= 2, my /= 2; - closeButton.HandleMouseButton(mx, my, false); - if (someWindow.WindowActive()) - someWindow.HandleMouseButton(mx, my, false); - mainMenu.HandleMouseButton(mx, my, false); + if (mainWindow) + mainWindow->HandleMouseButton(mx, my, false); + else + mainMenu.HandleMouseButton(mx, my, false); } // Draw the GUI... // The way we do things here is kinda stupid (redrawing the screen every frame), but // it's simple. Perhaps there may be a reason down the road to be more selective with // our clearing, but for now, this will suffice. - memset(backbuffer, 0x11, tom_getVideoModeWidth() * 240 * 2); +// memset(backbuffer, 0x11, tom_getVideoModeWidth() * 240 * 2); + memcpy(backbuffer, background, tom_getVideoModeWidth() * 240 * 2); - closeButton.Draw(); - if (someWindow.WindowActive()) - someWindow.Draw(); mainMenu.Draw(); + if (mainWindow) + mainWindow->Draw(); if (showMouse) DrawTransparentBitmap(backbuffer, mouseX, mouseY, mousePic); @@ -731,11 +1163,21 @@ bool GUIMain(void) // // GUI "action" functions // -void LoadROM(void) +Window * LoadROM(void) { + FileList * fileList = new FileList(8, 16, 304, 216); + + return (Window *)fileList; } -void RunEmu(void) +Window * ResetJaguar(void) +{ + jaguar_reset(); + return RunEmu(); +} + +bool debounceRunKey = true; +Window * RunEmu(void) { //This is crappy... !!! FIX !!! extern int16 * backbuffer; @@ -747,6 +1189,8 @@ void RunEmu(void) bool showMessage = true; uint32 showMsgFrames = 60; uint8 transparency = 0; + // Pass a message to the "joystick" code to debounce the ESC key... + debounceRunKey = true; while (!finished) { @@ -758,6 +1202,11 @@ void RunEmu(void) //if (totalFrames == 373) // doDSPDis = true; +//This sucks... !!! FIX !!! + joystick_exec(); + if (finished) + break; + // Some QnD GUI stuff here... if (showGUI) { @@ -789,64 +1238,46 @@ void RunEmu(void) } else nFrame++; + } - joystick_exec(); + // Reset the pitch, since it may have been changed in-game... + Element::SetScreenAndPitch(backbuffer, GetSDLScreenPitch() / 2); + + // Save the background for the GUI... +// memcpy(background, backbuffer, tom_getVideoModeWidth() * 240 * 2); + // In this case, we squash the color to monochrome, then force it to blue + green... + for(uint32 i=0; i> 10) & 0x1F, g = (word >> 5) & 0x1F, b = word & 0x1F; + word = ((r + g + b) / 3) & 0x001F; + word = (word << 5) | word; + background[i] = word; } + + return NULL; } -void Quit(void) +Window * Quit(void) { WriteLog("GUI: Quitting due to user request.\n"); log_done(); exit(0); + + return NULL; // We never get here... } -void About(void) +Window * About(void) { - extern int16 * backbuffer; - SDL_Event event; - uint16 * bgSave = (uint16 *)malloc(tom_getVideoModeWidth() * 240 * 2); - memcpy(bgSave, backbuffer, tom_getVideoModeWidth() * 240 * 2); - - bool done = false; - while (!done) - { - while (SDL_PollEvent(&event)) - { - if (event.type == SDL_KEYDOWN) - { - if (event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_RETURN) - done = true; - } - else if (event.type == SDL_MOUSEMOTION) - { - mouseX = event.motion.x, mouseY = event.motion.y; - if (vjs.useOpenGL) - mouseX /= 2, mouseY /= 2; - } - else if (event.type == SDL_MOUSEBUTTONDOWN) - { - uint32 mx = event.button.x, my = event.button.y; - if (vjs.useOpenGL) - mx /= 2, my /= 2; - - done = true; - } - - // Draw "About" box - memcpy(backbuffer, bgSave, tom_getVideoModeWidth() * 240 * 2); - - DrawStringOpaque(backbuffer, 64, 64, 0x1CFF, 0x000F, " "); - DrawStringOpaque(backbuffer, 64, 72, 0x1CFF, 0x000F, " Virtual Jaguar by JLH & crew "); - DrawStringOpaque(backbuffer, 64, 80, 0x1CFF, 0x000F, " "); - - DrawTransparentBitmap(backbuffer, mouseX, mouseY, mousePic); - - RenderBackbuffer(); - } - } - - free(bgSave); + Window * window = new Window(8, 16, 304, 160); + window->AddElement(new Text(8, 8, "Virtual Jaguar 1.0.7")); + window->AddElement(new Text(8, 24, "Coders:")); + window->AddElement(new Text(16, 32, "Niels Wagenaar (nwagenaar)")); + window->AddElement(new Text(16, 40, "Caz")); + window->AddElement(new Text(16, 48, "James L. Hammons (shamus)")); + window->AddElement(new Text(16, 56, "Adam Green")); + + return window; } // @@ -875,10 +1306,10 @@ void DrawTransparentBitmap(int16 * screen, uint32 x, uint32 y, uint16 * bitmap) // // Very very crude GUI file selector // -bool UserSelectFile(char * path, char * filename) +/*bool UserSelectFile(char * path, char * filename) { //Testing... -//GUIMain(); +GUIMain(); extern int16 * backbuffer; vector fileList; @@ -1041,4 +1472,126 @@ bool UserSelectFile(char * path, char * filename) strcat(filename, fileList[startFile + cursor].c_str()); return true; +}*/ + +// +// Generic ROM loading +// +uint32 JaguarLoadROM(uint8 * rom, char * path) +{ + uint32 romSize = 0; + + char * ext = strrchr(path, '.'); + if (ext != NULL) + { + WriteLog("VJ: Loading \"%s\"...", path); + + if (stricmp(ext, ".zip") == 0) + { + // Handle ZIP file loading here... + WriteLog("(ZIPped)..."); + + if (load_zipped_file(0, 0, path, NULL, &rom, &romSize) == -1) + { + WriteLog("Failed!\n"); + return 0; + } + } + else + { +/* FILE * fp = fopen(path, "rb"); + + if (fp == NULL) + { + WriteLog("Failed!\n"); + return 0; + } + + fseek(fp, 0, SEEK_END); + romSize = ftell(fp); + fseek(fp, 0, SEEK_SET); + fread(rom, 1, romSize, fp); + fclose(fp);*/ + + gzFile fp = gzopen(path, "rb"); + + if (fp == NULL) + { + WriteLog("Failed!\n"); + return 0; + } + + romSize = gzfilelength(fp); + gzseek(fp, 0, SEEK_SET); + gzread(fp, rom, romSize); + gzclose(fp); + } + + WriteLog("OK (%i bytes)\n", romSize); + } + + return romSize; +} + +// +// Jaguar cartridge ROM loading +// +void JaguarLoadCart(uint8 * mem, char * path) +{ + uint32 romSize = JaguarLoadROM(mem, path); + + if (romSize == 0) + { +/* char newPath[2048]; + WriteLog("VJ: Trying GUI...\n"); + +//This is not *nix friendly for some reason... +// if (!UserSelectFile(path, newPath)) + if (!UserSelectFile((strlen(path) == 0 ? (char *)"." : path), newPath)) + { + WriteLog("VJ: Could not find valid ROM in directory \"%s\"...\nAborting!\n", path); + log_done(); + exit(0); + } + + romSize = JaguarLoadROM(mem, newPath); +*/ + if (romSize == 0) + { +// WriteLog("VJ: Could not load ROM from file \"%s\"...\nAborting!\n", newPath); + WriteLog("VJ: Could not load ROM from file \"%s\"...\nAborting!\n", path); + log_done(); + exit(0); + } + } + + jaguar_mainRom_crc32 = crc32_calcCheckSum(jaguar_mainRom, romSize); + WriteLog("CRC: %08X\n", (unsigned int)jaguar_mainRom_crc32); + eeprom_init(); +} + +// +// Get the length of a (possibly) gzipped file +// +int gzfilelength(gzFile gd) +{ + int size = 0, length = 0; + unsigned char buffer[0x10000]; + + gzrewind(gd); + + do + { + // Read in chunks until EOF + size = gzread(gd, buffer, 0x10000); + + if (size <= 0) + break; + + length += size; + } + while (!gzeof(gd)); + + gzrewind(gd); + return length; } diff --git a/src/include/gui.h b/src/include/gui.h index 2a3ca2e..e8e516d 100644 --- a/src/include/gui.h +++ b/src/include/gui.h @@ -14,7 +14,11 @@ extern "C" { void InitGUI(void); void GUIDone(void); void DrawString(int16 * screen, uint32 x, uint32 y, bool invert, const char * text, ...); -bool UserSelectFile(char * path, char * filename); +//bool UserSelectFile(char * path, char * filename); +bool GUIMain(void); + +uint32 JaguarLoadROM(uint8 * rom, char * path); +void JaguarLoadCart(uint8 * mem, char * path); #ifdef __cplusplus } diff --git a/src/jaguar.cpp b/src/jaguar.cpp index 2ad0e96..6dbb14e 100644 --- a/src/jaguar.cpp +++ b/src/jaguar.cpp @@ -872,6 +872,7 @@ if (effect_start) WriteLog("JagExe: VP=%u, VI=%u, VDB=%u, VBB=%u CPU CPS=%u, GPU CPS=%u\n", vp, vi, vdb, vbb, M68KCyclesPerScanline, RISCCyclesPerScanline); }//*/ +//extern int start_logging; for(uint16 i=0; i phrase %08X %08X", op_pointer - 8, (int)(p0>>32), (int)(p0&0xFFFFFFFF)); @@ -451,16 +451,16 @@ if (!inhibit) // For OP testing only! // if (height) height--; - uint64 data = (p0 & 0xFFFFF80000000000) >> 40; + uint64 data = (p0 & 0xFFFFF80000000000LL) >> 40; uint64 dwidth = (p1 & 0xFFC0000) >> 15; data += dwidth; - p0 &= ~0xFFFFF80000FFC000; // Mask out old data... + p0 &= ~0xFFFFF80000FFC000LL; // Mask out old data... p0 |= (uint64)height << 14; p0 |= data << 40; OPStorePhrase(oldOPP, p0); } - op_pointer = (p0 & 0x000007FFFF000000) >> 21; + op_pointer = (p0 & 0x000007FFFF000000LL) >> 21; break; } case OBJECT_TYPE_SCALE: @@ -500,37 +500,88 @@ if (!inhibit) // For OP testing only! if (vscale == 0) vscale = 0x20; // OP bug??? Nope, it isn't...! Or is it? - remainder -= 0x20; // 1.0f in [3.5] fixed point format +/*extern int start_logging; +if (start_logging) + WriteLog("--> Returned from scaled bitmap processing (rem=%02X, vscale=%02X)...\n", remainder, vscale);*/ +//Locks up here: +//--> Returned from scaled bitmap processing (rem=20, vscale=80)... +//There are other problems here, it looks like... +/* +OP: Scaled bitmap 4x? 4bpp at 38,? hscale=7C fpix=0 data=00075E28 pitch 1 hflipped=no dwidth=? (linked to 00071118) Transluency=no +--> Returned from scaled bitmap processing (rem=50, vscale=7C)... +OP: Scaled bitmap 4x? 4bpp at 38,? hscale=7C fpix=0 data=00075E28 pitch 1 hflipped=no dwidth=? (linked to 00071118) Transluency=no +--> Returned from scaled bitmap processing (rem=30, vscale=7C)... +OP: Scaled bitmap 4x? 4bpp at 38,? hscale=7C fpix=0 data=00075E28 pitch 1 hflipped=no dwidth=? (linked to 00071118) Transluency=no +--> Returned from scaled bitmap processing (rem=10, vscale=7C)... +OP: Scaled bitmap 4x? 4bpp at 36,? hscale=7E fpix=0 data=000756A8 pitch 1 hflipped=no dwidth=? (linked to 00073058) Transluency=no +--> Returned from scaled bitmap processing (rem=00, vscale=7E)... +OP: Scaled bitmap 4x? 4bpp at 34,? hscale=80 fpix=0 data=000756C8 pitch 1 hflipped=no dwidth=? (linked to 00073078) Transluency=no +--> Returned from scaled bitmap processing (rem=00, vscale=80)... +OP: Scaled bitmap 4x? 4bpp at 36,? hscale=7E fpix=0 data=000756C8 pitch 1 hflipped=no dwidth=? (linked to 00073058) Transluency=no +--> Returned from scaled bitmap processing (rem=5E, vscale=7E)... +OP: Scaled bitmap 4x? 4bpp at 34,? hscale=80 fpix=0 data=000756E8 pitch 1 hflipped=no dwidth=? (linked to 00073078) Transluency=no +--> Returned from scaled bitmap processing (rem=60, vscale=80)... +OP: Scaled bitmap 4x? 4bpp at 36,? hscale=7E fpix=0 data=000756C8 pitch 1 hflipped=no dwidth=? (linked to 00073058) Transluency=no +--> Returned from scaled bitmap processing (rem=3E, vscale=7E)... +OP: Scaled bitmap 4x? 4bpp at 34,? hscale=80 fpix=0 data=000756E8 pitch 1 hflipped=no dwidth=? (linked to 00073078) Transluency=no +--> Returned from scaled bitmap processing (rem=40, vscale=80)... +OP: Scaled bitmap 4x? 4bpp at 36,? hscale=7E fpix=0 data=000756C8 pitch 1 hflipped=no dwidth=? (linked to 00073058) Transluency=no +--> Returned from scaled bitmap processing (rem=1E, vscale=7E)... +OP: Scaled bitmap 4x? 4bpp at 34,? hscale=80 fpix=0 data=000756E8 pitch 1 hflipped=no dwidth=? (linked to 00073078) Transluency=no +--> Returned from scaled bitmap processing (rem=20, vscale=80)... +*/ +//Here's another problem: +// [hsc: 20, vsc: 20, rem: 00] +// Since we're not checking for $E0 (but that's what we get from the above), we end +// up repeating this scanline unnecessarily... !!! FIX !!! [DONE, but... still not quite +// right. Either that, or the Accolade team that wrote Bubsy screwed up royal.] +//Also note: $E0 = 7.0 which IS a legal vscale value... + // if (remainder & 0x80) // I.e., it's negative - if ((remainder & 0x80) || remainder == 0) // I.e., it's <= 0 +// if ((remainder & 0x80) || remainder == 0) // I.e., it's <= 0 +// if ((remainder - 1) >= 0xE0) // I.e., it's <= 0 +// if ((remainder >= 0xE1) || remainder == 0)// I.e., it's <= 0 +// if ((remainder >= 0xE1 && remainder <= 0xFF) || remainder == 0)// I.e., it's <= 0 + if (remainder <= 0x20) // I.e., it's <= 0 { - uint64 data = (p0 & 0xFFFFF80000000000) >> 40; + uint64 data = (p0 & 0xFFFFF80000000000LL) >> 40; uint64 dwidth = (p1 & 0xFFC0000) >> 15; // while (remainder & 0x80) - while ((remainder & 0x80) || remainder == 0) +// while ((remainder & 0x80) || remainder == 0) +// while ((remainder - 1) >= 0xE0) +// while ((remainder >= 0xE1) || remainder == 0) +// while ((remainder >= 0xE1 && remainder <= 0xFF) || remainder == 0) + while (remainder <= 0x20) { remainder += vscale; + if (height) height--; data += dwidth; } - p0 &= ~0xFFFFF80000FFC000; // Mask out old data... + + p0 &= ~0xFFFFF80000FFC000LL; // Mask out old data... p0 |= (uint64)height << 14; p0 |= data << 40; OPStorePhrase(oldOPP, p0); } + remainder -= 0x20; // 1.0f in [3.5] fixed point format + +/*if (start_logging) + WriteLog("--> Finished writebacks...\n");*/ + //WriteLog(" [%08X%08X -> ", (uint32)(p2>>32), (uint32)(p2&0xFFFFFFFF)); - p2 &= ~0x0000000000FF0000; + p2 &= ~0x0000000000FF0000LL; p2 |= (uint64)remainder << 16; //WriteLog("%08X%08X]\n", (uint32)(p2>>32), (uint32)(p2&0xFFFFFFFF)); OPStorePhrase(oldOPP+16, p2); //remainder = (uint8)(p2 >> 16), vscale = (uint8)(p2 >> 8); //WriteLog(" [after]: rem=%02X, vscale=%02X\n", remainder, vscale); } - op_pointer = (p0 & 0x000007FFFF000000) >> 21; + op_pointer = (p0 & 0x000007FFFF000000LL) >> 21; break; } case OBJECT_TYPE_GPU: @@ -1044,7 +1095,7 @@ if (firstPix) //#endif // We can ignore the RELEASE (high order) bit for now--probably forever...! // uint8 flags = (p1 >> 45) & 0x0F; // REFLECT, RMW, TRANS, RELEASE -//Optimize: break these out to their own BOOL values +//Optimize: break these out to their own BOOL values [DONE] uint8 flags = (p1 >> 45) & 0x07; // REFLECT (0), RMW (1), TRANS (2) bool flagREFLECT = (flags & OPFLAG_REFLECT ? true : false), flagRMW = (flags & OPFLAG_RMW ? true : false), @@ -1071,9 +1122,13 @@ if (firstPix) if (!render || iwidth == 0 || hscale == 0) return; +/*extern int start_logging; +if (start_logging) + WriteLog("OP: Scaled bitmap %ix? %ibpp at %i,? hscale=%02X fpix=%i data=%08X pitch %i hflipped=%s dwidth=? (linked to %08X) Transluency=%s\n", + iwidth, op_bitmap_bit_depth[depth], xpos, hscale, firstPix, data, pitch, (flagREFLECT ? "yes" : "no"), op_pointer, (flagRMW ? "yes" : "no"));*/ //#define OP_DEBUG_BMP //#ifdef OP_DEBUG_BMP -// WriteLog("bitmap %ix%i %ibpp at %i,%i firstpix=%i data=0x%.8x pitch %i hflipped=%s dwidth=%i (linked to 0x%.8x) Transluency=%s\n", +// WriteLog("OP: Scaled bitmap %ix%i %ibpp at %i,%i firstpix=%i data=0x%.8x pitch %i hflipped=%s dwidth=%i (linked to 0x%.8x) Transluency=%s\n", // iwidth, height, op_bitmap_bit_depth[bitdepth], xpos, ypos, firstPix, ptr, pitch, (flags&OPFLAG_REFLECT ? "yes" : "no"), dwidth, op_pointer, (flags&OPFLAG_RMW ? "yes" : "no")); //#endif @@ -1096,7 +1151,7 @@ if (firstPix) // 4. image sits on right edge and no REFLECT; starts in bounds but ends out of bounds. //Numbers 2 & 4 can be caught by checking the LBUF clip while in the inner loop, // numbers 1 & 3 are of concern. -// This *indirectly* handles only cases 2 & 4! And is WRONG is REFLECT is set...! +// This *indirectly* handles only cases 2 & 4! And is WRONG if REFLECT is set...! // if (rightMargin < 0 || leftMargin > lbufWidth) // It might be easier to swap these (if REFLECTed) and just use XPOS down below... @@ -1141,30 +1196,58 @@ if (firstPix) DumpScaledObject(p0, p1, p2); }//*/ //NOTE: I'm almost 100% sure that this is wrong... And it is! :-p + +//Try a simple example... +// Let's say we have a 8 BPP scanline with an hscale of $80 (4). Our xpos is -10, +// non-flipped. Pixels in the bitmap are XYZXYZXYZXYZXYZ. +// Scaled up, they would be XXXXYYYYZZZZXXXXYYYYZZZZXXXXYYYYZZZZ... +// +// Normally, we would expect this in the line buffer: +// ZZXXXXYYYYZZZZXXXXYYYYZZZZ... +// +// But instead we're getting: +// XXXXYYYYZZZZXXXXYYYYZZZZ... +// +// or are we??? It would seem so, simply by virtue of the fact that we're NOT starting +// on negative boundary--or are we? Hmm... +// cw = 10, dcw = pcw = 10 / ([8 * 4 = 32] 32) = 0, sp = -10 +// +// Let's try a real world example: +// +//OP: Scaled bitmap (70, 8 BPP, spp=28) sp (-400) < 0... [new sp=-8, cw=400, dcw=pcw=14] +//OP: Scaled bitmap (6F, 8 BPP, spp=27) sp (-395) < 0... [new sp=-17, cw=395, dcw=pcw=14] +// +// Really, spp is 27.75 in the second case... +// So... If we do 395 / 27.75, we get 14. Ok so far... If we scale that against the +// start position (14 * 27.75), we get -6.5... NOT -17! + +//Now it seems we're working OK, at least for the first case... +uint32 scaledPhrasePixelsUS = phraseWidthToPixels[depth] * hscale; + if (startPos < 0) // Case #1: Begin out, end in, L to R -/* clippedWidth = 0 - startPos, - dataClippedWidth = phraseClippedWidth = clippedWidth / phraseWidthToPixels[depth], - startPos = 0 - (clippedWidth % phraseWidthToPixels[depth]);*/ - clippedWidth = 0 - startPos, - dataClippedWidth = phraseClippedWidth = clippedWidth / scaledPhrasePixels, - startPos = 0 - (clippedWidth % scaledPhrasePixels); +{ +extern int start_logging; +if (start_logging) + WriteLog("OP: Scaled bitmap (%02X, %u BPP, spp=%u) start pos (%i) < 0...", hscale, op_bitmap_bit_depth[depth], scaledPhrasePixels, startPos); +// clippedWidth = 0 - startPos, + clippedWidth = (0 - startPos) << 5, +// dataClippedWidth = phraseClippedWidth = clippedWidth / scaledPhrasePixels, + dataClippedWidth = phraseClippedWidth = (clippedWidth / scaledPhrasePixelsUS) >> 5, +// startPos = 0 - (clippedWidth % scaledPhrasePixels); + startPos += (dataClippedWidth * scaledPhrasePixelsUS) >> 5; +if (start_logging) + WriteLog(" [new sp=%i, cw=%i, dcw=pcw=%i]\n", startPos, clippedWidth, dataClippedWidth); +} if (endPos < 0) // Case #2: Begin in, end out, R to L -/* clippedWidth = 0 - endPos, - phraseClippedWidth = clippedWidth / phraseWidthToPixels[depth];*/ clippedWidth = 0 - endPos, phraseClippedWidth = clippedWidth / scaledPhrasePixels; if (endPos > lbufWidth) // Case #3: Begin in, end out, L to R -/* clippedWidth = endPos - lbufWidth, - phraseClippedWidth = clippedWidth / phraseWidthToPixels[depth];*/ clippedWidth = endPos - lbufWidth, phraseClippedWidth = clippedWidth / scaledPhrasePixels; if (startPos > lbufWidth) // Case #4: Begin out, end in, R to L -/* clippedWidth = startPos - lbufWidth, - dataClippedWidth = phraseClippedWidth = clippedWidth / phraseWidthToPixels[depth], - startPos = lbufWidth + (clippedWidth % phraseWidthToPixels[depth]);*/ clippedWidth = startPos - lbufWidth, dataClippedWidth = phraseClippedWidth = clippedWidth / scaledPhrasePixels, startPos = lbufWidth + (clippedWidth % scaledPhrasePixels); @@ -1190,8 +1273,10 @@ if (op_start_log && startPos == 13) // bitmap! This makes clipping & etc. MUCH, much easier...! // uint32 lbufAddress = 0x1800 + (!in24BPPMode ? leftMargin * 2 : leftMargin * 4); // uint32 lbufAddress = 0x1800 + (!in24BPPMode ? startPos * 2 : startPos * 4); - uint32 lbufAddress = 0x1800 + (!in24BPPMode ? startPos * 2 : startPos * 2); + uint32 lbufAddress = 0x1800 + startPos * 2; uint8 * currentLineBuffer = &tom_ram_8[lbufAddress]; +uint8 * lineBufferLowerLimit = &tom_ram_8[0x1800], + * lineBufferUpperLimit = &tom_ram_8[0x1800 + 719]; // Render. @@ -1378,6 +1463,10 @@ if (firstPix) // This is the *only* correct use of endian-dependent code // (i.e., mem-to-mem direct copying)! *(uint16 *)currentLineBuffer = paletteRAM16[bits]; +/* { + if (currentLineBuffer >= lineBufferLowerLimit && currentLineBuffer <= lineBufferUpperLimit) + *(uint16 *)currentLineBuffer = paletteRAM16[bits]; + }*/ else *currentLineBuffer = BLEND_CR(*currentLineBuffer, paletteRAM[bits << 1]), diff --git a/src/tom.cpp b/src/tom.cpp index c2e4a20..7f425b9 100644 --- a/src/tom.cpp +++ b/src/tom.cpp @@ -281,6 +281,8 @@ #define BG 0x58 #define INT1 0xE0 +//NOTE: These arbitrary cutoffs are NOT taken into account for PAL jaguar screens. !!! FIX !!! + // Arbitrary video cutoff values (i.e., first/last visible spots on a TV, in HC ticks) /*#define LEFT_VISIBLE_HC 208 #define RIGHT_VISIBLE_HC 1528//*/ diff --git a/src/version.cpp b/src/version.cpp index e7b2c28..07958da 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -14,7 +14,7 @@ void version_init(void) void version_display(FILE * fp) { - fprintf(fp, "VirtualJaguar v1.0.6 (Last full build was on %s %s)\n", __DATE__, __TIME__); + fprintf(fp, "VirtualJaguar v1.0.7 (Last full build was on %s %s)\n", __DATE__, __TIME__); } void version_done(void) diff --git a/src/video.cpp b/src/video.cpp index 1df9fca..601fc30 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -13,10 +13,11 @@ // External global variables //shouldn't these exist here??? Prolly. -extern SDL_Surface * surface, * mainSurface; -extern Uint32 mainSurfaceFlags; -extern int16 * backbuffer; -extern SDL_Joystick * joystick; +//And now, they do! :-) +SDL_Surface * surface, * mainSurface; +Uint32 mainSurfaceFlags; +int16 * backbuffer; +SDL_Joystick * joystick; // // Prime SDL and create surfaces @@ -102,6 +103,12 @@ bool InitVideo(void) } } + // Set up the backbuffer +//To be safe, this should be 1280 * 625 * 2... +// backbuffer = (int16 *)malloc(845 * 525 * sizeof(int16)); + backbuffer = (int16 *)malloc(1280 * 625 * sizeof(int16)); + memset(backbuffer, 0x44, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(int16)); + return true; } @@ -117,6 +124,8 @@ void VideoDone(void) SDL_FreeSurface(surface); SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER); SDL_Quit(); + + free(backbuffer); } // diff --git a/src/vj.cpp b/src/vj.cpp index e33ffe2..ef6ea79 100644 --- a/src/vj.cpp +++ b/src/vj.cpp @@ -10,13 +10,13 @@ #include #endif -#include // POSIX, but should compile with linux & mingw... +//#include // POSIX, but should compile with linux & mingw... #include #include #include "jaguar.h" -#include "crc32.h" -#include "zlib.h" -#include "unzip.h" +//#include "crc32.h" +//#include "zlib.h" +//#include "unzip.h" #include "video.h" #include "gui.h" #include "sdlemu_opengl.h" @@ -27,9 +27,9 @@ // Private function prototypes -uint32 JaguarLoadROM(uint8 *, char *); -void JaguarLoadCart(uint8 *, char *); -int gzfilelength(gzFile gd); +//uint32 JaguarLoadROM(uint8 *, char *); +//void JaguarLoadCart(uint8 *, char *); +//int gzfilelength(gzFile gd); // External variables @@ -46,10 +46,11 @@ extern uint8 * jaguar_mainRom; //char jaguar_boot_dir[MAX_PATH]; //These should go into video.cpp... -SDL_Surface * surface, * mainSurface; -int16 * backbuffer = NULL; -SDL_Joystick * joystick; -Uint32 mainSurfaceFlags = SDL_SWSURFACE; +//And they will! +//SDL_Surface * surface, * mainSurface; +//int16 * backbuffer = NULL; +//SDL_Joystick * joystick; +//Uint32 mainSurfaceFlags = SDL_SWSURFACE; bool finished = false; bool showGUI = false; @@ -71,7 +72,7 @@ int main(int argc, char * argv[]) int32 nFrameskip = 0; // Default: Show every frame int32 nFrame = 0; // No. of Frame - printf("Virtual Jaguar GCC/SDL Portable Jaguar Emulator v1.0.6\n"); + printf("Virtual Jaguar GCC/SDL Portable Jaguar Emulator v1.0.7\n"); printf("Based upon Virtual Jaguar core v1.0.0 by Cal2 of Potato emulation.\n"); printf("Written by Niels Wagenaar (Linux/WIN32), Caz (BeOS),\n"); printf("James L. Hammons (WIN32) and Adam Green (MacOS)\n"); @@ -174,7 +175,6 @@ int main(int argc, char * argv[]) } } -// getcwd(jaguar_boot_dir, 1024); memory_init(); version_init(); version_display(log_get()); @@ -186,21 +186,16 @@ int main(int argc, char * argv[]) SET32(jaguar_mainRam, 0, 0x00200000); // Set top of stack... - // Set up the backbuffer -//To be safe, this should be 1280 * 625 * 2... -// backbuffer = (int16 *)malloc(845 * 525 * sizeof(int16)); - backbuffer = (int16 *)malloc(1280 * 625 * sizeof(int16)); - memset(backbuffer, 0x44, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(int16)); - InitVideo(); InitGUI(); // Get the cartridge ROM (if passed in) // Now with crunchy GUI goodness! -// JaguarLoadCart(jaguar_mainRom, (haveCart ? argv[1] : (char *)"")); - JaguarLoadCart(jaguar_mainRom, (haveCart ? argv[1] : vjs.ROMPath)); +// JaguarLoadCart(jaguar_mainRom, (haveCart ? argv[1] : vjs.ROMPath)); +//Need to find a better way to handle this crap... + GUIMain(); - jaguar_reset(); +/* jaguar_reset(); totalFrames = 0; startTime = clock(); @@ -265,7 +260,7 @@ int main(int argc, char * argv[]) #ifdef SPEED_CONTROL } #endif - } + }*/ int elapsedTime = clock() - startTime; int fps = (1000 * totalFrames) / elapsedTime; @@ -279,124 +274,3 @@ int main(int argc, char * argv[]) return 0; } - -// -// Generic ROM loading -// -uint32 JaguarLoadROM(uint8 * rom, char * path) -{ - uint32 romSize = 0; - - char * ext = strrchr(path, '.'); - if (ext != NULL) - { - WriteLog("VJ: Loading \"%s\"...", path); - - if (stricmp(ext, ".zip") == 0) - { - // Handle ZIP file loading here... - WriteLog("(ZIPped)..."); - - if (load_zipped_file(0, 0, path, NULL, &rom, &romSize) == -1) - { - WriteLog("Failed!\n"); - return 0; - } - } - else - { -/* FILE * fp = fopen(path, "rb"); - - if (fp == NULL) - { - WriteLog("Failed!\n"); - return 0; - } - - fseek(fp, 0, SEEK_END); - romSize = ftell(fp); - fseek(fp, 0, SEEK_SET); - fread(rom, 1, romSize, fp); - fclose(fp);*/ - - gzFile fp = gzopen(path, "rb"); - - if (fp == NULL) - { - WriteLog("Failed!\n"); - return 0; - } - - romSize = gzfilelength(fp); - gzseek(fp, 0, SEEK_SET); - gzread(fp, rom, romSize); - gzclose(fp); - } - - WriteLog("OK (%i bytes)\n", romSize); - } - - return romSize; -} - -// -// Jaguar cartridge ROM loading -// -void JaguarLoadCart(uint8 * mem, char * path) -{ - uint32 romSize = JaguarLoadROM(mem, path); - - if (romSize == 0) - { - char newPath[2048]; - WriteLog("VJ: Trying GUI...\n"); - -//This is not *nix friendly for some reason... -// if (!UserSelectFile(path, newPath)) - if (!UserSelectFile((strlen(path) == 0 ? (char *)"." : path), newPath)) - { - WriteLog("VJ: Could not find valid ROM in directory \"%s\"...\nAborting!\n", path); - log_done(); - exit(0); - } - - romSize = JaguarLoadROM(mem, newPath); - - if (romSize == 0) - { - WriteLog("VJ: Could not load ROM from file \"%s\"...\nAborting!\n", newPath); - log_done(); - exit(0); - } - } - - jaguar_mainRom_crc32 = crc32_calcCheckSum(jaguar_mainRom, romSize); - WriteLog("CRC: %08X\n", (unsigned int)jaguar_mainRom_crc32); - eeprom_init(); -} - -// -// Get the length of a (possibly) gzipped file -// -int gzfilelength(gzFile gd) -{ - int size = 0, length = 0; - unsigned char buffer[0x10000]; - - gzrewind(gd); - - do - { - // Read in chunks until EOF - size = gzread(gd, buffer, 0x10000); - - if (size <= 0) - break; - - length += size; - } - while (!gzeof(gd)); - - gzrewind(gd); - return length; -}