diff --git a/apu/apu.cpp b/apu/apu.cpp index 4b7c6dc5..34460b20 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -190,6 +190,7 @@ #include <math.h> #include "snes9x.h" #include "apu.h" +#include "msu1.h" #include "snapshot.h" #include "display.h" #include "hermite_resampler.h" @@ -239,6 +240,13 @@ namespace spc static uint32 ratio_denominator = APU_DENOMINATOR_NTSC; } +namespace msu +{ + static int buffer_size; + static uint8 *landing_buffer = NULL; + static Resampler *resampler = NULL; +} + static void EightBitize (uint8 *, int); static void DeStereo (uint8 *, int); static void ReverseStereo (uint8 *, int); @@ -311,6 +319,9 @@ bool8 S9xMixSamples (uint8 *buffer, int sample_count) memset(dest, 0, sample_count << 1); spc::resampler->clear(); + if(Settings.MSU1) + msu::resampler->clear(); + return (FALSE); } else @@ -320,6 +331,17 @@ bool8 S9xMixSamples (uint8 *buffer, int sample_count) spc::resampler->read((short *) dest, sample_count); if (spc::lag == spc::lag_master) spc::lag = 0; + + if (Settings.MSU1) + { + if (msu::resampler->avail() >= sample_count) + { + uint8 *msu_sample = new uint8[sample_count * 2]; + msu::resampler->read((short *)msu_sample, sample_count); + for (uint32 i = 0; i < sample_count; ++i) + *((int16*)(dest+(i * 2))) += *((int16*)(msu_sample+(i * 2))); + } + } } else { @@ -361,7 +383,19 @@ void S9xFinalizeSamples (void) { if (!Settings.Mute) { - if (!spc::resampler->push((short *) spc::landing_buffer, SNES::dsp.spc_dsp.sample_count ())) + if (Settings.MSU1) + { + S9xMSU1Generate(SNES::dsp.spc_dsp.sample_count()); + if (!msu::resampler->push((short *)msu::landing_buffer, S9xMSU1Samples())) + { + //spc::sound_in_sync = FALSE; + + //if (Settings.SoundSync && !Settings.TurboMode) + //return; + } + } + + if (!spc::resampler->push((short *)spc::landing_buffer, SNES::dsp.spc_dsp.sample_count())) { /* We weren't able to process the entire buffer. Potential overrun. */ spc::sound_in_sync = FALSE; @@ -371,6 +405,7 @@ void S9xFinalizeSamples (void) } } + if (!Settings.SoundSync || Settings.TurboMode || Settings.Mute) spc::sound_in_sync = TRUE; else @@ -380,6 +415,9 @@ void S9xFinalizeSamples (void) spc::sound_in_sync = FALSE; SNES::dsp.spc_dsp.set_output((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size); + + if (Settings.MSU1) + S9xMSU1SetOutput((int16 *)msu::landing_buffer, msu::buffer_size); } void S9xLandSamples (void) @@ -393,6 +431,8 @@ void S9xLandSamples (void) void S9xClearSamples (void) { spc::resampler->clear(); + if (Settings.MSU1) + msu::resampler->clear(); spc::lag = spc::lag_master; } @@ -419,6 +459,12 @@ static void UpdatePlaybackRate (void) double time_ratio = (double) Settings.SoundInputRate * spc::timing_hack_numerator / (Settings.SoundPlaybackRate * spc::timing_hack_denominator); spc::resampler->time_ratio(time_ratio); + + if (Settings.MSU1) + { + time_ratio = (44100.0 / Settings.SoundPlaybackRate) * (Settings.SoundInputRate / 32040); + msu::resampler->time_ratio(time_ratio); + } } bool8 S9xInitSound (int buffer_ms, int lag_ms) @@ -426,8 +472,8 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) // buffer_ms : buffer size given in millisecond // lag_ms : allowable time-lag given in millisecond - int sample_count = buffer_ms * 32000 / 1000; - int lag_sample_count = lag_ms * 32000 / 1000; + int sample_count = buffer_ms * 32040 / 1000; + int lag_sample_count = lag_ms * 32040 / 1000; spc::lag_master = lag_sample_count; if (Settings.Stereo) @@ -442,6 +488,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) spc::buffer_size <<= 1; if (Settings.SixteenBitSound) spc::buffer_size <<= 1; + msu::buffer_size = ((buffer_ms * 44100 / 1000) * 44100 / 32040) << 2; // Always 16-bit, Stereo printf("Sound buffer size: %d (%d samples)\n", spc::buffer_size, sample_count); @@ -450,6 +497,11 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) spc::landing_buffer = new uint8[spc::buffer_size * 2]; if (!spc::landing_buffer) return (FALSE); + if (msu::landing_buffer) + delete[] msu::landing_buffer; + msu::landing_buffer = new uint8[msu::buffer_size * 2]; + if (!msu::landing_buffer) + return (FALSE); /* The resampler and spc unit use samples (16-bit short) as arguments. Use 2x in the resampler for buffer leveling with SoundSync */ @@ -465,6 +517,20 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) else spc::resampler->resize(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); + + if (!msu::resampler) + { + msu::resampler = new HermiteResampler(msu::buffer_size); + if (!msu::resampler) + { + delete[] msu::landing_buffer; + return (FALSE); + } + } + else + msu::resampler->resize(msu::buffer_size); + + SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size); UpdatePlaybackRate(); @@ -503,6 +569,7 @@ bool8 S9xInitAPU (void) spc::landing_buffer = NULL; spc::shrink_buffer = NULL; spc::resampler = NULL; + msu::resampler = NULL; return (TRUE); } @@ -526,6 +593,18 @@ void S9xDeinitAPU (void) delete[] spc::shrink_buffer; spc::shrink_buffer = NULL; } + + if (msu::resampler) + { + delete msu::resampler; + msu::resampler = NULL; + } + + if (msu::landing_buffer) + { + delete[] msu::landing_buffer; + msu::landing_buffer = NULL; + } } static inline int S9xAPUGetClock (int32 cpucycles) @@ -603,6 +682,9 @@ void S9xResetAPU (void) SNES::dsp.spc_dsp.set_spc_snapshot_callback(SPCSnapshotCallback); spc::resampler->clear(); + + if (Settings.MSU1) + msu::resampler->clear(); } void S9xSoftResetAPU (void) @@ -615,6 +697,9 @@ void S9xSoftResetAPU (void) SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); spc::resampler->clear(); + + if (Settings.MSU1) + msu::resampler->clear(); } void S9xAPUSaveState (uint8 *block) diff --git a/apu/hermite_resampler.h b/apu/hermite_resampler.h index 8c7dd96b..ea526ef1 100644 --- a/apu/hermite_resampler.h +++ b/apu/hermite_resampler.h @@ -4,6 +4,7 @@ #define __HERMITE_RESAMPLER_H #include "resampler.h" +#include <assert.h> #undef CLAMP #undef SHORT_CLAMP @@ -66,6 +67,7 @@ class HermiteResampler : public Resampler void read (short *data, int num_samples) { + assert((num_samples & 1) == 0); // resampler always processes both stereo samples int i_position = start >> 1; int max_samples = buffer_size >> 1; short *internal_buffer = (short *) buffer; diff --git a/bsx.cpp b/bsx.cpp index c317bd26..2b4454e3 100644 --- a/bsx.cpp +++ b/bsx.cpp @@ -199,7 +199,7 @@ //#define BSX_DEBUG #define BIOS_SIZE 0x100000 -#define FLASH_SIZE 0x200000 +#define FLASH_SIZE 0x100000 #define PSRAM_SIZE 0x80000 #define Map Memory.Map @@ -231,7 +231,7 @@ static const uint8 flashcard[20] = { 0x4D, 0x00, 0x50, 0x00, // vendor id 0x00, 0x00, // ? - 0x2B, 0x00, // 2MB Flash (1MB = 0x2A) + 0x1A, 0x00, // 2MB Flash (1MB = 0x2A) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -417,13 +417,22 @@ static void map_psram_mirror_sub (uint32 bank) { for (c = 0; c < 0x100; c += 16) { - for (i = c; i < c + 8; i++) - Map[i + bank] = &PSRAM[(c << 11) % PSRAM_SIZE]; + if ((bank & 0x7F) >= 0x40) + { + for (i = c; i < c + 8; i++) + Map[i + bank] = &PSRAM[(c << 11) % PSRAM_SIZE]; + + for (i = c; i < c + 8; i++) + { + BlockIsRAM[i + bank] = TRUE; + BlockIsROM[i + bank] = FALSE; + } + } for (i = c + 8; i < c + 16; i++) Map[i + bank] = &PSRAM[(c << 11) % PSRAM_SIZE] - 0x8000; - for (i = c; i < c + 16; i++) + for (i = c + 8; i < c + 16; i++) { BlockIsRAM[i + bank] = TRUE; BlockIsROM[i + bank] = FALSE; @@ -432,42 +441,126 @@ static void map_psram_mirror_sub (uint32 bank) } } -static void BSX_Map_PSRAM (void) +static void BSX_Map_PSRAM(void) { - int c; + int c, i; - // Banks 70->77:0000-FFFF - // FIXME: could be toggled by $03 - for (c = 0; c < 0x80; c++) + if (!BSX.MMC[0x02]) { - Map[c + 0x700] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; - BlockIsRAM[c + 0x700] = TRUE; - BlockIsROM[c + 0x700] = FALSE; - } + //LoROM Mode + if (!BSX.MMC[0x05] && !BSX.MMC[0x06]) + { + //Map PSRAM to 00-0F/80-8F + if (BSX.MMC[0x03]) + map_psram_mirror_sub(0x00); - // Banks 20->3F:6000-7FFF mirrors 70->77:6000-7FFF - for (c = 0x200; c < 0x400; c += 16) + if (BSX.MMC[0x04]) + map_psram_mirror_sub(0x80); + } + else if (BSX.MMC[0x05] && !BSX.MMC[0x06]) + { + //Map PSRAM to 20-2F/A0-AF + if (BSX.MMC[0x03]) + map_psram_mirror_sub(0x20); + + if (BSX.MMC[0x04]) + map_psram_mirror_sub(0xA0); + } + else if (!BSX.MMC[0x05] && BSX.MMC[0x06]) + { + //Map PSRAM to 40-4F/C0-CF + if (BSX.MMC[0x03]) + map_psram_mirror_sub(0x40); + + if (BSX.MMC[0x04]) + map_psram_mirror_sub(0xC0); + } + else + { + //Map PSRAM to 60-6F/E0-EF + if (BSX.MMC[0x03]) + map_psram_mirror_sub(0x60); + + if (BSX.MMC[0x04]) + map_psram_mirror_sub(0xE0); + } + + //Map PSRAM to 70-7D/F0-FF + if (BSX.MMC[0x03]) + map_psram_mirror_sub(0x70); + + if (BSX.MMC[0x04]) + map_psram_mirror_sub(0xF0); + } + else { - Map[c + 6] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; - Map[c + 7] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; - BlockIsRAM[c + 6] = TRUE; - BlockIsRAM[c + 7] = TRUE; - BlockIsROM[c + 6] = FALSE; - BlockIsROM[c + 7] = FALSE; + //HiROM Mode + if (!BSX.MMC[0x05] && !BSX.MMC[0x06]) + { + //Map PSRAM to 40-47/C0-C7 + if (BSX.MMC[0x03]) + map_psram_mirror_sub(0x40); + + if (BSX.MMC[0x04]) + map_psram_mirror_sub(0xC0); + + } + else if (BSX.MMC[0x05] && !BSX.MMC[0x06]) + { + //Map PSRAM to 50-57/D0-D7 + if (BSX.MMC[0x03]) + map_psram_mirror_sub(0x50); + + if (BSX.MMC[0x04]) + map_psram_mirror_sub(0xD0); + } + else if (!BSX.MMC[0x05] && BSX.MMC[0x06]) + { + //Map PSRAM to 60-67/E0-E7 + if (BSX.MMC[0x03]) + map_psram_mirror_sub(0x60); + + if (BSX.MMC[0x04]) + map_psram_mirror_sub(0xE0); + } + else + { + //Map PSRAM to 70-77/F0-F7 + if (BSX.MMC[0x03]) + map_psram_mirror_sub(0x70); + + if (BSX.MMC[0x04]) + map_psram_mirror_sub(0xF0); + } + + if (BSX.MMC[0x03]) + { + //Map PSRAM to 20->3F:6000-7FFF + for (c = 0x200; c < 0x400; c += 16) + { + Map[c + 6] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; + Map[c + 7] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; + BlockIsRAM[c + 6] = TRUE; + BlockIsRAM[c + 7] = TRUE; + BlockIsROM[c + 6] = FALSE; + BlockIsROM[c + 7] = FALSE; + } + } + + if (BSX.MMC[0x04]) + { + //Map PSRAM to A0->BF:6000-7FFF + for (c = 0xA00; c < 0xC00; c += 16) + { + Map[c + 6] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; + Map[c + 7] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; + BlockIsRAM[c + 6] = TRUE; + BlockIsRAM[c + 7] = TRUE; + BlockIsROM[c + 6] = FALSE; + BlockIsROM[c + 7] = FALSE; + } + } } - - if (!BSX.MMC[0x05]) - // Banks 40->4F:0000-FFFF mirrors 70->77:0000-7FFF - map_psram_mirror_sub(0x40); - - if (!BSX.MMC[0x06]) - // Banks 50->5F:0000-FFFF mirrors 70->77:0000-7FFF - map_psram_mirror_sub(0x50); - - // FIXME - if (!BSX.MMC[0x03]) - // Banks 60->6F:0000-FFFF mirrors 70->77:0000-7FFF (?) - map_psram_mirror_sub(0x60); } static void BSX_Map_BIOS (void) @@ -562,28 +655,8 @@ static void BSX_Map (void) memcpy(BSX.prevMMC, BSX.MMC, sizeof(BSX.MMC)); - // Do a quick bank change - if (BSX.dirty2 && !BSX.dirty) - { - BSX_Map_Dirty(); - BSX_Map_BIOS(); - - BSX.dirty2 = FALSE; - - Memory.map_WriteProtectROM(); - return; - } - - if (BSX.MMC[0x01]) - { - MapROM = PSRAM; - FlashSize = PSRAM_SIZE; - } - else - { - MapROM = FlashROM; - FlashSize = FLASH_SIZE; - } + MapROM = FlashROM; + FlashSize = FLASH_SIZE; BSX_Map_SNES(); @@ -592,12 +665,12 @@ static void BSX_Map (void) else BSX_Map_LoROM(); + BSX_Map_FlashIO(); BSX_Map_PSRAM(); BSX_Map_SRAM(); BSX_Map_RAM(); BSX_Map_BIOS(); - BSX_Map_FlashIO(); BSX_Map_MMC(); // Monitor new register changes @@ -607,30 +680,24 @@ static void BSX_Map (void) Memory.map_WriteProtectROM(); } -static uint8 BSX_Get_Bypass_FlashIO (uint16 offset) +static uint8 BSX_Get_Bypass_FlashIO (uint32 offset) { + MapROM = FlashROM = Memory.ROM + Multi.cartOffsetB; + if (BSX.MMC[0x02]) - return (MapROM[offset]); + return (MapROM[offset & 0x0FFFFF]); else - { - if (offset < 0x8000) - return (MapROM[offset]); - else - return (MapROM[offset - 0x8000]); - } + return (MapROM[(offset & 0x1F0000) >> 1 | (offset & 0x7FFF)]); } -static void BSX_Set_Bypass_FlashIO (uint16 offset, uint8 byte) +static void BSX_Set_Bypass_FlashIO (uint32 offset, uint8 byte) { + MapROM = FlashROM = Memory.ROM + Multi.cartOffsetB; + if (BSX.MMC[0x02]) - MapROM[offset] = byte; + MapROM[offset & 0x0FFFFF] = MapROM[offset & 0x0FFFFF] & byte; else - { - if (offset < 0x8000) - MapROM[offset] = byte; - else - MapROM[offset - 0x8000] = byte; - } + MapROM[(offset & 0x1F0000) >> 1 | (offset & 0x7FFF)] = MapROM[(offset & 0x1F0000) >> 1 | (offset & 0x7FFF)] & byte; } uint8 S9xGetBSX (uint32 address) @@ -640,43 +707,57 @@ uint8 S9xGetBSX (uint32 address) uint8 t = 0; // MMC - if ((bank >= 0x01 && bank <= 0x0E) && (offset == 0x5000)) + if ((bank >= 0x01 && bank <= 0x0E)) return (BSX.MMC[bank]); // Flash IO - if (bank == 0xC0) + if (bank >= 0xC0) { // default: read-through mode - t = BSX_Get_Bypass_FlashIO(offset); + t = BSX_Get_Bypass_FlashIO(address); // note: may be more registers, purposes unknown switch (offset) { - case 0x0002: - if (BSX.flash_enable) - t = 0x80; // status register? - break; + case 0x0002: + case 0x8002: + if (BSX.flash_bsr) + t = 0xC0; // Page Status Register + break; - case 0x5555: - if (BSX.flash_enable) - t = 0x80; // ??? - break; + case 0x0004: + case 0x8004: + if (BSX.flash_gsr) + t = 0x82; // Global Status Register + break; - case 0xFF00: - case 0xFF02: - case 0xFF04: - case 0xFF06: - case 0xFF08: - case 0xFF0A: - case 0xFF0C: - case 0xFF0E: - case 0xFF10: - case 0xFF12: - // return flash vendor information - if (BSX.read_enable) - t = flashcard[offset - 0xFF00]; - break; + case 0x5555: + if (BSX.flash_enable) + t = 0x80; // ??? + break; + + case 0xFF00: + case 0xFF02: + case 0xFF04: + case 0xFF06: + case 0xFF08: + case 0xFF0A: + case 0xFF0C: + case 0xFF0E: + case 0xFF10: + case 0xFF12: + // return flash vendor information + if (BSX.read_enable) + t = flashcard[offset - 0xFF00]; + break; } + + if (BSX.flash_csr) + { + t = 0x80; // Compatible Status Register + BSX.flash_csr = false; + } + } return (t); @@ -688,115 +769,126 @@ void S9xSetBSX (uint8 byte, uint32 address) uint16 offset = address & 0xFFFF; // MMC - if ((bank >= 0x01 && bank <= 0x0E) && (offset == 0x5000)) + if ((bank >= 0x01 && bank <= 0x0E)) { - switch (bank) - { - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - if (BSX.MMC[bank] != byte) - { - BSX.MMC[bank] = byte; - BSX.dirty = TRUE; - } - break; - - case 0x07: - case 0x08: - if (BSX.MMC[bank] != byte) - { - BSX.MMC[bank] = byte; - BSX.dirty2 = TRUE; - } - break; - - case 0x0E: - BSX.MMC[bank] = byte; - if (byte && (BSX.dirty || BSX.dirty2)) - BSX_Map(); - break; - } + BSX.MMC[bank] = byte; + if (bank == 0x0E) + BSX_Map(); } // Flash IO - if (bank == 0xC0) + if (bank >= 0xC0) { - BSX.old_write = BSX.new_write; - BSX.new_write = address; - - // ???: double writes to the desired address will bypass - // flash registers - if (BSX.old_write == BSX.new_write && BSX.write_enable) + // Write to Flash + if (BSX.write_enable) { - BSX_Set_Bypass_FlashIO(offset, byte); + BSX_Set_Bypass_FlashIO(address, byte); + //MapROM[address & 0x3FFFFF] = byte; + BSX.write_enable = false; return; } - // flash command handling - // note: incomplete - switch (offset) - { - case 0x0000: - BSX.flash_command <<= 8; - BSX.flash_command |= byte; - if ((BSX.flash_command & 0xFFFF) == 0x38D0) - { - // retrieve information about the flash card - BSX.flash_enable = TRUE; - BSX.read_enable = TRUE; - } - break; + // Flash Command Handling + if (BSX.MMC[0xC]) { + //Memory Pack Type 1 & 3 & 4 + BSX.flash_command <<= 8; + BSX.flash_command |= byte; - case 0x2AAA: - BSX.flash_command <<= 8; - BSX.flash_command |= byte; - break; + switch (BSX.flash_command & 0xFF) + { + case 0x00: + case 0xFF: + //Reset to normal + BSX.flash_enable = false; + BSX.flash_bsr = false; + BSX.flash_csr = false; + BSX.flash_gsr = false; + BSX.read_enable = false; + BSX.write_enable = false; + BSX.flash_cmd_done = true; + break; - case 0x5555: - BSX.flash_command <<= 8; - BSX.flash_command |= byte; + case 0x10: + case 0x40: + //Write Byte + BSX.flash_enable = false; + BSX.flash_bsr = false; + BSX.flash_csr = true; + BSX.flash_gsr = false; + BSX.read_enable = false; + BSX.write_enable = true; + BSX.flash_cmd_done = true; + break; - switch (BSX.flash_command & 0xFFFFFF) - { - case 0xAA55F0: - // turn off flash i/o - BSX.flash_enable = FALSE; - BSX.write_enable = FALSE; - BSX.read_enable = FALSE; - break; + case 0x50: + //Clear Status Register + BSX.flash_enable = false; + BSX.flash_bsr = false; + BSX.flash_csr = false; + BSX.flash_gsr = false; + BSX.flash_cmd_done = true; + break; - case 0xAA55A0: - // enable writing to flash - BSX.old_write = 0; - BSX.new_write = 0; - BSX.flash_enable = TRUE; - BSX.write_enable = TRUE; - BSX_Map(); - break; + case 0x70: + //Read CSR + BSX.flash_enable = false; + BSX.flash_bsr = false; + BSX.flash_csr = true; + BSX.flash_gsr = false; + BSX.read_enable = false; + BSX.write_enable = false; + BSX.flash_cmd_done = true; + break; - case 0xAA5570: - // turn on write-protection - BSX.write_enable = FALSE; - BSX_Map(); - break; + case 0x71: + //Read Extended Status Registers (Page and Global) + BSX.flash_enable = false; + BSX.flash_bsr = true; + BSX.flash_csr = false; + BSX.flash_gsr = true; + BSX.read_enable = false; + BSX.write_enable = false; + BSX.flash_cmd_done = true; + break; - case 0xAA5580: - case 0xAA5510: - // ??? - break; + case 0x75: + //Show Page Buffer / Vendor Info + BSX.flash_csr = false; + BSX.read_enable = true; + BSX.flash_cmd_done = true; + break; - } + case 0xD0: + //DO COMMAND + switch (BSX.flash_command & 0xFFFF) + { + case 0x20D0: //Block Erase + uint32 x; + for (x = 0; x < 0x10000; x++) { + //BSX_Set_Bypass_FlashIO(((address & 0xFF0000) + x), 0xFF); + if (BSX.MMC[0x02]) + MapROM[(address & 0x0F0000) + x] = 0xFF; + else + MapROM[((address & 0x1E0000) >> 1) + x] = 0xFF; + } + break; - break; + case 0xA7D0: //Chip Erase (ONLY IN TYPE 1 AND 4) + if ((flashcard[6] & 0xF0) == 0x10 || (flashcard[6] & 0xF0) == 0x40) + { + uint32 x; + for (x = 0; x < FLASH_SIZE; x++) { + //BSX_Set_Bypass_FlashIO(x, 0xFF); + MapROM[x] = 0xFF; + } + } + break; + + case 0x38D0: //Flashcart Reset + break; + } + break; + } } } } @@ -1082,7 +1174,7 @@ void S9xInitBSX (void) uint8 *header = r1 ? Memory.ROM + 0x7FC0 : Memory.ROM + 0xFFC0; FlashMode = (header[0x18] & 0xEF) == 0x20 ? FALSE : TRUE; - FlashSize = (header[0x19] & 0x20) ? PSRAM_SIZE : FLASH_SIZE; + FlashSize = FLASH_SIZE; #ifdef BSX_DEBUG for (int i = 0; i <= 0x1F; i++) @@ -1145,32 +1237,11 @@ void S9xResetBSX (void) memset(BSX.output, 0, sizeof(BSX.output)); // starting from the bios - if (BSX.bootup) - BSX.MMC[0x07] = BSX.MMC[0x08] = 0x80; - else - { - BSX.MMC[0x02] = FlashMode ? 0x80: 0; + BSX.MMC[0x02] = BSX.MMC[0x03] = BSX.MMC[0x05] = BSX.MMC[0x06] = 0x80; + BSX.MMC[0x09] = BSX.MMC[0x0B] = 0x80; - // per bios: run from psram or flash card - if (FlashSize == PSRAM_SIZE) - { - memcpy(PSRAM, FlashROM, PSRAM_SIZE); - - BSX.MMC[0x01] = 0x80; - BSX.MMC[0x03] = 0x80; - BSX.MMC[0x04] = 0x80; - BSX.MMC[0x0C] = 0x80; - BSX.MMC[0x0D] = 0x80; - } - else - { - BSX.MMC[0x03] = 0x80; - BSX.MMC[0x05] = 0x80; - BSX.MMC[0x06] = 0x80; - } - - BSX.MMC[0x0E] = 0x80; - } + BSX.MMC[0x07] = BSX.MMC[0x08] = 0x80; + BSX.MMC[0x0E] = 0x80; BSX_Map(); } diff --git a/bsx.h b/bsx.h index 5d5ea03d..ac5a2906 100644 --- a/bsx.h +++ b/bsx.h @@ -208,6 +208,11 @@ struct SBSX uint8 MMC[16]; uint8 prevMMC[16]; uint8 test2192[32]; + + bool flash_csr; + bool flash_gsr; + bool flash_bsr; + bool flash_cmd_done; }; extern struct SBSX BSX; diff --git a/conffile.h b/conffile.h index ed8a13b4..366706fa 100644 --- a/conffile.h +++ b/conffile.h @@ -197,7 +197,11 @@ #include <string> #ifdef UNZIP_SUPPORT -#include "unzip/unzip.h" +# ifdef SYSTEM_ZIP +# include <minizip/unzip.h> +# else +# include "unzip/unzip.h" +# endif #endif #include "snes9x.h" diff --git a/cpu.cpp b/cpu.cpp index 545cd116..474fba8a 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -295,6 +295,7 @@ void S9xReset (void) S9xResetPPU(); S9xResetDMA(); S9xResetAPU(); + S9xResetMSU(); if (Settings.DSP) S9xResetDSP(); @@ -312,6 +313,8 @@ void S9xReset (void) S9xResetOBC1(); if (Settings.SRTC) S9xResetSRTC(); + if (Settings.MSU1) + S9xMSU1Init(); S9xInitCheatData(); } @@ -329,6 +332,7 @@ void S9xSoftReset (void) S9xSoftResetPPU(); S9xResetDMA(); S9xSoftResetAPU(); + S9xResetMSU(); if (Settings.DSP) S9xResetDSP(); @@ -346,6 +350,8 @@ void S9xSoftReset (void) S9xResetOBC1(); if (Settings.SRTC) S9xResetSRTC(); + if (Settings.MSU1) + S9xMSU1Init(); S9xInitCheatData(); } diff --git a/getset.h b/getset.h index f72be543..747b5630 100644 --- a/getset.h +++ b/getset.h @@ -199,6 +199,7 @@ #include "obc1.h" #include "seta.h" #include "bsx.h" +#include "msu1.h" #define addCyclesInMemoryAccess \ if (!CPU.InDMAorHDMA) \ diff --git a/globals.cpp b/globals.cpp index f9e18888..25afc1c9 100644 --- a/globals.cpp +++ b/globals.cpp @@ -232,6 +232,7 @@ struct SSPC7110Snapshot s7snap; struct SSRTCSnapshot srtcsnap; struct SRTCData RTCData; struct SBSX BSX; +struct SMSU1 MSU1; struct SMulti Multi; struct SSettings Settings; struct SSNESGameFixes SNESGameFixes; diff --git a/gtk/Makefile.am b/gtk/Makefile.am index fad1cf22..54fb3e59 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -136,6 +136,11 @@ snes9x_gtk_SOURCES += \ ../apu/bapu/smp/smp.cpp \ ../apu/bapu/smp/smp_state.cpp +# MSU1 +snes9x_gtk_SOURCES += \ + ../msu1.cpp \ + ../msu1.h + # DSP snes9x_gtk_SOURCES += \ ../dsp.cpp \ @@ -196,12 +201,16 @@ snes9x_gtk_SOURCES += \ ../server.cpp endif + # Zip support is nonconfigurable. snes9x_gtk_SOURCES += \ - ../loadzip.cpp \ + ../loadzip.cpp +if ! SYSTEM_ZIP +snes9x_gtk_SOURCES += \ ../unzip/unzip.c \ ../unzip/ioapi.c \ ../unzip/zip.c +endif UNZIPDEFINES=-DUNZIP_SUPPORT if JMA diff --git a/gtk/configure.ac b/gtk/configure.ac index 4d21792a..50f204f3 100644 --- a/gtk/configure.ac +++ b/gtk/configure.ac @@ -138,6 +138,12 @@ AC_ARG_WITH(zlib, [], [with_zlib=yes]) +AC_ARG_WITH(system-zip, + [AS_HELP_STRING([--with(out)-system-zip], + [Use system zip])], + [], + [system_zip=check]) + AC_ARG_WITH(screenshot, [AS_HELP_STRING([--with(out)-screenshot], [Screenshot support through libpng if available (default: with)])], @@ -313,6 +319,25 @@ if test yes = "$with_screenshot"; then ]) fi +SYSTEM_ZIP=0 +SYSTEM_ZIP_CFLAGS="" +SYSTEM_ZIP_LIBS="" +ZIP_CFLAGS="-I../unzip" +if test no != "$with_system_zip" && test yes = "$with_zlib" ; then + PKG_CHECK_MODULES([SYSTEM_ZIP],[minizip],[ + ZIP_CFLAGS="" + SYSTEM_ZIP=yes + CFLAGS="$CFLAGS $SYSTEM_ZIP_CFLAGS -DSYSTEM_ZIP" + LIBS="$LIBS $SYSTEM_ZIP_LIBS" + ],[ + if test check = "$with_system_zip"; then + AC_MSG_WARN(Cannot find system minizip library) + else + AC_MSG_ERROR(--with-system-zip given but cannot find system minizip library) + fi + ]) +fi + if test yes = "$with_hq2x" ; then HQ2X=yes CFLAGS="$CFLAGS -DUSE_HQ2X" @@ -440,7 +465,7 @@ if test $ac_cv_my_sar_int8 = yes && \ CFLAGS="$CFLAGS -DRIGHTSHIFT_IS_SAR" fi -CFLAGS="$CFLAGS -DUNZIP_SUPPORT -DSPC700_C -I. -I.. -I../unzip" +CFLAGS="$CFLAGS -DUNZIP_SUPPORT -DSPC700_C -I. -I.. $ZIP_CFLAGS" CXXFLAGS="$CFLAGS" @@ -462,6 +487,7 @@ AM_CONDITIONAL(ALSA, [test yes = "$ALSA"]) AM_CONDITIONAL(PULSEAUDIO, [test yes = "$PULSEAUDIO"]) AM_CONDITIONAL(HQ2X, [test yes = "$HQ2X"]) AM_CONDITIONAL(XBRZ, [test yes = "$XBRZ"]) +AM_CONDITIONAL(SYSTEM_ZIP, [test yes = "$SYSTEM_ZIP"]) AC_SUBST(NASM) AC_SUBST(NASM_FLAGS) diff --git a/gtk/src/gtk_file.cpp b/gtk/src/gtk_file.cpp index 9c0e0009..b6607f75 100644 --- a/gtk/src/gtk_file.cpp +++ b/gtk/src/gtk_file.cpp @@ -422,7 +422,7 @@ S9xOpenROMDialog (void) { "*.smc", "*.SMC", "*.fig", "*.FIG", "*.sfc", "*.SFC", "*.jma", "*.JMA", "*.zip", "*.ZIP", "*.gd3", "*.GD3", - "*.swc", "*.SWC", "*.gz" , "*.GZ", + "*.swc", "*.SWC", "*.gz" , "*.GZ", "*.bs", "*.BS", NULL }; diff --git a/language.h b/language.h index c4c584f6..8304124f 100644 --- a/language.h +++ b/language.h @@ -208,7 +208,7 @@ #define SAVE_INFO_LOAD "Loaded" #define SAVE_INFO_OOPS "Auto-saving 'oops' snapshot" #define SAVE_ERR_WRONG_FORMAT "File not in Snes9x snapshot format" -#define SAVE_ERR_WRONG_VERSION "Incompatable snapshot version" +#define SAVE_ERR_WRONG_VERSION "Incompatible snapshot version" #define SAVE_ERR_ROM_NOT_FOUND "ROM image \"%s\" for snapshot not found" #define SAVE_ERR_SAVE_NOT_FOUND "Snapshot %s does not exist" diff --git a/libretro/Makefile b/libretro/Makefile index 852595bd..ea9c93ca 100644 --- a/libretro/Makefile +++ b/libretro/Makefile @@ -167,6 +167,8 @@ else ifneq (,$(findstring armv,$(platform))) CXXFLAGS += -marm -mcpu=cortex-a8 else ifneq (,$(findstring cortexa9,$(platform))) CXXFLAGS += -marm -mcpu=cortex-a9 + else ifneq (,$(findstring cortexa53,$(platform))) + CXXFLAGS += -marm -mcpu=cortex-a53 endif CXXFLAGS += -marm ifneq (,$(findstring neon,$(platform))) @@ -180,6 +182,14 @@ else ifneq (,$(findstring armv,$(platform))) endif CXXFLAGS += -DARM +# Android +else ifneq (,$(findstring android,$(platform))) + TARGET := $(TARGET_NAME)_libretro_android.so + SHARED := -shared -Wl,--no-undefined -march=armv7-a -Wl,--fix-cortex-a8 + fpic := -fPIC + CXXFLAGS += -marm -march=armv7-a -mfloat-abi=softfp -mfpu=neon -DANDROID -DARM + HAVE_NEON = 1 + # Windows else TARGET := $(TARGET_NAME)_libretro.dll diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 3025492b..7b29c937 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -30,11 +30,14 @@ SOURCES_CXX := $(CORE_DIR)/apu/apu.cpp \ $(CORE_DIR)/globals.cpp \ $(CORE_DIR)/logger.cpp \ $(CORE_DIR)/memmap.cpp \ + $(CORE_DIR)/movie.cpp \ + $(CORE_DIR)/msu1.cpp \ $(CORE_DIR)/obc1.cpp \ $(CORE_DIR)/ppu.cpp \ $(CORE_DIR)/stream.cpp \ $(CORE_DIR)/sa1.cpp \ $(CORE_DIR)/sa1cpu.cpp \ + $(CORE_DIR)/screenshot.cpp \ $(CORE_DIR)/sdd1.cpp \ $(CORE_DIR)/sdd1emu.cpp \ $(CORE_DIR)/seta.cpp \ diff --git a/libretro/libretro-win32.vcxproj b/libretro/libretro-win32.vcxproj index adbf9f08..cfc8c204 100644 --- a/libretro/libretro-win32.vcxproj +++ b/libretro/libretro-win32.vcxproj @@ -222,6 +222,7 @@ <ClInclude Include="..\messages.h" /> <ClInclude Include="..\missing.h" /> <ClInclude Include="..\movie.h" /> + <ClInclude Include="..\msu1.h" /> <ClInclude Include="..\netplay.h" /> <ClInclude Include="..\obc1.h" /> <ClInclude Include="..\pixform.h" /> @@ -274,6 +275,7 @@ <ClCompile Include="..\logger.cpp" /> <ClCompile Include="..\memmap.cpp" /> <ClCompile Include="..\movie.cpp" /> + <ClCompile Include="..\msu1.cpp" /> <ClCompile Include="..\netplay.cpp" /> <ClCompile Include="..\obc1.cpp" /> <ClCompile Include="..\ppu.cpp" /> diff --git a/libretro/libretro-win32.vcxproj.filters b/libretro/libretro-win32.vcxproj.filters index 998c0e74..bb0a5065 100644 --- a/libretro/libretro-win32.vcxproj.filters +++ b/libretro/libretro-win32.vcxproj.filters @@ -180,6 +180,9 @@ <ClInclude Include="libretro.h"> <Filter>libretro</Filter> </ClInclude> + <ClInclude Include="..\msu1.h"> + <Filter>s9x-source</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\bsx.cpp"> @@ -338,5 +341,8 @@ <ClCompile Include="libretro.cpp"> <Filter>libretro</Filter> </ClCompile> + <ClCompile Include="..\msu1.cpp"> + <Filter>s9x-source</Filter> + </ClCompile> </ItemGroup> </Project> \ No newline at end of file diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 859d3f8b..08ace347 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -76,7 +76,7 @@ static bool rom_loaded = false; void retro_set_environment(retro_environment_t cb) { environ_cb = cb; - + const struct retro_variable variables[] = { // These variable names and possible values constitute an ABI with ZMZ (ZSNES Libretro player). // Changing "Show layer 1" is fine, but don't change "layer_1"/etc or the possible values ("Yes|No"). @@ -98,7 +98,7 @@ void retro_set_environment(retro_environment_t cb) { "snes9x_sndchan_8", "Enable sound channel 8; Yes|No" }, { NULL, NULL }, }; - + environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void *)variables); const struct retro_controller_description port_1[] = { @@ -128,9 +128,9 @@ static void update_variables(void) { char key[256]; struct retro_variable var; - + var.key=key; - + int disabled_channels=0; strcpy(key, "snes9x_sndchan_x"); for (int i=0;i<8;i++) @@ -140,7 +140,7 @@ static void update_variables(void) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && var.value[0]=='N') disabled_channels|=1<<i; } S9xSetSoundControl(disabled_channels^0xFF); - + int disabled_layers=0; strcpy(key, "snes9x_layer_x"); for (int i=0;i<5;i++) @@ -150,7 +150,7 @@ static void update_variables(void) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && var.value[0]=='N') disabled_layers|=1<<i; } Settings.BG_Forced=disabled_layers; - + //for some reason, Transparency seems to control both the fixed color and the windowing registers? var.key="snes9x_gfx_clip"; var.value=NULL; @@ -178,7 +178,7 @@ void retro_get_system_info(struct retro_system_info *info) info->library_name = "Snes9x"; info->library_version = VERSION; - info->valid_extensions = "smc|sfc|swc|fig"; + info->valid_extensions = "smc|sfc|swc|fig|bs"; info->need_fullpath = false; info->block_extract = false; } @@ -192,7 +192,7 @@ void retro_get_system_av_info(struct retro_system_av_info *info) info->geometry.max_width = MAX_SNES_WIDTH; info->geometry.max_height = MAX_SNES_HEIGHT; info->geometry.aspect_ratio = 4.0f / 3.0f; - info->timing.sample_rate = 32040.5; + info->timing.sample_rate = 32040; info->timing.fps = retro_get_region() == RETRO_REGION_NTSC ? 21477272.0 / 357366.0 : 21281370.0 / 425568.0; } @@ -256,10 +256,10 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code) { uint32 address; uint8 val; - + bool8 sram; uint8 bytes[3];//used only by GoldFinger, ignored for now - + if (S9xGameGenieToRaw(code, address, val)!=NULL && S9xProActionReplayToRaw(code, address, val)!=NULL && S9xGoldFingerToRaw(code, address, sram, val, bytes)!=NULL) @@ -268,13 +268,13 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code) } if (index>Cheat.num_cheats) return; // cheat added in weird order, ignore if (index==Cheat.num_cheats) Cheat.num_cheats++; - + Cheat.c[index].address = address; Cheat.c[index].byte = val; Cheat.c[index].enabled = enabled; - + Cheat.c[index].saved = FALSE; // it'll be saved next time cheats run anyways - + Settings.ApplyCheats=true; S9xApplyCheats(); } @@ -374,7 +374,7 @@ bool retro_load_game(const struct retro_game_info *game) if (!rom_loaded && log_cb) log_cb(RETRO_LOG_ERROR, "[libretro]: Rom loading failed...\n"); - + return rom_loaded; } @@ -387,7 +387,7 @@ bool retro_load_game_special(unsigned game_type, init_descriptors(); switch (game_type) { case RETRO_GAME_TYPE_BSX: - + if(num_info == 1) { rom_loaded = Memory.LoadROMMem((const uint8_t*)info[0].data,info[0].size); } else if(num_info == 2) { @@ -399,7 +399,7 @@ bool retro_load_game_special(unsigned game_type, log_cb(RETRO_LOG_ERROR, "[libretro]: BSX ROM loading failed...\n"); break; - + case RETRO_GAME_TYPE_BSX_SLOTTED: if(num_info == 2) @@ -462,8 +462,8 @@ void retro_init() Settings.FrameTimeNTSC = 16667; Settings.SixteenBitSound = TRUE; Settings.Stereo = TRUE; - Settings.SoundPlaybackRate = 32000; - Settings.SoundInputRate = 32000; + Settings.SoundPlaybackRate = 32040; + Settings.SoundInputRate = 32040; Settings.SupportHiRes = TRUE; Settings.Transparency = TRUE; Settings.AutoDisplayMessages = TRUE; @@ -633,7 +633,7 @@ static void map_buttons() } -// libretro uses relative values for analogue devices. +// libretro uses relative values for analogue devices. // S9x seems to use absolute values, but do convert these into relative values in the core. (Why?!) // Hack around it. :) static int16_t snes_mouse_state[2][2] = {{0}, {0}}; @@ -692,7 +692,7 @@ static void report_buttons() for (int i = JUSTIFIER_TRIGGER; i <= JUSTIFIER_LAST; i++) S9xReportButton(MAKE_BUTTON(2, i), input_state_cb(port, RETRO_DEVICE_LIGHTGUN, 0, i)); break; - + default: if (log_cb) log_cb(RETRO_LOG_ERROR, "[libretro]: Unknown device...\n"); @@ -718,14 +718,14 @@ void retro_deinit() Memory.Deinit(); S9xGraphicsDeinit(); S9xUnmapAllControls(); - + free(GFX.Screen); } unsigned retro_get_region() -{ - return Settings.PAL ? RETRO_REGION_PAL : RETRO_REGION_NTSC; +{ + return Settings.PAL ? RETRO_REGION_PAL : RETRO_REGION_NTSC; } void* retro_get_memory_data(unsigned type) @@ -794,7 +794,7 @@ size_t retro_serialize_size() } bool retro_serialize(void *data, size_t size) -{ +{ if (S9xFreezeGameMem((uint8_t*)data,size) == FALSE) return false; @@ -802,7 +802,7 @@ bool retro_serialize(void *data, size_t size) } bool retro_unserialize(const void* data, size_t size) -{ +{ if (S9xUnfreezeGameMem((const uint8_t*)data,size) != SUCCESS) return false; return true; @@ -870,8 +870,8 @@ void S9xExit() {} bool S9xPollPointer(unsigned int, short*, short*) { return false; } const char *S9xChooseMovieFilename(unsigned char) { return NULL; } -bool8 S9xOpenSnapshotFile(const char* filepath, bool8 read_only, STREAM *file) -{ +bool8 S9xOpenSnapshotFile(const char* filepath, bool8 read_only, STREAM *file) +{ if(read_only) { if((*file = OPEN_STREAM(filepath, "rb")) != 0) @@ -889,12 +889,12 @@ bool8 S9xOpenSnapshotFile(const char* filepath, bool8 read_only, STREAM *file) return (FALSE); } -void S9xCloseSnapshotFile(STREAM file) +void S9xCloseSnapshotFile(STREAM file) { CLOSE_STREAM(file); } -void S9xAutoSaveSRAM() +void S9xAutoSaveSRAM() { return; } diff --git a/loadzip.cpp b/loadzip.cpp index 024bc793..d3168939 100644 --- a/loadzip.cpp +++ b/loadzip.cpp @@ -192,7 +192,11 @@ #include <assert.h> #include <ctype.h> +#ifdef SYSTEM_ZIP +#include <minizip/unzip.h> +#else #include "unzip/unzip.h" +#endif #include "snes9x.h" #include "memmap.h" @@ -257,7 +261,7 @@ bool8 LoadZip (const char *zipname, uint32 *TotalFileSize, uint8 *buffer) uint8 *ptr = buffer; bool8 more = FALSE; - unzLocateFile(file, filename, 1); + unzLocateFile(file, filename, NULL); unzGetCurrentFileInfo(file, &info, filename, 128, NULL, 0, NULL, 0); if (unzOpenCurrentFile(file) != UNZ_OK) @@ -279,7 +283,7 @@ bool8 LoadZip (const char *zipname, uint32 *TotalFileSize, uint8 *buffer) return (FALSE); } - if (l <= 0 || l != FileSize) + if (l <= 0 || l != (int) FileSize) { unzClose(file); return (FALSE); @@ -317,7 +321,7 @@ bool8 LoadZip (const char *zipname, uint32 *TotalFileSize, uint8 *buffer) if (more) { - if (unzLocateFile(file, filename, 1) != UNZ_OK || + if (unzLocateFile(file, filename, NULL) != UNZ_OK || unzGetCurrentFileInfo(file, &info, filename, 128, NULL, 0, NULL, 0) != UNZ_OK || unzOpenCurrentFile(file) != UNZ_OK) break; diff --git a/memmap.cpp b/memmap.cpp index 19df95cb..d55cfad4 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -193,7 +193,11 @@ #include <assert.h> #ifdef UNZIP_SUPPORT -#include "unzip/unzip.h" +# ifdef SYSTEM_ZIP +# include <minizip/unzip.h> +# else +# include "unzip/unzip.h" +# endif #endif #ifdef JMA_SUPPORT @@ -201,6 +205,7 @@ #endif #include <ctype.h> +#include <sys/stat.h> #include "snes9x.h" #include "memmap.h" @@ -952,9 +957,9 @@ static void S9xDeinterleaveGD24 (int, uint8 *); static bool8 allASCII (uint8 *, int); static bool8 is_SufamiTurbo_BIOS (const uint8 *, uint32); static bool8 is_SufamiTurbo_Cart (const uint8 *, uint32); -static bool8 is_SameGame_BIOS (const uint8 *, uint32); +static bool8 is_BSCart_BIOS (const uint8 *, uint32); static bool8 is_SameGame_Add_On (const uint8 *, uint32); -static bool8 is_GNEXT_BIOS (const uint8 *, uint32); +static bool8 is_BSCartSA1_BIOS(const uint8 *, uint32); static bool8 is_GNEXT_Add_On (const uint8 *, uint32); static uint32 caCRC32 (uint8 *, uint32, uint32 crc32 = 0xffffffff); static uint32 ReadUPSPointer (const uint8 *, unsigned &, unsigned); @@ -1238,10 +1243,22 @@ static bool8 is_SufamiTurbo_Cart (const uint8 *data, uint32 size) return (FALSE); } -static bool8 is_SameGame_BIOS (const uint8 *data, uint32 size) +static bool8 is_BSCart_BIOS(const uint8 *data, uint32 size) { - if (size == 0x100000 && strncmp((char *) (data + 0xffc0), "Same Game Tsume Game", 20) == 0) + if ((data[0x7FB2] == 0x5A) && (data[0x7FB5] != 0x20) && (data[0x7FDA] == 0x33)) + { + Memory.LoROM = TRUE; + Memory.HiROM = FALSE; + return (TRUE); + } + else if ((data[0xFFB2] == 0x5A) && (data[0xFFB5] != 0x20) && (data[0xFFDA] == 0x33)) + { + Memory.LoROM = FALSE; + Memory.HiROM = TRUE; + + return (TRUE); + } else return (FALSE); } @@ -1254,9 +1271,14 @@ static bool8 is_SameGame_Add_On (const uint8 *data, uint32 size) return (FALSE); } -static bool8 is_GNEXT_BIOS (const uint8 *data, uint32 size) +static bool8 is_BSCartSA1_BIOS (const uint8 *data, uint32 size) { - if (size == 0x180000 && strncmp((char *) (data + 0x7fc0), "SFC SDGUNDAMGNEXT", 17) == 0) + //Same basic check as BSCart + if (!is_BSCart_BIOS(data, size)) + return (FALSE); + + //Checks if the game is Itoi's Bass Fishing No. 1 (ZBPJ) or SD Gundam G-NEXT (ZX3J) + if (strncmp((char *)(data + 0x7fb2), "ZBPJ", 4) == 0 || strncmp((char *)(data + 0x7fb2), "ZX3J", 4) == 0) return (TRUE); else return (FALSE); @@ -1861,11 +1883,11 @@ bool8 CMemory::LoadMultiCartInt () if (is_SufamiTurbo_Cart(ROM + Multi.cartOffsetA, Multi.cartSizeA)) Multi.cartType = 4; else - if (is_SameGame_BIOS(ROM + Multi.cartOffsetA, Multi.cartSizeA)) - Multi.cartType = 3; - else - if (is_GNEXT_BIOS(ROM + Multi.cartOffsetA, Multi.cartSizeA)) + if (is_BSCartSA1_BIOS(ROM + Multi.cartOffsetA, Multi.cartSizeA)) Multi.cartType = 5; + else + if (is_BSCart_BIOS(ROM + Multi.cartOffsetA, Multi.cartSizeA)) + Multi.cartType = 3; } else if (Multi.cartSizeB) @@ -1883,7 +1905,7 @@ bool8 CMemory::LoadMultiCartInt () memmove(ROM + Multi.cartOffsetA, ROM, Multi.cartSizeA + Multi.cartSizeB); else if(Multi.cartOffsetB) // clear cart A so the bios can detect that it's not present memset(ROM, 0, Multi.cartOffsetB); - + FILE *fp; size_t size; char path[PATH_MAX + 1]; @@ -1913,11 +1935,8 @@ bool8 CMemory::LoadMultiCartInt () break; case 3: - r = LoadSameGame(); - break; - case 5: - r = LoadGNEXT(); + r = LoadBSCart(); break; default: @@ -1981,26 +2000,31 @@ bool8 CMemory::LoadSufamiTurbo () return (TRUE); } -bool8 CMemory::LoadSameGame () +bool8 CMemory::LoadBSCart () { Multi.sramA = SRAM; Multi.sramB = NULL; - Multi.sramSizeA = ROM[0xffd8]; + if (LoROM) + Multi.sramSizeA = ROM[0x7fd8]; + else + Multi.sramSizeA = ROM[0xffd8]; + Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0; Multi.sramSizeB = 0; Multi.sramMaskB = 0; - if (Multi.cartSizeB) - { - if (!is_SameGame_Add_On(ROM + Multi.cartOffsetB, Multi.cartSizeB)) - Multi.cartSizeB = 0; - } - - LoROM = FALSE; - HiROM = TRUE; CalculatedSize = Multi.cartSizeA; + if (Multi.cartSizeB == 0 && Multi.cartSizeA <= (MAX_ROM_SIZE - 0x100000 - Multi.cartOffsetA)) + { + //Initialize 1MB Empty Memory Pack only if cart B is cleared + //It does not make a Memory Pack if game is loaded like a normal ROM + Multi.cartOffsetB = Multi.cartOffsetA + CalculatedSize; + Multi.cartSizeB = 0x100000; + memset(Memory.ROM + Multi.cartOffsetB, 0xFF, 0x100000); + } + return (TRUE); } @@ -2209,6 +2233,32 @@ bool8 CMemory::SaveSRAM (const char *filename) return (FALSE); } +bool8 CMemory::SaveMPAK (const char *filename) +{ + if (Settings.BS || (Multi.cartSizeB && (Multi.cartType == 3))) + { + FILE *file; + int size; + char mempakName[PATH_MAX + 1]; + + strcpy(mempakName, filename); + size = 0x100000; + if (size) + { + file = fopen(mempakName, "wb"); + if (file) + { + size_t ignore; + ignore = fwrite((char *)Memory.ROM + Multi.cartOffsetB, size, 1, file); + fclose(file); + + return (TRUE); + } + } + } + return (FALSE); +} + // initialization static uint32 caCRC32 (uint8 *array, uint32 size, uint32 crc32) @@ -2360,6 +2410,7 @@ void CMemory::InitROM (void) Settings.SETA = 0; Settings.SRTC = FALSE; Settings.BS = FALSE; + Settings.MSU1 = FALSE; SuperFX.nRomBanks = CalculatedSize >> 15; @@ -2534,6 +2585,9 @@ void CMemory::InitROM (void) break; } + // MSU1 + Settings.MSU1 = S9xMSU1ROMExists(); + //// Map memory and calculate checksum Map_Initialize(); @@ -2551,7 +2605,7 @@ void CMemory::InitROM (void) Map_ExtendedHiROMMap(); else if (Multi.cartType == 3) - Map_SameGameHiROMMap(); + Map_BSCartHiROMMap(); else Map_HiROMMap(); } @@ -2569,7 +2623,7 @@ void CMemory::InitROM (void) if (Settings.SA1) { if (Multi.cartType == 5) - Map_GNEXTSA1LoROMMap(); + Map_BSSA1LoROMMap(); else Map_SA1LoROMMap(); } @@ -2583,6 +2637,13 @@ void CMemory::InitROM (void) if (strncmp(ROMName, "WANDERERS FROM YS", 17) == 0) Map_NoMAD1LoROMMap(); else + if (Multi.cartType == 3) + if (strncmp(ROMName, "SOUND NOVEL-TCOOL", 17) == 0 || + strncmp(ROMName, "DERBY STALLION 96", 17) == 0) + Map_BSCartLoROMMap(1); + else + Map_BSCartLoROMMap(0); + else if (strncmp(ROMName, "SOUND NOVEL-TCOOL", 17) == 0 || strncmp(ROMName, "DERBY STALLION 96", 17) == 0) Map_ROM24MBSLoROMMap(); @@ -3254,9 +3315,9 @@ void CMemory::Map_SA1LoROMMap (void) BWRAM = SRAM; } -void CMemory::Map_GNEXTSA1LoROMMap (void) +void CMemory::Map_BSSA1LoROMMap(void) { - printf("Map_GNEXTSA1LoROMMap\n"); + printf("Map_BSSA1LoROMMap\n"); map_System(); map_lorom_offset(0x00, 0x3f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); @@ -3272,9 +3333,6 @@ void CMemory::Map_GNEXTSA1LoROMMap (void) for (int c = 0x40; c < 0x80; c++) map_space(c, c, 0x0000, 0xffff, SRAM + (c & 1) * 0x10000); - // FIXME: untested! - map_hirom_offset(0x70, 0x7f, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); - map_WRAM(); map_WriteProtectROM(); @@ -3334,26 +3392,6 @@ void CMemory::Map_ExtendedHiROMMap (void) map_WriteProtectROM(); } -void CMemory::Map_SameGameHiROMMap (void) -{ - printf("Map_SameGameHiROMMap\n"); - map_System(); - - map_hirom_offset(0x00, 0x1f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); - map_hirom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); - map_hirom_offset(0x40, 0x5f, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); - map_hirom_offset(0x60, 0x7f, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); - map_hirom_offset(0x80, 0x9f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); - map_hirom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); - map_hirom_offset(0xc0, 0xdf, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); - map_hirom_offset(0xe0, 0xff, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); - - map_HiROMSRAM(); - map_WRAM(); - - map_WriteProtectROM(); -} - void CMemory::Map_SPC7110HiROMMap (void) { printf("Map_SPC7110HiROMMap\n"); @@ -3372,6 +3410,71 @@ void CMemory::Map_SPC7110HiROMMap (void) map_WriteProtectROM(); } +void CMemory::Map_BSCartLoROMMap(uint8 mapping) +{ + printf("Map_BSCartLoROMMap\n"); + + BSX.MMC[0x02] = 0x00; + BSX.MMC[0x0C] = 0x80; + + map_System(); + + if (mapping) + { + map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x100000, 0); + map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000); + map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x100000, 0x200000); + map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000); + } + else + { + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x40, 0x7f, 0x0000, 0x7fff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_lorom(0xc0, 0xff, 0x0000, 0x7fff, CalculatedSize); + } + + map_LoROMSRAM(); + map_index(0xc0, 0xef, 0x0000, 0xffff, MAP_BSX, MAP_TYPE_RAM); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_BSCartHiROMMap(void) +{ + printf("Map_BSCartHiROMMap\n"); + + BSX.MMC[0x02] = 0x80; + BSX.MMC[0x0C] = 0x80; + + map_System(); + map_hirom_offset(0x00, 0x1f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_hirom_offset(0x40, 0x5f, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0x60, 0x7f, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_hirom_offset(0x80, 0x9f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_hirom_offset(0xc0, 0xdf, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + + if ((ROM[Multi.cartOffsetB + 0xFF00] == 0x4D) + && (ROM[Multi.cartOffsetB + 0xFF02] == 0x50) + && ((ROM[Multi.cartOffsetB + 0xFF06] & 0xF0) == 0x70)) + { + //Type 7 Memory Pack detection - if detected, emulate it as Mask ROM + map_hirom_offset(0xe0, 0xff, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + } + else + { + map_index(0xe0, 0xff, 0x0000, 0xffff, MAP_BSX, MAP_TYPE_RAM); + } + + map_HiROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + // checksum uint16 CMemory::checksum_calc_sum (uint8 *data, uint32 length) @@ -3486,7 +3589,7 @@ const char * CMemory::KartContents (void) static char str[64]; static const char *contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" }; - char chip[16]; + char chip[20]; if (ROMType == 0 && !Settings.BS) return ("ROM"); @@ -3532,6 +3635,9 @@ const char * CMemory::KartContents (void) else strcpy(chip, ""); + if (Settings.MSU1) + sprintf(chip + strlen(chip), "+MSU-1"); + sprintf(str, "%s%s", contents[(ROMType & 0xf) % 3], chip); return (str); @@ -4128,8 +4234,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r { printf("Using BPS patch %s", fname); - ret = ReadBPSPatch(new fStream(patch_file), 0, rom_size); - CLOSE_FSTREAM(patch_file); + Stream *s = new fStream(patch_file); + ret = ReadBPSPatch(s, 0, rom_size); + s->closeStream(); if (ret) { @@ -4151,8 +4258,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r { printf(" in %s", rom_filename); - ret = ReadBPSPatch(new unzStream(file), offset, rom_size); - unzCloseCurrentFile(file); + Stream *s = new unzStream(file); + ret = ReadBPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) printf("!\n"); @@ -4169,8 +4277,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r { printf("Using BPS patch %s", n); - ret = ReadBPSPatch(new fStream(patch_file), 0, rom_size); - CLOSE_FSTREAM(patch_file); + Stream *s = new fStream(patch_file); + ret = ReadBPSPatch(s, 0, rom_size); + s->closeStream(); if (ret) { @@ -4189,8 +4298,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r { printf("Using UPS patch %s", fname); - ret = ReadUPSPatch(new fStream(patch_file), 0, rom_size); - CLOSE_FSTREAM(patch_file); + Stream *s = new fStream(patch_file); + ret = ReadUPSPatch(s, 0, rom_size); + s->closeStream(); if (ret) { @@ -4212,8 +4322,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r { printf(" in %s", rom_filename); - ret = ReadUPSPatch(new unzStream(file), offset, rom_size); - unzCloseCurrentFile(file); + Stream *s = new unzStream(file); + ret = ReadUPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) printf("!\n"); @@ -4230,8 +4341,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r { printf("Using UPS patch %s", n); - ret = ReadUPSPatch(new fStream(patch_file), 0, rom_size); - CLOSE_FSTREAM(patch_file); + Stream *s = new fStream(patch_file); + ret = ReadUPSPatch(s, 0, rom_size); + s->closeStream(); if (ret) { @@ -4250,8 +4362,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r { printf("Using IPS patch %s", fname); - ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); - CLOSE_FSTREAM(patch_file); + Stream *s = new fStream(patch_file); + ret = ReadIPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) { @@ -4277,8 +4390,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r printf("Using IPS patch %s", fname); - ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); - CLOSE_FSTREAM(patch_file); + Stream *s = new fStream(patch_file); + ret = ReadIPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) { @@ -4313,8 +4427,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r printf("Using IPS patch %s", fname); - ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); - CLOSE_FSTREAM(patch_file); + Stream *s = new fStream(patch_file); + ret = ReadIPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) { @@ -4347,8 +4462,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r printf("Using IPS patch %s", fname); - ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); - CLOSE_FSTREAM(patch_file); + Stream *s = new fStream(patch_file); + ret = ReadIPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) { @@ -4377,8 +4493,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r { printf(" in %s", rom_filename); - ret = ReadIPSPatch(new unzStream(file), offset, rom_size); - unzCloseCurrentFile(file); + Stream *s = new unzStream(file); + ret = ReadIPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) { @@ -4404,8 +4521,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r printf(" in %s", rom_filename); - ret = ReadIPSPatch(new unzStream(file), offset, rom_size); - unzCloseCurrentFile(file); + Stream *s = new unzStream(file); + ret = ReadIPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) { @@ -4438,8 +4556,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r printf(" in %s", rom_filename); - ret = ReadIPSPatch(new unzStream(file), offset, rom_size); - unzCloseCurrentFile(file); + Stream *s = new unzStream(file); + ret = ReadIPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) { @@ -4470,8 +4589,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r printf(" in %s", rom_filename); - ret = ReadIPSPatch(new unzStream(file), offset, rom_size); - unzCloseCurrentFile(file); + Stream *s = new unzStream(file); + ret = ReadIPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) { @@ -4503,8 +4623,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r { printf("Using IPS patch %s", n); - ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); - CLOSE_FSTREAM(patch_file); + Stream *s = new fStream(patch_file); + ret = ReadIPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) { @@ -4530,8 +4651,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r printf("Using IPS patch %s", n); - ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); - CLOSE_FSTREAM(patch_file); + Stream *s = new fStream(patch_file); + ret = ReadIPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) { @@ -4566,8 +4688,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r printf("Using IPS patch %s", n); - ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); - CLOSE_FSTREAM(patch_file); + Stream *s = new fStream(patch_file); + ret = ReadIPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) { @@ -4600,8 +4723,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r printf("Using IPS patch %s", n); - ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); - CLOSE_FSTREAM(patch_file); + Stream *s = new fStream(patch_file); + ret = ReadIPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) { diff --git a/memmap.h b/memmap.h index 6db01a7f..53826a98 100644 --- a/memmap.h +++ b/memmap.h @@ -293,13 +293,14 @@ struct CMemory bool8 LoadMultiCart (const char *, const char *); bool8 LoadMultiCartInt (); bool8 LoadSufamiTurbo (); - bool8 LoadSameGame (); + bool8 LoadBSCart (); bool8 LoadGNEXT (); bool8 LoadSRAM (const char *); bool8 SaveSRAM (const char *); void ClearSRAM (bool8 onlyNonSavedSRAM = 0); bool8 LoadSRTC (void); bool8 SaveSRTC (void); + bool8 SaveMPAK (const char *); char * Safe (const char *); char * SafeANK (const char *); @@ -335,11 +336,12 @@ struct CMemory void Map_SetaDSPLoROMMap (void); void Map_SDD1LoROMMap (void); void Map_SA1LoROMMap (void); - void Map_GNEXTSA1LoROMMap (void); + void Map_BSSA1LoROMMap (void); void Map_HiROMMap (void); void Map_ExtendedHiROMMap (void); - void Map_SameGameHiROMMap (void); void Map_SPC7110HiROMMap (void); + void Map_BSCartLoROMMap(uint8); + void Map_BSCartHiROMMap(void); uint16 checksum_calc_sum (uint8 *, uint32); uint16 checksum_mirror_sum (uint8 *, uint32 &, uint32 mask = 0x800000); diff --git a/movie.cpp b/movie.cpp index af2d8b3f..87426b1f 100644 --- a/movie.cpp +++ b/movie.cpp @@ -807,7 +807,9 @@ int S9xMovieOpen (const char *filename, bool8 read_only) restore_movie_settings(); lseek(fn, Movie.SaveStateOffset, SEEK_SET); - stream = REOPEN_STREAM(fn, "rb"); + + // reopen stream to access as gzipped data + stream = REOPEN_STREAM(fn, "rb"); if (!stream) return (FILE_NOT_FOUND); @@ -820,7 +822,11 @@ int S9xMovieOpen (const char *filename, bool8 read_only) else result = S9xUnfreezeFromStream(stream); - CLOSE_STREAM(stream); + // do not close stream but close FILE * + // (msvcrt will try to close all open FILE *handles on exit - if we do CLOSE_STREAM here + // the underlying file will be closed by zlib, causing problems when msvcrt tries to do it) + delete stream; + fclose(fd); if (result != SUCCESS) return (result); diff --git a/msu1.cpp b/msu1.cpp new file mode 100644 index 00000000..4ad05419 --- /dev/null +++ b/msu1.cpp @@ -0,0 +1,490 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + + (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2016 BearOso, + OV2 + + (c) Copyright 2011 - 2016 Hans-Kristian Arntzen, + Daniel De Matteis + (Under no circumstances will commercial rights be given) + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + S-SMP emulator code used in 1.54+ + (c) Copyright 2016 byuu + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2016 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2016 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2011 zones + + Libretro port + (c) Copyright 2011 - 2016 Hans-Kristian Arntzen, + Daniel De Matteis + (Under no circumstances will commercial rights be given) + + MSU-1 code + (c) Copyright 2016 qwertymodo + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com/ + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. + ***********************************************************************************/ + +#include "snes9x.h" +#include "display.h" +#include "msu1.h" +#include "apu/bapu/dsp/blargg_endian.h" +#include <fstream> +#include <sys/stat.h> + +std::ifstream dataFile, audioFile; +uint32 audioLoopPos; +uint32 partial_samples; + +// Sample buffer +int16 *bufPos, *bufBegin, *bufEnd; + +bool AudioOpen() +{ + MSU1.MSU1_STATUS |= AudioError; + + if (audioFile.is_open()) + audioFile.close(); + + char ext[_MAX_EXT]; + snprintf(ext, _MAX_EXT, "-%d.pcm", MSU1.MSU1_CURRENT_TRACK); + + audioFile.clear(); + audioFile.open(S9xGetFilename(ext, ROMFILENAME_DIR), std::ios::in | std::ios::binary); + if (audioFile.good()) + { + if (audioFile.get() != 'M') + return false; + if (audioFile.get() != 'S') + return false; + if (audioFile.get() != 'U') + return false; + if (audioFile.get() != '1') + return false; + + audioFile.read((char *)&audioLoopPos, 4); + audioLoopPos = GET_LE32(&audioLoopPos); + audioLoopPos <<= 2; + audioLoopPos += 8; + + MSU1.MSU1_STATUS &= ~AudioError; + return true; + } + + return false; +} + +bool DataOpen() +{ + if (dataFile.is_open()) + dataFile.close(); + + dataFile.clear(); + dataFile.open(S9xGetFilename(".msu", ROMFILENAME_DIR), std::ios::in | std::ios::binary); + return dataFile.is_open(); +} + +void S9xResetMSU(void) +{ + MSU1.MSU1_STATUS = 0; + MSU1.MSU1_DATA_SEEK = 0; + MSU1.MSU1_DATA_POS = 0; + MSU1.MSU1_TRACK_SEEK = 0; + MSU1.MSU1_CURRENT_TRACK = 0; + MSU1.MSU1_RESUME_TRACK = 0; + MSU1.MSU1_VOLUME = 0; + MSU1.MSU1_CONTROL = 0; + MSU1.MSU1_AUDIO_POS = 0; + MSU1.MSU1_RESUME_POS = 0; + + + bufPos = 0; + bufBegin = 0; + bufEnd = 0; + + partial_samples = 0; + + if (dataFile.is_open()) + dataFile.close(); + + if (audioFile.is_open()) + audioFile.close(); + + Settings.MSU1 = S9xMSU1ROMExists(); +} + +void S9xMSU1Init(void) +{ + S9xResetMSU(); + DataOpen(); +} + +bool S9xMSU1ROMExists(void) +{ + struct stat buf; + return (stat(S9xGetFilename(".msu", ROMFILENAME_DIR), &buf) == 0); +} + +void S9xMSU1Generate(int sample_count) +{ + partial_samples += 44100 * sample_count; + + while (((uintptr_t)bufPos < (uintptr_t)bufEnd) && (MSU1.MSU1_STATUS & AudioPlaying) && partial_samples > 32040) + { + if (audioFile.is_open()) + { + int16 sample; + if (audioFile.read((char *)&sample, 2).good()) + { + sample = (int16)((double)(int16)GET_LE16(&sample) * (double)MSU1.MSU1_VOLUME / 255.0); + + *(bufPos++) = sample; + MSU1.MSU1_AUDIO_POS += 2; + partial_samples -= 32040; + } + else + if (audioFile.eof()) + { + sample = (int16)((double)(int16)GET_LE16(&sample) * (double)MSU1.MSU1_VOLUME / 255.0); + + *(bufPos++) = sample; + MSU1.MSU1_AUDIO_POS += 2; + partial_samples -= 32040; + + if (MSU1.MSU1_STATUS & AudioRepeating) + { + audioFile.clear(); + MSU1.MSU1_AUDIO_POS = audioLoopPos; + audioFile.seekg(MSU1.MSU1_AUDIO_POS); + } + else + { + MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating); + audioFile.clear(); + audioFile.seekg(8); + return; + } + } + else + { + MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating); + return; + } + } + else + { + MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating); + return; + } + } +} + + +uint8 S9xMSU1ReadPort(int port) +{ + switch (port) + { + case 0: + return MSU1.MSU1_STATUS; + case 1: + if (MSU1.MSU1_STATUS & DataBusy) + return 0; + if (dataFile.fail() || dataFile.bad() || dataFile.eof()) + return 0; + MSU1.MSU1_DATA_POS++; + return dataFile.get(); + case 2: + return 'S'; + case 3: + return '-'; + case 4: + return 'M'; + case 5: + return 'S'; + case 6: + return 'U'; + case 7: + return '1'; + } + + return 0; +} + + +void S9xMSU1WritePort(int port, uint8 byte) +{ + switch (port) + { + case 0: + MSU1.MSU1_DATA_SEEK &= 0xFFFFFF00; + MSU1.MSU1_DATA_SEEK |= byte << 0; + break; + case 1: + MSU1.MSU1_DATA_SEEK &= 0xFFFF00FF; + MSU1.MSU1_DATA_SEEK |= byte << 8; + break; + case 2: + MSU1.MSU1_DATA_SEEK &= 0xFF00FFFF; + MSU1.MSU1_DATA_SEEK |= byte << 16; + break; + case 3: + MSU1.MSU1_DATA_SEEK &= 0x00FFFFFF; + MSU1.MSU1_DATA_SEEK |= byte << 24; + MSU1.MSU1_DATA_POS = MSU1.MSU1_DATA_SEEK; + if(dataFile.good()) + dataFile.seekg(MSU1.MSU1_DATA_POS); + break; + case 4: + MSU1.MSU1_TRACK_SEEK &= 0xFF00; + MSU1.MSU1_TRACK_SEEK |= byte; + break; + case 5: + MSU1.MSU1_TRACK_SEEK &= 0x00FF; + MSU1.MSU1_TRACK_SEEK |= (byte << 8); + MSU1.MSU1_CURRENT_TRACK = MSU1.MSU1_TRACK_SEEK; + + MSU1.MSU1_STATUS &= ~AudioPlaying; + MSU1.MSU1_STATUS &= ~AudioRepeating; + + if (AudioOpen()) + { + if (MSU1.MSU1_CURRENT_TRACK == MSU1.MSU1_RESUME_TRACK) + { + MSU1.MSU1_AUDIO_POS = MSU1.MSU1_RESUME_POS; + MSU1.MSU1_RESUME_POS = 0; + MSU1.MSU1_RESUME_TRACK = ~0; + } + else + { + MSU1.MSU1_AUDIO_POS = 8; + } + + audioFile.seekg(MSU1.MSU1_AUDIO_POS); + } + break; + case 6: + MSU1.MSU1_VOLUME = byte; + break; + case 7: + if (MSU1.MSU1_STATUS & (AudioBusy | AudioError)) + break; + + MSU1.MSU1_STATUS = (MSU1.MSU1_STATUS & ~0x30) | ((byte & 0x03) << 4); + + if ((byte & (Play | Resume)) == Resume) + { + MSU1.MSU1_RESUME_TRACK = MSU1.MSU1_CURRENT_TRACK; + MSU1.MSU1_RESUME_POS = MSU1.MSU1_AUDIO_POS; + } + break; + } +} + +uint16 S9xMSU1Samples(void) +{ + return bufPos - bufBegin; +} + +void S9xMSU1SetOutput(int16 * out, int size) +{ + bufPos = bufBegin = out; + bufEnd = out + size; +} + +void S9xMSU1PostLoadState(void) +{ + if (DataOpen()) + { + dataFile.seekg(MSU1.MSU1_DATA_POS); + } + + if (MSU1.MSU1_STATUS & AudioPlaying) + { + if (AudioOpen()) + { + audioFile.seekg(4); + audioFile.read((char *)&audioLoopPos, 4); + audioLoopPos = GET_LE32(&audioLoopPos); + audioLoopPos <<= 2; + audioLoopPos += 8; + + audioFile.seekg(MSU1.MSU1_AUDIO_POS); + } + else + { + MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating); + MSU1.MSU1_STATUS |= AudioError; + } + } + + bufPos = 0; + bufBegin = 0; + bufEnd = 0; + + partial_samples = 0; +} diff --git a/msu1.h b/msu1.h new file mode 100644 index 00000000..04a22941 --- /dev/null +++ b/msu1.h @@ -0,0 +1,239 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + + (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2016 BearOso, + OV2 + + (c) Copyright 2011 - 2016 Hans-Kristian Arntzen, + Daniel De Matteis + (Under no circumstances will commercial rights be given) + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + S-SMP emulator code used in 1.54+ + (c) Copyright 2016 byuu + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2016 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2016 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2011 zones + + Libretro port + (c) Copyright 2011 - 2016 Hans-Kristian Arntzen, + Daniel De Matteis + (Under no circumstances will commercial rights be given) + + MSU-1 code + (c) Copyright 2016 qwertymodo + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com/ + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. + ***********************************************************************************/ + +#ifndef _MSU1_H_ +#define _MSU1_H_ +#include "snes9x.h" + +struct SMSU1 +{ + uint8 MSU1_STATUS; + uint32 MSU1_DATA_SEEK; + uint32 MSU1_DATA_POS; + uint16 MSU1_TRACK_SEEK; + uint16 MSU1_CURRENT_TRACK; + uint32 MSU1_RESUME_TRACK; + uint8 MSU1_VOLUME; + uint8 MSU1_CONTROL; + uint32 MSU1_AUDIO_POS; + uint32 MSU1_RESUME_POS; +}; + +enum SMSU1_FLAG { + Revision = 0x02, //max: 0x07 + AudioResume = 0x04, + AudioError = 0x08, + AudioPlaying = 0x10, + AudioRepeating = 0x20, + AudioBusy = 0x40, + DataBusy = 0x80 +}; + +enum SMSU1_CMD { + Play = 0x01, + Repeat = 0x02, + Resume = 0x04 +}; + +extern struct SMSU1 MSU1; + +void S9xResetMSU(void); +void S9xMSU1Init(void); +bool S9xMSU1ROMExists(void); +void S9xMSU1Generate(int sample_count); +uint8 S9xMSU1ReadPort(int port); +void S9xMSU1WritePort(int port, uint8 byte); +uint16 S9xMSU1Samples(void); +void S9xMSU1SetOutput(int16 *out, int size); +void S9xMSU1PostLoadState(void); + +#endif diff --git a/port.h b/port.h index 7a806e69..2378057c 100644 --- a/port.h +++ b/port.h @@ -325,7 +325,7 @@ void SetInfoDlgColor(unsigned char, unsigned char, unsigned char); #endif // __WIN32_LIBSNES__ #endif // __WIN32__ -#ifdef __DJGPP +#if defined(__DJGPP) || defined(__WIN32__) #define SLASH_STR "\\" #define SLASH_CHAR '\\' #else diff --git a/ppu.cpp b/ppu.cpp index ebc99ac8..fe0328fa 100644 --- a/ppu.cpp +++ b/ppu.cpp @@ -344,6 +344,9 @@ void S9xSetPPU (uint8 Byte, uint16 Address) S9xTraceFormattedMessage("--- HDMA PPU %04X -> %02X", Address, Byte); #endif + if (Settings.MSU1 && (Address & 0xfff8) == 0x2000) // MSU-1 + S9xMSU1WritePort(Address & 7, Byte); + else if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3 // write_port will run the APU until given clock before writing value S9xAPUWritePort(Address & 3, Byte); @@ -1095,7 +1098,9 @@ void S9xSetPPU (uint8 Byte, uint16 Address) uint8 S9xGetPPU (uint16 Address) { // MAP_PPU: $2000-$3FFF - + if (Settings.MSU1 && (Address & 0xfff8) == 0x2000) + return (S9xMSU1ReadPort(Address & 7)); + else if (Address < 0x2100) return (OpenBus); diff --git a/sa1.cpp b/sa1.cpp index 16f63490..20d45946 100644 --- a/sa1.cpp +++ b/sa1.cpp @@ -313,7 +313,16 @@ static void S9xSetSA1MemMap (uint32 which1, uint8 map) for (int c = 0; c < 0x100; c += 16) { - uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 12)]; + uint8 *block; + if (Multi.cartType != 5) + block = &Memory.ROM[(map & 7) * 0x100000 + (c << 12)]; + else + { + if ((map & 7) < 4) + block = Memory.ROM + Multi.cartOffsetA + ((map & 7) * 0x100000 + (c << 12)); + else + block = Memory.ROM + Multi.cartOffsetB + (((map & 7) - 4) * 0x100000 + (c << 12)); + } for (int i = c; i < c + 16; i++) Memory.Map[start + i] = SA1.Map[start + i] = block; } @@ -321,8 +330,26 @@ static void S9xSetSA1MemMap (uint32 which1, uint8 map) for (int c = 0; c < 0x200; c += 16) { // conversion to int is needed here - map is promoted but which1 is not - int32 offset = (((map & 0x80) ? map : which1) & 7) * 0x100000 + (c << 11) - 0x8000; - uint8 *block = &Memory.ROM[offset]; + int32 offset; + uint8 *block; + if (Multi.cartType != 5) + { + offset = (((map & 0x80) ? map : which1) & 7) * 0x100000 + (c << 11) - 0x8000; + block = &Memory.ROM[offset]; + } + else + { + if ((map & 7) < 4) + { + offset = (((map & 0x80) ? map : which1) & 7) * 0x100000 + (c << 11) - 0x8000; + block = Memory.ROM + Multi.cartOffsetA + offset; + } + else + { + offset = (((map & 0x80) ? (map - 4) : which1) & 7) * 0x100000 + (c << 11) - 0x8000; + block = Memory.ROM + Multi.cartOffsetB + offset; + } + } for (int i = c + 8; i < c + 16; i++) Memory.Map[start2 + i] = SA1.Map[start2 + i] = block; } diff --git a/snapshot.cpp b/snapshot.cpp index b3dc6ac9..cb6eab29 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -1135,6 +1135,23 @@ static FreezeData SnapBSX[] = ARRAY_ENTRY(6, test2192, 32, uint8_ARRAY_V) }; +#undef STRUCT +#define STRUCT struct SMSU1 + +static FreezeData SnapMSU1[] = +{ + INT_ENTRY(9, MSU1_STATUS), + INT_ENTRY(9, MSU1_DATA_SEEK), + INT_ENTRY(9, MSU1_DATA_POS), + INT_ENTRY(9, MSU1_TRACK_SEEK), + INT_ENTRY(9, MSU1_CURRENT_TRACK), + INT_ENTRY(9, MSU1_RESUME_TRACK), + INT_ENTRY(9, MSU1_VOLUME), + INT_ENTRY(9, MSU1_CONTROL), + INT_ENTRY(9, MSU1_AUDIO_POS), + INT_ENTRY(9, MSU1_RESUME_POS) +}; + #undef STRUCT #define STRUCT struct SnapshotScreenshotInfo @@ -1306,8 +1323,6 @@ void S9xFreezeToStream (STREAM stream) char buffer[1024]; uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE]; - S9xSetSoundMute(TRUE); - sprintf(buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION); WRITE_STREAM(buffer, strlen(buffer), stream); @@ -1394,6 +1409,9 @@ void S9xFreezeToStream (STREAM stream) if (Settings.BS) FreezeStruct(stream, "BSX", &BSX, SnapBSX, COUNT(SnapBSX)); + if (Settings.MSU1) + FreezeStruct(stream, "MSU", &MSU1, SnapMSU1, COUNT(SnapMSU1)); + if (Settings.SnapshotScreenshots) { SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; @@ -1443,8 +1461,6 @@ void S9xFreezeToStream (STREAM stream) } } - S9xSetSoundMute(FALSE); - delete [] soundsnapshot; } @@ -1494,6 +1510,7 @@ int S9xUnfreezeFromStream (STREAM stream) uint8 *local_srtc = NULL; uint8 *local_rtc_data = NULL; uint8 *local_bsx_data = NULL; + uint8 *local_msu1_data = NULL; uint8 *local_screenshot = NULL; uint8 *local_movie_data = NULL; @@ -1599,6 +1616,10 @@ int S9xUnfreezeFromStream (STREAM stream) if (result != SUCCESS && Settings.BS) break; + result = UnfreezeStructCopy(stream, "MSU", &local_msu1_data, SnapMSU1, COUNT(SnapMSU1), version); + if (result != SUCCESS && Settings.MSU1) + break; + result = UnfreezeStructCopy(stream, "SHO", &local_screenshot, SnapScreenshot, COUNT(SnapScreenshot), version); SnapshotMovieInfo mi; @@ -1640,8 +1661,6 @@ int S9xUnfreezeFromStream (STREAM stream) uint32 old_flags = CPU.Flags; uint32 sa1_old_flags = SA1.Flags; - S9xSetSoundMute(TRUE); - S9xReset(); UnfreezeStructFromCopy(&CPU, SnapCPU, COUNT(SnapCPU), local_cpu, version); @@ -1717,6 +1736,9 @@ int S9xUnfreezeFromStream (STREAM stream) if (local_bsx_data) UnfreezeStructFromCopy(&BSX, SnapBSX, COUNT(SnapBSX), local_bsx_data, version); + if (local_msu1_data) + UnfreezeStructFromCopy(&MSU1, SnapMSU1, COUNT(SnapMSU1), local_msu1_data, version); + if (version < SNAPSHOT_VERSION_IRQ) { printf("Converting old snapshot version %d to %d\n...", version, SNAPSHOT_VERSION); @@ -1798,6 +1820,9 @@ int S9xUnfreezeFromStream (STREAM stream) if (local_bsx_data) S9xBSXPostLoadState(); + if (local_msu1_data) + S9xMSU1PostLoadState(); + if (local_movie_data) { // restore last displayed pad_read status @@ -1867,8 +1892,6 @@ int S9xUnfreezeFromStream (STREAM stream) for (uint32 y = 0; y < (uint32) (IMAGE_HEIGHT); y++) memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL * 2); } - - S9xSetSoundMute(FALSE); } if (local_cpu) delete [] local_cpu; diff --git a/snapshot.h b/snapshot.h index 33688e88..de45fd66 100644 --- a/snapshot.h +++ b/snapshot.h @@ -196,7 +196,7 @@ #define SNAPSHOT_MAGIC "#!s9xsnp" #define SNAPSHOT_VERSION_IRQ 7 #define SNAPSHOT_VERSION_BAPU 8 -#define SNAPSHOT_VERSION 8 +#define SNAPSHOT_VERSION 9 #define SUCCESS 1 #define WRONG_FORMAT (-1) diff --git a/snes9x.h b/snes9x.h index f7bd5740..fbb4cefe 100644 --- a/snes9x.h +++ b/snes9x.h @@ -377,6 +377,7 @@ struct SSettings bool8 BS; bool8 BSXItself; bool8 BSXBootup; + bool8 MSU1; bool8 MouseMaster; bool8 SuperScopeMaster; bool8 JustifierMaster; diff --git a/stream.cpp b/stream.cpp index 37051c32..bb64113d 100644 --- a/stream.cpp +++ b/stream.cpp @@ -192,7 +192,11 @@ #include <string> #ifdef UNZIP_SUPPORT -#include "unzip.h" +# ifdef SYSTEM_ZIP +# include <minizip/unzip.h> +# else +# include "unzip.h" +# endif #endif #include "snes9x.h" #include "stream.h" diff --git a/stream.h b/stream.h index b03dea9a..ea22df0a 100644 --- a/stream.h +++ b/stream.h @@ -229,8 +229,11 @@ class fStream : public Stream }; #ifdef UNZIP_SUPPORT - -#include "unzip.h" +# ifdef SYSTEM_ZIP +# include <minizip/unzip.h> +# else +# include "unzip.h" +# endif #define unz_BUFFSIZ 1024 diff --git a/tile.cpp b/tile.cpp index 3aae2efe..1bdd7351 100644 --- a/tile.cpp +++ b/tile.cpp @@ -1399,29 +1399,12 @@ extern struct SLineMatrixData LineMatrixData[240]; // We don't know how Sub(0, y) is handled. #define DRAW_PIXEL_H2x1(N, M) \ - if (Z1 > GFX.DB[Offset + 2 * N] && (M)) \ - { \ - GFX.S[Offset + 2 * N] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); \ - GFX.S[Offset + 2 * N + 1] = MATH((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N + 2]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); \ - GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; \ - } - -/* The logic above shifts everything one pixel to the left, thus producing a blank line on the right. The code below places the pixel on correct positions but - would incur two additional branches for the edges on every pixel. -*/ - -//#define DRAW_PIXEL_H2x1(N, M) \ -// if (Z1 > GFX.DB[Offset + 2 * N] && (M)) \ -// { \ -// GFX.S[Offset + 2 * N + 1] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); \ -// if ((Offset + 2 * N ) % GFX.RealPPL != (SNES_WIDTH - 1) << 1) \ -// GFX.S[Offset + 2 * N + 2] = MATH((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N + 2]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); \ -// if ((Offset + 2 * N) % GFX.RealPPL == 0) \ -// GFX.S[Offset + 2 * N] = MATH((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); \ -// GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; \ -// } - - + if (Z1 > GFX.DB[Offset + 2 * N] && (M)) \ + { \ + GFX.S[Offset + 2 * N] = MATH((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); \ + GFX.S[Offset + 2 * N + 1] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); \ + GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; \ + } #define DRAW_PIXEL(N, M) DRAW_PIXEL_H2x1(N, M) #define NAME2 Hires diff --git a/unix/Makefile.in b/unix/Makefile.in index 58495689..f0ef47d3 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -2,12 +2,13 @@ @S9XNETPLAY@ @S9XZIP@ @S9XJMA@ +@S9X_SYSTEM_ZIP@ # Fairly good and special-char-safe descriptor of the os being built on. OS = `uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"` BUILDDIR = . -OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/dsp/SPC_DSP.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o ../statemanager.o unix.o x11.o +OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/dsp/SPC_DSP.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../msu1.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o ../statemanager.o unix.o x11.o DEFS = -DMITSHM ifdef S9XDEBUGGER @@ -19,7 +20,11 @@ OBJECTS += ../netplay.o ../server.o endif ifdef S9XZIP -OBJECTS += ../loadzip.o ../unzip/ioapi.o ../unzip/unzip.o +OBJECTS += ../loadzip.o +ifndef SYSTEM_ZIP +OBJECTS += ../unzip/ioapi.o ../unzip/unzip.o +INCLUDES = -I../unzip/ +endif endif ifdef S9XJMA @@ -29,7 +34,7 @@ endif CCC = @CXX@ CC = @CC@ GASM = @CXX@ -INCLUDES = -I. -I.. -I../apu/ -I../apu/bapu -I../unzip/ -I../jma/ -I../filter/ +INCLUDES += -I. -I.. -I../apu/ -I../apu/bapu -I../jma/ -I../filter/ CCFLAGS = @S9XFLGS@ @S9XDEFS@ $(DEFS) CFLAGS = $(CCFLAGS) diff --git a/unix/aclocal.m4 b/unix/aclocal.m4 new file mode 100644 index 00000000..2a745e57 --- /dev/null +++ b/unix/aclocal.m4 @@ -0,0 +1,290 @@ +# generated automatically by aclocal 1.15 -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29.1) +dnl +dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>. +dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com> +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.1]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + diff --git a/unix/configure b/unix/configure index 23f99d3e..14be08d5 100755 --- a/unix/configure +++ b/unix/configure @@ -622,6 +622,7 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS LIBOBJS +S9X_SYSTEM_ZIP S9XJMA S9XZIP S9XNETPLAY @@ -635,6 +636,11 @@ X_LIBS X_PRE_LIBS X_CFLAGS XMKMF +SYSTEM_ZIP_LIBS +SYSTEM_ZIP_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG EGREP GREP CXXCPP @@ -708,6 +714,7 @@ enable_debugger enable_netplay enable_gzip enable_zip +with_system_zip enable_jma enable_screenshot with_x @@ -726,6 +733,11 @@ CXX CXXFLAGS CCC CXXCPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +SYSTEM_ZIP_CFLAGS +SYSTEM_ZIP_LIBS XMKMF' @@ -1363,6 +1375,7 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-system-zip Use system zip (default: check) --with-x use the X Window System Some influential environment variables: @@ -1376,6 +1389,15 @@ Some influential environment variables: CXX C++ compiler command CXXFLAGS C++ compiler flags CXXCPP C++ preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + SYSTEM_ZIP_CFLAGS + C compiler flags for SYSTEM_ZIP, overriding pkg-config + SYSTEM_ZIP_LIBS + linker flags for SYSTEM_ZIP, overriding pkg-config XMKMF Path to xmkmf, Makefile generator for X Window System Use these variables to override the choices made by `configure' or to help @@ -4831,17 +4853,241 @@ else fi +S9X_SYSTEM_ZIP="#SYSTEM_ZIP=1" + + +# Check whether --with-system-zip was given. +if test "${with_system_zip+set}" = set; then : + withval=$with_system_zip; +else + with_system_zip="check" +fi + + if test "x$enable_zip" = "xyes"; then - if test "x$snes9x_cv_zlib" = "xyes"; then - S9XZIP="S9XZIP=1" - S9XDEFS="$S9XDEFS -DUNZIP_SUPPORT" - if test "x$enable_gzip" = "xno"; then - S9XLIBS="$S9XLIBS -lz" - fi + if test "x$with_system_zip" != "xno"; then + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: zlib not found. Build without ZIP support." >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SYSTEM_ZIP" >&5 +$as_echo_n "checking for SYSTEM_ZIP... " >&6; } + +if test -n "$SYSTEM_ZIP_CFLAGS"; then + pkg_cv_SYSTEM_ZIP_CFLAGS="$SYSTEM_ZIP_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"minizip\""; } >&5 + ($PKG_CONFIG --exists --print-errors "minizip") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SYSTEM_ZIP_CFLAGS=`$PKG_CONFIG --cflags "minizip" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SYSTEM_ZIP_LIBS"; then + pkg_cv_SYSTEM_ZIP_LIBS="$SYSTEM_ZIP_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"minizip\""; } >&5 + ($PKG_CONFIG --exists --print-errors "minizip") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SYSTEM_ZIP_LIBS=`$PKG_CONFIG --libs "minizip" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SYSTEM_ZIP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "minizip" 2>&1` + else + SYSTEM_ZIP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "minizip" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SYSTEM_ZIP_PKG_ERRORS" >&5 + + if test "x${with_system_zip}" != "xcheck"; then + as_fn_error $? "--with-system-zip requested but no proper minizip lib found." "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: minizip not found. Build without SYSTEM_ZIP support." >&5 +$as_echo "$as_me: WARNING: minizip not found. Build without SYSTEM_ZIP support." >&2;} + fi + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test "x${with_system_zip}" != "xcheck"; then + as_fn_error $? "--with-system-zip requested but no proper minizip lib found." "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: minizip not found. Build without SYSTEM_ZIP support." >&5 +$as_echo "$as_me: WARNING: minizip not found. Build without SYSTEM_ZIP support." >&2;} + fi + +else + SYSTEM_ZIP_CFLAGS=$pkg_cv_SYSTEM_ZIP_CFLAGS + SYSTEM_ZIP_LIBS=$pkg_cv_SYSTEM_ZIP_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + S9XZIP="S9XZIP=1" + S9XDEFS="$S9XDEFS -DUNZIP_SUPPORT" + S9X_SYSTEM_ZIP="SYSTEM_ZIP=1" + S9XLIBS="$S9XLIBS $SYSTEM_ZIP_LIBS" + if test "x$enable_gzip" = "xno"; then + S9XLIBS="$S9XLIBS -lz" + fi + S9XDEFS="$S9XDEFS -DSYSTEM_ZIP" +fi + else + if test "x$snes9x_cv_zlib" = "xyes"; then + S9XZIP="S9XZIP=1" + S9XDEFS="$S9XDEFS -DUNZIP_SUPPORT" + if test "x$enable_gzip" = "xno"; then + S9XLIBS="$S9XLIBS -lz" + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: zlib not found. Build without ZIP support." >&5 $as_echo "$as_me: WARNING: zlib not found. Build without ZIP support." >&2;} - enable_zip="no" + enable_zip="no" + fi fi fi @@ -6068,9 +6314,12 @@ S9XLIBS="$LIBS $S9XLIBS" S9XFLGS="`echo \"$S9XFLGS\" | sed -e 's/ */ /g'`" S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/ */ /g'`" S9XLIBS="`echo \"$S9XLIBS\" | sed -e 's/ */ /g'`" +S9X_SYSTEM_ZIP="`echo \"$S9X_SYSTEM_ZIP\" | sed -e 's/ */ /g'`" S9XFLGS="`echo \"$S9XFLGS\" | sed -e 's/^ *//'`" S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/^ *//'`" S9XLIBS="`echo \"$S9XLIBS\" | sed -e 's/^ *//'`" +S9X_SYSTEM_ZIP="`echo \"$S9X_SYSTEM_ZIP\" | sed -e 's/^ *//'`" + @@ -6100,6 +6349,7 @@ netplay support...... $enable_netplay gamepad support...... $enable_gamepad GZIP support......... $enable_gzip ZIP support.......... $enable_zip +SYSTEM_ZIP........... $with_system_zip JMA support.......... $enable_jma debugger............. $enable_debugger diff --git a/unix/configure.ac b/unix/configure.ac index 3c851dcb..28186c67 100644 --- a/unix/configure.ac +++ b/unix/configure.ac @@ -201,16 +201,43 @@ AC_ARG_ENABLE([zip], [enable ZIP support through zlib (default: yes)])], [], [enable_zip="yes"]) +S9X_SYSTEM_ZIP="#SYSTEM_ZIP=1" + +AC_ARG_WITH([system-zip], + [AS_HELP_STRING([--with-system-zip], + [Use system zip (default: check)])], + [], [with_system_zip="check"]) + if test "x$enable_zip" = "xyes"; then - if test "x$snes9x_cv_zlib" = "xyes"; then - S9XZIP="S9XZIP=1" - S9XDEFS="$S9XDEFS -DUNZIP_SUPPORT" - if test "x$enable_gzip" = "xno"; then - S9XLIBS="$S9XLIBS -lz" - fi + if test "x$with_system_zip" != "xno"; then + PKG_CHECK_MODULES( + SYSTEM_ZIP, + minizip, + S9XZIP="S9XZIP=1" + S9XDEFS="$S9XDEFS -DUNZIP_SUPPORT" + S9X_SYSTEM_ZIP="SYSTEM_ZIP=1" + S9XLIBS="$S9XLIBS $SYSTEM_ZIP_LIBS" + if test "x$enable_gzip" = "xno"; then + S9XLIBS="$S9XLIBS -lz" + fi + S9XDEFS="$S9XDEFS -DSYSTEM_ZIP", + if test "x${with_system_zip}" != "xcheck"; then + AC_MSG_ERROR([--with-system-zip requested but no proper minizip lib found.]) + else + AC_MSG_WARN([minizip not found. Build without SYSTEM_ZIP support.]) + fi + ) else - AC_MSG_WARN([zlib not found. Build without ZIP support.]) - enable_zip="no" + if test "x$snes9x_cv_zlib" = "xyes"; then + S9XZIP="S9XZIP=1" + S9XDEFS="$S9XDEFS -DUNZIP_SUPPORT" + if test "x$enable_gzip" = "xno"; then + S9XLIBS="$S9XLIBS -lz" + fi + else + AC_MSG_WARN([zlib not found. Build without ZIP support.]) + enable_zip="no" + fi fi fi @@ -427,9 +454,11 @@ S9XLIBS="$LIBS $S9XLIBS" S9XFLGS="`echo \"$S9XFLGS\" | sed -e 's/ */ /g'`" S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/ */ /g'`" S9XLIBS="`echo \"$S9XLIBS\" | sed -e 's/ */ /g'`" +S9X_SYSTEM_ZIP="`echo \"$S9X_SYSTEM_ZIP\" | sed -e 's/ */ /g'`" S9XFLGS="`echo \"$S9XFLGS\" | sed -e 's/^ *//'`" S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/^ *//'`" S9XLIBS="`echo \"$S9XLIBS\" | sed -e 's/^ *//'`" +S9X_SYSTEM_ZIP="`echo \"$S9X_SYSTEM_ZIP\" | sed -e 's/^ *//'`" AC_SUBST(S9XFLGS) AC_SUBST(S9XDEFS) @@ -439,6 +468,7 @@ AC_SUBST(S9XDEBUGGER) AC_SUBST(S9XNETPLAY) AC_SUBST(S9XZIP) AC_SUBST(S9XJMA) +AC_SUBST(S9X_SYSTEM_ZIP) rm config.info 2>/dev/null @@ -459,6 +489,7 @@ netplay support...... $enable_netplay gamepad support...... $enable_gamepad GZIP support......... $enable_gzip ZIP support.......... $enable_zip +SYSTEM_ZIP........... $with_system_zip JMA support.......... $enable_jma debugger............. $enable_debugger diff --git a/win32/CD3DCG.cpp b/win32/CD3DCG.cpp index d5458cb6..95b61b5f 100644 --- a/win32/CD3DCG.cpp +++ b/win32/CD3DCG.cpp @@ -383,7 +383,7 @@ bool CD3DCG::LoadShader(const TCHAR *shaderFile) hr = pDevice->CreateVertexBuffer(sizeof(VERTEX)*4,D3DUSAGE_WRITEONLY,0,D3DPOOL_MANAGED,&pass.vertexBuffer,NULL); if(FAILED(hr)) { pass.vertexBuffer = NULL; - DXTRACE_ERR_MSGBOX(TEXT("Error creating vertex buffer"), hr); + DXTRACE_ERR_MSGBOX(L"Error creating vertex buffer", hr); return false; } @@ -449,7 +449,7 @@ void CD3DCG::ensureTextureSize(LPDIRECT3DTEXTURE9 &tex, D3DXVECTOR2 &texSize, texSize = wantedSize; if(FAILED(hr)) { - DXTRACE_ERR_MSGBOX(TEXT("Error while creating texture"), hr); + DXTRACE_ERR_MSGBOX(L"Error while creating texture", hr); return; } } @@ -860,7 +860,7 @@ void CD3DCG::setupVertexDeclaration(shaderPass &pass) LPDIRECT3DVERTEXDECLARATION9 vertexDeclaration; HRESULT hr = pDevice->CreateVertexDeclaration(vElems,&vertexDeclaration); if(FAILED(hr)) { - DXTRACE_ERR_MSGBOX(TEXT("Error creating vertex declaration"), hr); + DXTRACE_ERR_MSGBOX(L"Error creating vertex declaration", hr); } if(pass.vertexDeclaration) pass.vertexDeclaration->Release(); diff --git a/win32/CDirect3D.cpp b/win32/CDirect3D.cpp index 1c69d49d..7fd8d6eb 100644 --- a/win32/CDirect3D.cpp +++ b/win32/CDirect3D.cpp @@ -272,7 +272,7 @@ bool CDirect3D::Initialize(HWND hWnd) pD3D = Direct3DCreate9(D3D_SDK_VERSION); if(pD3D == NULL) { - DXTRACE_ERR_MSGBOX(TEXT("Error creating initial D3D9 object"), 0); + DXTRACE_ERR_MSGBOX(L"Error creating initial D3D9 object", 0); return false; } @@ -290,19 +290,19 @@ bool CDirect3D::Initialize(HWND hWnd) &dPresentParams, &pDevice); if(FAILED(hr)) { - DXTRACE_ERR_MSGBOX(TEXT("Error creating D3D9 device"), hr); + DXTRACE_ERR_MSGBOX(L"Error creating D3D9 device", hr); return false; } hr = pDevice->CreateVertexBuffer(sizeof(vertexStream),D3DUSAGE_WRITEONLY,0,D3DPOOL_MANAGED,&vertexBuffer,NULL); if(FAILED(hr)) { - DXTRACE_ERR_MSGBOX(TEXT("Error creating vertex buffer"), hr); + DXTRACE_ERR_MSGBOX(L"Error creating vertex buffer", hr); return false; } hr = pDevice->CreateVertexDeclaration(vertexElems,&vertexDeclaration); if(FAILED(hr)) { - DXTRACE_ERR_MSGBOX(TEXT("Error creating vertex declaration"), hr); + DXTRACE_ERR_MSGBOX(L"Error creating vertex declaration", hr); return false; } @@ -312,7 +312,7 @@ bool CDirect3D::Initialize(HWND hWnd) cgContext = cgCreateContext(); hr = cgD3D9SetDevice(pDevice); if(FAILED(hr)) { - DXTRACE_ERR_MSGBOX(TEXT("Error setting cg device"), hr); + DXTRACE_ERR_MSGBOX(L"Error setting cg device", hr); } cgShader = new CD3DCG(cgContext,pDevice); } @@ -650,14 +650,14 @@ void CDirect3D::Render(SSurface Src) ResetDevice(); return; default: - DXTRACE_ERR_MSGBOX( TEXT("Internal driver error"), hr); + DXTRACE_ERR_MSGBOX( L"Internal driver error", hr); return; } } //BlankTexture(drawSurface); if(FAILED(hr = drawSurface->LockRect(0, &lr, NULL, 0))) { - DXTRACE_ERR_MSGBOX( TEXT("Unable to lock texture"), hr); + DXTRACE_ERR_MSGBOX( L"Unable to lock texture", hr); return; } else { Dst.Surface = (unsigned char *)lr.pBits; @@ -757,7 +757,7 @@ void CDirect3D::CreateDrawSurface() NULL ); if(FAILED(hr)) { - DXTRACE_ERR_MSGBOX(TEXT("Error while creating texture"), hr); + DXTRACE_ERR_MSGBOX(L"Error while creating texture", hr); return; } } @@ -787,7 +787,7 @@ bool CDirect3D::BlankTexture(LPDIRECT3DTEXTURE9 texture) HRESULT hr; if(FAILED(hr = texture->LockRect(0, &lr, NULL, 0))) { - DXTRACE_ERR_MSGBOX( TEXT("Unable to lock texture"), hr); + DXTRACE_ERR_MSGBOX( L"Unable to lock texture", hr); return false; } else { memset(lr.pBits, 0, lr.Pitch * quadTextureSize); @@ -938,7 +938,7 @@ bool CDirect3D::ResetDevice() } if(FAILED(hr = pDevice->Reset(&dPresentParams))) { - DXTRACE_ERR(TEXT("Unable to reset device"), hr); + DXTRACE_ERR(L"Unable to reset device", hr); return false; } diff --git a/win32/CDirectSound.cpp b/win32/CDirectSound.cpp index 192f348e..01f19b06 100644 --- a/win32/CDirectSound.cpp +++ b/win32/CDirectSound.cpp @@ -314,7 +314,8 @@ bool CDirectSound::InitSoundBuffer() blockCount = 4; blockTime = GUI.SoundBufferSize / blockCount; - blockSamples = (Settings.SoundPlaybackRate * blockTime * (Settings.Stereo ? 2 : 1)) / 1000; + blockSamples = (Settings.SoundPlaybackRate * blockTime) / 1000; + blockSamples *= (Settings.Stereo ? 2 : 1); blockSize = blockSamples * (Settings.SixteenBitSound ? 2 : 1); bufferSize = blockSize * blockCount; diff --git a/win32/CXAudio2.cpp b/win32/CXAudio2.cpp index fa54ae00..7bfdb6ef 100644 --- a/win32/CXAudio2.cpp +++ b/win32/CXAudio2.cpp @@ -234,7 +234,7 @@ bool CXAudio2::InitXAudio2(void) HRESULT hr; if ( FAILED(hr = XAudio2Create( &pXAudio2, 0 , XAUDIO2_DEFAULT_PROCESSOR ) ) ) { - DXTRACE_ERR_MSGBOX(TEXT("Unable to create XAudio2 object."),hr); + DXTRACE_ERR_MSGBOX(L"Unable to create XAudio2 object.",hr); MessageBox (GUI.hWnd, TEXT("\ Unable to initialize XAudio2. You will not be able to hear any\n\ sound effects or music while playing.\n\n\ @@ -257,7 +257,7 @@ bool CXAudio2::InitVoices(void) HRESULT hr; if ( FAILED(hr = pXAudio2->CreateMasteringVoice( &pMasterVoice, (Settings.Stereo?2:1), Settings.SoundPlaybackRate, 0, 0 , NULL ) ) ) { - DXTRACE_ERR_MSGBOX(TEXT("Unable to create mastering voice."),hr); + DXTRACE_ERR_MSGBOX(L"Unable to create mastering voice.",hr); return false; } @@ -272,7 +272,7 @@ bool CXAudio2::InitVoices(void) if( FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx, XAUDIO2_VOICE_NOSRC , XAUDIO2_DEFAULT_FREQ_RATIO, this, NULL, NULL ) ) ) { - DXTRACE_ERR_MSGBOX(TEXT("Unable to create source voice."),hr); + DXTRACE_ERR_MSGBOX(L"Unable to create source voice.",hr); return false; } @@ -355,7 +355,8 @@ bool CXAudio2::SetupSound() blockCount = 8; UINT32 blockTime = GUI.SoundBufferSize / blockCount; - singleBufferSamples = (Settings.SoundPlaybackRate * blockTime * (Settings.Stereo ? 2 : 1)) / 1000; + singleBufferSamples = (Settings.SoundPlaybackRate * blockTime) / 1000; + singleBufferSamples *= (Settings.Stereo ? 2 : 1); singleBufferBytes = singleBufferSamples * (Settings.SixteenBitSound ? 2 : 1); sum_bufferSize = singleBufferBytes * blockCount; diff --git a/win32/InputCustom.cpp b/win32/InputCustom.cpp index c0dc1446..e2b2767d 100644 --- a/win32/InputCustom.cpp +++ b/win32/InputCustom.cpp @@ -959,17 +959,36 @@ static LRESULT CALLBACK InputCustomWndProc(HWND hwnd, UINT msg, WPARAM wParam, L return 1; case WM_USER+45: case WM_KEYDOWN: - TranslateKey(wParam,temp); - col = CheckButtonKey(wParam); + { + UINT scancode = (lParam & 0x00ff0000) >> 16; + int extended = (lParam & 0x01000000) != 0; - icp->crForeGnd = ((~col) & 0x00ffffff); - icp->crBackGnd = col; - SetWindowText(hwnd,_tFromChar(temp)); - InvalidateRect(icp->hwnd, NULL, FALSE); - UpdateWindow(icp->hwnd); - SendMessage(pappy,WM_USER+43,wParam,(LPARAM)hwnd); + switch (wParam) { + case VK_SHIFT: + wParam = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX); + break; + case VK_CONTROL: + wParam = extended ? VK_RCONTROL : VK_LCONTROL; + break; + case VK_MENU: + wParam = extended ? VK_RMENU : VK_LMENU; + break; + default: + break; + } - break; + TranslateKey(wParam, temp); + col = CheckButtonKey(wParam); + + icp->crForeGnd = ((~col) & 0x00ffffff); + icp->crBackGnd = col; + SetWindowText(hwnd, _tFromChar(temp)); + InvalidateRect(icp->hwnd, NULL, FALSE); + UpdateWindow(icp->hwnd); + SendMessage(pappy, WM_USER + 43, wParam, (LPARAM)hwnd); + + break; + } case WM_USER+44: TranslateKey(wParam,temp); diff --git a/win32/rsrc/resource.h b/win32/rsrc/resource.h index 0f6bf528..07ec2620 100644 --- a/win32/rsrc/resource.h +++ b/win32/rsrc/resource.h @@ -496,13 +496,14 @@ #define ID_WINDOW_SIZE_4X 40172 #define ID_DEBUG_APU_TRACE 40173 #define ID_EMULATION_BACKGROUNDINPUT 40174 +#define ID_SAVEMEMPACK 40175 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 151 -#define _APS_NEXT_COMMAND_VALUE 40175 +#define _APS_NEXT_COMMAND_VALUE 40176 #define _APS_NEXT_CONTROL_VALUE 3018 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/win32/rsrc/snes9x.rc b/win32/rsrc/snes9x.rc index 5c11c0a3..0629f188 100644 --- a/win32/rsrc/snes9x.rc +++ b/win32/rsrc/snes9x.rc @@ -716,14 +716,15 @@ IDB_HIDDENFOLDER BITMAP "hiddir.bmp" // remains consistent on all systems. IDI_ICON1 ICON "icon1.ico" + ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,5,3,0 - PRODUCTVERSION 1,5,3,0 + FILEVERSION 1,5,4,1 + PRODUCTVERSION 1,5,4,1 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -822,6 +823,7 @@ BEGIN MENUITEM "S&ave SPC Data", ID_FILE_SAVE_SPC_DATA MENUITEM "Save Screenshot", ID_SAVESCREENSHOT MENUITEM "Sa&ve S-RAM Data", ID_FILE_SAVE_SRAM_DATA + MENUITEM "Save Memory Pack", ID_SAVEMEMPACK END MENUITEM "ROM Information...", IDM_ROM_INFO MENUITEM SEPARATOR diff --git a/win32/snes9xw.vcxproj b/win32/snes9xw.vcxproj index 31b00270..ad885fcc 100644 --- a/win32/snes9xw.vcxproj +++ b/win32/snes9xw.vcxproj @@ -677,6 +677,7 @@ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> </CustomBuild> + <ClInclude Include="..\msu1.h" /> <ClInclude Include="..\statemanager.h" /> <CustomBuild Include="..\stream.h" /> <CustomBuild Include="..\tile.h" /> @@ -777,6 +778,7 @@ <ClCompile Include="..\logger.cpp" /> <ClCompile Include="..\memmap.cpp" /> <ClCompile Include="..\movie.cpp" /> + <ClCompile Include="..\msu1.cpp" /> <ClCompile Include="..\netplay.cpp" /> <ClCompile Include="..\obc1.cpp" /> <ClCompile Include="..\ppu.cpp" /> diff --git a/win32/snes9xw.vcxproj.filters b/win32/snes9xw.vcxproj.filters index d2279054..8020f00f 100644 --- a/win32/snes9xw.vcxproj.filters +++ b/win32/snes9xw.vcxproj.filters @@ -243,6 +243,9 @@ <ClInclude Include="dxerr.h"> <Filter>GUI</Filter> </ClInclude> + <ClInclude Include="..\msu1.h"> + <Filter>APU</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\bsx.cpp"> @@ -539,6 +542,9 @@ <ClCompile Include="dxerr.cpp"> <Filter>GUI</Filter> </ClCompile> + <ClCompile Include="..\msu1.cpp"> + <Filter>APU</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <None Include="rsrc\nodrop.cur"> diff --git a/win32/wlanguage.h b/win32/wlanguage.h index 2c68bede..50735f57 100644 --- a/win32/wlanguage.h +++ b/win32/wlanguage.h @@ -597,6 +597,8 @@ Nintendo is a trade mark.") #define INFO_SAVE_SPC "Saving SPC Data." +#define MPAK_SAVE_FAILED "Failed to save Memory Pack." + #define CHEATS_INFO_ENABLED "Cheats enabled." #define CHEATS_INFO_DISABLED "Cheats disabled." #define CHEATS_INFO_ENABLED_NONE "Cheats enabled. (None are active.)" diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 8a303486..b4de0412 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -2016,7 +2016,7 @@ LRESULT CALLBACK WinProc( { char localhostname [256]; gethostname(localhostname,256); - _stprintf(localhostmsg, TEXT("Your host name is: %s\nYour port number is: %d"), _tFromChar(localhostname), Settings.Port); + _stprintf(localhostmsg, TEXT("Your host name is: %s\nYour port number is: %d"), (TCHAR *)_tFromChar(localhostname), Settings.Port); MessageBox(GUI.hWnd,localhostmsg,TEXT("Note"),MB_OK); } } @@ -2248,6 +2248,17 @@ LRESULT CALLBACK WinProc( if(!success) S9xMessage(S9X_ERROR, S9X_FREEZE_FILE_INFO, SRM_SAVE_FAILED); } break; + case ID_SAVEMEMPACK: { + const char *filename = S9xGetFilenameInc(".bs", SRAM_DIR); + bool8 success = Memory.SaveMPAK(filename); + if (!success) + S9xMessage(S9X_ERROR, 0, MPAK_SAVE_FAILED); + else + { + sprintf(String, "Saved Memory Pack %s", filename); + S9xMessage(S9X_INFO, 0, String); + } + } break; case ID_FILE_RESET: #ifdef NETPLAY_SUPPORT if (Settings.NetPlayServer) @@ -2423,7 +2434,7 @@ LRESULT CALLBACK WinProc( { if (!LoadROM(GUI.RecentGames [i])) { - sprintf (String, ERR_ROM_NOT_FOUND, _tToChar(GUI.RecentGames [i])); + sprintf (String, ERR_ROM_NOT_FOUND, (char *)_tToChar(GUI.RecentGames [i])); S9xMessage (S9X_ERROR, S9X_ROM_NOT_FOUND, String); S9xRemoveFromRecentGames(i); } @@ -2694,7 +2705,7 @@ LRESULT CALLBACK WinProc( { TCHAR buf [NP_MAX_ACTION_LEN + 10]; - _stprintf (buf, TEXT("%s %3d%%"), _tFromChar(NetPlay.ActionMsg), (int) lParam); + _stprintf (buf, TEXT("%s %3d%%"), (TCHAR *)_tFromChar(NetPlay.ActionMsg), (int) lParam); SetWindowText (GUI.hWnd, buf); } #if 0 @@ -3693,7 +3704,7 @@ loop_exit: void FreezeUnfreeze (int slot, bool8 freeze) { - const char *filename; + char filename[_MAX_PATH +1]; char ext [_MAX_EXT + 1]; #ifdef NETPLAY_SUPPORT @@ -3706,7 +3717,7 @@ void FreezeUnfreeze (int slot, bool8 freeze) #endif snprintf(ext, _MAX_EXT, ".%03d", slot); - filename = S9xGetFilename(ext,SNAPSHOT_DIR); + strcpy(filename, S9xGetFilename(ext, SNAPSHOT_DIR)); S9xSetPause (PAUSE_FREEZE_FILE); @@ -5015,7 +5026,7 @@ INT_PTR CALLBACK DlgInfoProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { SetTextColor((HDC)wParam, GUI.InfoColor); SetBkColor((HDC)wParam, RGB(0,0,0)); - return (BOOL)GetStockObject( BLACK_BRUSH ); + return (INT_PTR)GetStockObject( BLACK_BRUSH ); } break; case WM_PAINT: @@ -5309,7 +5320,7 @@ void rominfo(const TCHAR *filename, TCHAR *namebuffer, TCHAR *sizebuffer) lstrcpy(namebuffer, ROM_ITEM_DESCNOTAVAILABLE); lstrcpy(sizebuffer, TEXT("? Mbits")); -#ifdef ZLIB +#ifdef UNZIP_SUPPORT if(IsCompressed(filename)) { unzFile uf = unzOpen(_tToChar(filename)); @@ -7006,6 +7017,7 @@ void MakeExtFile(void) out<<"smcN"<<endl<<"zipY"<<endl<<"gzY" <<endl<<"swcN"<<endl<<"figN"<<endl; out<<"sfcN"<<endl; + out<<"bsN"<<endl; out<<"jmaY"; out.close(); SetFileAttributes(TEXT("Valid.Ext"), FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY); @@ -10429,7 +10441,7 @@ static void set_movieinfo(const TCHAR* path, HWND hDlg) if(m.SyncFlags & MOVIE_SYNC_HASROMINFO) { - _stprintf(str, MOVIE_INFO_MOVIEROM MOVIE_INFO_ROMINFO, m.ROMCRC32, _tFromChar(m.ROMName)); + _stprintf(str, MOVIE_INFO_MOVIEROM MOVIE_INFO_ROMINFO, m.ROMCRC32, (TCHAR *)_tFromChar(m.ROMName)); SetWindowText(GetDlgItem(hDlg, IDC_MOVIEROMINFO), str); } else @@ -10439,7 +10451,7 @@ static void set_movieinfo(const TCHAR* path, HWND hDlg) } bool mismatch = (m.SyncFlags & MOVIE_SYNC_HASROMINFO) && m.ROMCRC32 != Memory.ROMCRC32; - _stprintf(str, MOVIE_INFO_CURRENTROM MOVIE_INFO_ROMINFO TEXT("%s"), Memory.ROMCRC32, _tFromChar(Memory.ROMName), mismatch?MOVIE_INFO_MISMATCH:TEXT("")); + _stprintf(str, MOVIE_INFO_CURRENTROM MOVIE_INFO_ROMINFO TEXT("%s"), Memory.ROMCRC32, (TCHAR *)_tFromChar(Memory.ROMName), mismatch?MOVIE_INFO_MISMATCH:TEXT("")); SetWindowText(GetDlgItem(hDlg, IDC_CURRENTROMINFO), str); _stprintf(str, TEXT("%s"), mismatch?MOVIE_WARNING_MISMATCH:MOVIE_WARNING_OK); @@ -10505,7 +10517,7 @@ static void set_movieinfo(const TCHAR* path, HWND hDlg) // no movie loaded SetWindowText(GetDlgItem(hDlg, IDC_MOVIEROMINFO), dirStr); - _stprintf(str, MOVIE_INFO_CURRENTROM MOVIE_INFO_ROMINFO, Memory.ROMCRC32, _tFromChar(Memory.ROMName)); + _stprintf(str, MOVIE_INFO_CURRENTROM MOVIE_INFO_ROMINFO, Memory.ROMCRC32, (TCHAR *)_tFromChar(Memory.ROMName)); SetWindowText(GetDlgItem(hDlg, IDC_CURRENTROMINFO), str); }