diff --git a/src/boards/mmc5.cpp b/src/boards/mmc5.cpp index 82095f04..5bf9d2a4 100644 --- a/src/boards/mmc5.cpp +++ b/src/boards/mmc5.cpp @@ -40,46 +40,50 @@ void MMC5RunSoundHQ(void); static INLINE void MMC5SPRVROM_BANK1(uint32 A, uint32 V) { if (CHRptr[0]) { V &= CHRmask1[0]; - MMC5SPRVPage[(A) >> 10] = &CHRptr[0][(V) << 10] - (A); + MMC5SPRVPage[(A) >> 9] = MMC5SPRVPage[((A) >> 9) + 1] = &CHRptr[0][(V) << 10] - (A); } } static INLINE void MMC5BGVROM_BANK1(uint32 A, uint32 V) { if (CHRptr[0]) { - V &= CHRmask1[0]; MMC5BGVPage[(A) >> 10] = &CHRptr[0][(V) << 10] - (A); + V &= CHRmask1[0]; MMC5BGVPage[(A) >> 9] = MMC5BGVPage[((A) >> 9) + 1] = &CHRptr[0][(V) << 10] - (A); } } static INLINE void MMC5SPRVROM_BANK2(uint32 A, uint32 V) { if (CHRptr[0]) { - V &= CHRmask2[0]; MMC5SPRVPage[(A) >> 10] = MMC5SPRVPage[((A) >> 10) + 1] = &CHRptr[0][(V) << 11] - (A); + V &= CHRmask2[0]; MMC5SPRVPage[(A) >> 9] = MMC5SPRVPage[((A) >> 9) + 1] = MMC5SPRVPage[((A) >> 9) + 2] = MMC5SPRVPage[((A) >> 9) + 3] = &CHRptr[0][(V) << 11] - (A); } } static INLINE void MMC5BGVROM_BANK2(uint32 A, uint32 V) { if (CHRptr[0]) { - V &= CHRmask2[0]; MMC5BGVPage[(A) >> 10] = MMC5BGVPage[((A) >> 10) + 1] = &CHRptr[0][(V) << 11] - (A); + V &= CHRmask2[0]; MMC5BGVPage[(A) >> 9] = MMC5BGVPage[((A) >> 9) + 1] = MMC5BGVPage[((A) >> 9) + 2] = MMC5BGVPage[((A) >> 9) + 3] = &CHRptr[0][(V) << 11] - (A); } } static INLINE void MMC5SPRVROM_BANK4(uint32 A, uint32 V) { if (CHRptr[0]) { - V &= CHRmask4[0]; MMC5SPRVPage[(A) >> 10] = MMC5SPRVPage[((A) >> 10) + 1] = MMC5SPRVPage[((A) >> 10) + 2] = MMC5SPRVPage[((A) >> 10) + 3] = &CHRptr[0][(V) << 12] - (A); + V &= CHRmask4[0]; MMC5SPRVPage[(A) >> 9] = MMC5SPRVPage[((A) >> 9) + 1] = MMC5SPRVPage[((A) >> 9) + 2] = MMC5SPRVPage[((A) >> 9) + 3] = + MMC5SPRVPage[((A) >> 9) + 4] = MMC5SPRVPage[((A) >> 9) + 5] = MMC5SPRVPage[((A) >> 9) + 6] = MMC5SPRVPage[((A) >> 9) + 7] = &CHRptr[0][(V) << 12] - (A); } } static INLINE void MMC5BGVROM_BANK4(uint32 A, uint32 V) { if (CHRptr[0]) { - V &= CHRmask4[0]; MMC5BGVPage[(A) >> 10] = MMC5BGVPage[((A) >> 10) + 1] = MMC5BGVPage[((A) >> 10) + 2] = MMC5BGVPage[((A) >> 10) + 3] = &CHRptr[0][(V) << 12] - (A); + V &= CHRmask4[0]; MMC5BGVPage[(A) >> 9] = MMC5BGVPage[((A) >> 9) + 1] = MMC5BGVPage[((A) >> 9) + 2] = MMC5BGVPage[((A) >> 9) + 3] = + MMC5BGVPage[((A) >> 9) + 4] = MMC5BGVPage[((A) >> 9) + 5] = MMC5BGVPage[((A) >> 9) + 6] = MMC5BGVPage[((A) >> 9) + 7] = &CHRptr[0][(V) << 12] - (A); } } static INLINE void MMC5SPRVROM_BANK8(uint32 V) { if (CHRptr[0]) { - V &= CHRmask8[0]; MMC5SPRVPage[0] = MMC5SPRVPage[1] = MMC5SPRVPage[2] = MMC5SPRVPage[3] = MMC5SPRVPage[4] = MMC5SPRVPage[5] = MMC5SPRVPage[6] = MMC5SPRVPage[7] = &CHRptr[0][(V) << 13]; + V &= CHRmask8[0]; MMC5SPRVPage[0] = MMC5SPRVPage[1] = MMC5SPRVPage[2] = MMC5SPRVPage[3] = MMC5SPRVPage[4] = MMC5SPRVPage[5] = MMC5SPRVPage[6] = MMC5SPRVPage[7] = + MMC5SPRVPage[8] = MMC5SPRVPage[9] = MMC5SPRVPage[10] = MMC5SPRVPage[11] = MMC5SPRVPage[12] = MMC5SPRVPage[13] = MMC5SPRVPage[14] = MMC5SPRVPage[15] = &CHRptr[0][(V) << 13]; } } static INLINE void MMC5BGVROM_BANK8(uint32 V) { if (CHRptr[0]) { - V &= CHRmask8[0]; MMC5BGVPage[0] = MMC5BGVPage[1] = MMC5BGVPage[2] = MMC5BGVPage[3] = MMC5BGVPage[4] = MMC5BGVPage[5] = MMC5BGVPage[6] = MMC5BGVPage[7] = &CHRptr[0][(V) << 13]; + V &= CHRmask8[0]; MMC5BGVPage[0] = MMC5BGVPage[1] = MMC5BGVPage[2] = MMC5BGVPage[3] = MMC5BGVPage[4] = MMC5BGVPage[5] = MMC5BGVPage[6] = MMC5BGVPage[7] = + MMC5BGVPage[8] = MMC5BGVPage[9] = MMC5BGVPage[10] = MMC5BGVPage[11] = MMC5BGVPage[12] = MMC5BGVPage[13] = MMC5BGVPage[14] = MMC5BGVPage[15] = &CHRptr[0][(V) << 13]; } } @@ -119,7 +123,7 @@ typedef struct __cartdata { uint8 size; } cartdata; -#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)] +#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 9][(V)] uint8* MMC5BGVRAMADR(uint32 A) { @@ -129,23 +133,23 @@ uint8* MMC5BGVRAMADR(uint32 A) { bool isPattern = PPUON != 0; if (ppuphase == PPUPHASE_OBJ && isPattern) - return &ABANKS[(A) >> 10][(A)]; + return &ABANKS[(A) >> 9][(A)]; if (ppuphase == PPUPHASE_BG && isPattern) - return &BBANKS[(A) >> 10][(A)]; + return &BBANKS[(A) >> 9][(A)]; else if(mmc5ABMode == 0) - return &ABANKS[(A) >> 10][(A)]; + return &ABANKS[(A) >> 9][(A)]; else - return &BBANKS[(A) >> 10][(A)]; + return &BBANKS[(A) >> 9][(A)]; } - else return &ABANKS[(A) >> 10][(A)];; + else return &ABANKS[(A) >> 9][(A)];; } if (!Sprite16) { if (mmc5ABMode == 0) - return &ABANKS[(A) >> 10][(A)]; + return &ABANKS[(A) >> 9][(A)]; else - return &BBANKS[(A) >> 10][(A)]; - } else return &BBANKS[(A) >> 10][(A)]; + return &BBANKS[(A) >> 9][(A)]; + } else return &BBANKS[(A) >> 9][(A)]; } static void mmc5_PPUWrite(uint32 A, uint8 V) { @@ -164,8 +168,8 @@ static void mmc5_PPUWrite(uint32 A, uint8 V) { } else PALRAM[tmp & 0x1F] = V & 0x3F; } else if (tmp < 0x2000) { - if (PPUCHRRAM & (1 << (tmp >> 10))) - VPage[tmp >> 10][tmp] = V; + if (PPUCHRRAM & (3 << (tmp >> 9))) + VPage[tmp >> 9][tmp] = V; } else { if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; @@ -201,7 +205,7 @@ uint8 FASTCALL mmc5_PPURead(uint32 A) { bool isPattern = !!PPUON; if (ppuphase == PPUPHASE_OBJ && isPattern) - return ABANKS[(A) >> 10][(A)]; + return ABANKS[(A) >> 9][(A)]; if (ppuphase == PPUPHASE_BG && isPattern) { if(split) @@ -212,12 +216,12 @@ uint8 FASTCALL mmc5_PPURead(uint32 A) if (MMC5HackCHRMode == 1) return *FCEUPPU_GetCHR(A,NTRefreshAddr); - return BBANKS[(A) >> 10][(A)]; + return BBANKS[(A) >> 9][(A)]; } else if(mmc5ABMode == 0) - return ABANKS[(A) >> 10][(A)]; + return ABANKS[(A) >> 9][(A)]; else - return BBANKS[(A) >> 10][(A)]; + return BBANKS[(A) >> 9][(A)]; } else { @@ -232,7 +236,7 @@ uint8 FASTCALL mmc5_PPURead(uint32 A) return *FCEUPPU_GetCHR(A,NTRefreshAddr); } - return ABANKS[(A) >> 10][(A)]; + return ABANKS[(A) >> 9][(A)]; } } else diff --git a/src/boards/rainbow13.cpp b/src/boards/rainbow13.cpp index 020f7d54..dca795a8 100644 --- a/src/boards/rainbow13.cpp +++ b/src/boards/rainbow13.cpp @@ -82,8 +82,16 @@ const uint32 CHRRAMSIZE = 32 * 1024; extern uint8 *ExtraNTARAM; -extern uint8 IRQCount, IRQLatch, IRQa; -extern uint8 IRQReload; +// Scanline IRQ +static uint8 S_IRQCount, S_IRQLatch, S_IRQa, S_IRQp; +static uint8 S_IRQReload; + +// CPU Cycle IRQ +static bool C_IRQa, C_IRQr, C_IRQp; +static int32 C_IRQLatch, C_IRQCount; + +// ESP message IRQ +static uint8 ESP_IRQp; static uint8 flash_mode[2]; static uint8 flash_sequence[2]; @@ -106,11 +114,22 @@ static SFORMAT FlashRegs[] = static SFORMAT Rainbow13StateRegs[] = { { prg, 3, "PRG" }, - { chr, 8, "CHR" }, - { &IRQReload, 1, "IRQR" }, - { &IRQCount, 1, "IRQC" }, - { &IRQLatch, 1, "IRQL" }, - { &IRQa, 1, "IRQA" }, + { chr, 16, "CHR" }, + + { &S_IRQReload, 1, "SCAR" }, + { &S_IRQCount, 1, "SCAC" }, + { &S_IRQLatch, 1, "SCAL" }, + { &S_IRQa, 1, "SCAA" }, + { &S_IRQp, 1, "SCAP" }, + + { &C_IRQa, 1, "CPUA" }, + { &C_IRQp, 1, "CPUP" }, + { &C_IRQr, 1, "CPUR" }, + { &C_IRQLatch, 4, "CPUL" }, + { &C_IRQCount, 4, "CPUC" }, + + { &ESP_IRQp, 1, "ESPP" }, + { 0 } }; @@ -158,18 +177,58 @@ static void clear_esp_message_received() { has_esp_message_received = false; } -static void Rainbow13EspMapIrq(int32) { +static void Rainbow13hb() { + int count = S_IRQCount; + if (!count || S_IRQReload) + { + S_IRQCount = S_IRQLatch; + S_IRQReload = 0; + } + else + S_IRQCount--; + + if ((count | 1) && !S_IRQCount) + { + if (S_IRQa) + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static void IRQEnd() { + if (!C_IRQp && !S_IRQp && !ESP_IRQp) + { + X6502_IRQEnd(FCEU_IQEXT); + } +} + +static void Rainbow13IRQ(int a) { + + // Cycle Counter IRQ + if (C_IRQa) { + C_IRQCount -= a; + if (C_IRQCount <= 0) { + C_IRQa = C_IRQr; + C_IRQp = true; + C_IRQCount = C_IRQLatch; + X6502_IRQBegin(FCEU_IQEXT); + } + } + + // ESP / new message IRQ if (esp_irq_enable) { if (esp_message_received()) { X6502_IRQBegin(FCEU_IQEXT); + ESP_IRQp = 1; } else { - X6502_IRQEnd(FCEU_IQEXT); + ESP_IRQp = 0; } } + + IRQEnd(); } static void Sync(void) { @@ -414,6 +473,7 @@ static DECLFR(Rainbow13Read) { static DECLFW(Rainbow13Write) { switch (A) { + // ESP case 0x4100: esp_enable = V & 0x01; esp_irq_enable = V & 0x02; @@ -445,15 +505,7 @@ static DECLFW(Rainbow13Write) { case 0x4105: rx_index = V; break; - case 0x4120: prg[0] = V; Sync(); break; - case 0x4121: prg[1] = V & 0x3f; Sync(); break; - case 0x4122: prg[2] = V & 0x3f; Sync(); break; - case 0x4123: fpga_wram_bank = V & 0x01; Sync(); break; - case 0x4124: - wram_bank = V & 0x3f; - wram_chip_select = (V & 0xc0) >> 6; - Sync(); - break; + // Mapper configuration case 0x4110: prg_mode = V & 0x01; chr_chip = (V & 0x08) >> 3; @@ -462,6 +514,17 @@ static DECLFW(Rainbow13Write) { nt_set = (V & 0xC0) >> 6; Sync(); break; + // PRG banking + case 0x4120: prg[0] = V & 0xbf; Sync(); break; + case 0x4121: prg[1] = V & 0xbf; Sync(); break; + case 0x4122: prg[2] = V & 0xbf; Sync(); break; + case 0x4123: fpga_wram_bank = V & 0x01; Sync(); break; + case 0x4124: + wram_bank = V & 0x3f; + wram_chip_select = (V & 0xc0) >> 6; + Sync(); + break; + // CHR banking case 0x4130: case 0x4131: case 0x4132: @@ -480,39 +543,34 @@ static DECLFW(Rainbow13Write) { break; } case 0x4138: chr_upper_bank = V & 0x01; Sync(); break; - case 0x4140: IRQLatch = V; break; - case 0x4141: IRQReload = 1; break; + // Scanline IRQ + case 0x4140: S_IRQLatch = V; break; + case 0x4141: S_IRQReload = 1; break; case 0x4142: - X6502_IRQEnd(FCEU_IQEXT); - IRQa = 0; + S_IRQa = 0; + S_IRQp = 0; + IRQEnd(); break; - case 0x4143: IRQa = 1; break; + case 0x4143: S_IRQa = 1; break; + // CPU Cycle IRQ + case 0x4144: C_IRQLatch &= 0xFF00; C_IRQLatch |= V; C_IRQCount = C_IRQLatch; break; + case 0x4145: C_IRQLatch &= 0x00FF; C_IRQLatch |= V << 8; C_IRQCount = C_IRQLatch; break; + case 0x4146: + C_IRQa = V & 0x01; + C_IRQr = (V & 0x02) >> 1; + if (C_IRQa) + C_IRQCount = C_IRQLatch; + break; + case 0x4147: + C_IRQp = false; + IRQEnd(); + break; + // Multiplier case 0x4160: mul_a = V; mul_result = mul_a * mul_b; break; case 0x4161: mul_b = V; mul_result = mul_a * mul_b; break; } } -static void ClockRainbow13Counter(void) { - int count = IRQCount; - if (!count || IRQReload) - { - IRQCount = IRQLatch; - IRQReload = 0; - } - else - IRQCount--; - - if ((count | 1) && !IRQCount) - { - if (IRQa) - X6502_IRQBegin(FCEU_IQEXT); - } -} - -static void Rainbow13hb() { - ClockRainbow13Counter(); -} - uint8 FASTCALL Rainbow13PPURead(uint32 A) { // if CHR-RAM, check if CHR-RAM exists, if not return data bus cache if (chr_chip == CHR_CHIP_RAM && CHRRAM == NULL) @@ -583,7 +641,7 @@ void Rainbow13FlashIDEnter(uint8 chip) if (flash_id[chip]) return; flash_id[chip] = 1; - if(bootloader) + if (bootloader) SetReadHandler(0x8000, 0xDFFF, Rainbow13FlashPrgID); else SetReadHandler(0x8000, 0xFFFF, Rainbow13FlashPrgID); @@ -826,13 +884,17 @@ static void Rainbow13Reset(void) { rx_address = 0; tx_address = 0; rx_index = 0; - IRQa = 0; + S_IRQa = S_IRQp = 0; + C_IRQa = C_IRQp = C_IRQr = 0; + ESP_IRQp = 0; } static void Rainbow13Power(void) { // mapper - IRQCount = IRQLatch = IRQa = 0; + S_IRQCount = S_IRQLatch = S_IRQa = 0; + C_IRQCount = C_IRQLatch = C_IRQa = C_IRQr = 0; + S_IRQp = C_IRQp = ESP_IRQp = 0; chr_mode &= 0x03; prg_mode &= 0x01; chr_upper_bank &= 0x01; @@ -1282,5 +1344,5 @@ void RAINBOW13_Init(CartInfo *info) { AddExState(&Rainbow13StateRegs, ~0, 0, 0); // set a hook on hblank to be able periodically check if we have to send an interupt - MapIRQHook = Rainbow13EspMapIrq; + MapIRQHook = Rainbow13IRQ; } diff --git a/src/boards/rainbow2.cpp b/src/boards/rainbow2.cpp new file mode 100644 index 00000000..c3e76c1c --- /dev/null +++ b/src/boards/rainbow2.cpp @@ -0,0 +1,1735 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2021-2022 Broke Studio + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + // mapper 3873 - Rainbow2 board v1.0 revA by Broke Studio + // + // documentation available here: https://github.com/BrokeStudio/rainbow-lib + +#include "mapinc.h" +#include "../ines.h" +#include "rainbow_esp.h" + +#undef RAINBOW_DEBUG + //define RAINBOW_DEBUG + +#ifdef RAINBOW_DEBUG +#define UDBG(...) FCEU_printf(__VA_ARGS__) +#else +#define UDBG(...) +#endif + +#define MAPPER_VERSION 0b01000001 + +#define MIRR_VERTICAL 0b00 // VRAM +#define MIRR_HORIZONTAL 0b01 // VRAM +#define MIRR_ONE_SCREEN 0b10 // VRAM [+ CHR-RAM] +#define MIRR_FOUR_SCREEN 0b11 // CHR-RAM + +#define PRG_ROM_MODE_0 0b000 // 32K +#define PRG_ROM_MODE_1 0b001 // 16K + 16K +#define PRG_ROM_MODE_2 0b010 // 16K + 8K + 8K +#define PRG_ROM_MODE_3 0b011 // 8K + 8K + 8K + 8K +#define PRG_ROM_MODE_4 0b100 // 4K + 4K + 4K + 4K + 4K + 4K + 4K + 4K + +#define PRG_RAM_MODE_0 0b0 // 8K +#define PRG_RAM_MODE_1 0b1 // 4K + +#define CHR_CHIP_ROM 0b00 // CHR-ROM +#define CHR_CHIP_RAM 0b01 // CHR-RAM +#define CHR_CHIP_FPGA_RAM 0b10 // FPGA-RAM + +#define CHR_MODE_0 0b000 // 8K mode +#define CHR_MODE_1 0b001 // 4K mode +#define CHR_MODE_2 0b010 // 2K mode +#define CHR_MODE_3 0b011 // 1K mode +#define CHR_MODE_4 0b100 // 512B mode + +#define CHIP_TYPE_PRG 0 +#define CHIP_TYPE_CHR 1 + +#define NT_CIRAM 0b00 +#define NT_CHR_RAM 0b01 +#define NT_FPGA_RAM 0b10 +#define NT_CHR_ROM 0b11 + +static uint8 prg_rom_mode, prg_ram_mode, bootloader; +static uint16 prg[11]; // 0: $5000, 1: $6000, 2: $7000, 3: $8000, etc + +static uint8 chr_chip, chr_spr_ext_mode, chr_mode; +static uint16 chr[16]; + +static uint8 NT_bank[4]; +static uint8 NT_control[4]; + +static uint8 mul_a, mul_b; +static uint16 mul_result; +static uint8 rx_address, tx_address, rx_index; + +static uint8 *WRAM = NULL; +const uint32 WRAMSIZE = 32 * 1024; + +static uint8 *FPGA_RAM = NULL; +const uint32 FPGA_RAMSIZE = 8 * 1024; + +static uint8 *DUMMY_CHRRAM = NULL; +const uint32 DUMMY_CHRRAMSIZE = 4 * 1024; + +static uint8 *DUMMY_CHRROM = NULL; +const uint32 DUMMY_CHRROMSIZE = 512 * 1024; + +static uint8 *CHRRAM = NULL; +const uint32 CHRRAMSIZE = 32 * 1024; + +extern uint8 *ExtraNTARAM; + +// Scanline IRQ +static uint8 S_IRQcontrol, S_IRQlatch, S_IRQoffset; // matches hardware register +// additional flags to emulate hardware correctly +static float S_IRQdotcount; +static uint8 S_IRQready, S_IRQlastSLtriggered; + +// CPU Cycle IRQ +static bool C_IRQe, C_IRQr, C_IRQp; +static int32 C_IRQLatch, C_IRQCount; + +// ESP message IRQ +static uint8 ESP_IRQp; + +static uint8 flash_mode[2]; +static uint8 flash_sequence[2]; +static uint8 flash_id[2]; + +static uint8 *PRG_FLASHROM = NULL; +const uint32 PRG_FLASHROMSIZE = 512 * 1024; + +static uint8 *CHR_FLASHROM = NULL; +const uint32 CHR_FLASHROMSIZE = 512 * 1024; + +static SFORMAT FlashRegs[] = +{ + { &flash_mode, 2, "FMOD" }, + { &flash_sequence, 2, "FSEQ" }, + { &flash_id, 2, "FMID" }, + { 0 } +}; + +static SFORMAT Rainbow2StateRegs[] = +{ + { prg, 11, "PRG" }, + { chr, 16, "CHR" }, + + { &S_IRQcontrol, 1, "SICO" }, + { &S_IRQlatch, 1, "SILA" }, + { &S_IRQoffset, 1, "SIOF" }, + { &S_IRQdotcount, 4, "SIDC" }, + { &S_IRQready, 1, "SIRE" }, + { &S_IRQlastSLtriggered, 1, "SITR" }, + + { &C_IRQe, 1, "CPUA" }, + { &C_IRQp, 1, "CPUP" }, + { &C_IRQr, 1, "CPUR" }, + { &C_IRQLatch, 4, "CPUL" }, + { &C_IRQCount, 4, "CPUC" }, + + { &ESP_IRQp, 1, "ESPP" }, + + { 0 } +}; + +static void(*sfun[3]) (void); +static uint8 vpsg1[8]; +static uint8 vpsg2[4]; +static int32 cvbc[3]; +static int32 vcount[3]; +static int32 dcount[2]; + +static SFORMAT SStateRegs[] = +{ + { vpsg1, 8, "PSG1" }, + { vpsg2, 4, "PSG2" }, + { 0 } +}; + +static EspFirmware *esp = NULL; +static bool esp_enable; +static bool esp_irq_enable; +static bool has_esp_message_received; +static bool esp_message_sent; + +static void esp_check_new_message() { + // get new message if needed + if (esp_enable && esp->getDataReadyIO() && has_esp_message_received == false) + { + uint8 message_length = esp->tx(); + FPGA_RAM[rx_address << 8] = message_length; + for (uint8 i = 0; i < message_length; i++) + { + FPGA_RAM[(rx_address << 8) + 1 + i] = esp->tx(); + } + rx_index = 0; + has_esp_message_received = true; + } +} + +static bool esp_message_received() { + esp_check_new_message(); + return has_esp_message_received; +} + +static void clear_esp_message_received() { + has_esp_message_received = false; +} + +static void IRQEnd() { + if (!C_IRQp && !(S_IRQcontrol & 0x80) && !ESP_IRQp) + { + X6502_IRQEnd(FCEU_IQEXT); + } +} +/* +static void Rainbow2hb() { + + +} +*/ +static void Rainbow2IRQ(int a) { + + // Scanline IRQ + int sl = newppu_get_scanline(); + int dot = newppu_get_dot(); + int ppuon = (PPU[1] & 0x18); + + if (!ppuon || sl >= 241) + { + // whenever rendering is off for any reason (vblank or forced disable + // the irq counter resets, as well as the inframe flag (easily verifiable from software) + S_IRQcontrol &= ~0x40; // in-frame flag cleared + S_IRQcontrol &= ~0x80; // pending IRQ flag cleared + S_IRQready = 0; + S_IRQlastSLtriggered = 255; + IRQEnd(); + } + else + { + if (!(S_IRQcontrol & 0x40)) + { + S_IRQcontrol |= 0x40; + S_IRQcontrol &= ~0x80; + IRQEnd(); + } + + // this is kind of hacky but result is pretty close to hardware + if ((sl == S_IRQlatch) & !S_IRQready & !(S_IRQcontrol & 0x80) & (sl != S_IRQlastSLtriggered)) + { + S_IRQready = 1; + S_IRQdotcount = (float)dot; + if (PAL) S_IRQdotcount -= a * 3.2; + else S_IRQdotcount -= (float)a * 3; + } + + if ((S_IRQready == 1) & !(S_IRQcontrol & 0x80)) + { + if (PAL) S_IRQdotcount += (float)a * 3.2; + else S_IRQdotcount += (float)a * 3; + + int dotTarget = (S_IRQoffset * 2); + if (PAL) dotTarget += 20; + else dotTarget += 24; + + if (((int)S_IRQdotcount) >= dotTarget) + { + S_IRQready = 2; + S_IRQlastSLtriggered = S_IRQlatch; + } + } + + if ((S_IRQcontrol & 0x01) && !(S_IRQcontrol & 0x80) && (S_IRQready == 2)) + { + X6502_IRQBegin(FCEU_IQEXT); + S_IRQcontrol |= 0x80; + S_IRQready = 0; + } + } + + // Cycle Counter IRQ + if (C_IRQe) { + C_IRQCount -= a; + if (C_IRQCount <= 0) { + C_IRQe = C_IRQr; + C_IRQp = true; + C_IRQCount = C_IRQLatch; + X6502_IRQBegin(FCEU_IQEXT); + } + } + + // ESP / new message IRQ + if (esp_irq_enable) + { + if (esp_message_received()) + { + X6502_IRQBegin(FCEU_IQEXT); + ESP_IRQp = 1; + } + else + { + ESP_IRQp = 0; + } + } + + IRQEnd(); +} + +static void Sync(void) { + static uint8 *address; + //uint32 start; + //uint32 offset; + uint8 cart_chr_map; + + // $8000-$ffff + + // 32K + if (prg_rom_mode == PRG_ROM_MODE_0) + { + // PRG-ROM + if (!(prg[3] & 0x8000)) + setprg32r(0x11, 0x8000, prg[3] & 0x7fff); + // WRAM + if (prg[3] & 0x8000) + setprg32r(0x10, 0x8000, 0); + } + + // 16K + 16K + if (prg_rom_mode == PRG_ROM_MODE_1) + { + // PRG-ROM + if (!(prg[3] & 0x8000)) + setprg16r(0x11, 0x8000, prg[3] & 0x7fff); + // WRAM + if (prg[3] & 0x8000) + setprg16r(0x10, 0x8000, prg[3] & 0x01); + + // PRG-ROM + if (!(prg[7] & 0x8000)) + setprg16r(0x11, 0xC000, prg[7] & 0x7fff); + // WRAM + if (prg[7] & 0x8000) + setprg16r(0x10, 0xC000, prg[7] & 0x01); + } + + // 16K + 8K + 8K + if (prg_rom_mode == PRG_ROM_MODE_2) + { + // PRG-ROM + if (!(prg[3] & 0x8000)) + setprg16r(0x11, 0x8000, prg[3] & 0x7fff); + // WRAM + if (prg[3] & 0x8000) + setprg16r(0x10, 0x8000, prg[3] & 0x01); + + // PRG-ROM + if (!(prg[7] & 0x8000)) + setprg8r(0x11, 0xc000, prg[7] & 0x7fff); + // WRAM + if (prg[7] & 0x8000) + setprg8r(0x10, 0xc000, prg[7] & 0x03); + + // PRG-ROM + if (!(prg[9] & 0x8000)) + setprg8r(0x11, 0xe000, prg[9] & 0x7fff); + // WRAM + if (prg[9] & 0x8000) + setprg8r(0x10, 0xe000, prg[9] & 0x03); + } + + // 8K + 8K + 8K + 8K + if (prg_rom_mode == PRG_ROM_MODE_3) + { + for (uint8 i = 0; i < 4; i++) + { + // PRG-ROM + if (!(prg[3 + i*2] & 0x8000)) + setprg8r(0x11, 0x8000 + 0x2000 * i, prg[3 + i*2] & 0x7fff); + // WRAM + if (prg[3 + i*2] & 0x8000) + setprg8r(0x10, 0x8000 + 0x2000 * i, prg[3 + i*2] & 0x03); + } + } + + // 4K + 4K + 4K + 4K + 4K + 4K + 4K + 4K + if (prg_rom_mode == PRG_ROM_MODE_4) + { + for (uint8 i = 0; i < 8; i++) + { + // PRG-ROM + if (!(prg[3+i] & 0x8000)) + setprg4r(0x11, 0x8000 + 0x1000 * i, prg[3+i] & 0x7fff); + // WRAM + if (prg[3+i] & 0x8000) + setprg4r(0x10, 0x8000 + 0x1000 * i, prg[3+i] & 0x07); + } + } + + // $6000-$7fff + + // 8K + if (prg_ram_mode == PRG_RAM_MODE_0) + { + // WRAM + if (((prg[1] & 0xC000) >> 14) == 2) + setprg8r(0x10, 0x6000, prg[1] & 0x03); + // FPGA-RAM + if (((prg[1] & 0xC000) >> 14) == 3) + setprg8r(0x12, 0x6000, 0); + // PRG-ROM + if (((prg[1] & 0x8000) >> 15) == 0) + setprg8r(0x11, 0x6000, prg[1] & 0x7fff); + } + + // 4K + if (prg_ram_mode == PRG_RAM_MODE_1) + { + // WRAM + if (((prg[1] & 0xC000) >> 14) == 2) + setprg4r(0x10, 0x6000, prg[1] & 0x07); + // FPGA-RAM + if (((prg[1] & 0xC000) >> 14) == 3) + setprg4r(0x12, 0x6000, prg[1] & 0x01); + // PRG-ROM + if (((prg[1] & 0x8000) >> 15) == 0) + setprg4r(0x11, 0x6000, prg[1] & 0x7fff); + + // WRAM + if (((prg[2] & 0xC000) >> 14) == 2) + setprg4r(0x10, 0x7000, prg[2] & 0x07); + // FPGA-RAM + if (((prg[2] & 0xC000) >> 14) == 3) + setprg4r(0x12, 0x7000, prg[2] & 0x01); + // PRG-ROM + if (((prg[2] & 0x8000) >> 15) == 0) + setprg4r(0x11, 0x7000, prg[2] & 0x7fff); + } + + // $5000-$5fff - 4K FPGA-RAM + if (bootloader == 1) + setprg4r(0x11, 0x5000, 125); // todo: why 125 ?! + else + setprg4r(0x12, 0x5000, prg[0] & 0x01); + + // $4800-$4fff + setprg2r(0x12, 0x4800, 3); + + if(chr_chip == CHR_CHIP_FPGA_RAM) + { + setchr4r(0x12, 0x0000, 0); + setchr4r(0x12, 0x1000, 0); + } + else + { + cart_chr_map = chr_chip + 0x10; + switch (chr_mode) + { + case CHR_MODE_0: + setchr8r(cart_chr_map, chr[0] & 0xffff); + break; + case CHR_MODE_1: + setchr4r(cart_chr_map, 0x0000, chr[0] & 0xffff); + setchr4r(cart_chr_map, 0x1000, chr[1] & 0xffff); + break; + case CHR_MODE_2: + setchr2r(cart_chr_map, 0x0000, chr[0] & 0xffff); + setchr2r(cart_chr_map, 0x0800, chr[1] & 0xffff); + setchr2r(cart_chr_map, 0x1000, chr[2] & 0xffff); + setchr2r(cart_chr_map, 0x1800, chr[3] & 0xffff); + break; + case CHR_MODE_3: + for (uint8 i = 0; i < 8; i++) { + setchr1r(cart_chr_map, i << 10, chr[i] & 0xffff); + } + break; + case CHR_MODE_4: + for (uint8 i = 0; i < 16; i++) { + setchr512r(cart_chr_map, i << 9, chr[i] & 0xffff); + } + break; + } + } + + for (int i = 0; i < 4; i++) + { + uint8 cur_NT_bank = NT_bank[i]; + uint8 cur_NT_chip = NT_control[i] >> 6; + uint8 cur_NT_1K_dest = (NT_control[i] & 0x0C) >> 2; + uint8 cur_NT_ext_mode = NT_control[i] & 0x03; + + switch (cur_NT_chip) + { + case NT_CIRAM: + vnapage[i] = NTARAM + 0x400 * (cur_NT_bank & 0x01); + break; + case NT_CHR_RAM: + vnapage[i] = CHRRAM + 0x400 * cur_NT_bank; + break; + case NT_FPGA_RAM: + vnapage[i] = FPGA_RAM + 0x400 * (cur_NT_bank & 0x03); + break; + case NT_CHR_ROM: + vnapage[i] = CHR_FLASHROM + 0x400 * cur_NT_bank; + break; + } + } + +/* + switch (mirr_mode) + { + case MIRR_VERTICAL: + setmirror(MI_V); + break; + case MIRR_HORIZONTAL: + setmirror(MI_H); + break; + case MIRR_ONE_SCREEN: + FCEUPPU_LineUpdate(); + switch (nt_set) + { + case 0: address = NTARAM; break; + case 1: address = NTARAM + 0x400; break; + case 2: address = ExtraNTARAM; break; + case 3: address = ExtraNTARAM + 0x400; break; + } + vnapage[0] = vnapage[1] = vnapage[2] = vnapage[3] = address; + PPUNTARAM = 0x0F; + break; + case MIRR_FOUR_SCREEN: + FCEUPPU_LineUpdate(); + if (CHRRAM != NULL) + { + for (int i = 0; i < 4; i++) + { + uint8 t = nt_set ^ 0x03; + start = (16 + t * 4) * 1024; + offset = i * 0x400; + vnapage[i] = CHRRAM + start + offset; + } + PPUNTARAM = 0x0F; + } + else + { + for (int i = 0; i < 4; i++) + { + offset = i * 0x400; + vnapage[i] = DUMMY_CHRRAM + offset; + } + } + } +*/ +} + +static DECLFW(Rainbow2SW) { + if (A >= 0x41A0 && A <= 0x41A2) + { + vpsg1[A & 3] = V; + if (sfun[0]) + sfun[0](); + } + else if (A >= 0x41A3 && A <= 0x41A5) + { + vpsg1[4 | ((A - 3) & 3)] = V; + if (sfun[1]) + sfun[1](); + } + else if (A >= 0x41A6 && A <= 0x41A8) + { + vpsg2[(A - 6) & 3] = V; + if (sfun[2]) + sfun[2](); + } +} + +static DECLFW(WRAM_0x6000Wr) +{ + // $6000-$7fff + + // 8K + if (prg_ram_mode == PRG_RAM_MODE_0) + { + if (((prg[1] & 0xC000) >> 14) == 0x11) + FPGA_RAM[A & 0x1fff] = V; // FPGA-RAM + else + CartBW(A, V); // PRG-ROM / WRAM + } + + // 4K + if (prg_ram_mode == PRG_RAM_MODE_1) + { + if (((prg[1] & 0xC000) >> 14) == 0x11) + FPGA_RAM[A & 0x1fff] = V; // FPGA-RAM + else + CartBW(A, V); // PRG-ROM / WRAM + + if (((prg[2] & 0xC000) >> 14) == 0x11) + FPGA_RAM[A & 0x1fff] = V; // FPGA-RAM + else + CartBW(A, V); // PRG-ROM / WRAM + } +} +static DECLFR(WRAM_0x6000Rd) +{ + // $6000-$7fff + + // 8K + if (prg_ram_mode == PRG_RAM_MODE_0) + { + if (((prg[1] & 0xC000) >> 14) == 0x11) + return FPGA_RAM[A & 0x1fff]; // FPGA-RAM + else + return CartBR(A); // PRG-ROM / WRAM + } + + // 4K + if (prg_ram_mode == PRG_RAM_MODE_1) + { + if (((prg[1] & 0xC000) >> 14) == 0x11) + return FPGA_RAM[A & 0x1fff]; // FPGA-RAM + else + return CartBR(A); // PRG-ROM / WRAM + + if (((prg[2] & 0xC000) >> 14) == 0x11) + return FPGA_RAM[A & 0x1fff]; // FPGA-RAM + else + return CartBR(A); // PRG-ROM / WRAM + } + return CartBR(A); +} +static DECLFW(WRAM_0x5000Wr) +{ + FPGA_RAM[(A & 0xfff) | ((prg[0] & 0x01) << 12)] = V; +} +static DECLFR(WRAM_0x5000Rd) +{ + return FPGA_RAM[(A & 0xfff) | ((prg[0] & 0x01) << 12)]; + return 0x00; +} +static DECLFW(FPGA_0x4800Wr) +{ + FPGA_RAM[(A & 0x7ff) + 0x1800] = V; +} +static DECLFR(FPGA_0x4800Rd) +{ + return FPGA_RAM[(A & 0x7ff) + 0x1800]; +} + +static DECLFR(Rainbow2Read) { + switch (A) + { + case 0x4100: return (prg_ram_mode << 6) | prg_rom_mode; + case 0x4120: return (chr_chip << 6) | (chr_spr_ext_mode << 5) | chr_mode; + case 0x4151: { + S_IRQcontrol &= ~0x80; + S_IRQready = 0; + IRQEnd(); + return CartBR(A); + } + case 0x4160: return MAPPER_VERSION; + case 0x4161: return mul_result & 0xff; + case 0x4162: return (mul_result >> 8) & 0xff; + + // ESP - WiFi + case 0x4170: + { + uint8 esp_enable_flag = esp_enable ? 0x01 : 0x00; + uint8 irq_enable_flag = esp_irq_enable ? 0x02 : 0x00; + UDBG("RAINBOW read flags %04x => %02xs\n", A, esp_enable_flag | irq_enable_flag); + return esp_enable_flag | irq_enable_flag; + } + case 0x4171: + { + uint8 esp_message_received_flag = esp_message_received() ? 0x80 : 0; + uint8 esp_rts_flag = esp->getDataReadyIO() ? 0x40 : 0x00; + return esp_message_received_flag | esp_rts_flag; + } + case 0x4172: return esp_message_sent ? 0x80 : 0; + case 0x4175: + { + uint8 retval = FPGA_RAM[0x1800 + (rx_address << 8) + rx_index]; + rx_index++; + return retval; + } + default: + return CartBR(A); + } +} + +static DECLFW(Rainbow2Write) { + switch (A) + { + // Mapper configuration + case 0x4100: + prg_rom_mode = V & 0x07; + prg_ram_mode = (V & 0x80) >> 7; + Sync(); + break; + // PRG banking + case 0x4106: + case 0x4107: + case 0x4108: + case 0x4109: + case 0x410A: + case 0x410B: + case 0x410C: + case 0x410D: + case 0x410E: + case 0x410F: + { + int bank = ( A & 0x0f ) - 5; + prg[bank] = (prg[bank] & 0x00ff) | (V << 8); + Sync(); + break; + } + case 0x4115: prg[0] = V & 0x01; Sync(); break; + case 0x4116: + case 0x4117: + case 0x4118: + case 0x4119: + case 0x411A: + case 0x411B: + case 0x411C: + case 0x411D: + case 0x411E: + case 0x411F: + { + int bank = ( A & 0x0f ) - 5; + prg[bank] = (prg[bank] & 0xff00) | V; + Sync(); + break; + } + // CHR banking / chip selector / sprite extended mode + case 0x4120: + chr_chip = (V & 0xC0) >> 6; + chr_spr_ext_mode = (V & 0x20) >> 5; + chr_mode = V & 0x07; + Sync(); + break; + // Nametables bank + case 0x4126: NT_bank[0] = V; Sync(); break; + case 0x4127: NT_bank[1] = V; Sync(); break; + case 0x4128: NT_bank[2] = V; Sync(); break; + case 0x4129: NT_bank[3] = V; Sync(); break; + // Nametables control + case 0x412A: NT_control[0] = V; Sync(); break; + case 0x412B: NT_control[1] = V; Sync(); break; + case 0x412C: NT_control[2] = V; Sync(); break; + case 0x412D: NT_control[3] = V; Sync(); break; + // CHR banking + case 0x4130: + case 0x4131: + case 0x4132: + case 0x4133: + case 0x4134: + case 0x4135: + case 0x4136: + case 0x4137: + case 0x4138: + case 0x4139: + case 0x413A: + case 0x413B: + case 0x413C: + case 0x413D: + case 0x413E: + case 0x413F: + { + int bank = A & 0x0f; + chr[bank] = (chr[bank] & 0x00ff) | (V << 8); + Sync(); + break; + } + case 0x4140: + case 0x4141: + case 0x4142: + case 0x4143: + case 0x4144: + case 0x4145: + case 0x4146: + case 0x4147: + case 0x4148: + case 0x4149: + case 0x414A: + case 0x414B: + case 0x414C: + case 0x414D: + case 0x414E: + case 0x414F: + { + int bank = A & 0x0f; + chr[bank] = (chr[bank] & 0xff00) | V; + Sync(); + break; + } + // Scanline IRQ + case 0x4150: S_IRQlatch = V; break; + case 0x4151: S_IRQcontrol |= (V & 0x01); break; + case 0x4152: S_IRQoffset = V > 169 ? 169 : V; break; + // CPU Cycle IRQ + case 0x4158: C_IRQLatch &= 0xFF00; C_IRQLatch |= V; C_IRQCount = C_IRQLatch; break; + case 0x4159: C_IRQLatch &= 0x00FF; C_IRQLatch |= V << 8; C_IRQCount = C_IRQLatch; break; + case 0x415A: + C_IRQe = V & 0x01; + C_IRQr = (V & 0x02) >> 1; + if (C_IRQe) + C_IRQCount = C_IRQLatch; + break; + case 0x415B: + C_IRQp = false; + IRQEnd(); + break; + // Multiplier + case 0x4161: mul_a = V; mul_result = mul_a * mul_b; break; + case 0x4162: mul_b = V; mul_result = mul_a * mul_b; break; + // ESP - WiFi + case 0x4170: + esp_enable = V & 0x01; + esp_irq_enable = V & 0x02; + break; + case 0x4171: + if (esp_enable) clear_esp_message_received(); + else FCEU_printf("RAINBOW warning: $4170.0 is not set\n"); + break; + case 0x4172: + if (esp_enable) + { + esp_message_sent = false; + uint8 message_length = FPGA_RAM[0x1800 + (tx_address << 8)]; + esp->rx(message_length); + for (uint8 i = 0; i < message_length; i++) + { + esp->rx(FPGA_RAM[0x1800 + (tx_address << 8) + 1 + i]); + } + esp_message_sent = true; + } + else FCEU_printf("RAINBOW warning: $4170.0 is not set\n"); + break; + case 0x4173: + rx_address = V & 0x03; + break; + case 0x4174: + tx_address = V & 0x03; + break; + case 0x4175: + rx_index = V; + break; + } +} + +uint8 FASTCALL Rainbow2PPURead(uint32 A) { + // if CHR-RAM, check if CHR-RAM exists, if not return data bus cache + if (chr_chip == CHR_CHIP_RAM && CHRRAM == NULL) + { + if (PPU_hook) PPU_hook(A); + return X.DB; + } + + // if CHR-ROM, check if CHR-ROM exists, if not return data bus cache + if (chr_chip == CHR_CHIP_ROM && CHR_FLASHROM == NULL) + { + if (PPU_hook) PPU_hook(A); + return X.DB; + } + + return FFCEUX_PPURead_Default(A); +} + +uint8 Rainbow2FlashID(uint8 chip, uint32 A) { + // Software ID mode is undefined by the datasheet for all but the lowest 2 addressable bytes, + // but some tests of the chip currently being used found it repeats in 512-byte patterns. + // http://forums.nesdev.com/viewtopic.php?p=178728#p178728 + + uint32 aid = A & 0x1FF; + switch (aid) + { + case 0: return 0xBF; + case 1: + { + switch (chip) + { + case CHIP_TYPE_PRG: + switch (ROM_size * 16) + { + case 128: return 0xB5; + case 256: return 0xB6; + case 512: return 0xB7; + default: return 0xFF; + } + case CHIP_TYPE_CHR: + switch (VROM_size * 8) + { + case 128: return 0xB5; + case 256: return 0xB6; + case 512: return 0xB7; + default: return 0xFF; + } + } + } + default: return 0xFF; + } +} + +uint8 FASTCALL Rainbow2FlashChrID(uint32 A) { + return Rainbow2FlashID(CHIP_TYPE_CHR, A); +} + +static DECLFR(Rainbow2FlashPrgID) +{ + return Rainbow2FlashID(CHIP_TYPE_PRG, A); +} + +void Rainbow2FlashIDEnter(uint8 chip) +{ + switch (chip) + { + case CHIP_TYPE_PRG: + if (flash_id[chip]) + return; + flash_id[chip] = 1; + if (bootloader) + SetReadHandler(0x8000, 0xDFFF, Rainbow2FlashPrgID); + else + SetReadHandler(0x8000, 0xFFFF, Rainbow2FlashPrgID); + break; + case CHIP_TYPE_CHR: + if (CHR_FLASHROM == NULL) + return; + if (flash_id[chip]) + return; + flash_id[chip] = 1; + FFCEUX_PPURead = Rainbow2FlashChrID; + break; + default: + return; + } +} + +void Rainbow2FlashIDExit(uint8 chip) +{ + switch (chip) + { + case CHIP_TYPE_PRG: + if (!flash_id[chip]) + return; + flash_id[chip] = 0; + SetReadHandler(0x8000, 0xFFFF, CartBR); + break; + case CHIP_TYPE_CHR: + if (!flash_id[chip]) + return; + flash_id[chip] = 0; + FFCEUX_PPURead = Rainbow2PPURead; + break; + default: + return; + } +} + +void Rainbow2Flash(uint8 chip, uint32 flash_addr, uint8 V) { + + uint32 command_addr = flash_addr & 0x7FFF; + + enum + { + flash_mode_READY = 0, + flash_mode_COMMAND, + flash_mode_BYTE_WRITE, + flash_mode_ERASE, + }; + + switch (flash_mode[chip]) + { + default: + case flash_mode_READY: + if (command_addr == 0x5555 && V == 0xAA) + { + flash_mode[chip] = flash_mode_COMMAND; + flash_sequence[chip] = 0; + } + else if (V == 0xF0) + { + Rainbow2FlashIDExit(chip); + } + break; + case flash_mode_COMMAND: + if (flash_sequence[chip] == 0) + { + if (command_addr == 0x2AAA && V == 0x55) + { + flash_sequence[chip] = 1; + } + else + { + flash_mode[chip] = flash_mode_READY; + } + } + else if (flash_sequence[chip] == 1) + { + if (command_addr == 0x5555) + { + flash_sequence[chip] = 0; + switch (V) + { + default: flash_mode[chip] = flash_mode_READY; break; + case 0xA0: flash_mode[chip] = flash_mode_BYTE_WRITE; break; + case 0x80: flash_mode[chip] = flash_mode_ERASE; break; + case 0x90: Rainbow2FlashIDEnter(chip); flash_mode[chip] = flash_mode_READY; break; + case 0xF0: Rainbow2FlashIDExit(chip); flash_mode[chip] = flash_mode_READY; break; + } + } + else + flash_mode[chip] = flash_mode_READY; + } + else + flash_mode[chip] = flash_mode_READY; // should be unreachable + break; + case flash_mode_BYTE_WRITE: + if (chip == CHIP_TYPE_PRG) + { + PRG_FLASHROM[flash_addr] &= V; + } + else if (chip == CHIP_TYPE_CHR) + { + CHR_FLASHROM[flash_addr] &= V; + } + flash_mode[chip] = flash_mode_READY; + break; + case flash_mode_ERASE: + if (flash_sequence[chip] == 0) + { + if (command_addr == 0x5555 && V == 0xAA) + flash_sequence[chip] = 1; + else + flash_mode[chip] = flash_mode_READY; + } + else if (flash_sequence[chip] == 1) + { + if (command_addr == 0x2AAA && V == 0x55) + flash_sequence[chip] = 2; + else + flash_mode[chip] = flash_mode_READY; + } + else if (flash_sequence[chip] == 2) + { + if (command_addr == 0x5555 && V == 0x10) // erase chip + { + if (chip == CHIP_TYPE_PRG) + { + memset(PRG_FLASHROM, 0xFF, PRG_FLASHROMSIZE); + } + else if (chip == CHIP_TYPE_CHR) + { + memset(CHR_FLASHROM, 0xFF, CHR_FLASHROMSIZE); + } + } + else if (V == 0x30) // erase 4k sector + { + uint32 sector = flash_addr & 0x7F000; + if (chip == CHIP_TYPE_PRG) + { + memset(PRG_FLASHROM + sector, 0xFF, 1024 * 4); + } + else if (chip == CHIP_TYPE_CHR) + { + memset(CHR_FLASHROM + sector, 0xFF, 1024 * 4); + } + } + flash_mode[chip] = flash_mode_READY; + } + else + flash_mode[chip] = flash_mode_READY; // should be unreachable + break; + } +} + +static DECLFW(Rainbow2PrgFlash) { + if (A < 0x6000 || A > 0xFFFF) + return; + + uint32 flash_addr = A; + if (A >= 0x6000 & A < 0x8000) + { + switch (prg_ram_mode) + { + case PRG_RAM_MODE_0: + if ((A >= 0x6000) & (A <= 0x7FFF) & !(prg[1] & 0x8000)) + { + flash_addr &= 0x1FFF; + flash_addr |= (prg[1] & 0x7FFF) << 13; + } + else + { + return; + } + break; + case PRG_RAM_MODE_1: + flash_addr &= 0x0FFF; + if ((A >= 0x6000) & (A <= 0x6FFF) & !(prg[1] & 0x8000)) + { + flash_addr |= (prg[1] & 0x7FFF) << 12; + } + else if ((A >= 0x7000) & (A <= 0x7FFF) & !(prg[2] & 0x8000)) + { + flash_addr |= (prg[2] & 0x7FFF) << 12; + } + else + { + return; + } + break; + } + } + else if (A >= 0x8000 & A <= 0xFFFF) + { + switch (prg_rom_mode) + { + case PRG_ROM_MODE_0: + flash_addr &= 0x7FFF; + flash_addr |= (prg[3] & 0x7FFF) << 15; + break; + case PRG_ROM_MODE_1: + flash_addr &= 0x3FFF; + if ((A >= 0x8000) & (A <= 0xBFFF)) + { + flash_addr |= (prg[3] & 0x7FFF) << 14; + } + else if ((A >= 0xC000) & (A <= 0xFFFF)) + { + flash_addr |= (prg[7] & 0x7FFF) << 14; + } + break; + case PRG_ROM_MODE_2: + if ((A >= 0x8000) & (A <= 0xBFFF)) + { + flash_addr &= 0x3FFF; + flash_addr |= (prg[3] & 0x3F) << 14; + } + else if ((A >= 0xC000) & (A <= 0xDFFF)) + { + flash_addr &= 0x1FFF; + flash_addr |= (prg[7] & 0x7FFF) << 13; + } + else if ((A >= 0xE000) & (A <= 0xFFFF)) + { + flash_addr &= 0x1FFF; + flash_addr |= (prg[9] & 0x7FFF) << 13; + } + break; + case PRG_ROM_MODE_3: + flash_addr &= 0x1FFF; + if ((A >= 0x8000) & (A <= 0x9FFF)) + { + flash_addr |= (prg[3] & 0x7FFF) << 13; + } + else if ((A >= 0xA000) & (A <= 0xBFFF)) + { + flash_addr |= (prg[5] & 0x7FFF) << 13; + } + else if ((A >= 0xC000) & (A <= 0xDFFF)) + { + flash_addr |= (prg[7] & 0x7FFF) << 13; + } + else if ((A >= 0xE000) & (A <= 0xFFFF)) + { + flash_addr |= (prg[9] & 0x7FFF) << 13; + } + break; + case PRG_ROM_MODE_4: + flash_addr &= 0x0FFF; + if ((A >= 0x8000) & (A <= 0x8FFF)) + { + flash_addr |= (prg[3] & 0x7FFF) << 12; + } + else if ((A >= 0x9000) & (A <= 0x9FFF)) + { + flash_addr |= (prg[4] & 0x7FFF) << 12; + } + else if ((A >= 0xA000) & (A <= 0xAFFF)) + { + flash_addr |= (prg[5] & 0x7FFF) << 12; + } + else if ((A >= 0xB000) & (A <= 0xBFFF)) + { + flash_addr |= (prg[6] & 0x7FFF) << 12; + } + else if ((A >= 0xC000) & (A <= 0xCFFF)) + { + flash_addr |= (prg[7] & 0x7FFF) << 12; + } + else if ((A >= 0xD000) & (A <= 0xDFFF)) + { + flash_addr |= (prg[8] & 0x7FFF) << 12; + } + else if ((A >= 0xE000) & (A <= 0xEFFF)) + { + flash_addr |= (prg[9] & 0x7FFF) << 12; + } + else if ((A >= 0xF000) & (A <= 0xFFFF)) + { + flash_addr |= (prg[10] & 0x7FFF) << 12; + } + break; + + default: + return; + } + } + Rainbow2Flash(CHIP_TYPE_PRG, flash_addr, V); +} + +static void Rainbow2PPUWrite(uint32 A, uint8 V) { + + // if CHR-RAM but CHR-RAM does not exist then return + if (chr_chip == CHR_CHIP_RAM && CHRRAM == NULL) + return; + + // if CHR-ROM but CHR-ROM does not exist then return + if (chr_chip == CHR_CHIP_ROM && CHR_FLASHROM == NULL) + return; + else + { + uint32 flash_addr = A; + if (A < 0x2000) + { + switch (chr_mode) + { + // NOTE: plus les bons modes ? + case CHR_MODE_0: + flash_addr &= 0x1FFF; + flash_addr |= (chr[0] & 0xffff) << 13; + break; + case CHR_MODE_1: + flash_addr &= 0xFFF; + flash_addr |= (chr[A >> 12] & 0xffff) << 12; + break; + case CHR_MODE_2: + flash_addr &= 0x7FF; + flash_addr |= (chr[A >> 11] & 0xffff) << 11; + break; + case CHR_MODE_3: + flash_addr &= 0x3FF; + flash_addr |= (chr[A >> 10] & 0xffff) << 10; + break; + case CHR_MODE_4: + flash_addr &= 0x1FF; + flash_addr |= (chr[A >> 9] & 0xffff) << 9; + break; + } + Rainbow2Flash(CHIP_TYPE_CHR, flash_addr, V); + } + } + FFCEUX_PPUWrite_Default(A, V); +} + +static void Rainbow2Reset(void) { + // Bootloader + + // PRG - 32K banks mapped to last PRG-ROM bank + prg_rom_mode = PRG_ROM_MODE_0; + prg[3] = 0x7FFF; + + // CHR - 8K banks mapped to first bank + chr_chip = CHR_CHIP_ROM; + chr_spr_ext_mode = 0; + chr_mode = CHR_MODE_0; + chr[0] = 0; + + // Nametables - CIRAM horizontal mirroring + NT_bank[0] = 0; + NT_bank[1] = 0; + NT_bank[2] = 1; + NT_bank[3] = 1; + NT_control[0] = 0; + NT_control[1] = 0; + NT_control[2] = 0; + NT_control[3] = 0; + + // Scanline IRQ + S_IRQcontrol = 0; + S_IRQoffset = 135; + + // CPU Cycle IRQ + C_IRQe = C_IRQp = C_IRQr = 0; + + // ESP / WiFi + esp_enable = false; + //clear_esp_message_received(); + esp_message_sent = true; + //rx_address = 0; + //tx_address = 0; + //rx_index = 0; + ESP_IRQp = 0; + Sync(); +} + +static void Rainbow2Power(void) { + + // mapper init + bootloader = 0x00; // 0x01; + Rainbow2Reset(); + + SetReadHandler(0x4800, 0xFFFF, CartBR); + SetWriteHandler(0x4800, 0x7FFF, CartBW); + if (WRAM) + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + FCEU_CheatAddRAM(FPGA_RAMSIZE >> 10, 0x5000, FPGA_RAM); + FCEU_CheatAddRAM(0x1800 >> 10, 0x4800, FPGA_RAM); + + // mapper registers (writes) + SetWriteHandler(0x4100, 0x47ff, Rainbow2Write); + + // mapper registers (reads) + SetReadHandler(0x4100, 0x47ff, Rainbow2Read); + + // audio expansion registers (writes) + SetWriteHandler(0x41A0, 0x41A8, Rainbow2SW); + + // FPGA WRAM @ $4800-$4fff (reads/writes) + SetWriteHandler(0x4800, 0x4fff, FPGA_0x4800Wr); + SetReadHandler(0x4800, 0x4fff, FPGA_0x4800Rd); + + // FPGA WRAM @ $5000-$5fff (reads/writes) + SetWriteHandler(0x5000, 0x5fff, WRAM_0x5000Wr); + SetReadHandler(0x5000, 0x5fff, WRAM_0x5000Rd); + + // WRAM @ $6000-$7fff (reads/writes) + SetWriteHandler(0x6000, 0x7fff, WRAM_0x6000Wr); + SetReadHandler(0x6000, 0x7fff, WRAM_0x6000Rd); + + // self-flashing + flash_mode[CHIP_TYPE_PRG] = 0; + flash_mode[CHIP_TYPE_CHR] = 0; + flash_sequence[CHIP_TYPE_PRG] = 0; + flash_sequence[CHIP_TYPE_CHR] = 0; + flash_id[CHIP_TYPE_PRG] = false; + flash_id[CHIP_TYPE_CHR] = false; + SetWriteHandler(0x8000, 0xFFFF, Rainbow2PrgFlash); + + // fill WRAM/FPGA_RAM/CHRRAM/DUMMY_CHRRAM/DUMMY_CHRROM with random values + if (WRAM) + FCEU_MemoryRand(WRAM, WRAMSIZE, false); + + if (FPGA_RAM) + FCEU_MemoryRand(FPGA_RAM, FPGA_RAMSIZE, false); + + if (CHRRAM) + FCEU_MemoryRand(CHRRAM, CHRRAMSIZE, false); + + if (DUMMY_CHRRAM) + FCEU_MemoryRand(DUMMY_CHRRAM, DUMMY_CHRRAMSIZE, false); + + if (DUMMY_CHRROM) + FCEU_MemoryRand(DUMMY_CHRROM, DUMMY_CHRROMSIZE, false); + + // ESP firmware + esp = new BrokeStudioFirmware; + //esp_enable = false; + //esp_irq_enable = false; + clear_esp_message_received(); + //esp_message_sent = true; + //rx_address = 0; + //tx_address = 0; + //rx_index = 0; +} + +static void Rainbow2Close(void) +{ + if (WRAM) + { + FCEU_gfree(WRAM); + WRAM = NULL; + } + + if (FPGA_RAM) + { + FCEU_gfree(FPGA_RAM); + FPGA_RAM = NULL; + } + + if (CHRRAM) + ExtraNTARAM = NULL; + + if (DUMMY_CHRRAM) + { + FCEU_gfree(DUMMY_CHRRAM); + DUMMY_CHRRAM = NULL; + ExtraNTARAM = NULL; + } + + if (PRG_FLASHROM) + { + FCEU_gfree(PRG_FLASHROM); + PRG_FLASHROM = NULL; + } + + if (CHR_FLASHROM) + { + FCEU_gfree(CHR_FLASHROM); + CHR_FLASHROM = NULL; + } + + if (esp) + { + esp_enable = false; + delete esp; + esp = NULL; + } +} + +static void StateRestore(int version) { + Sync(); +} + +// audio expansion + +static void DoSQV1(void); +static void DoSQV2(void); +static void DoSawV(void); + +static INLINE void DoSQV(int x) { + int32 V; + int32 amp = (((vpsg1[x << 2] & 15) << 8) * 6 / 8) >> 4; + int32 start, end; + + start = cvbc[x]; + end = (SOUNDTS << 16) / soundtsinc; + if (end <= start) + return; + cvbc[x] = end; + + if (vpsg1[(x << 2) | 0x2] & 0x80) + { + if (vpsg1[x << 2] & 0x80) + { + for (V = start; V < end; V++) + Wave[V >> 4] += amp; + } + else + { + int32 thresh = (vpsg1[x << 2] >> 4) & 7; + int32 freq = ((vpsg1[(x << 2) | 0x1] | ((vpsg1[(x << 2) | 0x2] & 15) << 8)) + 1) << 17; + for (V = start; V < end; V++) { + if (dcount[x] > thresh) + Wave[V >> 4] += amp; + vcount[x] -= nesincsize; + while (vcount[x] <= 0) { + vcount[x] += freq; + dcount[x] = (dcount[x] + 1) & 15; + } + } + } + } +} + +static void DoSQV1(void) { + DoSQV(0); +} + +static void DoSQV2(void) { + DoSQV(1); +} + +static void DoSawV(void) { + int V; + int32 start, end; + + start = cvbc[2]; + end = (SOUNDTS << 16) / soundtsinc; + if (end <= start) + return; + cvbc[2] = end; + + if (vpsg2[2] & 0x80) + { + static int32 saw1phaseacc = 0; + uint32 freq3; + static uint8 b3 = 0; + static int32 phaseacc = 0; + static uint32 duff = 0; + + freq3 = (vpsg2[1] + ((vpsg2[2] & 15) << 8) + 1); + + for (V = start; V < end; V++) { + saw1phaseacc -= nesincsize; + if (saw1phaseacc <= 0) + { + int32 t; + rea: + t = freq3; + t <<= 18; + saw1phaseacc += t; + phaseacc += vpsg2[0] & 0x3f; + b3++; + if (b3 == 7) + { + b3 = 0; + phaseacc = 0; + } + if (saw1phaseacc <= 0) + goto rea; + duff = (((phaseacc >> 3) & 0x1f) << 4) * 6 / 8; + } + Wave[V >> 4] += duff; + } + } +} + +static INLINE void DoSQVHQ(int x) { + int32 V; + int32 amp = ((vpsg1[x << 2] & 15) << 8) * 6 / 8; + + if (vpsg1[(x << 2) | 0x2] & 0x80) + { + if (vpsg1[x << 2] & 0x80) + { + for (V = cvbc[x]; V < (int)SOUNDTS; V++) + WaveHi[V] += amp; + } + else + { + int32 thresh = (vpsg1[x << 2] >> 4) & 7; + for (V = cvbc[x]; V < (int)SOUNDTS; V++) { + if (dcount[x] > thresh) + WaveHi[V] += amp; + vcount[x]--; + if (vcount[x] <= 0) + { + vcount[x] = (vpsg1[(x << 2) | 0x1] | ((vpsg1[(x << 2) | 0x2] & 15) << 8)) + 1; + dcount[x] = (dcount[x] + 1) & 15; + } + } + } + } + cvbc[x] = SOUNDTS; +} + +static void DoSQV1HQ(void) { + DoSQVHQ(0); +} + +static void DoSQV2HQ(void) { + DoSQVHQ(1); +} + +static void DoSawVHQ(void) { + static uint8 b3 = 0; + static int32 phaseacc = 0; + int32 V; + + if (vpsg2[2] & 0x80) + { + for (V = cvbc[2]; V < (int)SOUNDTS; V++) { + WaveHi[V] += (((phaseacc >> 3) & 0x1f) << 8) * 6 / 8; + vcount[2]--; + if (vcount[2] <= 0) + { + vcount[2] = (vpsg2[1] + ((vpsg2[2] & 15) << 8) + 1) << 1; + phaseacc += vpsg2[0] & 0x3f; + b3++; + if (b3 == 7) { + b3 = 0; + phaseacc = 0; + } + } + } + } + cvbc[2] = SOUNDTS; +} + +void Rainbow2Sound(int Count) { + int x; + + DoSQV1(); + DoSQV2(); + DoSawV(); + for (x = 0; x < 3; x++) + cvbc[x] = Count; +} + +void Rainbow2SoundHQ(void) { + DoSQV1HQ(); + DoSQV2HQ(); + DoSawVHQ(); +} + +void Rainbow2SyncHQ(int32 ts) { + int x; + for (x = 0; x < 3; x++) cvbc[x] = ts; +} + +static void Rainbow2ESI(void) { + GameExpSound.RChange = Rainbow2ESI; + GameExpSound.Fill = Rainbow2Sound; + GameExpSound.HiFill = Rainbow2SoundHQ; + GameExpSound.HiSync = Rainbow2SyncHQ; + + memset(cvbc, 0, sizeof(cvbc)); + memset(vcount, 0, sizeof(vcount)); + memset(dcount, 0, sizeof(dcount)); + if (FSettings.SndRate) + { + if (FSettings.soundq >= 1) + { + sfun[0] = DoSQV1HQ; + sfun[1] = DoSQV2HQ; + sfun[2] = DoSawVHQ; + } + else + { + sfun[0] = DoSQV1; + sfun[1] = DoSQV2; + sfun[2] = DoSawV; + } + } + else + memset(sfun, 0, sizeof(sfun)); + AddExState(&SStateRegs, ~0, 0, 0); +} + +#if 0 +// Let's disable NSF support for now since I don't have an NSF ROM file to test it yet. + +// NSF Init + +void NSFRainbow2_Init(void) { + Rainbow2ESI(); + SetWriteHandler(0x8000, 0xbfff, Rainbow2SW); +} +#endif + +// mapper init + +void RAINBOW2_Init(CartInfo *info) { + int save_game_index = 0; + info->Power = Rainbow2Power; + info->Reset = Rainbow2Reset; + info->Close = Rainbow2Close; + + //GameHBIRQHook = Rainbow2hb; + MapIRQHook = Rainbow2IRQ; + Rainbow2ESI(); + GameStateRestore = StateRestore; + + // WRAM + if (info->wram_size != 0) + { + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (info->battery) + { + info->SaveGame[save_game_index] = WRAM; + info->SaveGameLen[save_game_index] = WRAMSIZE; + save_game_index++; + } + } + + // FPGA_RAM + FPGA_RAM = (uint8*)FCEU_gmalloc(FPGA_RAMSIZE); + SetupCartPRGMapping(0x12, FPGA_RAM, FPGA_RAMSIZE, 1); + SetupCartCHRMapping(0x12, FPGA_RAM, FPGA_RAMSIZE, 1); + AddExState(FPGA_RAM, FPGA_RAMSIZE, 0, "FPGA_RAM"); + if (info->battery) + { + info->SaveGame[save_game_index] = FPGA_RAM; + info->SaveGameLen[save_game_index] = FPGA_RAMSIZE; + save_game_index++; + } + + // PRG FLASH ROM + PRG_FLASHROM = (uint8*)FCEU_gmalloc(PRG_FLASHROMSIZE); + AddExState(PRG_FLASHROM, PRG_FLASHROMSIZE, 0, "PFROM"); + if (info->battery) + { + info->SaveGame[save_game_index] = PRG_FLASHROM; + info->SaveGameLen[save_game_index] = PRG_FLASHROMSIZE; + save_game_index++; + } + + // copy PRG ROM into PRG_FLASHROM, use it instead of PRG ROM + const uint32 PRGSIZE = ROM_size * 16 * 1024; + for (uint32 w = 0, r = 0; w < PRG_FLASHROMSIZE; ++w) + { + PRG_FLASHROM[w] = ROM[r]; + ++r; + if (r >= PRGSIZE) + r = 0; + } + SetupCartPRGMapping(0x11, PRG_FLASHROM, PRG_FLASHROMSIZE, 0); + + // CHR-RAM + if (info->vram_size != 0) + { + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x11, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); + ExtraNTARAM = CHRRAM + 30 * 1024; + AddExState(ExtraNTARAM, 2048, 0, "EXNR"); + } + else + { + // create dummy CHR-RAM to avoid crash when trying to use CHR-RAM for nametables + // when no CHR-RAM is specified in the ROM header + DUMMY_CHRRAM = (uint8*)FCEU_gmalloc(DUMMY_CHRRAMSIZE); + ExtraNTARAM = DUMMY_CHRRAM; + AddExState(ExtraNTARAM, DUMMY_CHRRAMSIZE, 0, "EXNR"); + } + + // CHR FLASHROM + if (VROM_size != 0) + { + CHR_FLASHROM = (uint8*)FCEU_gmalloc(CHR_FLASHROMSIZE); + AddExState(CHR_FLASHROM, CHR_FLASHROMSIZE, 0, "CFROM"); + if (info->battery) + { + info->SaveGame[save_game_index] = CHR_FLASHROM; + info->SaveGameLen[save_game_index] = CHR_FLASHROMSIZE; + save_game_index++; + } + + // copy CHR ROM into CHR_FLASHROM, use it instead of CHR ROM + const uint32 CHRSIZE = VROM_size * 8 * 1024; + for (uint32 w = 0, r = 0; w < CHR_FLASHROMSIZE; ++w) + { + CHR_FLASHROM[w] = VROM[r]; + ++r; + if (r >= CHRSIZE) + r = 0; + } + SetupCartCHRMapping(0x10, CHR_FLASHROM, CHR_FLASHROMSIZE, 0); + + FFCEUX_PPURead = Rainbow2PPURead; + FFCEUX_PPUWrite = Rainbow2PPUWrite; + } + else + { + // create dummy CHR-ROM to avoid crash when trying to use CHR-ROM for pattern tables + // when no CHR-ROM is specified in the ROM header + DUMMY_CHRROM = (uint8*)FCEU_gmalloc(DUMMY_CHRROMSIZE); + SetupCartCHRMapping(0x10, DUMMY_CHRROM, DUMMY_CHRROMSIZE, 0); + } + + AddExState(&FlashRegs, ~0, 0, 0); + AddExState(&Rainbow2StateRegs, ~0, 0, 0); +} diff --git a/src/boards/rainbow_esp.cpp b/src/boards/rainbow_esp.cpp index ac3db6c7..2c46a36d 100644 --- a/src/boards/rainbow_esp.cpp +++ b/src/boards/rainbow_esp.cpp @@ -40,7 +40,7 @@ typedef SSIZE_T ssize_t; using easywsclient::WebSocket; -#define RAINBOW_DEBUG 0 +#define RAINBOW_DEBUG 1 #if RAINBOW_DEBUG >= 1 #define UDBG(...) FCEU_printf(__VA_ARGS__) @@ -1955,9 +1955,9 @@ std::pair BrokeStudioFirmware::curle_to_net_error(CURLcode curle) void BrokeStudioFirmware::downloadFile(std::string const& url, uint8 path, uint8 file) { UDBG("RAINBOW BrokeStudioFirmware download %s -> (%u,%u)\n", url.c_str(), (unsigned int)path, (unsigned int)file); //TODO asynchronous download using curl_multi_* (and maybe a thread, or regular ticks on rx/tx/getDataReadyIO) - - // Directly fail if the curl handle was not properly initialized - if (this->curl_handle == nullptr) { + /* + // Directly fail if the curl handle was not properly initialized or if WiFi is not enabled (wifiConfig bit 0) + if ((this->curl_handle == nullptr) || (wifiConfig & wifi_config_t::WIFI_ENABLED == 0)) { UDBG("RAINBOW BrokeStudioFirmware download failed: no handle\n"); this->tx_messages.push_back({ 2, @@ -1968,6 +1968,7 @@ void BrokeStudioFirmware::downloadFile(std::string const& url, uint8 path, uint8 }); return; } + */ // Download file std::vector data; diff --git a/src/cart.cpp b/src/cart.cpp index 73b5d57e..db35555b 100644 --- a/src/cart.cpp +++ b/src/cart.cpp @@ -38,11 +38,11 @@ #include #include -uint8 *Page[32], *VPage[8]; +uint8 *Page[32], *VPage[16]; uint8 **VPageR = VPage; -uint8 *VPageG[8]; -uint8 *MMC5SPRVPage[8]; -uint8 *MMC5BGVPage[8]; +uint8 *VPageG[16]; +uint8 *MMC5SPRVPage[16]; +uint8 *MMC5BGVPage[16]; static uint8 PRGIsRAM[32]; /* This page is/is not PRG RAM. */ @@ -62,6 +62,7 @@ uint32 PRGmask8[32]; uint32 PRGmask16[32]; uint32 PRGmask32[32]; +uint32 CHRmask512[32]; uint32 CHRmask1[32]; uint32 CHRmask2[32]; uint32 CHRmask4[32]; @@ -105,8 +106,8 @@ void ResetCartMapping(void) { PRGptr[x] = CHRptr[x] = 0; PRGsize[x] = CHRsize[x] = 0; } - for (x = 0; x < 8; x++) { - MMC5SPRVPage[x] = MMC5BGVPage[x] = VPageR[x] = nothing - 0x400 * x; + for (x = 0; x < 16; x++) { + MMC5SPRVPage[x] = MMC5BGVPage[x] = VPageR[x] = nothing - 0x200 * x; } } @@ -127,11 +128,13 @@ void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram) { CHRptr[chip] = p; CHRsize[chip] = size; + CHRmask512[chip] = (size >> 9) - 1; CHRmask1[chip] = (size >> 10) - 1; CHRmask2[chip] = (size >> 11) - 1; CHRmask4[chip] = (size >> 12) - 1; CHRmask8[chip] = (size >> 13) - 1; + if (CHRmask512[chip] >= (unsigned int)(-1)) CHRmask512[chip] = 0; if (CHRmask1[chip] >= (unsigned int)(-1)) CHRmask1[chip] = 0; if (CHRmask2[chip] >= (unsigned int)(-1)) CHRmask2[chip] = 0; if (CHRmask4[chip] >= (unsigned int)(-1)) CHRmask4[chip] = 0; @@ -225,38 +228,51 @@ void setprg32(uint32 A, uint32 V) { setprg32r(0, A, V); } +void setchr512r(int r, uint32 A, uint32 V) { + if (!CHRptr[r]) return; + FCEUPPU_LineUpdate(); + V &= CHRmask512[r]; + if (CHRram[r]) + PPUCHRRAM |= (1 << (A >> 9)); + else + PPUCHRRAM &= ~(1 << (A >> 9)); + VPageR[(A) >> 9] = &CHRptr[r][(V) << 9] - (A); +} + void setchr1r(int r, uint32 A, uint32 V) { if (!CHRptr[r]) return; FCEUPPU_LineUpdate(); V &= CHRmask1[r]; if (CHRram[r]) - PPUCHRRAM |= (1 << (A >> 10)); + PPUCHRRAM |= (3 << (A >> 9)); else - PPUCHRRAM &= ~(1 << (A >> 10)); - VPageR[(A) >> 10] = &CHRptr[r][(V) << 10] - (A); + PPUCHRRAM &= ~(3 << (A >> 9)); + VPageR[(A) >> 9] = VPageR[((A) >> 9) + 1] = &CHRptr[r][(V) << 10] - (A); } void setchr2r(int r, uint32 A, uint32 V) { if (!CHRptr[r]) return; FCEUPPU_LineUpdate(); V &= CHRmask2[r]; - VPageR[(A) >> 10] = VPageR[((A) >> 10) + 1] = &CHRptr[r][(V) << 11] - (A); + VPageR[(A) >> 9] = VPageR[((A) >> 9) + 1] = VPageR[((A) >> 9) + 2] = VPageR[((A) >> 9) + 3] = &CHRptr[r][(V) << 11] - (A); if (CHRram[r]) - PPUCHRRAM |= (3 << (A >> 10)); + PPUCHRRAM |= (15 << (A >> 9)); else - PPUCHRRAM &= ~(3 << (A >> 10)); + PPUCHRRAM &= ~(15 << (A >> 9)); } void setchr4r(int r, unsigned int A, unsigned int V) { if (!CHRptr[r]) return; FCEUPPU_LineUpdate(); V &= CHRmask4[r]; - VPageR[(A) >> 10] = VPageR[((A) >> 10) + 1] = - VPageR[((A) >> 10) + 2] = VPageR[((A) >> 10) + 3] = &CHRptr[r][(V) << 12] - (A); + VPageR[(A) >> 9] = VPageR[((A) >> 9) + 1] = + VPageR[((A) >> 9) + 2] = VPageR[((A) >> 9) + 3] = + VPageR[((A) >> 9) + 4] = VPageR[((A) >> 9) + 5] = + VPageR[((A) >> 9) + 6] = VPageR[((A) >> 9) + 7] = &CHRptr[r][(V) << 12] - (A); if (CHRram[r]) - PPUCHRRAM |= (15 << (A >> 10)); + PPUCHRRAM |= (255 << (A >> 9)); else - PPUCHRRAM &= ~(15 << (A >> 10)); + PPUCHRRAM &= ~(255 << (A >> 9)); } void setchr8r(int r, uint32 V) { @@ -265,10 +281,10 @@ void setchr8r(int r, uint32 V) { if (!CHRptr[r]) return; FCEUPPU_LineUpdate(); V &= CHRmask8[r]; - for (x = 7; x >= 0; x--) + for (x = 15; x >= 0; x--) VPageR[x] = &CHRptr[r][V << 13]; if (CHRram[r]) - PPUCHRRAM |= (255); + PPUCHRRAM |= (65535); else PPUCHRRAM = 0; } @@ -495,7 +511,7 @@ void FixGenieMap(void) { geniestage = 2; - for (x = 0; x < 8; x++) + for (x = 0; x < 16; x++) VPage[x] = VPageG[x]; VPageR = VPage; @@ -526,8 +542,8 @@ void FCEU_GeniePower(void) { SetWriteHandler(0x8000, 0xFFFF, GenieWrite); SetReadHandler(0x8000, 0xFFFF, GenieRead); - for (x = 0; x < 8; x++) - VPage[x] = GENIEROM + 4096 - 0x400 * x; + for (x = 0; x < 16; x++) + VPage[x] = GENIEROM + 4096 - 0x200 * x; if (AllocGenieRW()) VPageR = VPageG; diff --git a/src/cart.h b/src/cart.h index 0b581335..ecc036d4 100644 --- a/src/cart.h +++ b/src/cart.h @@ -86,7 +86,7 @@ void FCEU_SaveGameSave(CartInfo *LocalHWInfo); void FCEU_LoadGameSave(CartInfo *LocalHWInfo); void FCEU_ClearGameSave(CartInfo *LocalHWInfo); -extern uint8 *Page[32], *VPage[8], *MMC5SPRVPage[8], *MMC5BGVPage[8]; +extern uint8 *Page[32], *VPage[16], *MMC5SPRVPage[16], *MMC5BGVPage[16]; void ResetCartMapping(void); void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram); @@ -129,6 +129,7 @@ void setprg8r(int r, unsigned int A, unsigned int V); void setprg16r(int r, unsigned int A, unsigned int V); void setprg32r(int r, unsigned int A, unsigned int V); +void setchr512r(int r, unsigned int A, unsigned int V); void setchr1r(int r, unsigned int A, unsigned int V); void setchr2r(int r, unsigned int A, unsigned int V); void setchr4r(int r, unsigned int A, unsigned int V); diff --git a/src/debug.cpp b/src/debug.cpp index 4ccf4407..9a11e50b 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -366,7 +366,7 @@ uint8 GetMem(uint16 A) { uint8 GetPPUMem(uint8 A) { uint16 tmp = FCEUPPU_PeekAddress() & 0x3FFF; - if (tmp<0x2000) return VPage[tmp>>10][tmp]; + if (tmp<0x2000) return VPage[tmp>>9][tmp]; if (tmp>=0x3F00) return PALRAM[tmp&0x1F]; return vnapage[(tmp>>10)&0x3][tmp&0x3FF]; } diff --git a/src/debug.h b/src/debug.h index 708c12ef..1e27e138 100644 --- a/src/debug.h +++ b/src/debug.h @@ -119,7 +119,7 @@ extern void IncrementInstructionsCounters(); //------------- //internal variables that debuggers will want access to -extern uint8 *vnapage[4],*VPage[8]; +extern uint8 *vnapage[4],*VPage[16]; extern uint8 PPU[4],PALRAM[0x20],UPALRAM[3],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset; extern uint32 FCEUPPU_PeekAddress(); extern uint8 READPAL_MOTHEROFALL(uint32 A); diff --git a/src/drivers/Qt/HexEditor.cpp b/src/drivers/Qt/HexEditor.cpp index b1c5d8aa..3d187513 100644 --- a/src/drivers/Qt/HexEditor.cpp +++ b/src/drivers/Qt/HexEditor.cpp @@ -259,7 +259,7 @@ static int getPPU( unsigned int i ) return 0; } i &= 0x3FFF; - if (i < 0x2000)return VPage[(i) >> 10][(i)]; + if (i < 0x2000)return VPage[(i) >> 9][(i)]; //NSF PPU Viewer crash here (UGETAB) (Also disabled by 'MaxSize = 0x2000') if (GameInfo->type == GIT_NSF) return 0; @@ -356,7 +356,7 @@ static int writeMem( int mode, unsigned int addr, int value ) addr &= 0x3FFF; if (addr < 0x2000) { - VPage[addr >> 10][addr] = value; //todo: detect if this is vrom and turn it red if so + VPage[addr >> 9][addr] = value; //todo: detect if this is vrom and turn it red if so } if ((addr >= 0x2000) && (addr < 0x3F00)) { diff --git a/src/drivers/Qt/ppuViewer.cpp b/src/drivers/Qt/ppuViewer.cpp index 39071698..aefecbca 100644 --- a/src/drivers/Qt/ppuViewer.cpp +++ b/src/drivers/Qt/ppuViewer.cpp @@ -1323,7 +1323,7 @@ void ppuPatternView_t::paintEvent(QPaintEvent *event) static int getPPU( unsigned int i ) { i &= 0x3FFF; - if (i < 0x2000)return VPage[(i) >> 10][(i)]; + if (i < 0x2000)return VPage[(i) >> 9][(i)]; //NSF PPU Viewer crash here (UGETAB) (Also disabled by 'MaxSize = 0x2000') if (GameInfo->type == GIT_NSF) return 0; @@ -1363,7 +1363,7 @@ static int writeMemPPU( unsigned int addr, int value ) addr &= 0x3FFF; if (addr < 0x2000) { - VPage[addr >> 10][addr] = value; //todo: detect if this is vrom and turn it red if so + VPage[addr >> 9][addr] = value; //todo: detect if this is vrom and turn it red if so } if ((addr >= 0x2000) && (addr < 0x3F00)) { @@ -1626,8 +1626,8 @@ void FCEUD_UpdatePPUView(int scanline, int refreshchr) int i10, x10; for (i = 0, x=0x1000; i < 0x1000; i++, x++) { - i10 = i>>10; - x10 = x>>10; + i10 = i>>9; + x10 = x>>9; if ( VPage[i10] == NULL ) { diff --git a/src/drivers/sdl/memview.cpp b/src/drivers/sdl/memview.cpp index bc17ee3d..5f78d03c 100644 --- a/src/drivers/sdl/memview.cpp +++ b/src/drivers/sdl/memview.cpp @@ -64,7 +64,7 @@ static int getRAM( unsigned int i ) static int getPPU( unsigned int i ) { i &= 0x3FFF; - if (i < 0x2000)return VPage[(i) >> 10][(i)]; + if (i < 0x2000)return VPage[(i) >> 9][(i)]; //NSF PPU Viewer crash here (UGETAB) (Also disabled by 'MaxSize = 0x2000') if (GameInfo->type == GIT_NSF) return 0; @@ -255,7 +255,7 @@ struct memViewWin_t addr &= 0x3FFF; if (addr < 0x2000) { - VPage[addr >> 10][addr] = value; //todo: detect if this is vrom and turn it red if so + VPage[addr >> 9][addr] = value; //todo: detect if this is vrom and turn it red if so } if ((addr >= 0x2000) && (addr < 0x3F00)) { diff --git a/src/drivers/win/memview.cpp b/src/drivers/win/memview.cpp index 70b8b704..facd7597 100644 --- a/src/drivers/win/memview.cpp +++ b/src/drivers/win/memview.cpp @@ -1,22 +1,22 @@ /* FCE Ultra - NES/Famicom Emulator -* -* Copyright notice for this file: -* Copyright (C) 2002 Ben Parnell -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ + * + * Copyright notice for this file: + * Copyright (C) 2002 Ben Parnell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ #include @@ -40,9 +40,9 @@ #include "Win32InputBox.h" #include "utils/xstring.h" -extern Name* lastBankNames; -extern Name* loadedBankNames; -extern Name* ramBankNames; +extern Name *lastBankNames; +extern Name *loadedBankNames; +extern Name *ramBankNames; extern int RegNameCount; extern MemoryMappedRegister RegNames[]; @@ -53,133 +53,123 @@ extern bool JustFrameAdvanced; using namespace std; -#define MODE_NES_MEMORY 0 -#define MODE_NES_PPU 1 -#define MODE_NES_OAM 2 -#define MODE_NES_FILE 3 +#define MODE_NES_MEMORY 0 +#define MODE_NES_PPU 1 +#define MODE_NES_OAM 2 +#define MODE_NES_FILE 3 -#define ID_ADDRESS_FRZ_SUBMENU 1 -#define ID_ADDRESS_ADDBP_R 2 -#define ID_ADDRESS_ADDBP_W 3 -#define ID_ADDRESS_ADDBP_X 4 -#define ID_ADDRESS_SEEK_IN_ROM 5 -#define ID_ADDRESS_CREATE_GG_CODE 6 -#define ID_ADDRESS_ADD_BOOKMARK 20 -#define ID_ADDRESS_REMOVE_BOOKMARK 21 -#define ID_ADDRESS_EDIT_BOOKMARK 22 -#define ID_ADDRESS_SYMBOLIC_NAME 30 -#define BOOKMARKS_SUBMENU_POS 4 +#define ID_ADDRESS_FRZ_SUBMENU 1 +#define ID_ADDRESS_ADDBP_R 2 +#define ID_ADDRESS_ADDBP_W 3 +#define ID_ADDRESS_ADDBP_X 4 +#define ID_ADDRESS_SEEK_IN_ROM 5 +#define ID_ADDRESS_CREATE_GG_CODE 6 +#define ID_ADDRESS_ADD_BOOKMARK 20 +#define ID_ADDRESS_REMOVE_BOOKMARK 21 +#define ID_ADDRESS_EDIT_BOOKMARK 22 +#define ID_ADDRESS_SYMBOLIC_NAME 30 +#define BOOKMARKS_SUBMENU_POS 4 -#define ID_ADDRESS_FRZ_TOGGLE_STATE 1 -#define ID_ADDRESS_FRZ_FREEZE 50 -#define ID_ADDRESS_FRZ_UNFREEZE 51 -#define ID_ADDRESS_FRZ_SEP 52 -#define ID_ADDRESS_FRZ_UNFREEZE_ALL 53 +#define ID_ADDRESS_FRZ_TOGGLE_STATE 1 +#define ID_ADDRESS_FRZ_FREEZE 50 +#define ID_ADDRESS_FRZ_UNFREEZE 51 +#define ID_ADDRESS_FRZ_SEP 52 +#define ID_ADDRESS_FRZ_UNFREEZE_ALL 53 -#define HIGHLIGHTING_SUBMENU_POS 3 -#define HEXEDITOR_COLOR_SUBMENU_POS 4 -#define CDLOGGER_COLOR_SUBMENU_POS 5 -#define ID_COLOR_HEXEDITOR 600 -#define ID_COLOR_CDLOGGER 650 +#define HIGHLIGHTING_SUBMENU_POS 3 +#define HEXEDITOR_COLOR_SUBMENU_POS 4 +#define CDLOGGER_COLOR_SUBMENU_POS 5 +#define ID_COLOR_HEXEDITOR 600 +#define ID_COLOR_CDLOGGER 650 #define HIGHLIGHT_ACTIVITY_MIN_VALUE 0 #define HIGHLIGHT_ACTIVITY_NUM_COLORS 16 #define PREVIOUS_VALUE_UNDEFINED -1 -COLORREF highlightActivityColors[HIGHLIGHT_ACTIVITY_NUM_COLORS] = { 0x0, 0x004035, 0x185218, 0x5e5c34, 0x804c00, 0xba0300, 0xd10038, 0xb21272, 0xba00ab, 0x6f00b0, 0x3700c2, 0x000cba, 0x002cc9, 0x0053bf, 0x0072cf, 0x3c8bc7 }; +COLORREF highlightActivityColors[HIGHLIGHT_ACTIVITY_NUM_COLORS] = {0x0, 0x004035, 0x185218, 0x5e5c34, 0x804c00, 0xba0300, 0xd10038, 0xb21272, 0xba00ab, 0x6f00b0, 0x3700c2, 0x000cba, 0x002cc9, 0x0053bf, 0x0072cf, 0x3c8bc7}; -COLORREF custom_color[16] = { 0 }; // User defined color for ChooseColor() +COLORREF custom_color[16] = {0}; // User defined color for ChooseColor() -string memviewhelp = "HexEditor"; //Hex Editor Help Page +string memviewhelp = "HexEditor"; // Hex Editor Help Page -int HexRowHeightBorder = 0; //adelikat: This will determine the number of pixels between rows in the hex editor, to alter this, the user can change it in the .cfg file, changing one will revert to the way FCEUX2.1.0 did it -int HexCharSpacing = 1; // pixels between chars +int HexRowHeightBorder = 0; // adelikat: This will determine the number of pixels between rows in the hex editor, to alter this, the user can change it in the .cfg file, changing one will revert to the way FCEUX2.1.0 did it +int HexCharSpacing = 1; // pixels between chars int DefHexRGB, DefCdlRGB; // This defines all of our right click popup menus struct { - int minaddress; //The minimum address where this popup will appear - int maxaddress; //The maximum address where this popup will appear - int editingmode; //The editing mode which this popup appears in - int id; //The menu ID for this popup - char *text; //the text for the menu item (some of these need to be dynamic) -} -popupmenu[] = -{ - {0x0000,0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_SYMBOLIC_NAME, "Add symbolic debug name"}, - {0x0000,0x2000, MODE_NES_MEMORY, ID_ADDRESS_FRZ_SUBMENU, "Freeze/Unfreeze This Address"}, - {0x6000,0x7FFF, MODE_NES_MEMORY, ID_ADDRESS_FRZ_SUBMENU, "Freeze/Unfreeze This Address"}, - {0x0000,0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_ADDBP_R, "Add Debugger Read Breakpoint"}, - {0x0000,0x3FFF, MODE_NES_PPU, ID_ADDRESS_ADDBP_R, "Add Debugger Read Breakpoint"}, - {0x0000,0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_ADDBP_W, "Add Debugger Write Breakpoint"}, - {0x0000,0x3FFF, MODE_NES_PPU, ID_ADDRESS_ADDBP_W, "Add Debugger Write Breakpoint"}, - {0x0000,0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_ADDBP_X, "Add Debugger Execute Breakpoint"}, - {0x8000,0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_SEEK_IN_ROM, "Go Here In ROM File"}, - {0x8000,0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_CREATE_GG_CODE, "Create Game Genie Code At This Address"} -}; + int minaddress; // The minimum address where this popup will appear + int maxaddress; // The maximum address where this popup will appear + int editingmode; // The editing mode which this popup appears in + int id; // The menu ID for this popup + char *text; // the text for the menu item (some of these need to be dynamic) +} popupmenu[] = + { + {0x0000, 0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_SYMBOLIC_NAME, "Add symbolic debug name"}, + {0x0000, 0x2000, MODE_NES_MEMORY, ID_ADDRESS_FRZ_SUBMENU, "Freeze/Unfreeze This Address"}, + {0x6000, 0x7FFF, MODE_NES_MEMORY, ID_ADDRESS_FRZ_SUBMENU, "Freeze/Unfreeze This Address"}, + {0x0000, 0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_ADDBP_R, "Add Debugger Read Breakpoint"}, + {0x0000, 0x3FFF, MODE_NES_PPU, ID_ADDRESS_ADDBP_R, "Add Debugger Read Breakpoint"}, + {0x0000, 0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_ADDBP_W, "Add Debugger Write Breakpoint"}, + {0x0000, 0x3FFF, MODE_NES_PPU, ID_ADDRESS_ADDBP_W, "Add Debugger Write Breakpoint"}, + {0x0000, 0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_ADDBP_X, "Add Debugger Execute Breakpoint"}, + {0x8000, 0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_SEEK_IN_ROM, "Go Here In ROM File"}, + {0x8000, 0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_CREATE_GG_CODE, "Create Game Genie Code At This Address"}}; #define POPUPNUM (sizeof popupmenu / sizeof popupmenu[0]) // The color configure menu COLORMENU hexcolormenu[] = { - { "Normal text", PPRGB(HexFore) }, - { "Address header", PPRGB(HexAddr) }, -// { "Normal text background", PPRGB(HexBack) }, - { NULL }, - { "Selected text", PPRGB(HexHlFore) }, - { "Selected background", PPRGB(HexHlBack) }, - { "Selected text (unfocused)", PPRGB(HexHlShdFore) }, - { "Selected background (unfocused)", PPRGB(HexHlShdBack) }, - { NULL }, - { "Freezed address", PPRGB(HexFreeze), }, -// { "Freezed ROM address", PPRGB(RomFreeze), }, - { "Bookmark", PPRGB(HexBookmark) } -}, -cdlcolormenu[] = { - { "Code", PPRGB(CdlCode) }, - { "Data", PPRGB(CdlData) }, - { "PCM Data", PPRGB(CdlPcm) }, - { "Code && Data", PPRGB(CdlCodeData) }, - { NULL }, - { "Render", PPRGB(CdlRender) }, - { "Read", PPRGB(CdlRead) }, - { "Render && Read", PPRGB(CdlRenderRead) } -}; + {"Normal text", PPRGB(HexFore)}, + {"Address header", PPRGB(HexAddr)}, + // { "Normal text background", PPRGB(HexBack) }, + {NULL}, + {"Selected text", PPRGB(HexHlFore)}, + {"Selected background", PPRGB(HexHlBack)}, + {"Selected text (unfocused)", PPRGB(HexHlShdFore)}, + {"Selected background (unfocused)", PPRGB(HexHlShdBack)}, + {NULL}, + { + "Freezed address", + PPRGB(HexFreeze), + }, + // { "Freezed ROM address", PPRGB(RomFreeze), }, + {"Bookmark", PPRGB(HexBookmark)}}, + cdlcolormenu[] = {{"Code", PPRGB(CdlCode)}, {"Data", PPRGB(CdlData)}, {"PCM Data", PPRGB(CdlPcm)}, {"Code && Data", PPRGB(CdlCodeData)}, {NULL}, {"Render", PPRGB(CdlRender)}, {"Read", PPRGB(CdlRead)}, {"Render && Read", PPRGB(CdlRenderRead)}}; -struct { - COLORMENU* items; +struct +{ + COLORMENU *items; int base_id; int sub; int size; } colormenu[] = -{ - { hexcolormenu, ID_COLOR_HEXEDITOR, HEXEDITOR_COLOR_SUBMENU_POS, sizeof(hexcolormenu) / sizeof(hexcolormenu[0]) }, - { cdlcolormenu, ID_COLOR_CDLOGGER, CDLOGGER_COLOR_SUBMENU_POS, sizeof(cdlcolormenu) / sizeof(cdlcolormenu[0]) } -}; + { + {hexcolormenu, ID_COLOR_HEXEDITOR, HEXEDITOR_COLOR_SUBMENU_POS, sizeof(hexcolormenu) / sizeof(hexcolormenu[0])}, + {cdlcolormenu, ID_COLOR_CDLOGGER, CDLOGGER_COLOR_SUBMENU_POS, sizeof(cdlcolormenu) / sizeof(cdlcolormenu[0])}}; int LoadTableFile(); void UnloadTableFile(); void InputData(char *input); int GetMemViewData(uint32 i); -//int UpdateCheatColorCallB(char *name, uint32 a, uint8 v, int compare,int s,int type, void *data); //mbg merge 6/29/06 - added arg -//int DeleteCheatCallB(char *name, uint32 a, uint8 v, int compare,int s,int type); //mbg merge 6/29/06 - added arg +// int UpdateCheatColorCallB(char *name, uint32 a, uint8 v, int compare,int s,int type, void *data); //mbg merge 6/29/06 - added arg +// int DeleteCheatCallB(char *name, uint32 a, uint8 v, int compare,int s,int type); //mbg merge 6/29/06 - added arg void FreezeRam(int address, int mode, int final); int GetHexScreenCoordx(int offset); int GetHexScreenCoordy(int offset); -int GetAddyFromCoord(int x,int y); -void AutoScrollFromCoord(int x,int y); +int GetAddyFromCoord(int x, int y); +void AutoScrollFromCoord(int x, int y); LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK MemFindCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK ImportBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); void FindNext(); void OpenFindDialog(); static int GetFileData(uint32 offset); -static int WriteFileData(uint32 offset,int data); +static int WriteFileData(uint32 offset, int data); static void PalettePoke(uint32 addr, uint8 data); void SwitchEditingText(int editingText); - HWND hMemView, hMemFind; int CurOffset; @@ -187,7 +177,7 @@ int ClientHeight; int NoColors; int EditingMode; int EditingText; -int AddyWasText; //used by the GetAddyFromCoord() function. +int AddyWasText; // used by the GetAddyFromCoord() function. int TableFileLoaded; int MemView_wndx, MemView_wndy; @@ -201,10 +191,10 @@ static RECT newMemViewRect; static char chartable[256]; HDC HDataDC; -int CursorX=2, CursorY=9; +int CursorX = 2, CursorY = 9; int CursorStartAddy, CursorEndAddy = PREVIOUS_VALUE_UNDEFINED; -int CursorDragPoint = -1;//, CursorShiftPoint = -1; -//int CursorStartNibble=1, CursorEndNibble; //1 means that only half of the byte is selected +int CursorDragPoint = -1; //, CursorShiftPoint = -1; +// int CursorStartNibble=1, CursorEndNibble; //1 means that only half of the byte is selected int TempData = PREVIOUS_VALUE_UNDEFINED; int DataAmount; int MaxSize; @@ -219,7 +209,7 @@ COLORREF *AnsiBGColorList; COLORREF *AnsiTextColorList; int PreviousCurOffset; -int *PreviousValues; // for HighlightActivity feature and for speedhack too +int *PreviousValues; // for HighlightActivity feature and for speedhack too unsigned int *HighlightedBytes; int lbuttondown; @@ -232,15 +222,16 @@ char FindTextBox[60]; extern iNES_HEADER head; -//undo structure -struct UNDOSTRUCT { +// undo structure +struct UNDOSTRUCT +{ int addr; int size; unsigned char *data; - UNDOSTRUCT *last; //mbg merge 7/18/06 removed struct qualifier + UNDOSTRUCT *last; // mbg merge 7/18/06 removed struct qualifier }; -struct UNDOSTRUCT *undo_list=0; +struct UNDOSTRUCT *undo_list = 0; void resetHighlightingActivityLog() { @@ -252,60 +243,66 @@ void resetHighlightingActivityLog() } } -void ApplyPatch(int addr,int size, uint8* data){ - UNDOSTRUCT *tmp = (UNDOSTRUCT*)malloc(sizeof(UNDOSTRUCT)); //mbg merge 7/18/06 removed struct qualifiers and added cast +void ApplyPatch(int addr, int size, uint8 *data) +{ + UNDOSTRUCT *tmp = (UNDOSTRUCT *)malloc(sizeof(UNDOSTRUCT)); // mbg merge 7/18/06 removed struct qualifiers and added cast int i; - //while(tmp != 0){tmp=tmp->next;x++;}; - //tmp = malloc(sizeof(struct UNDOSTRUCT)); - //sprintf(str,"%d",x); - //MessageBox(hMemView,str,"info", MB_OK); + // while(tmp != 0){tmp=tmp->next;x++;}; + // tmp = malloc(sizeof(struct UNDOSTRUCT)); + // sprintf(str,"%d",x); + // MessageBox(hMemView,str,"info", MB_OK); tmp->addr = addr; tmp->size = size; - tmp->data = (uint8*)malloc(sizeof(uint8)*size); - tmp->last=undo_list; + tmp->data = (uint8 *)malloc(sizeof(uint8) * size); + tmp->last = undo_list; - for(i = 0;i < size;i++){ - tmp->data[i] = GetFileData((uint32)addr+i); - WriteFileData((uint32)addr+i,data[i]); + for (i = 0; i < size; i++) + { + tmp->data[i] = GetFileData((uint32)addr + i); + WriteFileData((uint32)addr + i, data[i]); } - undo_list=tmp; + undo_list = tmp; - //UpdateColorTable(); + // UpdateColorTable(); return; } -void UndoLastPatch(){ - struct UNDOSTRUCT *tmp=undo_list; +void UndoLastPatch() +{ + struct UNDOSTRUCT *tmp = undo_list; int i; - if(undo_list == 0)return; - //while(tmp->next != 0){tmp=tmp->next;}; //traverse to the one before the last one + if (undo_list == 0) + return; + // while(tmp->next != 0){tmp=tmp->next;}; //traverse to the one before the last one - for(i = 0;i < tmp->size;i++){ - WriteFileData((uint32)tmp->addr+i,tmp->data[i]); + for (i = 0; i < tmp->size; i++) + { + WriteFileData((uint32)tmp->addr + i, tmp->data[i]); } - undo_list=undo_list->last; + undo_list = undo_list->last; - ChangeMemViewFocus(MODE_NES_FILE,tmp->addr, -1); //move to the focus to where we are undoing at. + ChangeMemViewFocus(MODE_NES_FILE, tmp->addr, -1); // move to the focus to where we are undoing at. free(tmp->data); free(tmp); return; } -void GotoAddress(HWND hwnd) { +void GotoAddress(HWND hwnd) +{ char gotoaddressstring[8]; int gotoaddress; char gototitle[18]; gotoaddressstring[0] = '\0'; - sprintf(gototitle, "%s%X%s", "Goto (0-", MaxSize-1, ")"); - if(CWin32InputBox::InputBox(gototitle, "Goto which address:", gotoaddressstring, 8, false, hwnd) == IDOK) + sprintf(gototitle, "%s%X%s", "Goto (0-", MaxSize - 1, ")"); + if (CWin32InputBox::InputBox(gototitle, "Goto which address:", gotoaddressstring, 8, false, hwnd) == IDOK) { - if(EOF != sscanf(gotoaddressstring, "%x", &gotoaddress)) + if (EOF != sscanf(gotoaddressstring, "%x", &gotoaddress)) { SetHexEditorAddress(gotoaddress); } @@ -317,19 +314,21 @@ void SetHexEditorAddress(int gotoaddress) if (gotoaddress < 0) gotoaddress = 0; - if (gotoaddress > (MaxSize-1)) - gotoaddress = (MaxSize-1); - + if (gotoaddress > (MaxSize - 1)) + gotoaddress = (MaxSize - 1); + CursorStartAddy = gotoaddress; CursorEndAddy = -1; ChangeMemViewFocus(EditingMode, CursorStartAddy, -1); } -static void FlushUndoBuffer(){ +static void FlushUndoBuffer() +{ struct UNDOSTRUCT *tmp; - while(undo_list!= 0){ - tmp=undo_list; - undo_list=undo_list->last; + while (undo_list != 0) + { + tmp = undo_list; + undo_list = undo_list->last; free(tmp->data); free(tmp); } @@ -337,95 +336,118 @@ static void FlushUndoBuffer(){ return; } - -static int GetFileData(uint32 offset){ - if(offset < 16) return *((unsigned char *)&head+offset); - if(offset < 16+PRGsize[0])return PRGptr[0][offset-16]; - if(offset < 16+PRGsize[0]+CHRsize[0])return CHRptr[0][offset-16-PRGsize[0]]; +static int GetFileData(uint32 offset) +{ + if (offset < 16) + return *((unsigned char *)&head + offset); + if (offset < 16 + PRGsize[0]) + return PRGptr[0][offset - 16]; + if (offset < 16 + PRGsize[0] + CHRsize[0]) + return CHRptr[0][offset - 16 - PRGsize[0]]; return -1; } -static int WriteFileData(uint32 addr,int data){ - if (addr < 16) MessageBox(hMemView, "You can't edit ROM header here, however you can use NES Header Editor to edit the header if it's an iNES format file.", "Sorry", MB_OK | MB_ICONERROR); - if((addr >= 16) && (addr < PRGsize[0]+16)) *(uint8 *)(GetNesPRGPointer(addr-16)) = data; - if((addr >= PRGsize[0]+16) && (addr < CHRsize[0]+PRGsize[0]+16)) *(uint8 *)(GetNesCHRPointer(addr-16-PRGsize[0])) = data; +static int WriteFileData(uint32 addr, int data) +{ + if (addr < 16) + MessageBox(hMemView, "You can't edit ROM header here, however you can use NES Header Editor to edit the header if it's an iNES format file.", "Sorry", MB_OK | MB_ICONERROR); + if ((addr >= 16) && (addr < PRGsize[0] + 16)) + *(uint8 *)(GetNesPRGPointer(addr - 16)) = data; + if ((addr >= PRGsize[0] + 16) && (addr < CHRsize[0] + PRGsize[0] + 16)) + *(uint8 *)(GetNesCHRPointer(addr - 16 - PRGsize[0])) = data; return 0; } -static int GetRomFileSize(){ //todo: fix or remove this? +static int GetRomFileSize() +{ // todo: fix or remove this? return 0; } void SaveRomAs() { - const char filter[]="NES ROM file (*.nes)\0*.nes\0All Files (*.*)\0*.*\0\0"; + const char filter[] = "NES ROM file (*.nes)\0*.nes\0All Files (*.*)\0*.*\0\0"; char nameo[2048]; OPENFILENAME ofn; - memset(&ofn,0,sizeof(ofn)); - ofn.lStructSize=sizeof(ofn); - ofn.hInstance=fceu_hInstance; - ofn.lpstrTitle="Save Nes ROM as..."; - ofn.lpstrFilter=filter; + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hInstance = fceu_hInstance; + ofn.lpstrTitle = "Save Nes ROM as..."; + ofn.lpstrFilter = filter; strcpy(nameo, mass_replace(GetRomName(), "|", ".").c_str()); - ofn.lpstrFile=nameo; - ofn.lpstrDefExt="nes"; - ofn.nMaxFile=256; - ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY; + ofn.lpstrFile = nameo; + ofn.lpstrDefExt = "nes"; + ofn.nMaxFile = 256; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.hwndOwner = hMemView; if (GetSaveFileName(&ofn)) iNesSaveAs(nameo); } -int LoadTable(const char* nameo) +int LoadTable(const char *nameo) { char str[50]; FILE *FP; int i, line, charcode1, charcode2; - - for(i = 0;i < 256;i++){ + + for (i = 0; i < 256; i++) + { chartable[i] = 0; } - FP = fopen(nameo,"r"); + FP = fopen(nameo, "r"); line = 0; - while((fgets(str, 45, FP)) != NULL){/* get one line from the file */ + while ((fgets(str, 45, FP)) != NULL) + { /* get one line from the file */ line++; - if(strlen(str) < 3)continue; + if (strlen(str) < 3) + continue; charcode1 = charcode2 = -1; - if((str[0] >= 'a') && (str[0] <= 'f')) charcode1 = str[0]-('a'-0xA); - if((str[0] >= 'A') && (str[0] <= 'F')) charcode1 = str[0]-('A'-0xA); - if((str[0] >= '0') && (str[0] <= '9')) charcode1 = str[0]-'0'; + if ((str[0] >= 'a') && (str[0] <= 'f')) + charcode1 = str[0] - ('a' - 0xA); + if ((str[0] >= 'A') && (str[0] <= 'F')) + charcode1 = str[0] - ('A' - 0xA); + if ((str[0] >= '0') && (str[0] <= '9')) + charcode1 = str[0] - '0'; - if((str[1] >= 'a') && (str[1] <= 'f')) charcode2 = str[1]-('a'-0xA); - if((str[1] >= 'A') && (str[1] <= 'F')) charcode2 = str[1]-('A'-0xA); - if((str[1] >= '0') && (str[1] <= '9')) charcode2 = str[1]-'0'; + if ((str[1] >= 'a') && (str[1] <= 'f')) + charcode2 = str[1] - ('a' - 0xA); + if ((str[1] >= 'A') && (str[1] <= 'F')) + charcode2 = str[1] - ('A' - 0xA); + if ((str[1] >= '0') && (str[1] <= '9')) + charcode2 = str[1] - '0'; - if(charcode1 == -1){ + if (charcode1 == -1) + { UnloadTableFile(); fclose(FP); - return line; //we have an error getting the first input + return line; // we have an error getting the first input } - if(charcode2 != -1) charcode1 = (charcode1<<4)|charcode2; + if (charcode2 != -1) + charcode1 = (charcode1 << 4) | charcode2; - for(i = 0;i < (int)strlen(str);i++)if(str[i] == '=')break; + for (i = 0; i < (int)strlen(str); i++) + if (str[i] == '=') + break; - if(i == strlen(str)){ + if (i == strlen(str)) + { UnloadTableFile(); fclose(FP); - return line; //error no '=' found + return line; // error no '=' found } i++; - //ORing i with 32 just converts it to lowercase if it isn't - if(((str[i]|32) == 'r') && ((str[i+1]|32) == 'e') && ((str[i+2]|32) == 't')) + // ORing i with 32 just converts it to lowercase if it isn't + if (((str[i] | 32) == 'r') && ((str[i + 1] | 32) == 'e') && ((str[i + 2] | 32) == 't')) charcode2 = 0x0D; - else charcode2 = str[i]; + else + charcode2 = str[i]; chartable[charcode1] = charcode2; } @@ -434,33 +456,37 @@ int LoadTable(const char* nameo) return -1; } -//should return -1, otherwise returns the line number it had the error on +// should return -1, otherwise returns the line number it had the error on int LoadTableFile() { - const char filter[]="Table Files (*.TBL)\0*.tbl\0All Files (*.*)\0*.*\0\0"; + const char filter[] = "Table Files (*.TBL)\0*.tbl\0All Files (*.*)\0*.*\0\0"; char nameo[2048]; OPENFILENAME ofn; - memset(&ofn,0,sizeof(ofn)); - ofn.lStructSize=sizeof(ofn); - ofn.hInstance=fceu_hInstance; - ofn.lpstrTitle="Load Table File..."; - ofn.lpstrFilter=filter; - nameo[0]=0; - ofn.lpstrFile=nameo; - ofn.nMaxFile=256; - ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY; + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hInstance = fceu_hInstance; + ofn.lpstrTitle = "Load Table File..."; + ofn.lpstrFilter = filter; + nameo[0] = 0; + ofn.lpstrFile = nameo; + ofn.nMaxFile = 256; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.hwndOwner = hMemView; - if(!GetOpenFileName(&ofn))return -1; + if (!GetOpenFileName(&ofn)) + return -1; int result = LoadTable(nameo); return result; } -void UnloadTableFile(){ - for(int i = 0;i < 256;i++){ +void UnloadTableFile() +{ + for (int i = 0; i < 256; i++) + { int j = i; - if(j < 0x20) j = 0x2E; -// if(j > 0x7e) j = 0x2E; + if (j < 0x20) + j = 0x2E; + // if(j > 0x7e) j = 0x2E; chartable[i] = j; } TableFileLoaded = 0; @@ -468,7 +494,8 @@ void UnloadTableFile(){ } void UpdateMemoryView(int draw_all) { - if (!hMemView) return; + if (!hMemView) + return; const int MemFontWidth = debugSystem->HexeditorFontWidth + HexCharSpacing; const int MemFontHeight = debugSystem->HexeditorFontHeight + HexRowHeightBorder; const char hex[] = "0123456789ABCDEF"; @@ -489,11 +516,11 @@ void UpdateMemoryView(int draw_all) int pos = i - CurOffset; if ((PreviousCurOffset != CurOffset) || draw_all) { - SetBkColor(HDataDC, CBackColor); //addresses back color + SetBkColor(HDataDC, CBackColor); // addresses back color if (i < MaxSize) - SetTextColor(HDataDC, MKRGB(HexAddr)); //addresses text color #000000 = black, #FFFFFF = white + SetTextColor(HDataDC, MKRGB(HexAddr)); // addresses text color #000000 = black, #FFFFFF = white else - SetTextColor(HDataDC, MKRGB(HexBound)); //addresses out of bounds + SetTextColor(HDataDC, MKRGB(HexBound)); // addresses out of bounds sprintf(str, "%06X: :", i); ExtTextOut(HDataDC, 0, MemLineRow, NULL, NULL, str, strlen(str), NULL); } @@ -507,7 +534,7 @@ void UpdateMemoryView(int draw_all) if ((CursorEndAddy == -1) && (CursorStartAddy == i + j)) { - //print up single highlighted text + // print up single highlighted text if (TempData != PREVIOUS_VALUE_UNDEFINED) { // User is typing New Data @@ -545,12 +572,13 @@ void UpdateMemoryView(int draw_all) SetBkColor(HDataDC, EditingText ? MKRGB(HexHlBack) : MKRGB(HexHlShdBack)); SetTextColor(HDataDC, EditingText ? MKRGB(HexHlFore) : MKRGB(HexHlShdFore)); str[0] = chartable[byteValue]; - if ((u8)str[0] < 0x20) str[0] = 0x2E; -// if ((u8)str[0] > 0x7e) str[0] = 0x2E; + if ((u8)str[0] < 0x20) + str[0] = 0x2E; + // if ((u8)str[0] > 0x7e) str[0] = 0x2E; str[1] = 0; ExtTextOut(HDataDC, (59 + j) * MemFontWidth, MemLineRow, NULL, NULL, str, 1, NULL); - PreviousValues[pos] = PREVIOUS_VALUE_UNDEFINED; //set it to redraw this one next time + PreviousValues[pos] = PREVIOUS_VALUE_UNDEFINED; // set it to redraw this one next time } else if (draw_all || (PreviousValues[pos] != byteValue) || byteHighlightingValue) { @@ -589,8 +617,9 @@ void UpdateMemoryView(int draw_all) SetBkColor(HDataDC, AnsiBGColorList[pos]); SetTextColor(HDataDC, ansiTmpColor); str[0] = chartable[byteValue]; - if ((u8)str[0] < 0x20) str[0] = 0x2E; -// if ((u8)str[0] > 0x7e) str[0] = 0x2E; + if ((u8)str[0] < 0x20) + str[0] = 0x2E; + // if ((u8)str[0] > 0x7e) str[0] = 0x2E; str[1] = 0; ExtTextOut(HDataDC, (59 + j) * MemFontWidth, MemLineRow, NULL, NULL, str, 1, NULL); @@ -608,7 +637,7 @@ void UpdateMemoryView(int draw_all) return; } -char* EditString[4] = {"RAM","PPU","OAM","ROM"}; +char *EditString[4] = {"RAM", "PPU", "OAM", "ROM"}; void UpdateCaption() { @@ -624,7 +653,8 @@ void UpdateCaption() sprintf(str, "Hex Editor - (PRG) ROM: 0x%X", CursorStartAddy); else if (CursorStartAddy - 16 - PRGsize[0] < (int)CHRsize[0]) sprintf(str, "Hex Editor - (CHR) ROM: 0x%X", CursorStartAddy); - } else + } + else { sprintf(str, "Hex Editor - %s: 0x%X", EditString[EditingMode], CursorStartAddy); } @@ -633,28 +663,32 @@ void UpdateCaption() { // when watching RAM we may as well see Symbolic Debug names loadNameFiles(); - Name* node = findNode(getNamesPointerForAddress(CursorStartAddy), CursorStartAddy); + Name *node = findNode(getNamesPointerForAddress(CursorStartAddy), CursorStartAddy); if (node && node->name) { strcat(str, " - "); strcat(str, node->name); } - for (int i = 0; i < RegNameCount; i++) { - if (!symbRegNames) break; + for (int i = 0; i < RegNameCount; i++) + { + if (!symbRegNames) + break; int test = 0; sscanf(RegNames[i].offset, "$%4x", &test); - if (test == CursorStartAddy) { + if (test == CursorStartAddy) + { strcat(str, " - "); strcat(str, RegNames[i].name); } } } - } else + } + else { sprintf(str, "Hex Editor - %s: 0x%X - 0x%X (0x%X)", - EditString[EditingMode], CursorStartAddy, CursorEndAddy, CursorEndAddy - CursorStartAddy + 1); + EditString[EditingMode], CursorStartAddy, CursorEndAddy, CursorEndAddy - CursorStartAddy + 1); } - SetWindowText(hMemView,str); + SetWindowText(hMemView, str); return; } @@ -662,58 +696,64 @@ int GetMemViewData(uint32 i) { switch (EditingMode) { - case MODE_NES_MEMORY: - return GetMem(i); - case MODE_NES_PPU: - i &= 0x3FFF; - if (i < 0x2000)return VPage[(i) >> 10][(i)]; - //NSF PPU Viewer crash here (UGETAB) (Also disabled by 'MaxSize = 0x2000') - if (GameInfo->type == GIT_NSF) - return (0); - else - { - if (i < 0x3F00) - return vnapage[(i >> 10) & 0x3][i & 0x3FF]; - return READPAL_MOTHEROFALL(i & 0x1F); - } - break; - case MODE_NES_OAM: - return SPRAM[i & 0xFF]; - case MODE_NES_FILE: - //todo: use getfiledata() here - if (i < 16) return *((unsigned char *)&head + i); - if (i < 16 + PRGsize[0])return PRGptr[0][i - 16]; - if (i < 16 + PRGsize[0] + CHRsize[0])return CHRptr[0][i - 16 - PRGsize[0]]; + case MODE_NES_MEMORY: + return GetMem(i); + case MODE_NES_PPU: + i &= 0x3FFF; + if (i < 0x2000) + return VPage[(i) >> 9][(i)]; + // NSF PPU Viewer crash here (UGETAB) (Also disabled by 'MaxSize = 0x2000') + if (GameInfo->type == GIT_NSF) + return (0); + else + { + if (i < 0x3F00) + return vnapage[(i >> 10) & 0x3][i & 0x3FF]; + return READPAL_MOTHEROFALL(i & 0x1F); + } + break; + case MODE_NES_OAM: + return SPRAM[i & 0xFF]; + case MODE_NES_FILE: + // todo: use getfiledata() here + if (i < 16) + return *((unsigned char *)&head + i); + if (i < 16 + PRGsize[0]) + return PRGptr[0][i - 16]; + if (i < 16 + PRGsize[0] + CHRsize[0]) + return CHRptr[0][i - 16 - PRGsize[0]]; } return 0; } void UpdateColorTable() { - UNDOSTRUCT *tmp; //mbg merge 7/18/06 removed struct qualifier - int i,j; - if(!hMemView)return; - for(i = 0;i < DataAmount;i++) + UNDOSTRUCT *tmp; // mbg merge 7/18/06 removed struct qualifier + int i, j; + if (!hMemView) + return; + for (i = 0; i < DataAmount; i++) { - if((i+CurOffset >= CursorStartAddy) && (i+CurOffset <= CursorEndAddy)) + if ((i + CurOffset >= CursorStartAddy) && (i + CurOffset <= CursorEndAddy)) { - CurBGColorList[i] = MKRGB(HexHlBack); //Highlighter color bg - 2 columns + CurBGColorList[i] = MKRGB(HexHlBack); // Highlighter color bg - 2 columns DimBGColorList[i] = MKRGB(HexHlShdBack); - CurTextColorList[i] = MKRGB(HexHlFore); //Highlighter color text - 2 columns + CurTextColorList[i] = MKRGB(HexHlFore); // Highlighter color text - 2 columns DimTextColorList[i] = MKRGB(HexHlShdFore); continue; } - CurBGColorList[i] = MKRGB(HexBack); //Regular color bb - 2columns - DimBGColorList[i] = MKRGB(HexBack); //Regular color bb - 2columns - CurTextColorList[i] = MKRGB(HexFore); //Regular color text - 2 columns - DimTextColorList[i] = MKRGB(HexFore); //Regular color text - 2 columns + CurBGColorList[i] = MKRGB(HexBack); // Regular color bb - 2columns + DimBGColorList[i] = MKRGB(HexBack); // Regular color bb - 2columns + CurTextColorList[i] = MKRGB(HexFore); // Regular color text - 2 columns + DimTextColorList[i] = MKRGB(HexFore); // Regular color text - 2 columns } - for (j=0;j= CurOffset) && ((int)hexBookmarks[j].address < CurOffset+DataAmount)) + if (hexBookmarks[j].editmode != EditingMode) + continue; + if (((int)hexBookmarks[j].address >= CurOffset) && ((int)hexBookmarks[j].address < CurOffset + DataAmount)) { CurTextColorList[hexBookmarks[j].address - CurOffset] = MKRGB(HexBookmark); // Green for Bookmarks DimTextColorList[hexBookmarks[j].address - CurOffset] = MKRGB(HexBookmark); // Green for Bookmarks @@ -722,136 +762,140 @@ void UpdateColorTable() switch (EditingMode) { - case MODE_NES_MEMORY: - for (int a = CurOffset; a < CurOffset + DataAmount; ++a) - if (FCEUI_FindCheatMapByte(a)) - { - CurTextColorList[a - CurOffset] = MKRGB(HexFreeze); - DimTextColorList[a - CurOffset] = MKRGB(HexFreeze); - } - break; - case MODE_NES_FILE: - if (cdloggerdataSize) + case MODE_NES_MEMORY: + for (int a = CurOffset; a < CurOffset + DataAmount; ++a) + if (FCEUI_FindCheatMapByte(a)) { - int temp_offset; - for (i = 0; i < DataAmount; i++) + CurTextColorList[a - CurOffset] = MKRGB(HexFreeze); + DimTextColorList[a - CurOffset] = MKRGB(HexFreeze); + } + break; + case MODE_NES_FILE: + if (cdloggerdataSize) + { + int temp_offset; + for (i = 0; i < DataAmount; i++) + { + temp_offset = CurOffset + i - 16; // (minus NES header) + if (temp_offset >= 0) { - temp_offset = CurOffset + i - 16; // (minus NES header) - if (temp_offset >= 0) + if ((unsigned int)temp_offset < cdloggerdataSize) { - if ((unsigned int)temp_offset < cdloggerdataSize) + // PRG + if ((cdloggerdata[temp_offset] & 3) == 3) { - // PRG - if ((cdloggerdata[temp_offset] & 3) == 3) + // the byte is both Code and Data - green + CurTextColorList[i] = MKRGB(CdlCodeData); + DimTextColorList[i] = MKRGB(CdlCodeData); + } + else if ((cdloggerdata[temp_offset] & 3) == 1) + { + // the byte is Code - dark-yellow + CurTextColorList[i] = MKRGB(CdlCode); + DimTextColorList[i] = MKRGB(CdlCode); + } + else if ((cdloggerdata[temp_offset] & 3) == 2) + { + // the byte is Data - blue/cyan + if (cdloggerdata[temp_offset] & 0x40) { - // the byte is both Code and Data - green - CurTextColorList[i] = MKRGB(CdlCodeData); - DimTextColorList[i] = MKRGB(CdlCodeData); + // PCM data - cyan + CurTextColorList[i] = MKRGB(CdlPcm); + DimTextColorList[i] = MKRGB(CdlPcm); } - else if ((cdloggerdata[temp_offset] & 3) == 1) + else { - // the byte is Code - dark-yellow - CurTextColorList[i] = MKRGB(CdlCode); - DimTextColorList[i] = MKRGB(CdlCode); - } - else if ((cdloggerdata[temp_offset] & 3) == 2) - { - // the byte is Data - blue/cyan - if (cdloggerdata[temp_offset] & 0x40) - { - // PCM data - cyan - CurTextColorList[i] = MKRGB(CdlPcm); - DimTextColorList[i] = MKRGB(CdlPcm); - } - else - { - // non-PCM data - blue - CurTextColorList[i] = MKRGB(CdlData); - DimTextColorList[i] = MKRGB(CdlData); - } + // non-PCM data - blue + CurTextColorList[i] = MKRGB(CdlData); + DimTextColorList[i] = MKRGB(CdlData); } } - else + } + else + { + temp_offset -= cdloggerdataSize; + if (((unsigned int)temp_offset < cdloggerVideoDataSize)) { - temp_offset -= cdloggerdataSize; - if (((unsigned int)temp_offset < cdloggerVideoDataSize)) + // CHR + if ((cdloggervdata[temp_offset] & 3) == 3) { - // CHR - if ((cdloggervdata[temp_offset] & 3) == 3) - { - // the byte was both rendered and read programmatically - light-green - CurTextColorList[i] = MKRGB(CdlRenderRead); - DimTextColorList[i] = MKRGB(CdlRenderRead); - } - else if ((cdloggervdata[temp_offset] & 3) == 1) - { - // the byte was rendered - yellow - CurTextColorList[i] = MKRGB(CdlRender); - DimTextColorList[i] = MKRGB(CdlRender); - } - else if ((cdloggervdata[temp_offset] & 3) == 2) - { - // the byte was read programmatically - light-blue - CurTextColorList[i] = MKRGB(CdlRead); - DimTextColorList[i] = MKRGB(CdlRead); - } + // the byte was both rendered and read programmatically - light-green + CurTextColorList[i] = MKRGB(CdlRenderRead); + DimTextColorList[i] = MKRGB(CdlRenderRead); + } + else if ((cdloggervdata[temp_offset] & 3) == 1) + { + // the byte was rendered - yellow + CurTextColorList[i] = MKRGB(CdlRender); + DimTextColorList[i] = MKRGB(CdlRender); + } + else if ((cdloggervdata[temp_offset] & 3) == 2) + { + // the byte was read programmatically - light-blue + CurTextColorList[i] = MKRGB(CdlRead); + DimTextColorList[i] = MKRGB(CdlRead); } } } } } + } - tmp = undo_list; - while (tmp != 0) + tmp = undo_list; + while (tmp != 0) + { + // if((tmp->addr < CurOffset+DataAmount) && (tmp->addr+tmp->size > CurOffset)) + for (i = tmp->addr; i < tmp->addr + tmp->size; i++) { - //if((tmp->addr < CurOffset+DataAmount) && (tmp->addr+tmp->size > CurOffset)) - for (i = tmp->addr; i < tmp->addr + tmp->size; i++) { - if ((i > CurOffset) && (i < CurOffset + DataAmount)) - { - CurTextColorList[i - CurOffset] = MKRGB(RomFreeze); - DimTextColorList[i - CurOffset] = MKRGB(RomFreeze); - } + if ((i > CurOffset) && (i < CurOffset + DataAmount)) + { + CurTextColorList[i - CurOffset] = MKRGB(RomFreeze); + DimTextColorList[i - CurOffset] = MKRGB(RomFreeze); } - tmp = tmp->last; } - break; + tmp = tmp->last; + } + break; } - UpdateMemoryView(1); //anytime the colors change, the memory viewer needs to be completely redrawn + UpdateMemoryView(1); // anytime the colors change, the memory viewer needs to be completely redrawn } -int addrtodelete; // This is a very ugly hackish method of doing this +int addrtodelete; // This is a very ugly hackish method of doing this int cheatwasdeleted; // but it works and that is all that matters here. -int DeleteCheatCallB(const char *name, uint32 a, uint8 v, int compare,int s,int type, void *data){ //mbg merge 6/29/06 - added arg - if(cheatwasdeleted == -1)return 1; +int DeleteCheatCallB(const char *name, uint32 a, uint8 v, int compare, int s, int type, void *data) +{ // mbg merge 6/29/06 - added arg + if (cheatwasdeleted == -1) + return 1; cheatwasdeleted++; - if(a == addrtodelete){ - FCEUI_DelCheat(cheatwasdeleted-1); + if (a == addrtodelete) + { + FCEUI_DelCheat(cheatwasdeleted - 1); cheatwasdeleted = -1; return 0; } return 1; } -void dumpToFile(const char* buffer, unsigned int size) +void dumpToFile(const char *buffer, unsigned int size) { char name[513] = {0}; OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize=sizeof(ofn); - ofn.hInstance=fceu_hInstance; - ofn.lpstrTitle="Save to file ..."; - ofn.lpstrFilter="Binary File (*.BIN)\0*.bin\0All Files (*.*)\0*.*\0\0"; + ofn.lStructSize = sizeof(ofn); + ofn.hInstance = fceu_hInstance; + ofn.lpstrTitle = "Save to file ..."; + ofn.lpstrFilter = "Binary File (*.BIN)\0*.bin\0All Files (*.*)\0*.*\0\0"; strcpy(name, mass_replace(GetRomName(), "|", ".").c_str()); - ofn.lpstrFile=name; - ofn.lpstrDefExt="bin"; - ofn.nMaxFile=256; - ofn.Flags=OFN_EXPLORER|OFN_HIDEREADONLY; + ofn.lpstrFile = name; + ofn.lpstrDefExt = "bin"; + ofn.nMaxFile = 256; + ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY; if (GetSaveFileName(&ofn)) { - FILE* memfile = fopen(name, "wb"); + FILE *memfile = fopen(name, "wb"); if (!memfile || fwrite(buffer, 1, size, memfile) != size) { @@ -863,25 +907,25 @@ void dumpToFile(const char* buffer, unsigned int size) } } -bool loadFromFile(char* buffer, unsigned int size) +bool loadFromFile(char *buffer, unsigned int size) { - char name[513] = { 0 }; + char name[513] = {0}; OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize=sizeof(ofn); - ofn.hInstance=fceu_hInstance; - ofn.lpstrTitle="Save to file ..."; - ofn.lpstrFilter="Binary File (*.BIN)\0*.bin\0All Files (*.*)\0*.*\0\0"; + ofn.lStructSize = sizeof(ofn); + ofn.hInstance = fceu_hInstance; + ofn.lpstrTitle = "Save to file ..."; + ofn.lpstrFilter = "Binary File (*.BIN)\0*.bin\0All Files (*.*)\0*.*\0\0"; strcpy(name, mass_replace(GetRomName(), "|", ".").c_str()); - ofn.lpstrFile=name; - ofn.lpstrDefExt="bin"; - ofn.nMaxFile=256; - ofn.Flags=OFN_EXPLORER | OFN_FILEMUSTEXIST; + ofn.lpstrFile = name; + ofn.lpstrDefExt = "bin"; + ofn.nMaxFile = 256; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST; if (GetOpenFileName(&ofn)) { - FILE* memfile = fopen(name, "rb"); + FILE *memfile = fopen(name, "rb"); if (!memfile || fread(buffer, 1, size, memfile) != size) { @@ -897,32 +941,35 @@ bool loadFromFile(char* buffer, unsigned int size) return false; } -void UnfreezeAllRam() { +void UnfreezeAllRam() +{ - int i=0; + int i = 0; std::string Cname; uint32 Caddr; int Ctype; // Get last cheat number + 1 - while (FCEUI_GetCheat(i,NULL,NULL,NULL,NULL,NULL,NULL)) { + while (FCEUI_GetCheat(i, NULL, NULL, NULL, NULL, NULL, NULL)) + { i = i + 1; } // Subtract 1 to be on last cheat i = i - 1; - while (i >= 0) { + while (i >= 0) + { // Since this is automated, only remove unnamed variables, as they // would be added by the freeze command. Manual unfreeze should let them // make that mistake once or twice, in case they like it that way. - FCEUI_GetCheat(i,&Cname,&Caddr,NULL,NULL,NULL,&Ctype); - if ((Cname.empty()) && ((Caddr < 0x2000) || ((Caddr >= 0x6000) && (Caddr < 0x8000))) && (Ctype == 1)) { + FCEUI_GetCheat(i, &Cname, &Caddr, NULL, NULL, NULL, &Ctype); + if ((Cname.empty()) && ((Caddr < 0x2000) || ((Caddr >= 0x6000) && (Caddr < 0x8000))) && (Ctype == 1)) + { // Already Added, so consider it a success - FreezeRam(Caddr,-1,1); - + FreezeRam(Caddr, -1, 1); } i = i - 1; @@ -931,23 +978,25 @@ void UnfreezeAllRam() { return; } -void FreezeRam(int address, int mode, int final){ +void FreezeRam(int address, int mode, int final) +{ // mode: -1 == Unfreeze; 0 == Toggle; 1 == Freeze - if(FrozenAddressCount <= 256 && (address < 0x2000) || ((address >= 0x6000) && (address <= 0x7FFF))){ - //adelikat: added FrozenAddressCount check to if statement to prevent user from freezing more than 256 address (unfreezing when > 256 crashes) + if (FrozenAddressCount <= 256 && (address < 0x2000) || ((address >= 0x6000) && (address <= 0x7FFF))) + { + // adelikat: added FrozenAddressCount check to if statement to prevent user from freezing more than 256 address (unfreezing when > 256 crashes) addrtodelete = address; cheatwasdeleted = 0; if (mode == 0 || mode == -1) { - //mbg merge 6/29/06 - added argument + // mbg merge 6/29/06 - added argument FCEUI_ListCheats(DeleteCheatCallB, 0); - if(mode == 0 && cheatwasdeleted != -1) + if (mode == 0 && cheatwasdeleted != -1) FCEUI_AddCheat("", address, GetMem(address), -1, 1); } else { - //mbg merge 6/29/06 - added argument + // mbg merge 6/29/06 - added argument FCEUI_ListCheats(DeleteCheatCallB, 0); FCEUI_AddCheat("", address, GetMem(address), -1, 1); } @@ -957,29 +1006,37 @@ void FreezeRam(int address, int mode, int final){ } } -//input is expected to be an ASCII string -void InputData(char *input){ - //CursorEndAddy = -1; +// input is expected to be an ASCII string +void InputData(char *input) +{ + // CursorEndAddy = -1; int addr, datasize = 0; unsigned char *data; char inputc; - //char str[100]; - //mbg merge 7/18/06 added cast: - data = (uint8 *)malloc(strlen(input) + 1); //it can't be larger than the input string, so use that as the size + // char str[100]; + // mbg merge 7/18/06 added cast: + data = (uint8 *)malloc(strlen(input) + 1); // it can't be larger than the input string, so use that as the size - for(int i = 0;input[i] != 0;i++){ - if(!EditingText){ + for (int i = 0; input[i] != 0; i++) + { + if (!EditingText) + { inputc = -1; - if((input[i] >= 'a') && (input[i] <= 'f')) inputc = input[i]-('a'-0xA); - if((input[i] >= 'A') && (input[i] <= 'F')) inputc = input[i]-('A'-0xA); - if((input[i] >= '0') && (input[i] <= '9')) inputc = input[i]-'0'; - if(inputc == -1)continue; + if ((input[i] >= 'a') && (input[i] <= 'f')) + inputc = input[i] - ('a' - 0xA); + if ((input[i] >= 'A') && (input[i] <= 'F')) + inputc = input[i] - ('A' - 0xA); + if ((input[i] >= '0') && (input[i] <= '9')) + inputc = input[i] - '0'; + if (inputc == -1) + continue; - if(TempData != PREVIOUS_VALUE_UNDEFINED) + if (TempData != PREVIOUS_VALUE_UNDEFINED) { - data[datasize++] = inputc|(TempData<<4); + data[datasize++] = inputc | (TempData << 4); TempData = PREVIOUS_VALUE_UNDEFINED; - } else + } + else { TempData = inputc; } @@ -987,772 +1044,827 @@ void InputData(char *input){ else { int j; - for(j = 0; j < 256; j++) - if(chartable[j] == input[i]) + for (j = 0; j < 256; j++) + if (chartable[j] == input[i]) break; - if(j == 256) + if (j == 256) continue; data[datasize++] = j; } } - if(datasize+CursorStartAddy >= MaxSize){ //too big - datasize = MaxSize-CursorStartAddy; - //free(data); - //return; + if (datasize + CursorStartAddy >= MaxSize) + { // too big + datasize = MaxSize - CursorStartAddy; + // free(data); + // return; } - if (datasize < 1) return; // avoid adjusting cursor and accidentally writing at end + if (datasize < 1) + return; // avoid adjusting cursor and accidentally writing at end - //its possible for this loop not to get executed at all + // its possible for this loop not to get executed at all // for(addr = CursorStartAddy;addr < datasize+CursorStartAddy;addr++){ - //sprintf(str,"datasize = %d",datasize); - //MessageBox(hMemView,str, "debug", MB_OK); + // sprintf(str,"datasize = %d",datasize); + // MessageBox(hMemView,str, "debug", MB_OK); - if(EditingMode == MODE_NES_FILE) + if (EditingMode == MODE_NES_FILE) { ApplyPatch(CursorStartAddy, datasize, data); } else { - for(int i = 0;i < datasize;i++) + for (int i = 0; i < datasize; i++) { - addr = CursorStartAddy+i; + addr = CursorStartAddy + i; - if (addr >= MaxSize) continue; + if (addr >= MaxSize) + continue; - switch(EditingMode) + switch (EditingMode) { - case MODE_NES_MEMORY: - // RAM (system bus) - BWrite[addr](addr, data[i]); - break; - case MODE_NES_PPU: - // PPU - addr &= 0x3FFF; - if (addr < 0x2000) - VPage[addr >> 10][addr] = data[i]; //todo: detect if this is vrom and turn it red if so - if ((addr >= 0x2000) && (addr < 0x3F00)) - vnapage[(addr >> 10) & 0x3][addr & 0x3FF] = data[i]; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? - if ((addr >= 0x3F00) && (addr < 0x3FFF)) - PalettePoke(addr, data[i]); - break; - case MODE_NES_OAM: - addr &= 0xFF; - SPRAM[addr] = data[i]; - break; - case MODE_NES_FILE: - // ROM - ApplyPatch(addr, 1, &data[i]); - break; - } - } - } - CursorStartAddy+=datasize; - CursorEndAddy=-1; - if(CursorStartAddy >= MaxSize)CursorStartAddy = MaxSize-1; - - free(data); - ChangeMemViewFocus(EditingMode, CursorStartAddy, -1); - UpdateColorTable(); - return; -} - - -void ChangeMemViewFocus(int newEditingMode, int StartOffset,int EndOffset){ - - if(!hMemView)DoMemView(); - if(EditingMode != newEditingMode) - MemViewCallB(hMemView,WM_COMMAND,MENU_MV_VIEW_RAM+newEditingMode,0); //let the window handler change this for us - - if((EndOffset == StartOffset) || (EndOffset == -1)){ - CursorEndAddy = -1; - CursorStartAddy = StartOffset; - } else { - CursorStartAddy = std::min(StartOffset,EndOffset); - CursorEndAddy = std::max(StartOffset,EndOffset); - } - CursorDragPoint = -1; - - - if(std::min(StartOffset,EndOffset) >= MaxSize)return; //this should never happen - - if(StartOffset < CurOffset){ - CurOffset = (StartOffset/16)*16; - } - - if(StartOffset >= CurOffset+DataAmount){ - CurOffset = ((StartOffset/16)*16)-DataAmount+0x10; - if(CurOffset < 0)CurOffset = 0; - } - - SetFocus(hMemView); - - SCROLLINFO si; - ZeroMemory(&si, sizeof(SCROLLINFO)); - si.fMask = SIF_POS; - si.cbSize = sizeof(SCROLLINFO); - si.nPos = CurOffset / 16; - SetScrollInfo(hMemView,SB_VERT,&si,TRUE); - UpdateCaption(); - UpdateColorTable(); - return; -} - - -int GetHexScreenCoordx(int offset) -{ - return (8 * (debugSystem->HexeditorFontWidth + HexCharSpacing)) + ((offset % 16) * 3 * (debugSystem->HexeditorFontWidth + HexCharSpacing)); //todo: add Curoffset to this and to below function -} - -int GetHexScreenCoordy(int offset) -{ - return (offset - CurOffset) / 16 * (debugSystem->HexeditorFontHeight + HexRowHeightBorder); -} - -//0000E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ - -//if the mouse is in the text field, this function will set AddyWasText to 1 otherwise it is 0 -//if the mouse wasn't in any range, this function returns -1 -int GetAddyFromCoord(int x,int y) -{ - int MemFontWidth = debugSystem->HexeditorFontWidth + HexCharSpacing; - int MemFontHeight = debugSystem->HexeditorFontHeight + HexRowHeightBorder; - - if(y < 0)y = 0; - if(x < 8*MemFontWidth)x = 8*MemFontWidth+1; - - if(y > DataAmount*MemFontHeight) return -1; - - if(x < 55*MemFontWidth){ - AddyWasText = 0; - return ((y/MemFontHeight)*16)+((x-(8*MemFontWidth))/(3*MemFontWidth))+CurOffset; - } - - if((x > 59*MemFontWidth) && (x < 75*MemFontWidth)){ - AddyWasText = 1; - return ((y/MemFontHeight)*16)+((x-(59*MemFontWidth))/(MemFontWidth))+CurOffset; - } - - return -1; -} - -void AutoScrollFromCoord(int x,int y) -{ - SCROLLINFO si; - if(y < 0){ - ZeroMemory(&si, sizeof(SCROLLINFO)); - si.fMask = SIF_ALL; - si.cbSize = sizeof(SCROLLINFO); - GetScrollInfo(hMemView,SB_VERT,&si); - si.nPos += y / 16; - if (si.nPos < si.nMin) si.nPos = si.nMin; - if ((si.nPos+(int)si.nPage) > si.nMax) si.nPos = si.nMax-si.nPage; - CurOffset = si.nPos*16; - if (CurOffset + DataAmount >= MaxSize) CurOffset = MaxSize - DataAmount; - if (CurOffset < 0) CurOffset = 0; - SetScrollInfo(hMemView,SB_VERT,&si,TRUE); - return; - } - - if(y > ClientHeight){ - ZeroMemory(&si, sizeof(SCROLLINFO)); - si.fMask = SIF_ALL; - si.cbSize = sizeof(SCROLLINFO); - GetScrollInfo(hMemView,SB_VERT,&si); - si.nPos -= (ClientHeight-y) / 16; - if (si.nPos < si.nMin) si.nPos = si.nMin; - if ((si.nPos+(int)si.nPage) > si.nMax) si.nPos = si.nMax-si.nPage; - CurOffset = si.nPos*16; - if (CurOffset + DataAmount >= MaxSize) CurOffset = MaxSize - DataAmount; - if (CurOffset < 0) CurOffset = 0; - SetScrollInfo(hMemView,SB_VERT,&si,TRUE); - return; - } -} - -void KillMemView() -{ - if (hMemView) - { - ReleaseDC(hMemView, HDataDC); - DestroyWindow(hMemView); - UnregisterClass("MEMVIEW", fceu_hInstance); - hMemView = NULL; - hMemFind = NULL; - free(CurTextColorList); - free(DimTextColorList); - free(CurBGColorList); - free(DimBGColorList); - if (EditingMode == MODE_NES_MEMORY) - ReleaseCheatMap(); - for (int i = 0; i < sizeof(colormenu) / sizeof(colormenu[0]); ++i) - for (int j = 0; j < colormenu[i].size; ++j) - { - DeleteObject(colormenu[i].items[j].bitmap); - colormenu[i].items[j].bitmap = NULL; - } - } -} - -int GetMaxSize(int EditingMode) -{ - switch (EditingMode) - { - case MODE_NES_MEMORY: return 0x10000; - case MODE_NES_PPU: return (GameInfo->type == GIT_NSF ? 0x2000 : 0x4000); - case MODE_NES_OAM: return 0x100; - case MODE_NES_FILE: return 16 + CHRsize[0] + PRGsize[0]; //todo: add trainer size - } - return 0; -} - - -LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - static PAINTSTRUCT ps; - - // int tempAddy; - const int MemFontWidth = debugSystem->HexeditorFontWidth; - const int MemFontHeight = debugSystem->HexeditorFontHeight + HexRowHeightBorder; - -// char str[100]; - extern int debuggerWasActive; - - static int tmpStartAddy = -1; - static int tmpEndAddy = -1; - - switch (message) { - - case WM_ENTERMENULOOP:return 0; - case WM_INITMENUPOPUP: - if(undo_list != 0)EnableMenuItem(GetMenu(hMemView),MENU_MV_EDIT_UNDO,MF_BYCOMMAND | MF_ENABLED); - else EnableMenuItem(GetMenu(hMemView),MENU_MV_EDIT_UNDO,MF_BYCOMMAND | MF_GRAYED); - - if(TableFileLoaded)EnableMenuItem(GetMenu(hMemView),MENU_MV_FILE_UNLOAD_TBL,MF_BYCOMMAND | MF_ENABLED); - else EnableMenuItem(GetMenu(hMemView),MENU_MV_FILE_UNLOAD_TBL,MF_BYCOMMAND | MF_GRAYED); - - return 0; - - case WM_CREATE: - { - SetWindowPos(hwnd, 0, MemView_wndx, MemView_wndy, MemViewSizeX, MemViewSizeY, SWP_NOZORDER | SWP_NOOWNERZORDER); - - debuggerWasActive = 1; - HDataDC = GetDC(hwnd); - SelectObject(HDataDC, debugSystem->hHexeditorFont); - SetTextAlign(HDataDC, TA_NOUPDATECP | TA_TOP | TA_LEFT); - - // TEXTMETRIC textMetric; - // GetTextMetrics (HDataDC, &textMetric); - - MaxSize = 0x10000; - //Allocate Memory for color lists - DataAmount = 0x100; - //mbg merge 7/18/06 added casts: - CurTextColorList = (COLORREF*)malloc(DataAmount*sizeof(COLORREF)); - CurBGColorList = (COLORREF*)malloc(DataAmount*sizeof(COLORREF)); - DimTextColorList = (COLORREF*)malloc(DataAmount*sizeof(COLORREF)); - DimBGColorList = (COLORREF*)malloc(DataAmount*sizeof(COLORREF)); - HexTextColorList = CurTextColorList; - HexBGColorList = CurBGColorList; - AnsiTextColorList = DimTextColorList; - AnsiBGColorList = DimBGColorList; - PreviousValues = (int*)malloc(DataAmount*sizeof(int)); - HighlightedBytes = (unsigned int*)malloc(DataAmount*sizeof(unsigned int)); - resetHighlightingActivityLog(); - EditingText = CurOffset = 0; - EditingMode = MODE_NES_MEMORY; - CreateCheatMap(); - - //set the default table - UnloadTableFile(); - UpdateColorTable(); //draw it - - // update menus - HMENU menu = GetMenu(hwnd); - - for (int i = MODE_NES_MEMORY; i <= MODE_NES_FILE; i++) - if (EditingMode == i) { - CheckMenuRadioItem(menu, MENU_MV_VIEW_RAM, MENU_MV_VIEW_ROM, MENU_MV_VIEW_RAM, MF_BYCOMMAND); + case MODE_NES_MEMORY: + // RAM (system bus) + BWrite[addr](addr, data[i]); + break; + case MODE_NES_PPU: + // PPU + addr &= 0x3FFF; + if (addr < 0x2000) + VPage[addr >> 9][addr] = data[i]; // todo: detect if this is vrom and turn it red if so + if ((addr >= 0x2000) && (addr < 0x3F00)) + vnapage[(addr >> 10) & 0x3][addr & 0x3FF] = data[i]; // todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? + if ((addr >= 0x3F00) && (addr < 0x3FFF)) + PalettePoke(addr, data[i]); + break; + case MODE_NES_OAM: + addr &= 0xFF; + SPRAM[addr] = data[i]; + break; + case MODE_NES_FILE: + // ROM + ApplyPatch(addr, 1, &data[i]); break; } - CheckMenuItem(menu, ID_HIGHLIGHTING_HIGHLIGHT_ACTIVITY, (MemView_HighlightActivity) ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(menu, ID_HIGHLIGHTING_FADEWHENPAUSED, (MemView_HighlightActivity_FadeWhenPaused) ? MF_CHECKED : MF_UNCHECKED); - - updateBookmarkMenus(GetSubMenu(menu, BOOKMARKS_SUBMENU_POS)); - - HMENU hilightMenu = GetSubMenu(menu, HIGHLIGHTING_SUBMENU_POS); - for (int i = 0; i < sizeof(colormenu) / sizeof(colormenu[0]); ++i) - for (int j = 0; j < colormenu[i].size; ++j) - InsertColorMenu(hwnd, GetSubMenu(hilightMenu, colormenu[i].sub), &colormenu[i].items[j], j, colormenu[i].base_id + j); - } - return 0; - case WM_PAINT: - BeginPaint(hwnd, &ps); - EndPaint(hwnd, &ps); - UpdateMemoryView(1); - return 0; - - case WM_DROPFILES: - { - UINT len; - char *ftmp; - - len=DragQueryFile((HDROP)wParam,0,0,0)+1; - if(ftmp = (char*)malloc(len)) - { - DragQueryFile((HDROP)wParam,0,ftmp,len); - string fileDropped = ftmp; - //adelikat: Drag and Drop only checks file extension, the internal functions are responsible for file error checking - //------------------------------------------------------- - //Check if .tbl - //------------------------------------------------------- - if (!(fileDropped.find(".tbl") == string::npos) && (fileDropped.find(".tbl") == fileDropped.length()-4)) - { - LoadTable(fileDropped.c_str()); - } - else - { - std::string str = "Could not open " + fileDropped; - MessageBox(hwnd, str.c_str(), "File error", 0); - } - free(ftmp); - } - } - break; - case WM_VSCROLL: - { - SCROLLINFO si; - ZeroMemory(&si, sizeof(SCROLLINFO)); - si.fMask = SIF_ALL; - si.cbSize = sizeof(SCROLLINFO); - GetScrollInfo(hwnd, SB_VERT, &si); - switch (LOWORD(wParam)) { - case SB_ENDSCROLL: - case SB_TOP: - case SB_BOTTOM: break; - case SB_LINEUP: si.nPos--; break; - case SB_LINEDOWN:si.nPos++; break; - case SB_PAGEUP: si.nPos -= si.nPage; break; - case SB_PAGEDOWN: si.nPos += si.nPage; break; - case SB_THUMBPOSITION: //break; - case SB_THUMBTRACK: si.nPos = si.nTrackPos; break; } - if (si.nPos < si.nMin) si.nPos = si.nMin; - if ((si.nPos + (int)si.nPage) > si.nMax) si.nPos = si.nMax - si.nPage; //mbg merge 7/18/06 added cast - CurOffset = si.nPos * 16; - SetScrollInfo(hwnd, SB_VERT, &si, TRUE); - UpdateColorTable(); - return 0; - } - case WM_CHAR: - if(GetKeyState(VK_CONTROL) & 0x8000) return 0; //prevents input when pressing ctrl+c - char c[2]; - c[0] = (char)(wParam&0xFF); - c[1] = 0; - InputData(c); - UpdateColorTable(); - UpdateCaption(); - return 0; + CursorStartAddy += datasize; + CursorEndAddy = -1; + if (CursorStartAddy >= MaxSize) + CursorStartAddy = MaxSize - 1; - case WM_KEYDOWN: + free(data); + ChangeMemViewFocus(EditingMode, CursorStartAddy, -1); + UpdateColorTable(); + return; + } + + void ChangeMemViewFocus(int newEditingMode, int StartOffset, int EndOffset) { - if (wParam == VK_DOWN || wParam == VK_UP || wParam == VK_RIGHT || wParam == VK_LEFT || wParam == VK_PRIOR || wParam == VK_NEXT || wParam == VK_HOME || wParam == VK_END) + if (!hMemView) + DoMemView(); + if (EditingMode != newEditingMode) + MemViewCallB(hMemView, WM_COMMAND, MENU_MV_VIEW_RAM + newEditingMode, 0); // let the window handler change this for us + + if ((EndOffset == StartOffset) || (EndOffset == -1)) { - if (GetKeyState(VK_SHIFT) & 0x8000) - { - // Shift+ArrowKeys to select a range data - if (CursorEndAddy == -1) - { - tmpStartAddy = CursorStartAddy; - tmpEndAddy = CursorStartAddy; - } - if (wParam == VK_RIGHT) - { - if (tmpEndAddy >= MaxSize - 1) - return 0; - ++tmpEndAddy; - } - else if (wParam == VK_LEFT) - { - if (tmpEndAddy <= 0) - return 0; - --tmpEndAddy; - } - else if (wParam == VK_DOWN) - { - if (tmpEndAddy >= MaxSize - 1) - return 0; - tmpEndAddy += 16; - } - else if (wParam == VK_UP) - { - if (tmpEndAddy <= 0) - return 0; - tmpEndAddy -= 16; - } - else if (wParam == VK_PRIOR) - { - if (tmpEndAddy <= 0) - return 0; - tmpEndAddy -= DataAmount; - CurOffset -= DataAmount; - } - else if (wParam == VK_NEXT) - { - if (tmpEndAddy >= MaxSize - 1) - return 0; - tmpEndAddy += DataAmount; - CurOffset += DataAmount; - } - else if (wParam == VK_HOME) - { - if (tmpEndAddy <= 0) - return 0; - if (GetKeyState(VK_CONTROL) & 0x8000) - tmpEndAddy = 0; - else - tmpEndAddy = tmpEndAddy / 16 * 16; - } - else if (wParam == VK_END) - { - if (tmpEndAddy >= MaxSize - 1) - return 0; - if (GetKeyState(VK_CONTROL) & 0x8000) - tmpEndAddy = MaxSize - 1; - else - tmpEndAddy = tmpEndAddy / 16 * 16 + 15; - } + CursorEndAddy = -1; + CursorStartAddy = StartOffset; + } + else + { + CursorStartAddy = std::min(StartOffset, EndOffset); + CursorEndAddy = std::max(StartOffset, EndOffset); + } + CursorDragPoint = -1; - if (tmpEndAddy < 0) - tmpEndAddy = 0; - else if (tmpEndAddy >= MaxSize) - tmpEndAddy = MaxSize - 1; - if (tmpStartAddy < 0) - tmpStartAddy = 0; - else if (tmpStartAddy >= MaxSize) - tmpStartAddy = MaxSize - 1; + if (std::min(StartOffset, EndOffset) >= MaxSize) + return; // this should never happen - if (tmpEndAddy < tmpStartAddy) - { - CursorStartAddy = tmpEndAddy; - CursorEndAddy = tmpStartAddy; - if (CursorStartAddy < CurOffset) - CurOffset = CursorStartAddy / 16 * 16; - else if (CursorStartAddy >= CurOffset + DataAmount) - CurOffset = CursorStartAddy / 16 * 16 - DataAmount + 0x10; - } - else if (tmpEndAddy > tmpStartAddy) - { - CursorStartAddy = tmpStartAddy; - CursorEndAddy = tmpEndAddy; - if (CursorEndAddy < CurOffset) - CurOffset = CursorEndAddy / 16 * 16; - else if (CursorEndAddy > CurOffset + DataAmount - 0x10) - CurOffset = CursorEndAddy / 16 * 16 - DataAmount + 0x10; - } - else - { - CursorStartAddy = tmpStartAddy; - CursorEndAddy = -1; - } - } - else if (GetKeyState(VK_CONTROL) & 0x8000) - { - if (wParam == VK_UP) - { - if (CurOffset <= 0) - return 0; - CurOffset -= 16; - if (CursorEndAddy == -1 && CursorStartAddy >= CurOffset + DataAmount) - CursorStartAddy -= 16; - } - else if (wParam == VK_DOWN) - { - if (CurOffset >= (MaxSize - DataAmount) / 16 * 16) - return 0; - CurOffset += 16; - if (CursorEndAddy == -1 && CursorStartAddy < CurOffset) - CursorStartAddy += 16; - } - else if (wParam == VK_PRIOR) - { - if (CurOffset <= 0) - return 0; - CurOffset -= DataAmount; - } - else if (wParam == VK_NEXT) - { - if (CurOffset >= (MaxSize - DataAmount) / 16 * 16) - return 0; - CurOffset += DataAmount; - } - else if (wParam == VK_HOME) - { - if (CursorStartAddy == 0 && CursorEndAddy == -1 && CurOffset == 0) - return 0; - CursorStartAddy = 0; - CursorEndAddy = -1; - CurOffset = 0; - } - else if (wParam == VK_END) - { - if (CursorStartAddy == 0 && CursorEndAddy == -1 && CurOffset ==(MaxSize - DataAmount) / 16 * 16) - return 0; - CurOffset = (MaxSize - DataAmount) / 16 * 16; - CursorStartAddy = MaxSize - 1; - CursorEndAddy = -1; - } + if (StartOffset < CurOffset) + { + CurOffset = (StartOffset / 16) * 16; + } - TempData = PREVIOUS_VALUE_UNDEFINED; - } - else - { - // Move the cursor - - if (wParam == VK_RIGHT) - { - if (CursorStartAddy >= MaxSize - 1) - return 0; - CursorStartAddy++; - } - else if (wParam == VK_DOWN) - { - if (CursorStartAddy >= MaxSize - 1) - return 0; - CursorStartAddy += 16; - } - else if (wParam == VK_UP) - { - if (CursorStartAddy <= 0) - return 0; - CursorStartAddy -= 16; - } - else if (wParam == VK_LEFT) - { - if (CursorStartAddy <= 0) - return 0; - CursorStartAddy--; - } else if (wParam == VK_PRIOR) - { - if (CurOffset <= 0) - return 0; - CurOffset -= DataAmount; - CursorStartAddy -= DataAmount; - } - else if (wParam == VK_NEXT) - { - if (CurOffset >= (MaxSize - DataAmount) / 16 * 16) - return 0; - CurOffset += DataAmount; - CursorStartAddy += DataAmount; - } - else if (wParam == VK_HOME) - { - if (CurOffset <= 0) - return 0; - CurOffset = 0; - CursorStartAddy = 0; - } - else if (wParam == VK_END) { - if (CurOffset >= (MaxSize - DataAmount) / 16 * 16) - CurOffset = (MaxSize - DataAmount) / 16 * 16; - CursorStartAddy = MaxSize - 1; - } - - CursorEndAddy = -1; - if (CursorStartAddy < CurOffset) - CurOffset = (CursorStartAddy / 16) * 16; - if (CursorStartAddy > CurOffset + DataAmount - 0x10) - CurOffset = (CursorStartAddy - DataAmount + 0x10) / 16 * 16; - } - TempData = PREVIOUS_VALUE_UNDEFINED; - - - // Cursor Out of bound check - if (CursorStartAddy < 0) - CursorStartAddy = 0; - if (CursorStartAddy >= MaxSize) - CursorStartAddy = MaxSize - 1; - if (CursorEndAddy >= MaxSize) - CursorEndAddy = MaxSize - 1; - if (CursorEndAddy == CursorStartAddy) - CursorEndAddy = -1; - if (CurOffset + DataAmount >= MaxSize) - CurOffset = (MaxSize - DataAmount) / 16 * 16; + if (StartOffset >= CurOffset + DataAmount) + { + CurOffset = ((StartOffset / 16) * 16) - DataAmount + 0x10; if (CurOffset < 0) CurOffset = 0; } - else if (GetKeyState(VK_CONTROL) & 0x8000) { - if (wParam >= '0' && wParam <= '9') - { - char buf[3]; - sprintf(buf, "%c", (int)wParam); - int key_num; - sscanf(buf, "%d", &key_num); - key_num = (key_num + 9) % 10; - if (hexBookmarks.shortcuts[key_num] != -1) - { - int address = hexBookmarks[hexBookmarks.shortcuts[key_num]].address; - if (address != -1) - { - ChangeMemViewFocus(hexBookmarks[hexBookmarks.shortcuts[key_num]].editmode, address, -1); - // it stops here to prevent update the scroll info, color table and caption twice, - // because ChangeMemViewFocus already contained those codes. - return 0; - } - } - } + SetFocus(hMemView); - switch (wParam) { - case 0x43: //Ctrl+C - MemViewCallB(hMemView, WM_COMMAND, MENU_MV_EDIT_COPY, 0); //recursion at work - return 0; - case 0x56: //Ctrl+V - MemViewCallB(hMemView, WM_COMMAND, MENU_MV_EDIT_PASTE, 0); - return 0; - case 0x5a: //Ctrl+Z - UndoLastPatch(); - break; - case 0x41: //Ctrl+A - // Fall through to Ctrl+G - case 0x47: //Ctrl+G - GotoAddress(hwnd); - break; - case 0x46: //Ctrl+F - OpenFindDialog(); - break; - default: - return 0; - } - } - else if (wParam == VK_TAB && (GetKeyState(VK_CONTROL) & 0x8000) == 0 && (GetKeyState(VK_MENU) & 0x8000) == 0) - { - SwitchEditingText(!EditingText); - TempData = PREVIOUS_VALUE_UNDEFINED; - } - else - // Pressed a key without any function, stop - return 0; - - //This updates the scroll bar to curoffset SCROLLINFO si; ZeroMemory(&si, sizeof(SCROLLINFO)); si.fMask = SIF_POS; si.cbSize = sizeof(SCROLLINFO); si.nPos = CurOffset / 16; - SetScrollInfo(hwnd, SB_VERT, &si, TRUE); - UpdateColorTable(); + SetScrollInfo(hMemView, SB_VERT, &si, TRUE); UpdateCaption(); + UpdateColorTable(); + return; + } + + int GetHexScreenCoordx(int offset) + { + return (8 * (debugSystem->HexeditorFontWidth + HexCharSpacing)) + ((offset % 16) * 3 * (debugSystem->HexeditorFontWidth + HexCharSpacing)); // todo: add Curoffset to this and to below function + } + + int GetHexScreenCoordy(int offset) + { + return (offset - CurOffset) / 16 * (debugSystem->HexeditorFontHeight + HexRowHeightBorder); + } + + // 0000E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ + + // if the mouse is in the text field, this function will set AddyWasText to 1 otherwise it is 0 + // if the mouse wasn't in any range, this function returns -1 + int GetAddyFromCoord(int x, int y) + { + int MemFontWidth = debugSystem->HexeditorFontWidth + HexCharSpacing; + int MemFontHeight = debugSystem->HexeditorFontHeight + HexRowHeightBorder; + + if (y < 0) + y = 0; + if (x < 8 * MemFontWidth) + x = 8 * MemFontWidth + 1; + + if (y > DataAmount * MemFontHeight) + return -1; + + if (x < 55 * MemFontWidth) + { + AddyWasText = 0; + return ((y / MemFontHeight) * 16) + ((x - (8 * MemFontWidth)) / (3 * MemFontWidth)) + CurOffset; + } + + if ((x > 59 * MemFontWidth) && (x < 75 * MemFontWidth)) + { + AddyWasText = 1; + return ((y / MemFontHeight) * 16) + ((x - (59 * MemFontWidth)) / (MemFontWidth)) + CurOffset; + } + + return -1; + } + + void AutoScrollFromCoord(int x, int y) + { + SCROLLINFO si; + if (y < 0) + { + ZeroMemory(&si, sizeof(SCROLLINFO)); + si.fMask = SIF_ALL; + si.cbSize = sizeof(SCROLLINFO); + GetScrollInfo(hMemView, SB_VERT, &si); + si.nPos += y / 16; + if (si.nPos < si.nMin) + si.nPos = si.nMin; + if ((si.nPos + (int)si.nPage) > si.nMax) + si.nPos = si.nMax - si.nPage; + CurOffset = si.nPos * 16; + if (CurOffset + DataAmount >= MaxSize) + CurOffset = MaxSize - DataAmount; + if (CurOffset < 0) + CurOffset = 0; + SetScrollInfo(hMemView, SB_VERT, &si, TRUE); + return; + } + + if (y > ClientHeight) + { + ZeroMemory(&si, sizeof(SCROLLINFO)); + si.fMask = SIF_ALL; + si.cbSize = sizeof(SCROLLINFO); + GetScrollInfo(hMemView, SB_VERT, &si); + si.nPos -= (ClientHeight - y) / 16; + if (si.nPos < si.nMin) + si.nPos = si.nMin; + if ((si.nPos + (int)si.nPage) > si.nMax) + si.nPos = si.nMax - si.nPage; + CurOffset = si.nPos * 16; + if (CurOffset + DataAmount >= MaxSize) + CurOffset = MaxSize - DataAmount; + if (CurOffset < 0) + CurOffset = 0; + SetScrollInfo(hMemView, SB_VERT, &si, TRUE); + return; + } + } + + void KillMemView() + { + if (hMemView) + { + ReleaseDC(hMemView, HDataDC); + DestroyWindow(hMemView); + UnregisterClass("MEMVIEW", fceu_hInstance); + hMemView = NULL; + hMemFind = NULL; + free(CurTextColorList); + free(DimTextColorList); + free(CurBGColorList); + free(DimBGColorList); + if (EditingMode == MODE_NES_MEMORY) + ReleaseCheatMap(); + for (int i = 0; i < sizeof(colormenu) / sizeof(colormenu[0]); ++i) + for (int j = 0; j < colormenu[i].size; ++j) + { + DeleteObject(colormenu[i].items[j].bitmap); + colormenu[i].items[j].bitmap = NULL; + } + } + } + + int GetMaxSize(int EditingMode) + { + switch (EditingMode) + { + case MODE_NES_MEMORY: + return 0x10000; + case MODE_NES_PPU: + return (GameInfo->type == GIT_NSF ? 0x2000 : 0x4000); + case MODE_NES_OAM: + return 0x100; + case MODE_NES_FILE: + return 16 + CHRsize[0] + PRGsize[0]; // todo: add trainer size + } return 0; } - case WM_LBUTTONDOWN: - SetCapture(hwnd); - lbuttondown = 1; - tmpStartAddy = GetAddyFromCoord(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); - if(tmpStartAddy < 0) - { - CursorDragPoint = -1; - return 0; - } - if(tmpStartAddy > MaxSize) - { - CursorDragPoint = -1; - return 0; - } - SwitchEditingText(AddyWasText); - CursorStartAddy = tmpStartAddy; - CursorDragPoint = tmpStartAddy; - CursorEndAddy = -1; - UpdateCaption(); - UpdateColorTable(); - return 0; - case WM_RBUTTONDOWN: + + LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - if (!lbuttondown && CursorEndAddy == -1) + static PAINTSTRUCT ps; + + // int tempAddy; + const int MemFontWidth = debugSystem->HexeditorFontWidth; + const int MemFontHeight = debugSystem->HexeditorFontHeight + HexRowHeightBorder; + + // char str[100]; + extern int debuggerWasActive; + + static int tmpStartAddy = -1; + static int tmpEndAddy = -1; + + switch (message) { - int addr = GetAddyFromCoord(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); - if (addr >= 0 && addr < MaxSize) + + case WM_ENTERMENULOOP: + return 0; + case WM_INITMENUPOPUP: + if (undo_list != 0) + EnableMenuItem(GetMenu(hMemView), MENU_MV_EDIT_UNDO, MF_BYCOMMAND | MF_ENABLED); + else + EnableMenuItem(GetMenu(hMemView), MENU_MV_EDIT_UNDO, MF_BYCOMMAND | MF_GRAYED); + + if (TableFileLoaded) + EnableMenuItem(GetMenu(hMemView), MENU_MV_FILE_UNLOAD_TBL, MF_BYCOMMAND | MF_ENABLED); + else + EnableMenuItem(GetMenu(hMemView), MENU_MV_FILE_UNLOAD_TBL, MF_BYCOMMAND | MF_GRAYED); + + return 0; + + case WM_CREATE: + { + SetWindowPos(hwnd, 0, MemView_wndx, MemView_wndy, MemViewSizeX, MemViewSizeY, SWP_NOZORDER | SWP_NOOWNERZORDER); + + debuggerWasActive = 1; + HDataDC = GetDC(hwnd); + SelectObject(HDataDC, debugSystem->hHexeditorFont); + SetTextAlign(HDataDC, TA_NOUPDATECP | TA_TOP | TA_LEFT); + + // TEXTMETRIC textMetric; + // GetTextMetrics (HDataDC, &textMetric); + + MaxSize = 0x10000; + // Allocate Memory for color lists + DataAmount = 0x100; + // mbg merge 7/18/06 added casts: + CurTextColorList = (COLORREF *)malloc(DataAmount * sizeof(COLORREF)); + CurBGColorList = (COLORREF *)malloc(DataAmount * sizeof(COLORREF)); + DimTextColorList = (COLORREF *)malloc(DataAmount * sizeof(COLORREF)); + DimBGColorList = (COLORREF *)malloc(DataAmount * sizeof(COLORREF)); + HexTextColorList = CurTextColorList; + HexBGColorList = CurBGColorList; + AnsiTextColorList = DimTextColorList; + AnsiBGColorList = DimBGColorList; + PreviousValues = (int *)malloc(DataAmount * sizeof(int)); + HighlightedBytes = (unsigned int *)malloc(DataAmount * sizeof(unsigned int)); + resetHighlightingActivityLog(); + EditingText = CurOffset = 0; + EditingMode = MODE_NES_MEMORY; + CreateCheatMap(); + + // set the default table + UnloadTableFile(); + UpdateColorTable(); // draw it + + // update menus + HMENU menu = GetMenu(hwnd); + + for (int i = MODE_NES_MEMORY; i <= MODE_NES_FILE; i++) + if (EditingMode == i) + { + CheckMenuRadioItem(menu, MENU_MV_VIEW_RAM, MENU_MV_VIEW_ROM, MENU_MV_VIEW_RAM, MF_BYCOMMAND); + break; + } + CheckMenuItem(menu, ID_HIGHLIGHTING_HIGHLIGHT_ACTIVITY, (MemView_HighlightActivity) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menu, ID_HIGHLIGHTING_FADEWHENPAUSED, (MemView_HighlightActivity_FadeWhenPaused) ? MF_CHECKED : MF_UNCHECKED); + + updateBookmarkMenus(GetSubMenu(menu, BOOKMARKS_SUBMENU_POS)); + + HMENU hilightMenu = GetSubMenu(menu, HIGHLIGHTING_SUBMENU_POS); + for (int i = 0; i < sizeof(colormenu) / sizeof(colormenu[0]); ++i) + for (int j = 0; j < colormenu[i].size; ++j) + InsertColorMenu(hwnd, GetSubMenu(hilightMenu, colormenu[i].sub), &colormenu[i].items[j], j, colormenu[i].base_id + j); + } + return 0; + case WM_PAINT: + BeginPaint(hwnd, &ps); + EndPaint(hwnd, &ps); + UpdateMemoryView(1); + return 0; + + case WM_DROPFILES: + { + UINT len; + char *ftmp; + + len = DragQueryFile((HDROP)wParam, 0, 0, 0) + 1; + if (ftmp = (char *)malloc(len)) { - SwitchEditingText(AddyWasText); - tmpStartAddy = addr; - UpdateCaption(); - UpdateColorTable(); - return 0; + DragQueryFile((HDROP)wParam, 0, ftmp, len); + string fileDropped = ftmp; + // adelikat: Drag and Drop only checks file extension, the internal functions are responsible for file error checking + //------------------------------------------------------- + // Check if .tbl + //------------------------------------------------------- + if (!(fileDropped.find(".tbl") == string::npos) && (fileDropped.find(".tbl") == fileDropped.length() - 4)) + { + LoadTable(fileDropped.c_str()); + } + else + { + std::string str = "Could not open " + fileDropped; + MessageBox(hwnd, str.c_str(), "File error", 0); + } + free(ftmp); } } break; - } - case WM_MOUSEMOVE: - { - if (CursorDragPoint < 0) - return 0; - int x = GET_X_LPARAM(lParam); - int y = GET_Y_LPARAM(lParam); - if(lbuttondown){ - AutoScrollFromCoord(x,y); - tmpEndAddy = GetAddyFromCoord(x,y); - if (tmpEndAddy >= MaxSize) - tmpEndAddy = MaxSize - 1; - SwitchEditingText(AddyWasText); - if(tmpEndAddy >= 0){ - CursorStartAddy = std::min(tmpStartAddy, tmpEndAddy); - CursorEndAddy = std::max(tmpStartAddy, tmpEndAddy); - if(CursorEndAddy == CursorStartAddy) - CursorEndAddy = -1; + case WM_VSCROLL: + { + SCROLLINFO si; + ZeroMemory(&si, sizeof(SCROLLINFO)); + si.fMask = SIF_ALL; + si.cbSize = sizeof(SCROLLINFO); + GetScrollInfo(hwnd, SB_VERT, &si); + switch (LOWORD(wParam)) + { + case SB_ENDSCROLL: + case SB_TOP: + case SB_BOTTOM: + break; + case SB_LINEUP: + si.nPos--; + break; + case SB_LINEDOWN: + si.nPos++; + break; + case SB_PAGEUP: + si.nPos -= si.nPage; + break; + case SB_PAGEDOWN: + si.nPos += si.nPage; + break; + case SB_THUMBPOSITION: // break; + case SB_THUMBTRACK: + si.nPos = si.nTrackPos; + break; } + if (si.nPos < si.nMin) + si.nPos = si.nMin; + if ((si.nPos + (int)si.nPage) > si.nMax) + si.nPos = si.nMax - si.nPage; // mbg merge 7/18/06 added cast + CurOffset = si.nPos * 16; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + UpdateColorTable(); + return 0; + } + case WM_CHAR: + if (GetKeyState(VK_CONTROL) & 0x8000) + return 0; // prevents input when pressing ctrl+c + char c[2]; + c[0] = (char)(wParam & 0xFF); + c[1] = 0; + InputData(c); + UpdateColorTable(); + UpdateCaption(); + return 0; + case WM_KEYDOWN: + { + + if (wParam == VK_DOWN || wParam == VK_UP || wParam == VK_RIGHT || wParam == VK_LEFT || wParam == VK_PRIOR || wParam == VK_NEXT || wParam == VK_HOME || wParam == VK_END) + { + if (GetKeyState(VK_SHIFT) & 0x8000) + { + // Shift+ArrowKeys to select a range data + if (CursorEndAddy == -1) + { + tmpStartAddy = CursorStartAddy; + tmpEndAddy = CursorStartAddy; + } + if (wParam == VK_RIGHT) + { + if (tmpEndAddy >= MaxSize - 1) + return 0; + ++tmpEndAddy; + } + else if (wParam == VK_LEFT) + { + if (tmpEndAddy <= 0) + return 0; + --tmpEndAddy; + } + else if (wParam == VK_DOWN) + { + if (tmpEndAddy >= MaxSize - 1) + return 0; + tmpEndAddy += 16; + } + else if (wParam == VK_UP) + { + if (tmpEndAddy <= 0) + return 0; + tmpEndAddy -= 16; + } + else if (wParam == VK_PRIOR) + { + if (tmpEndAddy <= 0) + return 0; + tmpEndAddy -= DataAmount; + CurOffset -= DataAmount; + } + else if (wParam == VK_NEXT) + { + if (tmpEndAddy >= MaxSize - 1) + return 0; + tmpEndAddy += DataAmount; + CurOffset += DataAmount; + } + else if (wParam == VK_HOME) + { + if (tmpEndAddy <= 0) + return 0; + if (GetKeyState(VK_CONTROL) & 0x8000) + tmpEndAddy = 0; + else + tmpEndAddy = tmpEndAddy / 16 * 16; + } + else if (wParam == VK_END) + { + if (tmpEndAddy >= MaxSize - 1) + return 0; + if (GetKeyState(VK_CONTROL) & 0x8000) + tmpEndAddy = MaxSize - 1; + else + tmpEndAddy = tmpEndAddy / 16 * 16 + 15; + } + + if (tmpEndAddy < 0) + tmpEndAddy = 0; + else if (tmpEndAddy >= MaxSize) + tmpEndAddy = MaxSize - 1; + if (tmpStartAddy < 0) + tmpStartAddy = 0; + else if (tmpStartAddy >= MaxSize) + tmpStartAddy = MaxSize - 1; + + if (tmpEndAddy < tmpStartAddy) + { + CursorStartAddy = tmpEndAddy; + CursorEndAddy = tmpStartAddy; + if (CursorStartAddy < CurOffset) + CurOffset = CursorStartAddy / 16 * 16; + else if (CursorStartAddy >= CurOffset + DataAmount) + CurOffset = CursorStartAddy / 16 * 16 - DataAmount + 0x10; + } + else if (tmpEndAddy > tmpStartAddy) + { + CursorStartAddy = tmpStartAddy; + CursorEndAddy = tmpEndAddy; + if (CursorEndAddy < CurOffset) + CurOffset = CursorEndAddy / 16 * 16; + else if (CursorEndAddy > CurOffset + DataAmount - 0x10) + CurOffset = CursorEndAddy / 16 * 16 - DataAmount + 0x10; + } + else + { + CursorStartAddy = tmpStartAddy; + CursorEndAddy = -1; + } + } + else if (GetKeyState(VK_CONTROL) & 0x8000) + { + if (wParam == VK_UP) + { + if (CurOffset <= 0) + return 0; + CurOffset -= 16; + if (CursorEndAddy == -1 && CursorStartAddy >= CurOffset + DataAmount) + CursorStartAddy -= 16; + } + else if (wParam == VK_DOWN) + { + if (CurOffset >= (MaxSize - DataAmount) / 16 * 16) + return 0; + CurOffset += 16; + if (CursorEndAddy == -1 && CursorStartAddy < CurOffset) + CursorStartAddy += 16; + } + else if (wParam == VK_PRIOR) + { + if (CurOffset <= 0) + return 0; + CurOffset -= DataAmount; + } + else if (wParam == VK_NEXT) + { + if (CurOffset >= (MaxSize - DataAmount) / 16 * 16) + return 0; + CurOffset += DataAmount; + } + else if (wParam == VK_HOME) + { + if (CursorStartAddy == 0 && CursorEndAddy == -1 && CurOffset == 0) + return 0; + CursorStartAddy = 0; + CursorEndAddy = -1; + CurOffset = 0; + } + else if (wParam == VK_END) + { + if (CursorStartAddy == 0 && CursorEndAddy == -1 && CurOffset == (MaxSize - DataAmount) / 16 * 16) + return 0; + CurOffset = (MaxSize - DataAmount) / 16 * 16; + CursorStartAddy = MaxSize - 1; + CursorEndAddy = -1; + } + + TempData = PREVIOUS_VALUE_UNDEFINED; + } + else + { + // Move the cursor + + if (wParam == VK_RIGHT) + { + if (CursorStartAddy >= MaxSize - 1) + return 0; + CursorStartAddy++; + } + else if (wParam == VK_DOWN) + { + if (CursorStartAddy >= MaxSize - 1) + return 0; + CursorStartAddy += 16; + } + else if (wParam == VK_UP) + { + if (CursorStartAddy <= 0) + return 0; + CursorStartAddy -= 16; + } + else if (wParam == VK_LEFT) + { + if (CursorStartAddy <= 0) + return 0; + CursorStartAddy--; + } + else if (wParam == VK_PRIOR) + { + if (CurOffset <= 0) + return 0; + CurOffset -= DataAmount; + CursorStartAddy -= DataAmount; + } + else if (wParam == VK_NEXT) + { + if (CurOffset >= (MaxSize - DataAmount) / 16 * 16) + return 0; + CurOffset += DataAmount; + CursorStartAddy += DataAmount; + } + else if (wParam == VK_HOME) + { + if (CurOffset <= 0) + return 0; + CurOffset = 0; + CursorStartAddy = 0; + } + else if (wParam == VK_END) + { + if (CurOffset >= (MaxSize - DataAmount) / 16 * 16) + CurOffset = (MaxSize - DataAmount) / 16 * 16; + CursorStartAddy = MaxSize - 1; + } + + CursorEndAddy = -1; + if (CursorStartAddy < CurOffset) + CurOffset = (CursorStartAddy / 16) * 16; + if (CursorStartAddy > CurOffset + DataAmount - 0x10) + CurOffset = (CursorStartAddy - DataAmount + 0x10) / 16 * 16; + } + TempData = PREVIOUS_VALUE_UNDEFINED; + + // Cursor Out of bound check + if (CursorStartAddy < 0) + CursorStartAddy = 0; + if (CursorStartAddy >= MaxSize) + CursorStartAddy = MaxSize - 1; + if (CursorEndAddy >= MaxSize) + CursorEndAddy = MaxSize - 1; + if (CursorEndAddy == CursorStartAddy) + CursorEndAddy = -1; + if (CurOffset + DataAmount >= MaxSize) + CurOffset = (MaxSize - DataAmount) / 16 * 16; + if (CurOffset < 0) + CurOffset = 0; + } + else if (GetKeyState(VK_CONTROL) & 0x8000) + { + + if (wParam >= '0' && wParam <= '9') + { + char buf[3]; + sprintf(buf, "%c", (int)wParam); + int key_num; + sscanf(buf, "%d", &key_num); + key_num = (key_num + 9) % 10; + if (hexBookmarks.shortcuts[key_num] != -1) + { + int address = hexBookmarks[hexBookmarks.shortcuts[key_num]].address; + if (address != -1) + { + ChangeMemViewFocus(hexBookmarks[hexBookmarks.shortcuts[key_num]].editmode, address, -1); + // it stops here to prevent update the scroll info, color table and caption twice, + // because ChangeMemViewFocus already contained those codes. + return 0; + } + } + } + + switch (wParam) + { + case 0x43: // Ctrl+C + MemViewCallB(hMemView, WM_COMMAND, MENU_MV_EDIT_COPY, 0); // recursion at work + return 0; + case 0x56: // Ctrl+V + MemViewCallB(hMemView, WM_COMMAND, MENU_MV_EDIT_PASTE, 0); + return 0; + case 0x5a: // Ctrl+Z + UndoLastPatch(); + break; + case 0x41: // Ctrl+A + // Fall through to Ctrl+G + case 0x47: // Ctrl+G + GotoAddress(hwnd); + break; + case 0x46: // Ctrl+F + OpenFindDialog(); + break; + default: + return 0; + } + } + else if (wParam == VK_TAB && (GetKeyState(VK_CONTROL) & 0x8000) == 0 && (GetKeyState(VK_MENU) & 0x8000) == 0) + { + SwitchEditingText(!EditingText); + TempData = PREVIOUS_VALUE_UNDEFINED; + } + else + // Pressed a key without any function, stop + return 0; + + // This updates the scroll bar to curoffset + SCROLLINFO si; + ZeroMemory(&si, sizeof(SCROLLINFO)); + si.fMask = SIF_POS; + si.cbSize = sizeof(SCROLLINFO); + si.nPos = CurOffset / 16; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + UpdateColorTable(); + UpdateCaption(); + return 0; + } + case WM_LBUTTONDOWN: + SetCapture(hwnd); + lbuttondown = 1; + tmpStartAddy = GetAddyFromCoord(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + if (tmpStartAddy < 0) + { + CursorDragPoint = -1; + return 0; + } + if (tmpStartAddy > MaxSize) + { + CursorDragPoint = -1; + return 0; + } + SwitchEditingText(AddyWasText); + CursorStartAddy = tmpStartAddy; + CursorDragPoint = tmpStartAddy; + CursorEndAddy = -1; UpdateCaption(); UpdateColorTable(); - } - return 0; - } - case WM_LBUTTONUP: - lbuttondown = 0; - if (CursorEndAddy == CursorStartAddy) - CursorEndAddy = -1; - if((CursorEndAddy < CursorStartAddy) && (CursorEndAddy != -1)){ //this reverses them if they're not right - int tmpAddy = CursorStartAddy; - CursorStartAddy = CursorEndAddy; - CursorEndAddy = tmpAddy; - } - UpdateCaption(); - UpdateColorTable(); - ReleaseCapture(); - return 0; - case WM_CONTEXTMENU: - { - POINT ptScreen = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - POINT ptClient; - int curAddy; - if (ptScreen.x == -1 && ptScreen.y == -1) + return 0; + case WM_RBUTTONDOWN: { - ptClient.x = GetHexScreenCoordx(CursorStartAddy); - ptClient.y = GetHexScreenCoordy(CursorEndAddy == -1 ? CursorStartAddy + 16 : CursorEndAddy + 16); - ptScreen = ptClient; - ClientToScreen(hMemView, &ptScreen); - curAddy = CursorStartAddy; - } - else - { - ptClient = ptScreen; - ScreenToClient(hMemView, &ptClient); - curAddy = GetAddyFromCoord(ptClient.x, ptClient.y); - } - - int bank = getBank(curAddy); - HMENU hMenu = CreatePopupMenu(); - - char str[128]; - for(int i = 0;i < POPUPNUM;i++) - { - if((curAddy >= popupmenu[i].minaddress) && (curAddy <= popupmenu[i].maxaddress) && (EditingMode == popupmenu[i].editingmode)) + if (!lbuttondown && CursorEndAddy == -1) { - switch(popupmenu[i].id) + int addr = GetAddyFromCoord(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + if (addr >= 0 && addr < MaxSize) { + SwitchEditingText(AddyWasText); + tmpStartAddy = addr; + UpdateCaption(); + UpdateColorTable(); + return 0; + } + } + break; + } + case WM_MOUSEMOVE: + { + if (CursorDragPoint < 0) + return 0; + int x = GET_X_LPARAM(lParam); + int y = GET_Y_LPARAM(lParam); + if (lbuttondown) + { + AutoScrollFromCoord(x, y); + tmpEndAddy = GetAddyFromCoord(x, y); + if (tmpEndAddy >= MaxSize) + tmpEndAddy = MaxSize - 1; + SwitchEditingText(AddyWasText); + if (tmpEndAddy >= 0) + { + CursorStartAddy = std::min(tmpStartAddy, tmpEndAddy); + CursorEndAddy = std::max(tmpStartAddy, tmpEndAddy); + if (CursorEndAddy == CursorStartAddy) + CursorEndAddy = -1; + } + + UpdateCaption(); + UpdateColorTable(); + } + return 0; + } + case WM_LBUTTONUP: + lbuttondown = 0; + if (CursorEndAddy == CursorStartAddy) + CursorEndAddy = -1; + if ((CursorEndAddy < CursorStartAddy) && (CursorEndAddy != -1)) + { // this reverses them if they're not right + int tmpAddy = CursorStartAddy; + CursorStartAddy = CursorEndAddy; + CursorEndAddy = tmpAddy; + } + UpdateCaption(); + UpdateColorTable(); + ReleaseCapture(); + return 0; + case WM_CONTEXTMENU: + { + POINT ptScreen = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; + POINT ptClient; + int curAddy; + if (ptScreen.x == -1 && ptScreen.y == -1) + { + ptClient.x = GetHexScreenCoordx(CursorStartAddy); + ptClient.y = GetHexScreenCoordy(CursorEndAddy == -1 ? CursorStartAddy + 16 : CursorEndAddy + 16); + ptScreen = ptClient; + ClientToScreen(hMemView, &ptScreen); + curAddy = CursorStartAddy; + } + else + { + ptClient = ptScreen; + ScreenToClient(hMemView, &ptClient); + curAddy = GetAddyFromCoord(ptClient.x, ptClient.y); + } + + int bank = getBank(curAddy); + HMENU hMenu = CreatePopupMenu(); + + char str[128]; + for (int i = 0; i < POPUPNUM; i++) + { + if ((curAddy >= popupmenu[i].minaddress) && (curAddy <= popupmenu[i].maxaddress) && (EditingMode == popupmenu[i].editingmode)) + { + switch (popupmenu[i].id) + { case ID_ADDRESS_SYMBOLIC_NAME: { if (curAddy <= CursorEndAddy && curAddy >= CursorStartAddy) @@ -1761,7 +1873,8 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa sprintf(str, "Add Symbolic Debug Name For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); else sprintf(str, "Add Symbolic Debug Name For Address %04X-%04X", CursorStartAddy, CursorEndAddy); - } else + } + else { if (curAddy >= 0x8000 && bank != -1) sprintf(str, "Add Symbolic Debug Name For Address %02X:%04X", bank, curAddy); @@ -1771,7 +1884,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa popupmenu[i].text = str; break; } - //this will set the text for the menu dynamically based on the id + // this will set the text for the menu dynamically based on the id case ID_ADDRESS_FRZ_SUBMENU: { HMENU sub = CreatePopupMenu(); @@ -1781,14 +1894,16 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa AppendMenu(sub, MF_STRING, ID_ADDRESS_FRZ_UNFREEZE, "Unfreeze"); AppendMenu(sub, MF_SEPARATOR, ID_ADDRESS_FRZ_SEP, "-"); AppendMenu(sub, MF_STRING, ID_ADDRESS_FRZ_UNFREEZE_ALL, "Unfreeze all"); - + int tempAddy; - if (CursorEndAddy == -1) tempAddy = CursorStartAddy; - else tempAddy = CursorEndAddy; //This is necessary because CursorEnd = -1 if only 1 address is selected - if (tempAddy - CursorStartAddy + FrozenAddressCount > 255) //There is a limit of 256 possible frozen addresses, therefore if the user has selected more than this limit, disable freeze menu items - { - EnableMenuItem(sub,ID_ADDRESS_FRZ_TOGGLE_STATE,MF_GRAYED); - EnableMenuItem(sub,ID_ADDRESS_FRZ_FREEZE,MF_GRAYED); + if (CursorEndAddy == -1) + tempAddy = CursorStartAddy; + else + tempAddy = CursorEndAddy; // This is necessary because CursorEnd = -1 if only 1 address is selected + if (tempAddy - CursorStartAddy + FrozenAddressCount > 255) // There is a limit of 256 possible frozen addresses, therefore if the user has selected more than this limit, disable freeze menu items + { + EnableMenuItem(sub, ID_ADDRESS_FRZ_TOGGLE_STATE, MF_GRAYED); + EnableMenuItem(sub, ID_ADDRESS_FRZ_FREEZE, MF_GRAYED); } continue; } @@ -1798,15 +1913,16 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) { if (curAddy >= 0x8000 && bank != -1) - sprintf(str,"Add Read Breakpoint For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); + sprintf(str, "Add Read Breakpoint For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); else - sprintf(str,"Add Read Breakpoint For Address %04X-%04X", CursorStartAddy, CursorEndAddy); - } else + sprintf(str, "Add Read Breakpoint For Address %04X-%04X", CursorStartAddy, CursorEndAddy); + } + else { if (curAddy >= 0x8000 && bank != -1) - sprintf(str,"Add Read Breakpoint For Address %02X:%04X", bank, curAddy); + sprintf(str, "Add Read Breakpoint For Address %02X:%04X", bank, curAddy); else - sprintf(str,"Add Read Breakpoint For Address %04X", curAddy); + sprintf(str, "Add Read Breakpoint For Address %04X", curAddy); } popupmenu[i].text = str; break; @@ -1816,15 +1932,16 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) { if (curAddy >= 0x8000 && bank != -1) - sprintf(str,"Add Write Breakpoint For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); + sprintf(str, "Add Write Breakpoint For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); else - sprintf(str,"Add Write Breakpoint For Address %04X-%04X", CursorStartAddy, CursorEndAddy); - } else + sprintf(str, "Add Write Breakpoint For Address %04X-%04X", CursorStartAddy, CursorEndAddy); + } + else { if (curAddy >= 0x8000 && bank != -1) - sprintf(str,"Add Write Breakpoint For Address %02X:%04X", bank, curAddy); + sprintf(str, "Add Write Breakpoint For Address %02X:%04X", bank, curAddy); else - sprintf(str,"Add Write Breakpoint For Address %04X", curAddy); + sprintf(str, "Add Write Breakpoint For Address %04X", curAddy); } popupmenu[i].text = str; break; @@ -1834,37 +1951,38 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) { if (curAddy >= 0x8000 && bank != -1) - sprintf(str,"Add Execute Breakpoint For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); + sprintf(str, "Add Execute Breakpoint For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); else - sprintf(str,"Add Execute Breakpoint For Address %04X-%04X", CursorStartAddy, CursorEndAddy); - } else + sprintf(str, "Add Execute Breakpoint For Address %04X-%04X", CursorStartAddy, CursorEndAddy); + } + else { if (curAddy >= 0x8000 && bank != -1) - sprintf(str,"Add Execute Breakpoint For Address %02X:%04X", bank, curAddy); + sprintf(str, "Add Execute Breakpoint For Address %02X:%04X", bank, curAddy); else - sprintf(str,"Add Execute Breakpoint For Address %04X", curAddy); + sprintf(str, "Add Execute Breakpoint For Address %04X", curAddy); } popupmenu[i].text = str; break; } + } + AppendMenu(hMenu, MF_STRING, popupmenu[i].id, popupmenu[i].text); } - AppendMenu(hMenu, MF_STRING, popupmenu[i].id, popupmenu[i].text); } - } - // Add / Edit / Remove bookmark - int foundBookmark = findBookmark(CursorStartAddy, EditingMode); - if (foundBookmark != -1) - { - AppendMenu(hMenu, MF_STRING, ID_ADDRESS_EDIT_BOOKMARK, "Edit Bookmark"); - AppendMenu(hMenu, MF_STRING, ID_ADDRESS_REMOVE_BOOKMARK, "Remove Bookmark"); - } - else - AppendMenu(hMenu, MF_STRING, ID_ADDRESS_ADD_BOOKMARK, "Add Bookmark"); + // Add / Edit / Remove bookmark + int foundBookmark = findBookmark(CursorStartAddy, EditingMode); + if (foundBookmark != -1) + { + AppendMenu(hMenu, MF_STRING, ID_ADDRESS_EDIT_BOOKMARK, "Edit Bookmark"); + AppendMenu(hMenu, MF_STRING, ID_ADDRESS_REMOVE_BOOKMARK, "Remove Bookmark"); + } + else + AppendMenu(hMenu, MF_STRING, ID_ADDRESS_ADD_BOOKMARK, "Add Bookmark"); - int id = TrackPopupMenuEx(hMenu, TPM_RETURNCMD | TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y, hMemView, NULL); - switch(id) - { + int id = TrackPopupMenuEx(hMenu, TPM_RETURNCMD | TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y, hMemView, NULL); + switch (id) + { case ID_ADDRESS_FRZ_TOGGLE_STATE: { for (int frzAddr = CursorStartAddy; (CursorEndAddy == -1 && frzAddr == CursorStartAddy) || frzAddr <= CursorEndAddy; frzAddr++) @@ -1907,7 +2025,8 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa { watchpoint[numWPs].address = CursorStartAddy; watchpoint[numWPs].endaddress = CursorEndAddy; - } else + } + else { watchpoint[numWPs].address = curAddy; watchpoint[numWPs].endaddress = 0; @@ -1944,7 +2063,8 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa { watchpoint[numWPs].address = CursorStartAddy; watchpoint[numWPs].endaddress = CursorEndAddy; - } else + } + else { watchpoint[numWPs].address = curAddy; watchpoint[numWPs].endaddress = 0; @@ -1959,8 +2079,10 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa checkCondition(condition, numWPs); numWPs++; - { extern int myNumWPs; - myNumWPs++; } + { + extern int myNumWPs; + myNumWPs++; + } if (hDebug) AddBreakList(); else @@ -1973,11 +2095,12 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa if (numWPs < MAXIMUM_NUMBER_OF_BREAKPOINTS) { watchpoint[numWPs].flags = WP_E | WP_X; - if((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) + if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) { watchpoint[numWPs].address = CursorStartAddy; watchpoint[numWPs].endaddress = CursorEndAddy; - } else + } + else { watchpoint[numWPs].address = curAddy; watchpoint[numWPs].endaddress = 0; @@ -1992,8 +2115,10 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa checkCondition(condition, numWPs); numWPs++; - { extern int myNumWPs; - myNumWPs++; } + { + extern int myNumWPs; + myNumWPs++; + } if (hDebug) AddBreakList(); else @@ -2076,801 +2201,835 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa break; } break; - } - //6 = Create GG Code - - return 0; - } - case WM_MBUTTONDOWN: - { - if (EditingMode != MODE_NES_MEMORY) return 0; - int addr = GetAddyFromCoord(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); - if(addr < 0) return 0; - FreezeRam(addr, 0, 1); - return 0; - } - case WM_MOUSEWHEEL: - { - SCROLLINFO si; - int delta = (short)HIWORD(wParam);///WHEEL_DELTA; - ZeroMemory(&si, sizeof(SCROLLINFO)); - si.fMask = SIF_ALL; - si.cbSize = sizeof(SCROLLINFO); - GetScrollInfo(hwnd,SB_VERT,&si); - if(delta < 0)si.nPos+=si.nPage; - if(delta > 0)si.nPos-=si.nPage; - if (si.nPos < si.nMin) si.nPos = si.nMin; - if ((si.nPos+(int)si.nPage) > si.nMax) si.nPos = si.nMax-si.nPage; //added cast - CurOffset = si.nPos*16; - if (CurOffset >= MaxSize - DataAmount) CurOffset = MaxSize - DataAmount; - if (CurOffset < 0) CurOffset = 0; - SetScrollInfo(hwnd,SB_VERT,&si,TRUE); - UpdateColorTable(); - return 0; - } - case WM_SIZE: - if(wParam == SIZE_RESTORED) //If dialog was resized - { - GetWindowRect(hwnd,&newMemViewRect); //Get new size - MemViewSizeX = newMemViewRect.right-newMemViewRect.left; //Store new size (this will be used to store in the .cfg file) - MemViewSizeY = newMemViewRect.bottom-newMemViewRect.top; - } - ClientHeight = HIWORD (lParam); - if (DataAmount != ((ClientHeight/MemFontHeight)*16)) - { - DataAmount = ((ClientHeight/MemFontHeight)*16); - if (CurOffset >= MaxSize - DataAmount) CurOffset = MaxSize - DataAmount; - if (CurOffset < 0) CurOffset = 0; - //mbg merge 7/18/06 added casts: - CurTextColorList = (COLORREF*)realloc(CurTextColorList, DataAmount*sizeof(COLORREF)); - CurBGColorList = (COLORREF*)realloc(CurBGColorList, DataAmount*sizeof(COLORREF)); - DimTextColorList = (COLORREF*)realloc(DimTextColorList, DataAmount*sizeof(COLORREF)); - DimBGColorList = (COLORREF*)realloc(DimBGColorList, DataAmount*sizeof(COLORREF)); - HexTextColorList = EditingText ? DimTextColorList : CurTextColorList; - HexBGColorList = EditingText ? DimBGColorList : CurBGColorList; - AnsiTextColorList = EditingText ? CurTextColorList : DimTextColorList; - AnsiBGColorList = EditingText ? CurBGColorList : DimBGColorList; - PreviousValues = (int*)realloc(PreviousValues,(DataAmount)*sizeof(int)); - HighlightedBytes = (unsigned int*)realloc(HighlightedBytes,(DataAmount)*sizeof(unsigned int)); - resetHighlightingActivityLog(); - } - //Set vertical scroll bar range and page size - SCROLLINFO si; - ZeroMemory(&si, sizeof(SCROLLINFO)); - si.cbSize = sizeof (si) ; - si.fMask = (SIF_RANGE|SIF_PAGE) ; - si.nMin = 0 ; - si.nMax = MaxSize/16 ; - si.nPage = ClientHeight/MemFontHeight; - SetScrollInfo (hwnd, SB_VERT, &si, TRUE); - UpdateColorTable(); - return 0 ; - - case WM_COMMAND: - - switch(wParam) - { - case MENU_MV_FILE_SAVE: - FlushUndoBuffer(); - iNesSave(); - UpdateColorTable(); - return 0; - - case MENU_MV_FILE_SAVE_AS: - SaveRomAs(); - return 0; - - case MENU_MV_FILE_LOAD_TBL: - { - int errLine = LoadTableFile(); - if (errLine != -1) { - char str[128]; - sprintf(str, "Error loading table file at Line %d", errLine); - MessageBox(hMemView, str, "Error", MB_OK | MB_ICONERROR); } - UpdateColorTable(); + // 6 = Create GG Code + + return 0; } - return 0; - case MENU_MV_FILE_UNLOAD_TBL: - UnloadTableFile(); + case WM_MBUTTONDOWN: + { + if (EditingMode != MODE_NES_MEMORY) + return 0; + int addr = GetAddyFromCoord(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + if (addr < 0) + return 0; + FreezeRam(addr, 0, 1); + return 0; + } + case WM_MOUSEWHEEL: + { + SCROLLINFO si; + int delta = (short)HIWORD(wParam); /// WHEEL_DELTA; + ZeroMemory(&si, sizeof(SCROLLINFO)); + si.fMask = SIF_ALL; + si.cbSize = sizeof(SCROLLINFO); + GetScrollInfo(hwnd, SB_VERT, &si); + if (delta < 0) + si.nPos += si.nPage; + if (delta > 0) + si.nPos -= si.nPage; + if (si.nPos < si.nMin) + si.nPos = si.nMin; + if ((si.nPos + (int)si.nPage) > si.nMax) + si.nPos = si.nMax - si.nPage; // added cast + CurOffset = si.nPos * 16; + if (CurOffset >= MaxSize - DataAmount) + CurOffset = MaxSize - DataAmount; + if (CurOffset < 0) + CurOffset = 0; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); UpdateColorTable(); return 0; - - case MENU_MV_FILE_DUMP_RAM: - { - char bar[0x800]; - unsigned int i; - for (i=0;i>10][(i)]; - else if(i < 0x3F00) bar[i] = vnapage[(i>>10)&0x3][i&0x3FF]; - else bar[i] = READPAL_MOTHEROFALL(i & 0x1F); + GetWindowRect(hwnd, &newMemViewRect); // Get new size + MemViewSizeX = newMemViewRect.right - newMemViewRect.left; // Store new size (this will be used to store in the .cfg file) + MemViewSizeY = newMemViewRect.bottom - newMemViewRect.top; } - dumpToFile(bar, sizeof(bar)); + ClientHeight = HIWORD(lParam); + if (DataAmount != ((ClientHeight / MemFontHeight) * 16)) + { + DataAmount = ((ClientHeight / MemFontHeight) * 16); + if (CurOffset >= MaxSize - DataAmount) + CurOffset = MaxSize - DataAmount; + if (CurOffset < 0) + CurOffset = 0; + // mbg merge 7/18/06 added casts: + CurTextColorList = (COLORREF *)realloc(CurTextColorList, DataAmount * sizeof(COLORREF)); + CurBGColorList = (COLORREF *)realloc(CurBGColorList, DataAmount * sizeof(COLORREF)); + DimTextColorList = (COLORREF *)realloc(DimTextColorList, DataAmount * sizeof(COLORREF)); + DimBGColorList = (COLORREF *)realloc(DimBGColorList, DataAmount * sizeof(COLORREF)); + HexTextColorList = EditingText ? DimTextColorList : CurTextColorList; + HexBGColorList = EditingText ? DimBGColorList : CurBGColorList; + AnsiTextColorList = EditingText ? CurTextColorList : DimTextColorList; + AnsiBGColorList = EditingText ? CurBGColorList : DimBGColorList; + PreviousValues = (int *)realloc(PreviousValues, (DataAmount) * sizeof(int)); + HighlightedBytes = (unsigned int *)realloc(HighlightedBytes, (DataAmount) * sizeof(unsigned int)); + resetHighlightingActivityLog(); + } + // Set vertical scroll bar range and page size + SCROLLINFO si; + ZeroMemory(&si, sizeof(SCROLLINFO)); + si.cbSize = sizeof(si); + si.fMask = (SIF_RANGE | SIF_PAGE); + si.nMin = 0; + si.nMax = MaxSize / 16; + si.nPage = ClientHeight / MemFontHeight; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + UpdateColorTable(); return 0; - } - case MENU_MV_FILE_DUMP_OAM: + + case WM_COMMAND: + + switch (wParam) + { + case MENU_MV_FILE_SAVE: + FlushUndoBuffer(); + iNesSave(); + UpdateColorTable(); + return 0; + + case MENU_MV_FILE_SAVE_AS: + SaveRomAs(); + return 0; + + case MENU_MV_FILE_LOAD_TBL: + { + int errLine = LoadTableFile(); + if (errLine != -1) + { + char str[128]; + sprintf(str, "Error loading table file at Line %d", errLine); + MessageBox(hMemView, str, "Error", MB_OK | MB_ICONERROR); + } + UpdateColorTable(); + } + return 0; + case MENU_MV_FILE_UNLOAD_TBL: + UnloadTableFile(); + UpdateColorTable(); + return 0; + + case MENU_MV_FILE_DUMP_RAM: + { + char bar[0x800]; + unsigned int i; + for (i = 0; i < sizeof(bar); i++) + bar[i] = GetMem(i); + + dumpToFile(bar, sizeof(bar)); + return 0; + } + case MENU_MV_FILE_DUMP_64K: + { + char *bar = new char[65536]; + unsigned int i; + for (i = 0; i < 65536; i++) + bar[i] = GetMem(i); + + dumpToFile(bar, 65536); + delete[] bar; + return 0; + } + case MENU_MV_FILE_DUMP_PPU: + { + char bar[0x4000]; + unsigned int i; + for (i = 0; i < sizeof(bar); i++) + { + i &= 0x3FFF; + if (i < 0x2000) + bar[i] = VPage[(i) >> 9][(i)]; + else if (i < 0x3F00) + bar[i] = vnapage[(i >> 10) & 0x3][i & 0x3FF]; + else + bar[i] = READPAL_MOTHEROFALL(i & 0x1F); + } + dumpToFile(bar, sizeof(bar)); + return 0; + } + case MENU_MV_FILE_DUMP_OAM: { char bar[0x100]; unsigned int i; - for (i=0;i<0x100;i++) bar[i] = SPRAM[i]; - dumpToFile(bar,0x100); + for (i = 0; i < 0x100; i++) + bar[i] = SPRAM[i]; + dumpToFile(bar, 0x100); return 0; } - case MENU_MV_FILE_LOAD_RAM: - { - char bar[0x800]; - if (loadFromFile(bar, sizeof(bar))) + case MENU_MV_FILE_LOAD_RAM: { - for (uint16 addr=0; addr>10][addr] = v; //todo: detect if this is vrom and turn it red if so - if((addr >= 0x2000) && (addr < 0x3F00)) - vnapage[(addr>>10)&0x3][addr&0x3FF] = v; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? - if((addr >= 0x3F00) && (addr < 0x3FFF)) - PalettePoke(addr,v); + for (uint16 addr = 0; addr < sizeof(bar); ++addr) + BWrite[addr](addr, bar[addr]); } + return 0; } - return 0; - } - case MENU_MV_FILE_LOAD_OAM: - { - char bar[0x100]; - if (loadFromFile(bar, sizeof(bar))) + case MENU_MV_FILE_LOAD_PPU: { - for (uint16 addr=0; addr> 9][addr] = v; // todo: detect if this is vrom and turn it red if so + if ((addr >= 0x2000) && (addr < 0x3F00)) + vnapage[(addr >> 10) & 0x3][addr & 0x3FF] = v; // todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? + if ((addr >= 0x3F00) && (addr < 0x3FFF)) + PalettePoke(addr, v); + } } + return 0; } - GlobalUnlock(hGlobal); - OpenClipboard(hwnd); - EmptyClipboard(); - SetClipboardData(CF_TEXT, hGlobal); - SetClipboardData(CF_LOCALE, hGlobal); - CloseClipboard(); - return 0; - } - case MENU_MV_EDIT_PASTE: - { - OpenClipboard(hwnd); - HANDLE hGlobal = GetClipboardData(CF_TEXT); - if(hGlobal == NULL){ + case MENU_MV_FILE_LOAD_OAM: + { + char bar[0x100]; + if (loadFromFile(bar, sizeof(bar))) + { + for (uint16 addr = 0; addr < sizeof(bar); ++addr) + SPRAM[addr] = bar[addr]; + } + return 0; + } + case ID_MEMWVIEW_FILE_CLOSE: + KillMemView(); + return 0; + + case MENU_MV_FILE_GOTO_ADDRESS: + GotoAddress(hwnd); + return 0; + + case MENU_MV_EDIT_UNDO: + UndoLastPatch(); + return 0; + + case MENU_MV_EDIT_COPY: + { + int size; + if (CursorEndAddy == -1) + size = 1; + else + size = CursorEndAddy - CursorStartAddy + 1; + + // i*2 is two characters per byte, plus terminating null + HGLOBAL hGlobal = GlobalAlloc(GHND, size * 2 + 1); + + char *pGlobal = (char *)GlobalLock(hGlobal); // mbg merge 7/18/06 added cast + char str[4]; + if (!EditingText) + { + for (int i = 0; i < size; i++) + { + str[0] = 0; + sprintf(str, "%02X", GetMemViewData((uint32)i + CursorStartAddy)); + strcat(pGlobal, str); + } + } + else + { + for (int i = 0; i < size; i++) + { + str[0] = 0; + sprintf(str, "%c", chartable[GetMemViewData((uint32)i + CursorStartAddy)]); + strcat(pGlobal, str); + } + } + GlobalUnlock(hGlobal); + OpenClipboard(hwnd); + EmptyClipboard(); + SetClipboardData(CF_TEXT, hGlobal); + SetClipboardData(CF_LOCALE, hGlobal); CloseClipboard(); return 0; } - char* pGlobal = (char*)GlobalLock (hGlobal) ; //mbg merge 7/18/06 added cast - //for(i = 0;pGlobal[i] != 0;i++){ - InputData(pGlobal); - //} - GlobalUnlock (hGlobal); - CloseClipboard(); - return 0; - } - case MENU_MV_EDIT_FIND: - OpenFindDialog(); - return 0; - - - case MENU_MV_VIEW_RAM: - case MENU_MV_VIEW_PPU: - case MENU_MV_VIEW_OAM: - case MENU_MV_VIEW_ROM: - { - int _EditingMode = wParam - MENU_MV_VIEW_RAM; - // Leave NES Memory - if (_EditingMode == MODE_NES_MEMORY && EditingMode != MODE_NES_MEMORY) - CreateCheatMap(); - // Enter NES Memory - if (_EditingMode != MODE_NES_MEMORY && EditingMode == MODE_NES_MEMORY) - ReleaseCheatMap(); - EditingMode = _EditingMode; - for (int i = MODE_NES_MEMORY; i <= MODE_NES_FILE; i++) - if(EditingMode == i) + case MENU_MV_EDIT_PASTE: + { + OpenClipboard(hwnd); + HANDLE hGlobal = GetClipboardData(CF_TEXT); + if (hGlobal == NULL) { - CheckMenuRadioItem(GetMenu(hMemView), MENU_MV_VIEW_RAM, MENU_MV_VIEW_ROM, MENU_MV_VIEW_RAM + i, MF_BYCOMMAND); - break; - } - - MaxSize = GetMaxSize(EditingMode); - - if (CurOffset >= MaxSize - DataAmount) CurOffset = MaxSize - DataAmount; - if (CurOffset < 0) CurOffset = 0; - if(CursorEndAddy >= MaxSize) CursorEndAddy = -1; - if(CursorStartAddy >= MaxSize) CursorStartAddy= MaxSize-1; - - //Set vertical scroll bar range and page size - ZeroMemory(&si, sizeof(SCROLLINFO)); - si.cbSize = sizeof (si) ; - si.fMask = (SIF_RANGE|SIF_PAGE) ; - si.nMin = 0 ; - si.nMax = MaxSize/16 ; - si.nPage = ClientHeight/MemFontHeight; - SetScrollInfo (hwnd, SB_VERT, &si, TRUE); - - resetHighlightingActivityLog(); - UpdateColorTable(); - UpdateCaption(); - return 0; - } - case ID_HIGHLIGHTING_HIGHLIGHT_ACTIVITY: - { - MemView_HighlightActivity ^= 1; - CheckMenuItem(GetMenu(hMemView), ID_HIGHLIGHTING_HIGHLIGHT_ACTIVITY, (MemView_HighlightActivity) ? MF_CHECKED: MF_UNCHECKED); - resetHighlightingActivityLog(); - if (!MemView_HighlightActivity) - UpdateMemoryView(1); - return 0; - } - case ID_HIGHLIGHTING_SETFADINGPERIOD: - { - int newValue = MemView_HighlightActivity_FadingPeriod - 1; - if (CWin32InputBox::GetInteger("Highlighting fading period", "Highlight changed bytes for how many frames?", newValue, hMemView) == IDOK) - { - if (newValue <= 0) - newValue = HIGHLIGHT_ACTIVITY_NUM_COLORS; - else - newValue++; - - if (MemView_HighlightActivity_FadingPeriod != newValue) - { - MemView_HighlightActivity_FadingPeriod = newValue; - resetHighlightingActivityLog(); + CloseClipboard(); + return 0; } + char *pGlobal = (char *)GlobalLock(hGlobal); // mbg merge 7/18/06 added cast + // for(i = 0;pGlobal[i] != 0;i++){ + InputData(pGlobal); + //} + GlobalUnlock(hGlobal); + CloseClipboard(); + return 0; } - return 0; - } - case ID_HIGHLIGHTING_FADEWHENPAUSED: - { - MemView_HighlightActivity_FadeWhenPaused ^= 1; - CheckMenuItem(GetMenu(hMemView), ID_HIGHLIGHTING_FADEWHENPAUSED, (MemView_HighlightActivity_FadeWhenPaused) ? MF_CHECKED: MF_UNCHECKED); - resetHighlightingActivityLog(); - return 0; - } - case ID_COLOR_HEXEDITOR: - case ID_COLOR_HEXEDITOR + 1: - case ID_COLOR_HEXEDITOR + 2: - case ID_COLOR_HEXEDITOR + 3: - case ID_COLOR_HEXEDITOR + 4: - case ID_COLOR_HEXEDITOR + 5: - case ID_COLOR_HEXEDITOR + 6: - case ID_COLOR_HEXEDITOR + 7: - case ID_COLOR_HEXEDITOR + 8: - case ID_COLOR_HEXEDITOR + 9: - { - int index = wParam - ID_COLOR_HEXEDITOR; - if (ChangeColor(hwnd, &hexcolormenu[index])) - { - UpdateColorTable(); - ModifyColorMenu(hwnd, GetHexColorMenu(hwnd), &hexcolormenu[index], index, wParam); - } - } - break; - case ID_HEXEDITOR_DEFCOLOR: - { - if (!IsHexColorDefault() && MessageBox(hwnd, "Do you want to restore all the colors to default?", "Restore default colors", MB_YESNO | MB_ICONINFORMATION) == IDYES) - { - RestoreDefaultHexColor(); - UpdateColorTable(); - for (int i = 0; i < sizeof(hexcolormenu) / sizeof(COLORMENU); ++i) - ModifyColorMenu(hwnd, GetHexColorMenu(hwnd), &hexcolormenu[i], i, ID_COLOR_HEXEDITOR + i); - } - } - break; - case ID_COLOR_CDLOGGER: - case ID_COLOR_CDLOGGER + 1: - case ID_COLOR_CDLOGGER + 2: - case ID_COLOR_CDLOGGER + 3: - case ID_COLOR_CDLOGGER + 4: - case ID_COLOR_CDLOGGER + 5: - case ID_COLOR_CDLOGGER + 6: - case ID_COLOR_CDLOGGER + 7: - case ID_COLOR_CDLOGGER + 8: - case ID_COLOR_CDLOGGER + 9: - { - int index = wParam - ID_COLOR_CDLOGGER; - if (ChangeColor(hwnd, &cdlcolormenu[index])) - { - UpdateColorTable(); - ModifyColorMenu(hwnd, GetCdlColorMenu(hwnd), &cdlcolormenu[index], index, wParam); - } - } - break; - case ID_CDLOGGER_DEFCOLOR: - if (!IsCdlColorDefault() && MessageBox(hwnd, "Do you want to restore all the colors to default?", "Restore default colors", MB_YESNO | MB_ICONINFORMATION) == IDYES) - { - RestoreDefaultCdlColor(); - UpdateColorTable(); - for (int i = 0; i < sizeof(hexcolormenu) / sizeof(COLORMENU); ++i) - ModifyColorMenu(hwnd, GetCdlColorMenu(hwnd), &cdlcolormenu[i], i, ID_COLOR_CDLOGGER + i); - } - break; - case MENU_MV_BOOKMARKS_RM_ALL: - if (hexBookmarks.bookmarkCount) - { - if (MessageBox(hwnd, "Remove All Bookmarks?", "Bookmarks", MB_YESNO | MB_ICONINFORMATION) == IDYES) - { - removeAllBookmarks(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS)); - UpdateColorTable(); - } - } - return 0; - case ID_BOOKMARKS_EXPORT: - { - char name[2048] = { 0 }; + case MENU_MV_EDIT_FIND: + OpenFindDialog(); + return 0; - OPENFILENAME ofn; - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hInstance = fceu_hInstance; - ofn.lpstrTitle = "Save bookmarks as..."; - ofn.lpstrFilter = "Hex Editor Bookmark list (*.hbm)\0*.hbm\0All Files (*.*)\0*.*\0\0"; - strcpy(name, mass_replace(GetRomName(), "|", ".").c_str()); - ofn.lpstrFile = name; - ofn.lpstrDefExt = "hbm"; - ofn.nMaxFile = 2048; - ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; - ofn.hwndOwner = hwnd; - - int success = false; - if (GetSaveFileName(&ofn)) + case MENU_MV_VIEW_RAM: + case MENU_MV_VIEW_PPU: + case MENU_MV_VIEW_OAM: + case MENU_MV_VIEW_ROM: { - FILE* bld = fopen(name, "wb"); - if (bld) - { - // write the header - fwrite("HexBookmarkList", strlen("HexBookmarkList"), 1, bld); - // it shares the same logic of creating the hexpreference part of .deb file - extern int storeHexPreferences(FILE*, HexBookmarkList& = hexBookmarks); - if (!storeHexPreferences(bld)) - success = true; - fclose(bld); - } - if (!success) - MessageBox(hwnd, "Error saving bookmarks.", "Error saving bookmarks", MB_OK | MB_ICONERROR); - } - return 0; - } - case ID_BOOKMARKS_IMPORT: - { - char nameo[2048] = { 0 }; - OPENFILENAME ofn; - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hInstance = fceu_hInstance; - ofn.lpstrTitle = "Load bookmarks..."; - ofn.lpstrFilter = "Hex Editor Bookmarks (*.hbm)\0*.hbm\0All Files (*.*)\0*.*\0\0"; - ofn.lpstrFile = nameo; - ofn.lpstrDefExt = "hbm"; - ofn.nMaxFile = 2048; - ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; - ofn.hwndOwner = hwnd; - - bool success = false; - if (GetOpenFileName(&ofn)) - { - char buffer[256] = { 0 }; - FILE* bld = fopen(nameo, "r"); - if (bld) - { - // Read the header to know it's hex bookmark list - fread(buffer, strlen("HexBookmarkList"), 1, bld); - if (!strcmp(buffer, "HexBookmarkList")) + int _EditingMode = wParam - MENU_MV_VIEW_RAM; + // Leave NES Memory + if (_EditingMode == MODE_NES_MEMORY && EditingMode != MODE_NES_MEMORY) + CreateCheatMap(); + // Enter NES Memory + if (_EditingMode != MODE_NES_MEMORY && EditingMode == MODE_NES_MEMORY) + ReleaseCheatMap(); + EditingMode = _EditingMode; + for (int i = MODE_NES_MEMORY; i <= MODE_NES_FILE; i++) + if (EditingMode == i) { - HexBookmarkList import; - // it shares the same logic of creating the hexpreference part of .deb file - extern int loadHexPreferences(FILE*, HexBookmarkList& = hexBookmarks); - if (!loadHexPreferences(bld, import) && import.bookmarkCount > 0) - { - if (importBookmarkProps & IMPORT_DISCARD_ORIGINAL) - { - discard_original: - if (importBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT || hexBookmarks.bookmarkCount == 0 || MessageBox(hwnd, "All your existing bookmarks will be discarded after importing the new bookmarks! Do you want to continue?", "Bookmark Import", MB_YESNO | MB_ICONWARNING) == IDYES) - { - removeAllBookmarks(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS)); - for (int i = 0; i < import.bookmarkCount; ++i) - { - hexBookmarks[i].address = import[i].address; - hexBookmarks[i].editmode = import[i].editmode; - strcpy(hexBookmarks[i].description, import[i].description); - memcpy(hexBookmarks.shortcuts, import.shortcuts, sizeof(hexBookmarks.shortcuts)); - hexBookmarks.bookmarkCount = import.bookmarkCount; - hexBookmarks.shortcutCount = import.shortcutCount; - } - updateBookmarkMenus(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS)); - UpdateColorTable(); - } - } - else - { - // conflict bookmark count - int conflictBookmarkCount = 0; - // the conflict bookmark indexes of the main list - int conflictBookmarkIndex[64]; - // conflict shortcut count - int conflictShortcutCount = 0; - // discarded bookmark count - int discardBookmarkCount = 0; - // bookmark that is out of scope - int outOfRangeBookmarkCount = 0; - - // store the count of bookmarks after importing finished - int finalBookmarkCount = hexBookmarks.bookmarkCount; - // the reference index number in main bookmark list - // -1 means this bookmark is not be indexed - int indexRef[64]; - memset(indexRef, -1, sizeof(indexRef)); - - for (int i = 0, j; i < import.bookmarkCount; ++i) - { - bool conflict = false; - for (j = 0; j < hexBookmarks.bookmarkCount; ++j) - { - // to find if there are any conflict bookmarks - // currently, one address can have only one bookmark - // if the address and editmode are the same, then they are considered conflict - if (import[i].address == hexBookmarks[j].address && import[j].editmode == hexBookmarks[j].editmode) - { - conflictBookmarkIndex[conflictBookmarkCount] = i; - indexRef[i] = j; - ++conflictBookmarkCount; - conflict = true; - break; - } - } - - // after a loop, this bookmark doesn't have conflict with the original one - if (!conflict) - if (finalBookmarkCount >= 64) - // the total bookmark count has reached the limit of bookmarks (64), - // discard it - ++discardBookmarkCount; - else if (import[j].address > (unsigned int)GetMaxSize(import[j].editmode)) - // the bookmark is out of valid range for current game, - // discard it. - ++outOfRangeBookmarkCount; - else - { - // if the bookmark is still not discarded, - // then it's not a conflict one, append it to the last of the main list - indexRef[i] = finalBookmarkCount; - hexBookmarks[finalBookmarkCount].address = import[i].address; - hexBookmarks[finalBookmarkCount].editmode = import[i].editmode; - strcpy(hexBookmarks[finalBookmarkCount].description, import[i].description); - ++finalBookmarkCount; - } - } - - // the result of overwriting the shortcuts - int shortcutListOverwrite[10]; - memcpy(shortcutListOverwrite, hexBookmarks.shortcuts, sizeof(hexBookmarks.shortcuts)); - int shortcutListOverwriteCount = hexBookmarks.shortcutCount; - // the result of keep the shortcut as original - int shortcutListKeep[10]; - memcpy(shortcutListKeep, hexBookmarks.shortcuts, sizeof(hexBookmarks.shortcuts)); - int shortcutListKeepCount = hexBookmarks.shortcutCount; - - for (int i = 0, j; i < 10; ++i) - if (import.shortcuts[i] != -1) - { - bool repeat = false; - for (j = 0; j < 10; ++j) - if (indexRef[import.shortcuts[i]] == hexBookmarks.shortcuts[j] && i != j) - { - // the slot in the original list had this bookmark but different - // slot, remove the bookmark in the original slot - shortcutListOverwrite[j] = -1; - --shortcutListOverwriteCount; - ++conflictShortcutCount; - repeat = true; - break; - } - - if (shortcutListOverwrite[i] == -1) - ++shortcutListOverwriteCount; - shortcutListOverwrite[i] = indexRef[import.shortcuts[i]]; - - // after a loop, the original list doesn't have a slot with same - // bookmark but different slot, and the slot in original list - // is empty, then the bookmark can occupy it. - if (!repeat && hexBookmarks.shortcuts[i] == -1) - { - shortcutListKeep[i] = indexRef[import.shortcuts[i]]; - ++shortcutListKeepCount; - } - } - - int tmpImportBookmarkProps = importBookmarkProps; - bool continue_ = true; - - // show the prompt message if there are conflicts - if (!(tmpImportBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT) && (conflictBookmarkCount || conflictShortcutCount)) - { - char units[32]; - strcpy(buffer, "The importing bookmark list has "); - sprintf(units, "%d duplicate bookmark", conflictBookmarkCount); - if (conflictBookmarkCount != 1) - strcat(units, "s"); - strcat(buffer, units); - - if (conflictShortcutCount) - { - if (conflictBookmarkCount) strcat(buffer, " and "); - sprintf(units, "%d conflict shortcut", conflictShortcutCount); - if (conflictShortcutCount != 1) - strcat(units, "s"); - strcat(buffer, units); - } - strcat(buffer, " with yours.\r\nYou must choose which side would be reserved. Do you want to continue?"); - - continue_ = MessageBox(hwnd, buffer, "Bookmark conflict", MB_YESNO | MB_ICONEXCLAMATION) == IDYES && DialogBoxParam(fceu_hInstance, "IMPORTBOOKMARKOPTIONDIALOG", hwnd, ImportBookmarkCallB, (LPARAM)&tmpImportBookmarkProps); - - if (tmpImportBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT) - importBookmarkProps = tmpImportBookmarkProps; - - // in case user's mind changes on the fly - if (tmpImportBookmarkProps & IMPORT_DISCARD_ORIGINAL) - goto discard_original; - - } - - if (continue_) - { - if (tmpImportBookmarkProps & IMPORT_OVERWRITE_BOOKMARK) - // when it is set to overwrite conflicted bookmark, otherwise do nothing - for (int i = 0; i < conflictBookmarkCount; ++i) - // the conflict bookmarks are all before the bookmark count in main list - strcpy(hexBookmarks[indexRef[conflictBookmarkIndex[i]]].description, import[conflictBookmarkIndex[i]].description); - - // update the bookmark shortcut mapping - if (tmpImportBookmarkProps & IMPORT_OVERWRITE_SHORTCUT) - { - memcpy(hexBookmarks.shortcuts, shortcutListOverwrite, sizeof(hexBookmarks.shortcuts)); - hexBookmarks.shortcutCount = shortcutListOverwriteCount; - } - else - { - memcpy(hexBookmarks.shortcuts, shortcutListKeep, sizeof(hexBookmarks.shortcuts)); - hexBookmarks.shortcutCount = shortcutListKeepCount; - } - - // set the count of the main list to the imported count - hexBookmarks.bookmarkCount = finalBookmarkCount; - - updateBookmarkMenus(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS)); - UpdateColorTable(); - } - - // tell user there are bookmarks that imported failed. - if (discardBookmarkCount || outOfRangeBookmarkCount) - { - char reason[64]; - sprintf(buffer, "Import complete, but %d bookmark%s %s not imported:\n", discardBookmarkCount + outOfRangeBookmarkCount, discardBookmarkCount + outOfRangeBookmarkCount == 1 ? "" : "s", discardBookmarkCount + outOfRangeBookmarkCount == 1 ? "is" : "are"); - if (outOfRangeBookmarkCount) - { - sprintf(reason, "%d %s outside the valid address range of the game.", outOfRangeBookmarkCount, outOfRangeBookmarkCount == 1 ? "is" : "are"); - strcat(buffer, reason); - } - - if (discardBookmarkCount) - { - if (outOfRangeBookmarkCount) - strcat(buffer, "\n"); - sprintf(reason, "%d %s discaded due to the list has reached its max limit (64).", discardBookmarkCount, discardBookmarkCount == 1 ? "is" : "are"); - strcat(buffer, reason); - } - MessageBox(hwnd, buffer, "Loading Hex Editor bookmarks", MB_OK | MB_ICONEXCLAMATION); - } - } - } - else - MessageBox(hwnd, "An error occurred while loading bookmarks.", "Error loading bookmarks", MB_OK | MB_ICONERROR); + CheckMenuRadioItem(GetMenu(hMemView), MENU_MV_VIEW_RAM, MENU_MV_VIEW_ROM, MENU_MV_VIEW_RAM + i, MF_BYCOMMAND); + break; } - else - MessageBox(hwnd, "This file is not a Hex Editor bookmark list.", "Error loading bookmarks", MB_OK | MB_ICONERROR); - fclose(bld); - } - else - MessageBox(hwnd, "Error opening bookmark file", "Error loading bookmarks", MB_OK | MB_ICONERROR); + + MaxSize = GetMaxSize(EditingMode); + + if (CurOffset >= MaxSize - DataAmount) + CurOffset = MaxSize - DataAmount; + if (CurOffset < 0) + CurOffset = 0; + if (CursorEndAddy >= MaxSize) + CursorEndAddy = -1; + if (CursorStartAddy >= MaxSize) + CursorStartAddy = MaxSize - 1; + + // Set vertical scroll bar range and page size + ZeroMemory(&si, sizeof(SCROLLINFO)); + si.cbSize = sizeof(si); + si.fMask = (SIF_RANGE | SIF_PAGE); + si.nMin = 0; + si.nMax = MaxSize / 16; + si.nPage = ClientHeight / MemFontHeight; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + + resetHighlightingActivityLog(); + UpdateColorTable(); + UpdateCaption(); + return 0; } - } - return 0; - case ID_BOOKMARKS_OPTION: - { - int tmpImportBookmarkProps = importBookmarkProps; - if (DialogBoxParam(fceu_hInstance, "IMPORTBOOKMARKOPTIONDIALOG", hwnd, ImportBookmarkCallB, (LPARAM)&tmpImportBookmarkProps)) - importBookmarkProps = tmpImportBookmarkProps; - } - return 0; - case MENU_MV_HELP: - OpenHelpWindow(memviewhelp); - return 0; - - default: - if (wParam >= ID_FIRST_BOOKMARK && wParam < (ID_FIRST_BOOKMARK + 64)) + case ID_HIGHLIGHTING_HIGHLIGHT_ACTIVITY: { - int bookmark = wParam - ID_FIRST_BOOKMARK; - int newValue = handleBookmarkMenu(bookmark); - - if (newValue != -1) + MemView_HighlightActivity ^= 1; + CheckMenuItem(GetMenu(hMemView), ID_HIGHLIGHTING_HIGHLIGHT_ACTIVITY, (MemView_HighlightActivity) ? MF_CHECKED : MF_UNCHECKED); + resetHighlightingActivityLog(); + if (!MemView_HighlightActivity) + UpdateMemoryView(1); + return 0; + } + case ID_HIGHLIGHTING_SETFADINGPERIOD: + { + int newValue = MemView_HighlightActivity_FadingPeriod - 1; + if (CWin32InputBox::GetInteger("Highlighting fading period", "Highlight changed bytes for how many frames?", newValue, hMemView) == IDOK) { - ChangeMemViewFocus(hexBookmarks[bookmark].editmode,newValue,-1); - UpdateColorTable(); + if (newValue <= 0) + newValue = HIGHLIGHT_ACTIVITY_NUM_COLORS; + else + newValue++; + + if (MemView_HighlightActivity_FadingPeriod != newValue) + { + MemView_HighlightActivity_FadingPeriod = newValue; + resetHighlightingActivityLog(); + } } return 0; } - } + case ID_HIGHLIGHTING_FADEWHENPAUSED: + { + MemView_HighlightActivity_FadeWhenPaused ^= 1; + CheckMenuItem(GetMenu(hMemView), ID_HIGHLIGHTING_FADEWHENPAUSED, (MemView_HighlightActivity_FadeWhenPaused) ? MF_CHECKED : MF_UNCHECKED); + resetHighlightingActivityLog(); + return 0; + } + case ID_COLOR_HEXEDITOR: + case ID_COLOR_HEXEDITOR + 1: + case ID_COLOR_HEXEDITOR + 2: + case ID_COLOR_HEXEDITOR + 3: + case ID_COLOR_HEXEDITOR + 4: + case ID_COLOR_HEXEDITOR + 5: + case ID_COLOR_HEXEDITOR + 6: + case ID_COLOR_HEXEDITOR + 7: + case ID_COLOR_HEXEDITOR + 8: + case ID_COLOR_HEXEDITOR + 9: + { + int index = wParam - ID_COLOR_HEXEDITOR; + if (ChangeColor(hwnd, &hexcolormenu[index])) + { + UpdateColorTable(); + ModifyColorMenu(hwnd, GetHexColorMenu(hwnd), &hexcolormenu[index], index, wParam); + } + } + break; + case ID_HEXEDITOR_DEFCOLOR: + { + if (!IsHexColorDefault() && MessageBox(hwnd, "Do you want to restore all the colors to default?", "Restore default colors", MB_YESNO | MB_ICONINFORMATION) == IDYES) + { + RestoreDefaultHexColor(); + UpdateColorTable(); + for (int i = 0; i < sizeof(hexcolormenu) / sizeof(COLORMENU); ++i) + ModifyColorMenu(hwnd, GetHexColorMenu(hwnd), &hexcolormenu[i], i, ID_COLOR_HEXEDITOR + i); + } + } + break; + case ID_COLOR_CDLOGGER: + case ID_COLOR_CDLOGGER + 1: + case ID_COLOR_CDLOGGER + 2: + case ID_COLOR_CDLOGGER + 3: + case ID_COLOR_CDLOGGER + 4: + case ID_COLOR_CDLOGGER + 5: + case ID_COLOR_CDLOGGER + 6: + case ID_COLOR_CDLOGGER + 7: + case ID_COLOR_CDLOGGER + 8: + case ID_COLOR_CDLOGGER + 9: + { + int index = wParam - ID_COLOR_CDLOGGER; + if (ChangeColor(hwnd, &cdlcolormenu[index])) + { + UpdateColorTable(); + ModifyColorMenu(hwnd, GetCdlColorMenu(hwnd), &cdlcolormenu[index], index, wParam); + } + } + break; + case ID_CDLOGGER_DEFCOLOR: + if (!IsCdlColorDefault() && MessageBox(hwnd, "Do you want to restore all the colors to default?", "Restore default colors", MB_YESNO | MB_ICONINFORMATION) == IDYES) + { + RestoreDefaultCdlColor(); + UpdateColorTable(); + for (int i = 0; i < sizeof(hexcolormenu) / sizeof(COLORMENU); ++i) + ModifyColorMenu(hwnd, GetCdlColorMenu(hwnd), &cdlcolormenu[i], i, ID_COLOR_CDLOGGER + i); + } + break; + case MENU_MV_BOOKMARKS_RM_ALL: + if (hexBookmarks.bookmarkCount) + { + if (MessageBox(hwnd, "Remove All Bookmarks?", "Bookmarks", MB_YESNO | MB_ICONINFORMATION) == IDYES) + { + removeAllBookmarks(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS)); + UpdateColorTable(); + } + } + return 0; + case ID_BOOKMARKS_EXPORT: + { + char name[2048] = {0}; - case WM_MOVE: { - if (!IsIconic(hwnd)) { - RECT wrect; - GetWindowRect(hwnd,&wrect); - MemView_wndx = wrect.left; - MemView_wndy = wrect.top; + OPENFILENAME ofn; + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hInstance = fceu_hInstance; + ofn.lpstrTitle = "Save bookmarks as..."; + ofn.lpstrFilter = "Hex Editor Bookmark list (*.hbm)\0*.hbm\0All Files (*.*)\0*.*\0\0"; + strcpy(name, mass_replace(GetRomName(), "|", ".").c_str()); + ofn.lpstrFile = name; + ofn.lpstrDefExt = "hbm"; + ofn.nMaxFile = 2048; + ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; + ofn.hwndOwner = hwnd; - #ifdef WIN32 - WindowBoundsCheckResize(MemView_wndx,MemView_wndy,MemViewSizeX,wrect.right); - #endif - } - return 0; - } + int success = false; + if (GetSaveFileName(&ofn)) + { + FILE *bld = fopen(name, "wb"); + if (bld) + { + // write the header + fwrite("HexBookmarkList", strlen("HexBookmarkList"), 1, bld); + // it shares the same logic of creating the hexpreference part of .deb file + extern int storeHexPreferences(FILE *, HexBookmarkList & = hexBookmarks); + if (!storeHexPreferences(bld)) + success = true; + fclose(bld); + } + if (!success) + MessageBox(hwnd, "Error saving bookmarks.", "Error saving bookmarks", MB_OK | MB_ICONERROR); + } + return 0; + } + case ID_BOOKMARKS_IMPORT: + { + char nameo[2048] = {0}; + OPENFILENAME ofn; + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hInstance = fceu_hInstance; + ofn.lpstrTitle = "Load bookmarks..."; + ofn.lpstrFilter = "Hex Editor Bookmarks (*.hbm)\0*.hbm\0All Files (*.*)\0*.*\0\0"; + ofn.lpstrFile = nameo; + ofn.lpstrDefExt = "hbm"; + ofn.nMaxFile = 2048; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + ofn.hwndOwner = hwnd; - case WM_CLOSE: - KillMemView(); - return 0; - } - return DefWindowProc (hwnd, message, wParam, lParam) ; -} + bool success = false; + if (GetOpenFileName(&ofn)) + { + char buffer[256] = {0}; + FILE *bld = fopen(nameo, "r"); + if (bld) + { + // Read the header to know it's hex bookmark list + fread(buffer, strlen("HexBookmarkList"), 1, bld); + if (!strcmp(buffer, "HexBookmarkList")) + { + HexBookmarkList import; + // it shares the same logic of creating the hexpreference part of .deb file + extern int loadHexPreferences(FILE *, HexBookmarkList & = hexBookmarks); + if (!loadHexPreferences(bld, import) && import.bookmarkCount > 0) + { + if (importBookmarkProps & IMPORT_DISCARD_ORIGINAL) + { + discard_original: + if (importBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT || hexBookmarks.bookmarkCount == 0 || MessageBox(hwnd, "All your existing bookmarks will be discarded after importing the new bookmarks! Do you want to continue?", "Bookmark Import", MB_YESNO | MB_ICONWARNING) == IDYES) + { + removeAllBookmarks(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS)); + for (int i = 0; i < import.bookmarkCount; ++i) + { + hexBookmarks[i].address = import[i].address; + hexBookmarks[i].editmode = import[i].editmode; + strcpy(hexBookmarks[i].description, import[i].description); + memcpy(hexBookmarks.shortcuts, import.shortcuts, sizeof(hexBookmarks.shortcuts)); + hexBookmarks.bookmarkCount = import.bookmarkCount; + hexBookmarks.shortcutCount = import.shortcutCount; + } + updateBookmarkMenus(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS)); + UpdateColorTable(); + } + } + else + { + // conflict bookmark count + int conflictBookmarkCount = 0; + // the conflict bookmark indexes of the main list + int conflictBookmarkIndex[64]; + // conflict shortcut count + int conflictShortcutCount = 0; + // discarded bookmark count + int discardBookmarkCount = 0; + // bookmark that is out of scope + int outOfRangeBookmarkCount = 0; + // store the count of bookmarks after importing finished + int finalBookmarkCount = hexBookmarks.bookmarkCount; + // the reference index number in main bookmark list + // -1 means this bookmark is not be indexed + int indexRef[64]; + memset(indexRef, -1, sizeof(indexRef)); + for (int i = 0, j; i < import.bookmarkCount; ++i) + { + bool conflict = false; + for (j = 0; j < hexBookmarks.bookmarkCount; ++j) + { + // to find if there are any conflict bookmarks + // currently, one address can have only one bookmark + // if the address and editmode are the same, then they are considered conflict + if (import[i].address == hexBookmarks[j].address && import[j].editmode == hexBookmarks[j].editmode) + { + conflictBookmarkIndex[conflictBookmarkCount] = i; + indexRef[i] = j; + ++conflictBookmarkCount; + conflict = true; + break; + } + } -void DoMemView() -{ - WNDCLASSEX wndclass ; - //static RECT al; + // after a loop, this bookmark doesn't have conflict with the original one + if (!conflict) + if (finalBookmarkCount >= 64) + // the total bookmark count has reached the limit of bookmarks (64), + // discard it + ++discardBookmarkCount; + else if (import[j].address > (unsigned int)GetMaxSize(import[j].editmode)) + // the bookmark is out of valid range for current game, + // discard it. + ++outOfRangeBookmarkCount; + else + { + // if the bookmark is still not discarded, + // then it's not a conflict one, append it to the last of the main list + indexRef[i] = finalBookmarkCount; + hexBookmarks[finalBookmarkCount].address = import[i].address; + hexBookmarks[finalBookmarkCount].editmode = import[i].editmode; + strcpy(hexBookmarks[finalBookmarkCount].description, import[i].description); + ++finalBookmarkCount; + } + } - if (!GameInfo) { - FCEUD_PrintError("You must have a game loaded before you can use the Hex Editor."); - return; - } - //if (GameInfo->type==GIT_NSF) { - // FCEUD_PrintError("Sorry, you can't yet use the Memory Viewer with NSFs."); - // return; - //} + // the result of overwriting the shortcuts + int shortcutListOverwrite[10]; + memcpy(shortcutListOverwrite, hexBookmarks.shortcuts, sizeof(hexBookmarks.shortcuts)); + int shortcutListOverwriteCount = hexBookmarks.shortcutCount; + // the result of keep the shortcut as original + int shortcutListKeep[10]; + memcpy(shortcutListKeep, hexBookmarks.shortcuts, sizeof(hexBookmarks.shortcuts)); + int shortcutListKeepCount = hexBookmarks.shortcutCount; - if (!hMemView) - { - memset(&wndclass,0,sizeof(wndclass)); - wndclass.cbSize=sizeof(WNDCLASSEX); - wndclass.style = CS_HREDRAW | CS_VREDRAW ; - wndclass.lpfnWndProc = MemViewCallB ; - wndclass.cbClsExtra = 0 ; - wndclass.cbWndExtra = 0 ; - wndclass.hInstance = fceu_hInstance; - wndclass.hIcon = LoadIcon(fceu_hInstance, "ICON_1"); - wndclass.hIconSm = LoadIcon(fceu_hInstance, "ICON_1"); - wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); - wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); - wndclass.lpszMenuName = "MEMVIEWMENU"; - wndclass.lpszClassName = "MEMVIEW"; + for (int i = 0, j; i < 10; ++i) + if (import.shortcuts[i] != -1) + { + bool repeat = false; + for (j = 0; j < 10; ++j) + if (indexRef[import.shortcuts[i]] == hexBookmarks.shortcuts[j] && i != j) + { + // the slot in the original list had this bookmark but different + // slot, remove the bookmark in the original slot + shortcutListOverwrite[j] = -1; + --shortcutListOverwriteCount; + ++conflictShortcutCount; + repeat = true; + break; + } - if(!RegisterClassEx(&wndclass)) + if (shortcutListOverwrite[i] == -1) + ++shortcutListOverwriteCount; + shortcutListOverwrite[i] = indexRef[import.shortcuts[i]]; + + // after a loop, the original list doesn't have a slot with same + // bookmark but different slot, and the slot in original list + // is empty, then the bookmark can occupy it. + if (!repeat && hexBookmarks.shortcuts[i] == -1) + { + shortcutListKeep[i] = indexRef[import.shortcuts[i]]; + ++shortcutListKeepCount; + } + } + + int tmpImportBookmarkProps = importBookmarkProps; + bool continue_ = true; + + // show the prompt message if there are conflicts + if (!(tmpImportBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT) && (conflictBookmarkCount || conflictShortcutCount)) + { + char units[32]; + strcpy(buffer, "The importing bookmark list has "); + sprintf(units, "%d duplicate bookmark", conflictBookmarkCount); + if (conflictBookmarkCount != 1) + strcat(units, "s"); + strcat(buffer, units); + + if (conflictShortcutCount) + { + if (conflictBookmarkCount) + strcat(buffer, " and "); + sprintf(units, "%d conflict shortcut", conflictShortcutCount); + if (conflictShortcutCount != 1) + strcat(units, "s"); + strcat(buffer, units); + } + strcat(buffer, " with yours.\r\nYou must choose which side would be reserved. Do you want to continue?"); + + continue_ = MessageBox(hwnd, buffer, "Bookmark conflict", MB_YESNO | MB_ICONEXCLAMATION) == IDYES && DialogBoxParam(fceu_hInstance, "IMPORTBOOKMARKOPTIONDIALOG", hwnd, ImportBookmarkCallB, (LPARAM)&tmpImportBookmarkProps); + + if (tmpImportBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT) + importBookmarkProps = tmpImportBookmarkProps; + + // in case user's mind changes on the fly + if (tmpImportBookmarkProps & IMPORT_DISCARD_ORIGINAL) + goto discard_original; + } + + if (continue_) + { + if (tmpImportBookmarkProps & IMPORT_OVERWRITE_BOOKMARK) + // when it is set to overwrite conflicted bookmark, otherwise do nothing + for (int i = 0; i < conflictBookmarkCount; ++i) + // the conflict bookmarks are all before the bookmark count in main list + strcpy(hexBookmarks[indexRef[conflictBookmarkIndex[i]]].description, import[conflictBookmarkIndex[i]].description); + + // update the bookmark shortcut mapping + if (tmpImportBookmarkProps & IMPORT_OVERWRITE_SHORTCUT) + { + memcpy(hexBookmarks.shortcuts, shortcutListOverwrite, sizeof(hexBookmarks.shortcuts)); + hexBookmarks.shortcutCount = shortcutListOverwriteCount; + } + else + { + memcpy(hexBookmarks.shortcuts, shortcutListKeep, sizeof(hexBookmarks.shortcuts)); + hexBookmarks.shortcutCount = shortcutListKeepCount; + } + + // set the count of the main list to the imported count + hexBookmarks.bookmarkCount = finalBookmarkCount; + + updateBookmarkMenus(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS)); + UpdateColorTable(); + } + + // tell user there are bookmarks that imported failed. + if (discardBookmarkCount || outOfRangeBookmarkCount) + { + char reason[64]; + sprintf(buffer, "Import complete, but %d bookmark%s %s not imported:\n", discardBookmarkCount + outOfRangeBookmarkCount, discardBookmarkCount + outOfRangeBookmarkCount == 1 ? "" : "s", discardBookmarkCount + outOfRangeBookmarkCount == 1 ? "is" : "are"); + if (outOfRangeBookmarkCount) + { + sprintf(reason, "%d %s outside the valid address range of the game.", outOfRangeBookmarkCount, outOfRangeBookmarkCount == 1 ? "is" : "are"); + strcat(buffer, reason); + } + + if (discardBookmarkCount) + { + if (outOfRangeBookmarkCount) + strcat(buffer, "\n"); + sprintf(reason, "%d %s discaded due to the list has reached its max limit (64).", discardBookmarkCount, discardBookmarkCount == 1 ? "is" : "are"); + strcat(buffer, reason); + } + MessageBox(hwnd, buffer, "Loading Hex Editor bookmarks", MB_OK | MB_ICONEXCLAMATION); + } + } + } + else + MessageBox(hwnd, "An error occurred while loading bookmarks.", "Error loading bookmarks", MB_OK | MB_ICONERROR); + } + else + MessageBox(hwnd, "This file is not a Hex Editor bookmark list.", "Error loading bookmarks", MB_OK | MB_ICONERROR); + fclose(bld); + } + else + MessageBox(hwnd, "Error opening bookmark file", "Error loading bookmarks", MB_OK | MB_ICONERROR); + } + } + return 0; + case ID_BOOKMARKS_OPTION: + { + int tmpImportBookmarkProps = importBookmarkProps; + if (DialogBoxParam(fceu_hInstance, "IMPORTBOOKMARKOPTIONDIALOG", hwnd, ImportBookmarkCallB, (LPARAM)&tmpImportBookmarkProps)) + importBookmarkProps = tmpImportBookmarkProps; + } + return 0; + case MENU_MV_HELP: + OpenHelpWindow(memviewhelp); + return 0; + + default: + if (wParam >= ID_FIRST_BOOKMARK && wParam < (ID_FIRST_BOOKMARK + 64)) + { + int bookmark = wParam - ID_FIRST_BOOKMARK; + int newValue = handleBookmarkMenu(bookmark); + + if (newValue != -1) + { + ChangeMemViewFocus(hexBookmarks[bookmark].editmode, newValue, -1); + UpdateColorTable(); + } + return 0; + } + } + + case WM_MOVE: { - FCEUD_PrintError("Error Registering MEMVIEW Window Class."); + if (!IsIconic(hwnd)) + { + RECT wrect; + GetWindowRect(hwnd, &wrect); + MemView_wndx = wrect.left; + MemView_wndy = wrect.top; + +#ifdef WIN32 + WindowBoundsCheckResize(MemView_wndx, MemView_wndy, MemViewSizeX, wrect.right); +#endif + } + return 0; + } + + case WM_CLOSE: + KillMemView(); + return 0; + } + return DefWindowProc(hwnd, message, wParam, lParam); + } + + void DoMemView() + { + WNDCLASSEX wndclass; + // static RECT al; + + if (!GameInfo) + { + FCEUD_PrintError("You must have a game loaded before you can use the Hex Editor."); return; } + // if (GameInfo->type==GIT_NSF) { + // FCEUD_PrintError("Sorry, you can't yet use the Memory Viewer with NSFs."); + // return; + // } - hMemView = CreateWindowEx(0,"MEMVIEW","Memory Editor", - //WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS, /* Style */ - WS_SYSMENU|WS_MAXIMIZEBOX|WS_MINIMIZEBOX|WS_THICKFRAME|WS_VSCROLL, - CW_USEDEFAULT,CW_USEDEFAULT,580,248, /* X,Y ; Width, Height */ - NULL,NULL,fceu_hInstance,NULL ); - ShowWindow (hMemView, SW_SHOW) ; - UpdateCaption(); - } else - { - //SetWindowPos(hMemView, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER); - ShowWindow(hMemView, SW_SHOWNORMAL); - SetForegroundWindow(hMemView); - UpdateCaption(); + if (!hMemView) + { + memset(&wndclass, 0, sizeof(wndclass)); + wndclass.cbSize = sizeof(WNDCLASSEX); + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = MemViewCallB; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = fceu_hInstance; + wndclass.hIcon = LoadIcon(fceu_hInstance, "ICON_1"); + wndclass.hIconSm = LoadIcon(fceu_hInstance, "ICON_1"); + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + wndclass.lpszMenuName = "MEMVIEWMENU"; + wndclass.lpszClassName = "MEMVIEW"; + + if (!RegisterClassEx(&wndclass)) + { + FCEUD_PrintError("Error Registering MEMVIEW Window Class."); + return; + } + + hMemView = CreateWindowEx(0, "MEMVIEW", "Memory Editor", + // WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS, /* Style */ + WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME | WS_VSCROLL, + CW_USEDEFAULT, CW_USEDEFAULT, 580, 248, /* X,Y ; Width, Height */ + NULL, NULL, fceu_hInstance, NULL); + ShowWindow(hMemView, SW_SHOW); + UpdateCaption(); + } + else + { + // SetWindowPos(hMemView, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER); + ShowWindow(hMemView, SW_SHOWNORMAL); + SetForegroundWindow(hMemView); + UpdateCaption(); + } + + DragAcceptFiles(hMemView, 1); + + if (hMemView) + { + // UpdateMemView(0); + // MemViewDoBlit(); + } } - DragAcceptFiles(hMemView, 1); - - if (hMemView) + INT_PTR CALLBACK MemFindCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - //UpdateMemView(0); - //MemViewDoBlit(); - } -} -INT_PTR CALLBACK MemFindCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - - switch(uMsg) - { + switch (uMsg) + { case WM_INITDIALOG: - SetWindowPos(hwndDlg,0,MemFind_wndx,MemFind_wndy,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER); + SetWindowPos(hwndDlg, 0, MemFind_wndx, MemFind_wndy, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER); - if(FindDirectionUp) CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_DIR_UP, BST_CHECKED); - else CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_DIR_DOWN, BST_CHECKED); + if (FindDirectionUp) + CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_DIR_UP, BST_CHECKED); + else + CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_DIR_DOWN, BST_CHECKED); - if(FindAsText) CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_TYPE_TEXT, BST_CHECKED); - else CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_TYPE_HEX, BST_CHECKED); + if (FindAsText) + CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_TYPE_TEXT, BST_CHECKED); + else + CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_TYPE_HEX, BST_CHECKED); - if(FindTextBox[0])SetDlgItemText(hwndDlg,IDC_MEMVIEWFIND_WHAT,FindTextBox); + if (FindTextBox[0]) + SetDlgItemText(hwndDlg, IDC_MEMVIEWFIND_WHAT, FindTextBox); - SendDlgItemMessage(hwndDlg,IDC_MEMVIEWFIND_WHAT,EM_SETLIMITTEXT,59,0); + SendDlgItemMessage(hwndDlg, IDC_MEMVIEWFIND_WHAT, EM_SETLIMITTEXT, 59, 0); break; case WM_CREATE: @@ -2879,23 +3038,25 @@ INT_PTR CALLBACK MemFindCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa break; case WM_CLOSE: case WM_QUIT: - GetDlgItemText(hwndDlg,IDC_MEMVIEWFIND_WHAT,FindTextBox,60); + GetDlgItemText(hwndDlg, IDC_MEMVIEWFIND_WHAT, FindTextBox, 60); DestroyWindow(hwndDlg); hMemFind = 0; hwndDlg = 0; break; case WM_MOVING: break; - case WM_MOVE: { - if (!IsIconic(hwndDlg)) { + case WM_MOVE: + { + if (!IsIconic(hwndDlg)) + { RECT wrect; - GetWindowRect(hwndDlg,&wrect); + GetWindowRect(hwndDlg, &wrect); MemFind_wndx = wrect.left; MemFind_wndy = wrect.top; - - #ifdef WIN32 - WindowBoundsCheckNoResize(MemFind_wndx,MemFind_wndy,wrect.right); - #endif + +#ifdef WIN32 + WindowBoundsCheckNoResize(MemFind_wndx, MemFind_wndy, wrect.right); +#endif } break; } @@ -2906,173 +3067,212 @@ INT_PTR CALLBACK MemFindCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa break; case WM_COMMAND: - switch(HIWORD(wParam)) { - case BN_CLICKED: - switch(LOWORD(wParam)) - { - case IDC_MEMVIEWFIND_TYPE_HEX : - FindAsText=0; - break; - case IDC_MEMVIEWFIND_TYPE_TEXT : - FindAsText=1; - break; + switch (HIWORD(wParam)) + { + case BN_CLICKED: + switch (LOWORD(wParam)) + { + case IDC_MEMVIEWFIND_TYPE_HEX: + FindAsText = 0; + break; + case IDC_MEMVIEWFIND_TYPE_TEXT: + FindAsText = 1; + break; - case IDC_MEMVIEWFIND_DIR_UP : - FindDirectionUp = 1; - break; - case IDC_MEMVIEWFIND_DIR_DOWN : - FindDirectionUp = 0; - break; - case IDC_MEMVIEWFIND_NEXT : - FindNext(); - break; - } + case IDC_MEMVIEWFIND_DIR_UP: + FindDirectionUp = 1; + break; + case IDC_MEMVIEWFIND_DIR_DOWN: + FindDirectionUp = 0; + break; + case IDC_MEMVIEWFIND_NEXT: + FindNext(); + break; + } break; - } - break; + } + break; case WM_HSCROLL: break; + } + return FALSE; } - return FALSE; -} -void FindNext(){ - char str[60]; - unsigned char data[60]; - int datasize = 0, i, j, inputc = -1, found; + void FindNext() + { + char str[60]; + unsigned char data[60]; + int datasize = 0, i, j, inputc = -1, found; - if(hMemFind) GetDlgItemText(hMemFind,IDC_MEMVIEWFIND_WHAT,str,60); - else strcpy(str,FindTextBox); + if (hMemFind) + GetDlgItemText(hMemFind, IDC_MEMVIEWFIND_WHAT, str, 60); + else + strcpy(str, FindTextBox); - for(i = 0;str[i] != 0;i++){ - if(!FindAsText){ - if(inputc == -1){ - if((str[i] >= 'a') && (str[i] <= 'f')) inputc = str[i]-('a'-0xA); - if((str[i] >= 'A') && (str[i] <= 'F')) inputc = str[i]-('A'-0xA); - if((str[i] >= '0') && (str[i] <= '9')) inputc = str[i]-'0'; - } else { - if((str[i] >= 'a') && (str[i] <= 'f')) inputc = (inputc<<4)|(str[i]-('a'-0xA)); - if((str[i] >= 'A') && (str[i] <= 'F')) inputc = (inputc<<4)|(str[i]-('A'-0xA)); - if((str[i] >= '0') && (str[i] <= '9')) inputc = (inputc<<4)|(str[i]-'0'); + for (i = 0; str[i] != 0; i++) + { + if (!FindAsText) + { + if (inputc == -1) + { + if ((str[i] >= 'a') && (str[i] <= 'f')) + inputc = str[i] - ('a' - 0xA); + if ((str[i] >= 'A') && (str[i] <= 'F')) + inputc = str[i] - ('A' - 0xA); + if ((str[i] >= '0') && (str[i] <= '9')) + inputc = str[i] - '0'; + } + else + { + if ((str[i] >= 'a') && (str[i] <= 'f')) + inputc = (inputc << 4) | (str[i] - ('a' - 0xA)); + if ((str[i] >= 'A') && (str[i] <= 'F')) + inputc = (inputc << 4) | (str[i] - ('A' - 0xA)); + if ((str[i] >= '0') && (str[i] <= '9')) + inputc = (inputc << 4) | (str[i] - '0'); - if(((str[i] >= 'a') && (str[i] <= 'f')) || - ((str[i] >= 'A') && (str[i] <= 'F')) || - ((str[i] >= '0') && (str[i] <= '9'))){ + if (((str[i] >= 'a') && (str[i] <= 'f')) || + ((str[i] >= 'A') && (str[i] <= 'F')) || + ((str[i] >= '0') && (str[i] <= '9'))) + { data[datasize++] = inputc; inputc = -1; + } } } - } else { - for(j = 0;j < 256;j++)if(chartable[j] == str[i])break; - if(j == 256)continue; - data[datasize++] = j; - } - } - - if(datasize < 1){ - MessageBox(hMemView,"Invalid String","Error", MB_OK); - return; - } - if(!FindDirectionUp){ - for(i = CursorStartAddy+1;i+datasize <= MaxSize;i++){ - found = 1; - for(j = 0;j < datasize;j++){ - if(GetMemViewData(i+j) != data[j])found = 0; - } - if(found == 1){ - ChangeMemViewFocus(EditingMode,i, i+datasize-1); - return; + else + { + for (j = 0; j < 256; j++) + if (chartable[j] == str[i]) + break; + if (j == 256) + continue; + data[datasize++] = j; } } - for(i = 0;i < CursorStartAddy;i++){ - found = 1; - for(j = 0;j < datasize;j++){ - if(GetMemViewData(i+j) != data[j])found = 0; - } - if(found == 1){ - ChangeMemViewFocus(EditingMode,i, i+datasize-1); - return; - } - } - } else { //FindDirection is up - for(i = CursorStartAddy-1;i >= 0;i--){ - found = 1; - for(j = 0;j < datasize;j++){ - if(GetMemViewData(i+j) != data[j])found = 0; - } - if(found == 1){ - ChangeMemViewFocus(EditingMode,i, i+datasize-1); - return; - } - } - for(i = MaxSize-datasize;i > CursorStartAddy;i--){ - found = 1; - for(j = 0;j < datasize;j++){ - if(GetMemViewData(i+j) != data[j])found = 0; - } - if(found == 1){ - ChangeMemViewFocus(EditingMode,i, i+datasize-1); - return; - } - } - } - - MessageBox(hMemView,"String Not Found","Error", MB_OK); - return; -} - - -void OpenFindDialog() -{ - if (!hMemView) - return; - if (hMemFind) - // set focus to the text field - SendMessage(hMemFind, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hMemFind, IDC_MEMVIEWFIND_WHAT), true); - else - hMemFind = CreateDialog(fceu_hInstance,"MEMVIEWFIND",hMemView,MemFindCallB); - return; -} - -void PalettePoke(uint32 addr, uint8 data) -{ - data = data & 0x3F; - addr = addr & 0x1F; - if ((addr & 3) == 0) - { - addr = (addr & 0xC) >> 2; - if (addr == 0) + if (datasize < 1) { - PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = data; + MessageBox(hMemView, "Invalid String", "Error", MB_OK); + return; + } + if (!FindDirectionUp) + { + for (i = CursorStartAddy + 1; i + datasize <= MaxSize; i++) + { + found = 1; + for (j = 0; j < datasize; j++) + { + if (GetMemViewData(i + j) != data[j]) + found = 0; + } + if (found == 1) + { + ChangeMemViewFocus(EditingMode, i, i + datasize - 1); + return; + } + } + for (i = 0; i < CursorStartAddy; i++) + { + found = 1; + for (j = 0; j < datasize; j++) + { + if (GetMemViewData(i + j) != data[j]) + found = 0; + } + if (found == 1) + { + ChangeMemViewFocus(EditingMode, i, i + datasize - 1); + return; + } + } + } + else + { // FindDirection is up + for (i = CursorStartAddy - 1; i >= 0; i--) + { + found = 1; + for (j = 0; j < datasize; j++) + { + if (GetMemViewData(i + j) != data[j]) + found = 0; + } + if (found == 1) + { + ChangeMemViewFocus(EditingMode, i, i + datasize - 1); + return; + } + } + for (i = MaxSize - datasize; i > CursorStartAddy; i--) + { + found = 1; + for (j = 0; j < datasize; j++) + { + if (GetMemViewData(i + j) != data[j]) + found = 0; + } + if (found == 1) + { + ChangeMemViewFocus(EditingMode, i, i + datasize - 1); + return; + } + } + } + + MessageBox(hMemView, "String Not Found", "Error", MB_OK); + return; + } + + void OpenFindDialog() + { + if (!hMemView) + return; + if (hMemFind) + // set focus to the text field + SendMessage(hMemFind, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hMemFind, IDC_MEMVIEWFIND_WHAT), true); + else + hMemFind = CreateDialog(fceu_hInstance, "MEMVIEWFIND", hMemView, MemFindCallB); + return; + } + + void PalettePoke(uint32 addr, uint8 data) + { + data = data & 0x3F; + addr = addr & 0x1F; + if ((addr & 3) == 0) + { + addr = (addr & 0xC) >> 2; + if (addr == 0) + { + PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = data; + } + else + { + UPALRAM[addr - 1] = data; + } } else { - UPALRAM[addr-1] = data; + PALRAM[addr] = data; } } - else + + INT_PTR CALLBACK ImportBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - PALRAM[addr] = data; - } -} + static int *tmpImportBookmarkProps; -INT_PTR CALLBACK ImportBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - static int* tmpImportBookmarkProps; + static HWND hTipMerge; + static HWND hTipIgnore; + static HWND hTipOverwrite; + static HWND hTipKeep; + static HWND hTipReassign; + static HWND hTipDiscard; + static HWND hTipConfirm; - static HWND hTipMerge; - static HWND hTipIgnore; - static HWND hTipOverwrite; - static HWND hTipKeep; - static HWND hTipReassign; - static HWND hTipDiscard; - static HWND hTipConfirm; - - switch (uMsg) - { + switch (uMsg) + { case WM_INITDIALOG: CenterWindow(hwndDlg); - tmpImportBookmarkProps = (int*)lParam; + tmpImportBookmarkProps = (int *)lParam; if (!(*tmpImportBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT)) CheckDlgButton(hwndDlg, IDC_CHECK_BOOKMARKIMPORTOPTION_CONFIRMEVERYTIMEONCONFLICT, BST_CHECKED); @@ -3182,142 +3382,142 @@ INT_PTR CALLBACK ImportBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPA case WM_COMMAND: switch (HIWORD(wParam)) { - case BN_CLICKED: - switch (LOWORD(wParam)) - { - case IDC_RADIO_BOOKMARKIMPORTOPTION_DISCARD: - EnableWindow(GetDlgItem(hwndDlg, IDC_GROUP_BOOKMARKIMPORTOPTION_SOLVECONFLICT), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_BOOKMARK), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_SHORTCUT), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN), FALSE); - break; - case IDC_RADIO_BOOKMARKIMPORTOPTION_MERGE: - EnableWindow(GetDlgItem(hwndDlg, IDC_GROUP_BOOKMARKIMPORTOPTION_SOLVECONFLICT), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_BOOKMARK), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_SHORTCUT), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN), TRUE); - break; - case IDOK: - if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_BOOKMARKIMPORTOPTION_CONFIRMEVERYTIMEONCONFLICT) == BST_UNCHECKED) - *tmpImportBookmarkProps |= IMPORT_OVERWRITE_NO_PROMPT; - else - *tmpImportBookmarkProps &= ~IMPORT_OVERWRITE_NO_PROMPT; + case BN_CLICKED: + switch (LOWORD(wParam)) + { + case IDC_RADIO_BOOKMARKIMPORTOPTION_DISCARD: + EnableWindow(GetDlgItem(hwndDlg, IDC_GROUP_BOOKMARKIMPORTOPTION_SOLVECONFLICT), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_BOOKMARK), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_SHORTCUT), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN), FALSE); + break; + case IDC_RADIO_BOOKMARKIMPORTOPTION_MERGE: + EnableWindow(GetDlgItem(hwndDlg, IDC_GROUP_BOOKMARKIMPORTOPTION_SOLVECONFLICT), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_BOOKMARK), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_SHORTCUT), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN), TRUE); + break; + case IDOK: + if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_BOOKMARKIMPORTOPTION_CONFIRMEVERYTIMEONCONFLICT) == BST_UNCHECKED) + *tmpImportBookmarkProps |= IMPORT_OVERWRITE_NO_PROMPT; + else + *tmpImportBookmarkProps &= ~IMPORT_OVERWRITE_NO_PROMPT; - if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_DISCARD)) - *tmpImportBookmarkProps |= IMPORT_DISCARD_ORIGINAL; - if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_MERGE)) - *tmpImportBookmarkProps &= ~IMPORT_DISCARD_ORIGINAL; + if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_DISCARD)) + *tmpImportBookmarkProps |= IMPORT_DISCARD_ORIGINAL; + if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_MERGE)) + *tmpImportBookmarkProps &= ~IMPORT_DISCARD_ORIGINAL; - if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE)) - *tmpImportBookmarkProps |= IMPORT_OVERWRITE_BOOKMARK; - if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE)) - *tmpImportBookmarkProps &= ~IMPORT_OVERWRITE_BOOKMARK; + if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE)) + *tmpImportBookmarkProps |= IMPORT_OVERWRITE_BOOKMARK; + if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE)) + *tmpImportBookmarkProps &= ~IMPORT_OVERWRITE_BOOKMARK; - if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN)) - *tmpImportBookmarkProps |= IMPORT_OVERWRITE_SHORTCUT; - if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP)) - *tmpImportBookmarkProps &= ~IMPORT_OVERWRITE_SHORTCUT; - EndDialog(hwndDlg, 1); - break; - case IDCANCEL: - case IDCLOSE: - EndDialog(hwndDlg, 0); - break; - } + if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN)) + *tmpImportBookmarkProps |= IMPORT_OVERWRITE_SHORTCUT; + if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP)) + *tmpImportBookmarkProps &= ~IMPORT_OVERWRITE_SHORTCUT; + EndDialog(hwndDlg, 1); + break; + case IDCANCEL: + case IDCLOSE: + EndDialog(hwndDlg, 0); + break; + } } + } + return FALSE; } - return FALSE; -} -void SwitchEditingText(int editingText) { - if (EditingText != editingText) + void SwitchEditingText(int editingText) { - if (editingText) { - HexTextColorList = DimTextColorList; - HexBGColorList = DimBGColorList; - AnsiTextColorList = CurTextColorList; - AnsiBGColorList = CurBGColorList; + if (EditingText != editingText) + { + if (editingText) + { + HexTextColorList = DimTextColorList; + HexBGColorList = DimBGColorList; + AnsiTextColorList = CurTextColorList; + AnsiBGColorList = CurBGColorList; + } + else + { + HexTextColorList = CurTextColorList; + HexBGColorList = CurBGColorList; + AnsiTextColorList = DimTextColorList; + AnsiBGColorList = DimBGColorList; + } + EditingText = editingText; + } + } + + bool ChangeColor(HWND hwnd, COLORMENU * item) + { + int backup = RGB(*item->r, *item->g, *item->b); + CHOOSECOLOR choose; + memset(&choose, 0, sizeof(CHOOSECOLOR)); + choose.lStructSize = sizeof(CHOOSECOLOR); + choose.hwndOwner = hwnd; + choose.rgbResult = backup; + choose.lpCustColors = custom_color; + choose.Flags = CC_RGBINIT | CC_FULLOPEN | CC_ANYCOLOR; + if (ChooseColor(&choose) && choose.rgbResult != backup) + { + *item->r = GetRValue(choose.rgbResult); + *item->g = GetGValue(choose.rgbResult); + *item->b = GetBValue(choose.rgbResult); + return true; + } + return false; + } + + BOOL OpColorMenu(HWND hwnd, HMENU menu, COLORMENU * item, int pos, int id, BOOL(WINAPI * opMenu)(HMENU hmenu, UINT item, BOOL byPos, LPCMENUITEMINFO info)) + { + + MENUITEMINFO info; + memset(&info, 0, sizeof(MENUITEMINFO)); + info.cbSize = sizeof(MENUITEMINFO); + + if (item->text) + { + HDC hdc = GetDC(hwnd); + HDC memdc = CreateCompatibleDC(hdc); + + int width = GetSystemMetrics(SM_CXMENUCHECK); + int height = GetSystemMetrics(SM_CYMENUCHECK); + + if (!item->bitmap) + item->bitmap = CreateCompatibleBitmap(hdc, width, height); + SelectObject(memdc, item->bitmap); + HBRUSH brush = CreateSolidBrush(RGB(*item->r, *item->g, *item->b)); + RECT rect = {1, 1, width - 1, height - 1}; + FillRect(memdc, &rect, brush); + DeleteObject(brush); + DeleteDC(memdc); + ReleaseDC(hwnd, hdc); + + char menu_str[64]; + sprintf(menu_str, "%s\t#%02X%02X%02X", item->text, *item->r, *item->g, *item->b); + + info.dwTypeData = menu_str; + info.cch = strlen(menu_str); + info.hbmpUnchecked = item->bitmap; + info.wID = id; + + info.fMask = MIIM_ID | MIIM_TYPE | MIIM_CHECKMARKS; + info.fType = MFT_STRING; } else { - HexTextColorList = CurTextColorList; - HexBGColorList = CurBGColorList; - AnsiTextColorList = DimTextColorList; - AnsiBGColorList = DimBGColorList; + info.fMask = MIIM_TYPE; + info.fType = MFT_SEPARATOR; } - EditingText = editingText; - } -} -bool ChangeColor(HWND hwnd, COLORMENU* item) -{ - int backup = RGB(*item->r, *item->g, *item->b); - CHOOSECOLOR choose; - memset(&choose, 0, sizeof(CHOOSECOLOR)); - choose.lStructSize = sizeof(CHOOSECOLOR); - choose.hwndOwner = hwnd; - choose.rgbResult = backup; - choose.lpCustColors = custom_color; - choose.Flags = CC_RGBINIT | CC_FULLOPEN | CC_ANYCOLOR; - if (ChooseColor(&choose) && choose.rgbResult != backup) - { - *item->r = GetRValue(choose.rgbResult); - *item->g = GetGValue(choose.rgbResult); - *item->b = GetBValue(choose.rgbResult); - return true; - } - return false; - -} - - -BOOL OpColorMenu(HWND hwnd, HMENU menu, COLORMENU* item, int pos, int id, BOOL (WINAPI *opMenu)(HMENU hmenu, UINT item, BOOL byPos, LPCMENUITEMINFO info)) -{ - - MENUITEMINFO info; - memset(&info, 0, sizeof(MENUITEMINFO)); - info.cbSize = sizeof(MENUITEMINFO); - - if (item->text) - { - HDC hdc = GetDC(hwnd); - HDC memdc = CreateCompatibleDC(hdc); - - int width = GetSystemMetrics(SM_CXMENUCHECK); - int height = GetSystemMetrics(SM_CYMENUCHECK); - - if (!item->bitmap) - item->bitmap = CreateCompatibleBitmap(hdc, width, height); - SelectObject(memdc, item->bitmap); - HBRUSH brush = CreateSolidBrush(RGB(*item->r, *item->g, *item->b)); - RECT rect = { 1, 1, width - 1, height - 1}; - FillRect(memdc, &rect, brush); - DeleteObject(brush); - DeleteDC(memdc); - ReleaseDC(hwnd, hdc); - - char menu_str[64]; - sprintf(menu_str, "%s\t#%02X%02X%02X", item->text, *item->r, *item->g, *item->b); - - info.dwTypeData = menu_str; - info.cch = strlen(menu_str); - info.hbmpUnchecked = item->bitmap; - info.wID = id; - - info.fMask = MIIM_ID | MIIM_TYPE | MIIM_CHECKMARKS; - info.fType = MFT_STRING; - } - else - { - info.fMask = MIIM_TYPE; - info.fType = MFT_SEPARATOR; - } - - return opMenu(menu, pos, TRUE, &info); -} \ No newline at end of file + return opMenu(menu, pos, TRUE, &info); + } \ No newline at end of file diff --git a/src/drivers/win/ppuview.cpp b/src/drivers/win/ppuview.cpp index 95dbb55a..b0adc40b 100644 --- a/src/drivers/win/ppuview.cpp +++ b/src/drivers/win/ppuview.cpp @@ -27,7 +27,7 @@ HWND hPPUView; -extern uint8 *VPage[8]; +extern uint8 *VPage[16]; extern uint8 PALRAM[0x20]; extern uint8 UPALRAM[3]; @@ -158,16 +158,16 @@ void FCEUD_UpdatePPUView(int scanline, int refreshchr) { for (i = 0, x=0x1000; i < 0x1000; i++, x++) { - chrcache0[i] = VPage[i>>10][i]; - chrcache1[i] = VPage[x>>10][x]; + chrcache0[i] = VPage[i>>9][i]; + chrcache1[i] = VPage[x>>9][x]; if (debug_loggingCD) { if (cdloggerVideoDataSize) { int addr; - addr = &VPage[i >> 10][i] - CHRptr[0]; + addr = &VPage[i >> 9][i] - CHRptr[0]; if ((addr >= 0) && (addr < (int)cdloggerVideoDataSize)) logcache0[i] = cdloggervdata[addr]; - addr = &VPage[x >> 10][x] - CHRptr[0]; + addr = &VPage[x >> 9][x] - CHRptr[0]; if ((addr >= 0) && (addr < (int)cdloggerVideoDataSize)) logcache1[i] = cdloggervdata[addr]; } else { diff --git a/src/drivers/win/texthook.cpp b/src/drivers/win/texthook.cpp index f1879d5d..5d192ec7 100644 --- a/src/drivers/win/texthook.cpp +++ b/src/drivers/win/texthook.cpp @@ -52,7 +52,7 @@ extern void FCEUD_BlitScreen(uint8 *XBuf); //needed for pause, not sure where th extern uint8 PALRAM[0x20]; extern uint8 PPU[4]; extern uint8 *vnapage[4]; -extern uint8 *VPage[8]; +extern uint8 *VPage[16]; //------------------------------ HWND hTextHooker; @@ -303,14 +303,14 @@ void UpdateTextHooker() { if ( EmulationPaused == 1 ) { //if the selection has changed since we paused if ( tileToggles[x][y] != pausedTileToggles[x][y] ) { - DrawTextHookerChr(pbitmap,&VPage[(ptable+chr)>>10][ptable+chr],tileattr,1); + DrawTextHookerChr(pbitmap,&VPage[(ptable+chr)>>9][ptable+chr],tileattr,1); } else { //nothing has changed since we paused - DrawTextHookerChr(pbitmap,&VPage[(ptable+chr)>>10][ptable+chr],tileattr,0); + DrawTextHookerChr(pbitmap,&VPage[(ptable+chr)>>9][ptable+chr],tileattr,0); } //after updates have been made to tileToggles, reset pausedTileToggles pausedTileToggles[x][y] = tileToggles[x][y]; } else { //we aren't paused, do a normal call - DrawTextHookerChr(pbitmap,&VPage[(ptable+chr)>>10][ptable+chr],tileattr,tileToggles[x][y]); + DrawTextHookerChr(pbitmap,&VPage[(ptable+chr)>>9][ptable+chr],tileattr,tileToggles[x][y]); } pbitmap += (8*3); } diff --git a/src/ines.cpp b/src/ines.cpp index 78dfe507..71249fd5 100644 --- a/src/ines.cpp +++ b/src/ines.cpp @@ -799,6 +799,7 @@ BMAPPINGLocal bmap[] = { {"KONAMI QTAi Board", 547, QTAi_Init }, {"RAINBOW13", 3872, RAINBOW13_Init }, + {"RAINBOW2", 3873, RAINBOW2_Init }, {"", 0, NULL} }; @@ -1182,7 +1183,7 @@ static int iNES_Init(int num) { } if (CHRRAMSize > 0) { - int mCHRRAMSize = (CHRRAMSize < 1024) ? 1024 : CHRRAMSize; // VPage has a resolution of 1k banks, ensure minimum allocation to prevent malicious access from NES software + int mCHRRAMSize = (CHRRAMSize < 512) ? 512 : CHRRAMSize; // VPage has a resolution of 512B banks, ensure minimum allocation to prevent malicious access from NES software if ((UNIFchrrama = VROM = (uint8*)FCEU_dmalloc(mCHRRAMSize)) == NULL) return 2; FCEU_MemoryRand(VROM, CHRRAMSize); SetupCartCHRMapping(0, VROM, CHRRAMSize, 1); diff --git a/src/ppu.cpp b/src/ppu.cpp index 68a6df89..3425aa09 100644 --- a/src/ppu.cpp +++ b/src/ppu.cpp @@ -28,7 +28,7 @@ #include "file.h" #include "utils/endian.h" #include "utils/memory.h" - + #include "cart.h" #include "palette.h" #include "state.h" @@ -36,30 +36,30 @@ #include "input.h" #include "driver.h" #include "debug.h" - + #include #include #include -#define VBlankON (PPU[0] & 0x80) //Generate VBlank NMI -#define Sprite16 (PPU[0] & 0x20) //Sprites 8x16/8x8 -#define BGAdrHI (PPU[0] & 0x10) //BG pattern adr $0000/$1000 -#define SpAdrHI (PPU[0] & 0x08) //Sprite pattern adr $0000/$1000 -#define INC32 (PPU[0] & 0x04) //auto increment 1/32 +#define VBlankON (PPU[0] & 0x80) // Generate VBlank NMI +#define Sprite16 (PPU[0] & 0x20) // Sprites 8x16/8x8 +#define BGAdrHI (PPU[0] & 0x10) // BG pattern adr $0000/$1000 +#define SpAdrHI (PPU[0] & 0x08) // Sprite pattern adr $0000/$1000 +#define INC32 (PPU[0] & 0x04) // auto increment 1/32 -#define SpriteON (PPU[1] & 0x10) //Show Sprite -#define ScreenON (PPU[1] & 0x08) //Show screen -#define PPUON (PPU[1] & 0x18) //PPU should operate -#define GRAYSCALE (PPU[1] & 0x01) //Grayscale (AND palette entries with 0x30) +#define SpriteON (PPU[1] & 0x10) // Show Sprite +#define ScreenON (PPU[1] & 0x08) // Show screen +#define PPUON (PPU[1] & 0x18) // PPU should operate +#define GRAYSCALE (PPU[1] & 0x01) // Grayscale (AND palette entries with 0x30) #define SpriteLeft8 (PPU[1] & 0x04) -#define BGLeft8 (PPU[1] & 0x02) +#define BGLeft8 (PPU[1] & 0x02) -#define PPU_status (PPU[2]) +#define PPU_status (PPU[2]) -#define READPALNOGS(ofs) (PALRAM[(ofs)]) -#define READPAL(ofs) (PALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF)) -#define READUPAL(ofs) (UPALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF)) +#define READPALNOGS(ofs) (PALRAM[(ofs)]) +#define READPAL(ofs) (PALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF)) +#define READUPAL(ofs) (UPALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF)) static void FetchSpriteData(void); static void RefreshLine(int lastpixel); @@ -75,10 +75,12 @@ static bool new_ppu_reset = false; int test = 0; -template -struct BITREVLUT { - T* lut; - BITREVLUT() { +template +struct BITREVLUT +{ + T *lut; + BITREVLUT() + { int bits = BITS; int n = 1 << BITS; lut = new T[n]; @@ -90,7 +92,8 @@ struct BITREVLUT { lut[0] = 0; lut[1] = a; - while (--bits) { + while (--bits) + { m <<= 1; a >>= 1; for (int i = 0; i < m; i++) @@ -98,18 +101,21 @@ struct BITREVLUT { } } - T operator[](int index) { + T operator[](int index) + { return lut[index]; } }; BITREVLUT bitrevlut; -struct PPUSTATUS { +struct PPUSTATUS +{ int32 sl; int32 cycle, end_cycle; }; -struct SPRITE_READ { +struct SPRITE_READ +{ int32 num; int32 count; int32 fetch; @@ -119,13 +125,15 @@ struct SPRITE_READ { int32 last; int32 mode; - void reset() { + void reset() + { num = count = fetch = found = ret = last = mode = 0; found_pos[0] = found_pos[1] = found_pos[2] = found_pos[3] = 0; found_pos[4] = found_pos[5] = found_pos[6] = found_pos[7] = 0; } - void start_scanline() { + void start_scanline() + { num = 1; found = 0; fetch = 1; @@ -137,39 +145,41 @@ struct SPRITE_READ { } }; -//doesn't need to be savestated as it is just a reflection of the current position in the ppu loop +// doesn't need to be savestated as it is just a reflection of the current position in the ppu loop PPUPHASE ppuphase; -//this needs to be savestated since a game may be trying to read from this across vblanks +// this needs to be savestated since a game may be trying to read from this across vblanks SPRITE_READ spr_read; -//definitely needs to be savestated +// definitely needs to be savestated uint8 idleSynch = 1; -//uses the internal counters concept at http://nesdev.icequake.net/PPU%20addressing.txt -struct PPUREGS { - //normal clocked regs. as the game can interfere with these at any time, they need to be savestated - uint32 fv; //3 - uint32 v; //1 - uint32 h; //1 - uint32 vt; //5 - uint32 ht; //5 +// uses the internal counters concept at http://nesdev.icequake.net/PPU%20addressing.txt +struct PPUREGS +{ + // normal clocked regs. as the game can interfere with these at any time, they need to be savestated + uint32 fv; // 3 + uint32 v; // 1 + uint32 h; // 1 + uint32 vt; // 5 + uint32 ht; // 5 - //temp unlatched regs (need savestating, can be written to at any time) + // temp unlatched regs (need savestating, can be written to at any time) uint32 _fv, _v, _h, _vt, _ht; - //other regs that need savestating - uint32 fh; //3 (horz scroll) - uint32 s; //1 ($2000 bit 4: "Background pattern table address (0: $0000; 1: $1000)") + // other regs that need savestating + uint32 fh; // 3 (horz scroll) + uint32 s; // 1 ($2000 bit 4: "Background pattern table address (0: $0000; 1: $1000)") - //other regs that don't need saving - uint32 par; //8 (sort of a hack, just stored in here, but not managed by this system) + // other regs that don't need saving + uint32 par; // 8 (sort of a hack, just stored in here, but not managed by this system) - //cached state data. these are always reset at the beginning of a frame and don't need saving - //but just to be safe, we're gonna save it + // cached state data. these are always reset at the beginning of a frame and don't need saving + // but just to be safe, we're gonna save it PPUSTATUS status; - void reset() { + void reset() + { fv = v = h = vt = ht = 0; fh = par = s = 0; _fv = _v = _h = _vt = _ht = 0; @@ -178,7 +188,8 @@ struct PPUREGS { status.sl = 241; } - void install_latches() { + void install_latches() + { fv = _fv; v = _v; h = _h; @@ -186,32 +197,37 @@ struct PPUREGS { ht = _ht; } - void install_h_latches() { + void install_h_latches() + { ht = _ht; h = _h; } - void clear_latches() { + void clear_latches() + { _fv = _v = _h = _vt = _ht = 0; fh = 0; } - void increment_hsc() { - //The first one, the horizontal scroll counter, consists of 6 bits, and is - //made up by daisy-chaining the HT counter to the H counter. The HT counter is - //then clocked every 8 pixel dot clocks (or every 8/3 CPU clock cycles). + void increment_hsc() + { + // The first one, the horizontal scroll counter, consists of 6 bits, and is + // made up by daisy-chaining the HT counter to the H counter. The HT counter is + // then clocked every 8 pixel dot clocks (or every 8/3 CPU clock cycles). ht++; h += (ht >> 5); ht &= 31; h &= 1; } - void increment_vs() { + void increment_vs() + { fv++; int fv_overflow = (fv >> 3); vt += fv_overflow; - vt &= 31; //fixed tecmo super bowl - if (vt == 30 && fv_overflow == 1) { //caution here (only do it at the exact instant of overflow) fixes p'radikus conflict + vt &= 31; // fixed tecmo super bowl + if (vt == 30 && fv_overflow == 1) + { // caution here (only do it at the exact instant of overflow) fixes p'radikus conflict v++; vt = 0; } @@ -219,53 +235,61 @@ struct PPUREGS { v &= 1; } - uint32 get_ntread() { + uint32 get_ntread() + { return 0x2000 | (v << 0xB) | (h << 0xA) | (vt << 5) | ht; } - uint32 get_2007access() { + uint32 get_2007access() + { return ((fv & 3) << 0xC) | (v << 0xB) | (h << 0xA) | (vt << 5) | ht; } - //The PPU has an internal 4-position, 2-bit shifter, which it uses for - //obtaining the 2-bit palette select data during an attribute table byte - //fetch. To represent how this data is shifted in the diagram, letters a..c - //are used in the diagram to represent the right-shift position amount to - //apply to the data read from the attribute data (a is always 0). This is why - //you only see bits 0 and 1 used off the read attribute data in the diagram. - uint32 get_atread() { + // The PPU has an internal 4-position, 2-bit shifter, which it uses for + // obtaining the 2-bit palette select data during an attribute table byte + // fetch. To represent how this data is shifted in the diagram, letters a..c + // are used in the diagram to represent the right-shift position amount to + // apply to the data read from the attribute data (a is always 0). This is why + // you only see bits 0 and 1 used off the read attribute data in the diagram. + uint32 get_atread() + { return 0x2000 | (v << 0xB) | (h << 0xA) | 0x3C0 | ((vt & 0x1C) << 1) | ((ht & 0x1C) >> 2); } - //address line 3 relates to the pattern table fetch occuring (the PPU always makes them in pairs). - uint32 get_ptread() { + // address line 3 relates to the pattern table fetch occuring (the PPU always makes them in pairs). + uint32 get_ptread() + { return (s << 0xC) | (par << 0x4) | fv; } - void increment2007(bool rendering, bool by32) { + void increment2007(bool rendering, bool by32) + { if (rendering) { - //don't do this: - //if (by32) increment_vs(); - //else increment_hsc(); - //do this instead: - increment_vs(); //yes, even if we're moving by 32 + // don't do this: + // if (by32) increment_vs(); + // else increment_hsc(); + // do this instead: + increment_vs(); // yes, even if we're moving by 32 return; } - //If the VRAM address increment bit (2000.2) is clear (inc. amt. = 1), all the - //scroll counters are daisy-chained (in the order of HT, VT, H, V, FV) so that - //the carry out of each counter controls the next counter's clock rate. The - //result is that all 5 counters function as a single 15-bit one. Any access to - //2007 clocks the HT counter here. + // If the VRAM address increment bit (2000.2) is clear (inc. amt. = 1), all the + // scroll counters are daisy-chained (in the order of HT, VT, H, V, FV) so that + // the carry out of each counter controls the next counter's clock rate. The + // result is that all 5 counters function as a single 15-bit one. Any access to + // 2007 clocks the HT counter here. // - //If the VRAM address increment bit is set (inc. amt. = 32), the only - //difference is that the HT counter is no longer being clocked, and the VT - //counter is now being clocked by access to 2007. - if (by32) { + // If the VRAM address increment bit is set (inc. amt. = 32), the only + // difference is that the HT counter is no longer being clocked, and the VT + // counter is now being clocked by access to 2007. + if (by32) + { vt++; - } else { + } + else + { ht++; vt += (ht >> 5) & 1; } @@ -281,10 +305,10 @@ struct PPUREGS { void debug_log() { - FCEU_printf("ppur: fv(%d), v(%d), h(%d), vt(%d), ht(%d)\n",fv,v,h,vt,ht); - FCEU_printf(" _fv(%d), _v(%d), _h(%d), _vt(%d), _ht(%d)\n",_fv,_v,_h,_vt,_ht); - FCEU_printf(" fh(%d), s(%d), par(%d)\n",fh,s,par); - FCEU_printf(" .status cycle(%d), end_cycle(%d), sl(%d)\n",status.cycle,status.end_cycle,status.sl); + FCEU_printf("ppur: fv(%d), v(%d), h(%d), vt(%d), ht(%d)\n", fv, v, h, vt, ht); + FCEU_printf(" _fv(%d), _v(%d), _h(%d), _vt(%d), _ht(%d)\n", _fv, _v, _h, _vt, _ht); + FCEU_printf(" fh(%d), s(%d), par(%d)\n", fh, s, par); + FCEU_printf(" .status cycle(%d), end_cycle(%d), sl(%d)\n", status.cycle, status.end_cycle, status.sl); } } ppur; @@ -292,27 +316,31 @@ int newppu_get_scanline() { return ppur.status.sl; } int newppu_get_dot() { return ppur.status.cycle; } void newppu_hacky_emergency_reset() { - if(ppur.status.end_cycle == 0) + if (ppur.status.end_cycle == 0) ppur.reset(); } -static void makeppulut(void) { +static void makeppulut(void) +{ int x; int y; int cc, xo, pixel; - - for (x = 0; x < 256; x++) { + for (x = 0; x < 256; x++) + { ppulut1[x] = 0; for (y = 0; y < 8; y++) ppulut1[x] |= ((x >> (7 - y)) & 1) << (y * 4); ppulut2[x] = ppulut1[x] << 1; } - for (cc = 0; cc < 16; cc++) { - for (xo = 0; xo < 8; xo++) { + for (cc = 0; cc < 16; cc++) + { + for (xo = 0; xo < 8; xo++) + { ppulut3[xo | (cc << 3)] = 0; - for (pixel = 0; pixel < 8; pixel++) { + for (pixel = 0; pixel < 8; pixel++) + { int shiftr; shiftr = (pixel + xo) / 8; shiftr *= 2; @@ -326,9 +354,9 @@ static int ppudead = 1; static int kook = 0; int fceuindbg = 0; -//mbg 6/23/08 -//make the no-bg fill color configurable -//0xFF shall indicate to use palette[0] +// mbg 6/23/08 +// make the no-bg fill color configurable +// 0xFF shall indicate to use palette[0] uint8 gNoBGFillColor = 0xFF; int MMC5Hack = 0; @@ -350,9 +378,9 @@ uint8 qtaintramreg; uint8 VRAMBuffer = 0, PPUGenLatch = 0; uint8 *vnapage[4]; uint8 PPUNTARAM = 0; -uint8 PPUCHRRAM = 0; +uint16 PPUCHRRAM = 0; -//Color deemphasis emulation. Joy... +// Color deemphasis emulation. Joy... static uint8 deemp = 0; static int deempcnt[8]; @@ -367,7 +395,7 @@ uint32 TempAddr = 0, RefreshAddr = 0, DummyRead = 0, NTRefreshAddr = 0; static int maxsprites = 8; -//scanline is equal to the current visible scanline we're on. +// scanline is equal to the current visible scanline we're on. int scanline; int g_rasterpos; static uint32 scanlines_per_frame; @@ -375,18 +403,19 @@ static uint32 scanlines_per_frame; uint8 PPU[4]; uint8 PPUSPL; uint8 NTARAM[0x800], PALRAM[0x20], SPRAM[0x100], SPRBUF[0x100]; -uint8 UPALRAM[0x03];//for 0x4/0x8/0xC addresses in palette, the ones in - //0x20 are 0 to not break fceu rendering. +uint8 UPALRAM[0x03]; // for 0x4/0x8/0xC addresses in palette, the ones in + // 0x20 are 0 to not break fceu rendering. -#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)] -#define VRAMADR(V) &VPage[(V) >> 10][(V)] +#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 9][(V)] +#define VRAMADR(V) &VPage[(V) >> 9][(V)] -uint8* MMC5BGVRAMADR(uint32 A); +uint8 *MMC5BGVRAMADR(uint32 A); uint8 READPAL_MOTHEROFALL(uint32 A) { - if(!(A & 3)) { - if(!(A & 0xC)) + if (!(A & 3)) + { + if (!(A & 0xC)) return READPAL(0x00); else return READUPAL(((A & 0xC) >> 2) - 1); @@ -395,25 +424,33 @@ uint8 READPAL_MOTHEROFALL(uint32 A) return READPAL(A & 0x1F); } -//this duplicates logic which is embedded in the ppu rendering code -//which figures out where to get CHR data from depending on various hack modes -//mostly involving mmc5. -//this might be incomplete. -uint8* FCEUPPU_GetCHR(uint32 vadr, uint32 refreshaddr) { - if (MMC5Hack) { - if (MMC5HackCHRMode == 1) { +// this duplicates logic which is embedded in the ppu rendering code +// which figures out where to get CHR data from depending on various hack modes +// mostly involving mmc5. +// this might be incomplete. +uint8 *FCEUPPU_GetCHR(uint32 vadr, uint32 refreshaddr) +{ + if (MMC5Hack) + { + if (MMC5HackCHRMode == 1) + { uint8 *C = MMC5HackVROMPTR; C += (((MMC5HackExNTARAMPtr[refreshaddr & 0x3ff]) & 0x3f & MMC5HackVROMMask) << 12) + (vadr & 0xfff); - C += (MMC50x5130 & 0x3) << 18; //11-jun-2009 for kuja_killer + C += (MMC50x5130 & 0x3) << 18; // 11-jun-2009 for kuja_killer return C; - } else { + } + else + { return MMC5BGVRAMADR(vadr); } - } else return VRAMADR(vadr); + } + else + return VRAMADR(vadr); } -//likewise for ATTR -int FCEUPPU_GetAttr(int ntnum, int xt, int yt) { +// likewise for ATTR +int FCEUPPU_GetAttr(int ntnum, int xt, int yt) +{ int attraddr = 0x3C0 + ((yt >> 2) << 3) + (xt >> 2); int temp = (((yt & 2) << 1) + (xt & 2)); int refreshaddr = xt + yt * 32; @@ -423,31 +460,44 @@ int FCEUPPU_GetAttr(int ntnum, int xt, int yt) { return (vnapage[ntnum][attraddr] & (3 << temp)) >> temp; } -//new ppu----- -void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) { +// new ppu----- +void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) +{ uint32 tmp = A; - if (PPU_hook) PPU_hook(A); + if (PPU_hook) + PPU_hook(A); - if (tmp < 0x2000) { - if (PPUCHRRAM & (1 << (tmp >> 10))) - VPage[tmp >> 10][tmp] = V; - } else if (tmp < 0x3F00) { - if (QTAIHack && (qtaintramreg & 1)) { + if (tmp < 0x2000) + { + if (PPUCHRRAM & (1 << (tmp >> 9))) + VPage[tmp >> 9][tmp] = V; + } + else if (tmp < 0x3F00) + { + if (QTAIHack && (qtaintramreg & 1)) + { QTAINTRAM[((((tmp & 0xF00) >> 10) >> ((qtaintramreg >> 1)) & 1) << 10) | (tmp & 0x3FF)] = V; - } else { + } + else + { if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; } - } else { - if (!(tmp & 3)) { - if (!(tmp & 0xC)) { + } + else + { + if (!(tmp & 3)) + { + if (!(tmp & 0xC)) + { PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = V & 0x3F; PALRAM[0x10] = PALRAM[0x14] = PALRAM[0x18] = PALRAM[0x1C] = V & 0x3F; } else UPALRAM[((tmp & 0xC) >> 2) - 1] = V & 0x3F; - } else + } + else PALRAM[tmp & 0x1F] = V & 0x3F; } } @@ -456,14 +506,14 @@ volatile int rendercount, vromreadcount, undefinedvromcount, LogAddress = -1; unsigned char *cdloggervdata = NULL; unsigned int cdloggerVideoDataSize = 0; -int GetCHRAddress(int A) +int GetCHRAddress(int A) { - if (cdloggerVideoDataSize) + if (cdloggerVideoDataSize) { int result = -1; - if ( (A >= 0) && (A < 0x2000) ) + if ((A >= 0) && (A < 0x2000)) { - result = &VPage[A >> 10][A] - CHRptr[0]; + result = &VPage[A >> 9][A] - CHRptr[0]; } if ((result >= 0) && (result < (int)cdloggerVideoDataSize)) { @@ -472,110 +522,136 @@ int GetCHRAddress(int A) } else { - if ( (A >= 0) && (A < 0x2000) ) return A; + if ((A >= 0) && (A < 0x2000)) + return A; } return -1; } -int GetCHROffset(uint8 *ptr) { +int GetCHROffset(uint8 *ptr) +{ int result = ptr - CHRptr[0]; - if (cdloggerVideoDataSize) { + if (cdloggerVideoDataSize) + { if ((result >= 0) && (result < (int)cdloggerVideoDataSize)) return result; - } else { + } + else + { if ((result >= 0) && (result < 0x2000)) return result; } return -1; } -#define RENDER_LOG(tmp) { \ - if (debug_loggingCD) \ - { \ - int addr = GetCHRAddress(tmp); \ - if (addr != -1) \ - { \ - if (!(cdloggervdata[addr] & 1)) \ - { \ - cdloggervdata[addr] |= 1; \ - if(cdloggerVideoDataSize) { \ - if (!(cdloggervdata[addr] & 2)) undefinedvromcount--; \ - rendercount++; \ - } \ - } \ - } \ - } \ -} +#define RENDER_LOG(tmp) \ + { \ + if (debug_loggingCD) \ + { \ + int addr = GetCHRAddress(tmp); \ + if (addr != -1) \ + { \ + if (!(cdloggervdata[addr] & 1)) \ + { \ + cdloggervdata[addr] |= 1; \ + if (cdloggerVideoDataSize) \ + { \ + if (!(cdloggervdata[addr] & 2)) \ + undefinedvromcount--; \ + rendercount++; \ + } \ + } \ + } \ + } \ + } -#define RENDER_LOGP(tmp) { \ - if (debug_loggingCD) \ - { \ - int addr = GetCHROffset(tmp); \ - if (addr != -1) \ - { \ - if (!(cdloggervdata[addr] & 1)) \ - { \ - cdloggervdata[addr] |= 1; \ - if(cdloggerVideoDataSize) { \ - if (!(cdloggervdata[addr] & 2)) undefinedvromcount--; \ - rendercount++; \ - } \ - } \ - } \ - } \ -} +#define RENDER_LOGP(tmp) \ + { \ + if (debug_loggingCD) \ + { \ + int addr = GetCHROffset(tmp); \ + if (addr != -1) \ + { \ + if (!(cdloggervdata[addr] & 1)) \ + { \ + cdloggervdata[addr] |= 1; \ + if (cdloggerVideoDataSize) \ + { \ + if (!(cdloggervdata[addr] & 2)) \ + undefinedvromcount--; \ + rendercount++; \ + } \ + } \ + } \ + } \ + } -uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A) { +uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A) +{ uint32 tmp = A; - if (PPU_hook) PPU_hook(A); + if (PPU_hook) + PPU_hook(A); - if (tmp < 0x2000) { - return VPage[tmp >> 10][tmp]; - } else if (tmp < 0x3F00) { + if (tmp < 0x2000) + { + return VPage[tmp >> 9][tmp]; + } + else if (tmp < 0x3F00) + { return vnapage[(tmp >> 10) & 0x3][tmp & 0x3FF]; - } else { + } + else + { uint8 ret; - if (!(tmp & 3)) { + if (!(tmp & 3)) + { if (!(tmp & 0xC)) ret = READPAL(0x00); else ret = READUPAL(((tmp & 0xC) >> 2) - 1); - } else + } + else ret = READPAL(tmp & 0x1F); return ret; } } - -uint8 (FASTCALL *FFCEUX_PPURead)(uint32 A) = 0; +uint8(FASTCALL *FFCEUX_PPURead)(uint32 A) = 0; void (*FFCEUX_PPUWrite)(uint32 A, uint8 V) = 0; #define CALL_PPUREAD(A) (FFCEUX_PPURead(A)) #define CALL_PPUWRITE(A, V) (FFCEUX_PPUWrite ? FFCEUX_PPUWrite(A, V) : FFCEUX_PPUWrite_Default(A, V)) -//whether to use the new ppu +// whether to use the new ppu int newppu = 0; -void ppu_getScroll(int &xpos, int &ypos) { - if (newppu) { +void ppu_getScroll(int &xpos, int &ypos) +{ + if (newppu) + { ypos = ppur._vt * 8 + ppur._fv + ppur._v * 256; xpos = ppur._ht * 8 + ppur.fh + ppur._h * 256; - } else { + } + else + { xpos = ((RefreshAddr & 0x400) >> 2) | ((RefreshAddr & 0x1F) << 3) | XOffset; ypos = ((RefreshAddr & 0x3E0) >> 2) | ((RefreshAddr & 0x7000) >> 12); - if (RefreshAddr & 0x800) ypos += 240; + if (RefreshAddr & 0x800) + ypos += 240; } } //--------------- -static DECLFR(A2002) { - if (newppu) { - //once we thought we clear latches here, but that caused midframe glitches. - //i think we should only reset the state machine for 2005/2006 - //ppur.clear_latches(); +static DECLFR(A2002) +{ + if (newppu) + { + // once we thought we clear latches here, but that caused midframe glitches. + // i think we should only reset the state machine for 2005/2006 + // ppur.clear_latches(); } uint8 ret; @@ -596,19 +672,26 @@ static DECLFR(A2002) { return ret; } -static DECLFR(A2004) { - if (newppu) { - if ((ppur.status.sl < 241) && PPUON) { +static DECLFR(A2004) +{ + if (newppu) + { + if ((ppur.status.sl < 241) && PPUON) + { // from cycles 0 to 63, the // 32 byte OAM buffer gets init // to 0xFF if (ppur.status.cycle < 64) return spr_read.ret = 0xFF; - else { + else + { for (int i = spr_read.last; - i != ppur.status.cycle; ++i) { - if (i < 256) { - switch (spr_read.mode) { + i != ppur.status.cycle; ++i) + { + if (i < 256) + { + switch (spr_read.mode) + { case 0: if (spr_read.count < 2) spr_read.ret = (PPU[3] & 0xF8) + (spr_read.count << 2); @@ -618,36 +701,49 @@ static DECLFR(A2004) { spr_read.found_pos[spr_read.found] = spr_read.ret; spr_read.ret = SPRAM[spr_read.ret]; - if (i & 1) { - //odd cycle - //see if in range - if (!((ppur.status.sl - 1 - spr_read.ret) & ~(Sprite16 ? 0xF : 0x7))) { + if (i & 1) + { + // odd cycle + // see if in range + if (!((ppur.status.sl - 1 - spr_read.ret) & ~(Sprite16 ? 0xF : 0x7))) + { ++spr_read.found; spr_read.fetch = 1; spr_read.mode = 1; - } else { - if (++spr_read.count == 64) { + } + else + { + if (++spr_read.count == 64) + { spr_read.mode = 4; spr_read.count = 0; - } else if (spr_read.found == 8) { + } + else if (spr_read.found == 8) + { spr_read.fetch = 0; spr_read.mode = 2; } } } break; - case 1: //sprite is in range fetch next 3 bytes - if (i & 1) { + case 1: // sprite is in range fetch next 3 bytes + if (i & 1) + { ++spr_read.fetch; - if (spr_read.fetch == 4) { + if (spr_read.fetch == 4) + { spr_read.fetch = 1; - if (++spr_read.count == 64) { + if (++spr_read.count == 64) + { spr_read.count = 0; spr_read.mode = 4; - } else if (spr_read.found == 8) { + } + else if (spr_read.found == 8) + { spr_read.fetch = 0; spr_read.mode = 2; - } else + } + else spr_read.mode = 0; } } @@ -659,55 +755,72 @@ static DECLFR(A2004) { spr_read.ret = SPRAM[spr_read.ret | spr_read.fetch]; break; - case 2: //8th sprite fetched + case 2: // 8th sprite fetched spr_read.ret = SPRAM[(spr_read.count << 2) | spr_read.fetch]; - if (i & 1) { - if (!((ppur.status.sl - 1 - SPRAM[((spr_read.count << 2) | spr_read.fetch)]) & ~((Sprite16) ? 0xF : 0x7))) { + if (i & 1) + { + if (!((ppur.status.sl - 1 - SPRAM[((spr_read.count << 2) | spr_read.fetch)]) & ~((Sprite16) ? 0xF : 0x7))) + { spr_read.fetch = 1; spr_read.mode = 3; - } else { - if (++spr_read.count == 64) { + } + else + { + if (++spr_read.count == 64) + { spr_read.count = 0; spr_read.mode = 4; } spr_read.fetch = - (spr_read.fetch + 1) & 3; + (spr_read.fetch + 1) & 3; } } spr_read.ret = spr_read.count; break; - case 3: //9th sprite overflow detected + case 3: // 9th sprite overflow detected spr_read.ret = SPRAM[spr_read.count | spr_read.fetch]; - if (i & 1) { - if (++spr_read.fetch == 4) { + if (i & 1) + { + if (++spr_read.fetch == 4) + { spr_read.count = (spr_read.count + 1) & 63; spr_read.mode = 4; } } break; - case 4: //read OAM[n][0] until hblank + case 4: // read OAM[n][0] until hblank if (i & 1) spr_read.count = (spr_read.count + 1) & 63; spr_read.fetch = 0; spr_read.ret = SPRAM[spr_read.count << 2]; break; } - } else if (i < 320) { + } + else if (i < 320) + { spr_read.ret = (i & 0x38) >> 3; - if (spr_read.found < (spr_read.ret + 1)) { - if (spr_read.num) { + if (spr_read.found < (spr_read.ret + 1)) + { + if (spr_read.num) + { spr_read.ret = SPRAM[252]; spr_read.num = 0; - } else + } + else spr_read.ret = 0xFF; - } else if ((i & 7) < 4) { + } + else if ((i & 7) < 4) + { spr_read.ret = - SPRAM[spr_read.found_pos[spr_read.ret] | spr_read.fetch++]; + SPRAM[spr_read.found_pos[spr_read.ret] | spr_read.fetch++]; if (spr_read.fetch == 4) spr_read.fetch = 0; - } else - spr_read.ret = SPRAM[spr_read.found_pos [spr_read.ret | 3]]; - } else { + } + else + spr_read.ret = SPRAM[spr_read.found_pos[spr_read.ret | 3]]; + } + else + { if (!spr_read.found) spr_read.ret = SPRAM[252]; else @@ -718,52 +831,68 @@ static DECLFR(A2004) { spr_read.last = ppur.status.cycle; return spr_read.ret; } - } else + } + else return SPRAM[PPU[3]]; - } else { + } + else + { FCEUPPU_LineUpdate(); return PPUGenLatch; } } -static DECLFR(A200x) { /* Not correct for $2004 reads. */ +static DECLFR(A200x) +{ /* Not correct for $2004 reads. */ FCEUPPU_LineUpdate(); return PPUGenLatch; } -static DECLFR(A2007) { +static DECLFR(A2007) +{ uint8 ret; uint32 tmp = RefreshAddr & 0x3FFF; - if (debug_loggingCD) { - if (!DummyRead && (LogAddress != -1)) { - if (!(cdloggervdata[LogAddress] & 2)) { + if (debug_loggingCD) + { + if (!DummyRead && (LogAddress != -1)) + { + if (!(cdloggervdata[LogAddress] & 2)) + { cdloggervdata[LogAddress] |= 2; - if ((!(cdloggervdata[LogAddress] & 1)) && cdloggerVideoDataSize) undefinedvromcount--; + if ((!(cdloggervdata[LogAddress] & 1)) && cdloggerVideoDataSize) + undefinedvromcount--; vromreadcount++; } - } else + } + else DummyRead = 0; } - if (newppu) { + if (newppu) + { ret = VRAMBuffer; RefreshAddr = ppur.get_2007access() & 0x3FFF; - if ((RefreshAddr & 0x3F00) == 0x3F00) { - //if it is in the palette range bypass the - //delayed read, and what gets filled in the temp - //buffer is the address - 0x1000, also - //if grayscale is set then the return is AND with 0x30 - //to get a gray color reading - if (!(tmp & 3)) { + if ((RefreshAddr & 0x3F00) == 0x3F00) + { + // if it is in the palette range bypass the + // delayed read, and what gets filled in the temp + // buffer is the address - 0x1000, also + // if grayscale is set then the return is AND with 0x30 + // to get a gray color reading + if (!(tmp & 3)) + { if (!(tmp & 0xC)) ret = READPAL(0x00); else ret = READUPAL(((tmp & 0xC) >> 2) - 1); - } else + } + else ret = READPAL(tmp & 0x1F); VRAMBuffer = CALL_PPUREAD(RefreshAddr - 0x1000); - } else { + } + else + { if (debug_loggingCD && (RefreshAddr < 0x2000)) LogAddress = GetCHRAddress(RefreshAddr); VRAMBuffer = CALL_PPUREAD(RefreshAddr); @@ -771,58 +900,70 @@ static DECLFR(A2007) { ppur.increment2007(ppur.status.sl >= 0 && ppur.status.sl < 241 && PPUON, INC32 != 0); RefreshAddr = ppur.get_2007access(); return ret; - } else { + } + else + { - //OLDPPU + // OLDPPU FCEUPPU_LineUpdate(); - if (tmp >= 0x3F00) { // Palette RAM tied directly to the output data, without VRAM buffer - if (!(tmp & 3)) { + if (tmp >= 0x3F00) + { // Palette RAM tied directly to the output data, without VRAM buffer + if (!(tmp & 3)) + { if (!(tmp & 0xC)) ret = READPAL(0x00); else ret = READUPAL(((tmp & 0xC) >> 2) - 1); - } else + } + else ret = READPAL(tmp & 0x1F); - #ifdef FCEUDEF_DEBUGGER +#ifdef FCEUDEF_DEBUGGER if (!fceuindbg) - #endif +#endif { if ((tmp - 0x1000) < 0x2000) - VRAMBuffer = VPage[(tmp - 0x1000) >> 10][tmp - 0x1000]; + VRAMBuffer = VPage[(tmp - 0x1000) >> 9][tmp - 0x1000]; else VRAMBuffer = vnapage[((tmp - 0x1000) >> 10) & 0x3][(tmp - 0x1000) & 0x3FF]; - if (PPU_hook) PPU_hook(tmp); + if (PPU_hook) + PPU_hook(tmp); } - } else { + } + else + { ret = VRAMBuffer; - #ifdef FCEUDEF_DEBUGGER +#ifdef FCEUDEF_DEBUGGER if (!fceuindbg) - #endif +#endif { - if (PPU_hook) PPU_hook(tmp); + if (PPU_hook) + PPU_hook(tmp); PPUGenLatch = VRAMBuffer; - if (tmp < 0x2000) { + if (tmp < 0x2000) + { if (debug_loggingCD) LogAddress = GetCHRAddress(tmp); - if(MMC5Hack && newppu) + if (MMC5Hack && newppu) VRAMBuffer = *MMC5BGVRAMADR(tmp); else - VRAMBuffer = VPage[tmp >> 10][tmp]; - - } else if (tmp < 0x3F00) + VRAMBuffer = VPage[tmp >> 9][tmp]; + } + else if (tmp < 0x3F00) VRAMBuffer = vnapage[(tmp >> 10) & 0x3][tmp & 0x3FF]; } } - #ifdef FCEUDEF_DEBUGGER +#ifdef FCEUDEF_DEBUGGER if (!fceuindbg) - #endif +#endif { - if ((ScreenON || SpriteON) && (scanline < 240)) { + if ((ScreenON || SpriteON) && (scanline < 240)) + { uint32 rad = RefreshAddr; - if ((rad & 0x7000) == 0x7000) { + if ((rad & 0x7000) == 0x7000) + { rad ^= 0x7000; if ((rad & 0x3E0) == 0x3A0) rad ^= 0xBA0; @@ -830,22 +971,27 @@ static DECLFR(A2007) { rad ^= 0x3e0; else rad += 0x20; - } else + } + else rad += 0x1000; RefreshAddr = rad; - } else { + } + else + { if (INC32) RefreshAddr += 32; else RefreshAddr++; } - if (PPU_hook) PPU_hook(RefreshAddr & 0x3fff); + if (PPU_hook) + PPU_hook(RefreshAddr & 0x3fff); } return ret; } } -static DECLFW(B2000) { +static DECLFW(B2000) +{ FCEUPPU_LineUpdate(); PPUGenLatch = V; @@ -861,41 +1007,51 @@ static DECLFW(B2000) { ppur.s = (V >> 4) & 1; } -static DECLFW(B2001) { +static DECLFW(B2001) +{ FCEUPPU_LineUpdate(); if (paldeemphswap) - V = (V&0x9F)|((V&0x40)>>1)|((V&0x20)<<1); + V = (V & 0x9F) | ((V & 0x40) >> 1) | ((V & 0x20) << 1); PPUGenLatch = V; PPU[1] = V; if (V & 0xE0) deemp = V >> 5; } -static DECLFW(B2002) { +static DECLFW(B2002) +{ PPUGenLatch = V; } -static DECLFW(B2003) { +static DECLFW(B2003) +{ PPUGenLatch = V; PPU[3] = V; PPUSPL = V & 0x7; } -static DECLFW(B2004) { +static DECLFW(B2004) +{ PPUGenLatch = V; - if (newppu) { - //the attribute upper bits are not connected - //so AND them out on write, since reading them - //should return 0 in those bits. + if (newppu) + { + // the attribute upper bits are not connected + // so AND them out on write, since reading them + // should return 0 in those bits. if ((PPU[3] & 3) == 2) V &= 0xE3; SPRAM[PPU[3]] = V; PPU[3] = (PPU[3] + 1) & 0xFF; - } else { - if (PPUSPL >= 8) { + } + else + { + if (PPUSPL >= 8) + { if (PPU[3] >= 8) SPRAM[PPU[3]] = V; - } else { + } + else + { SPRAM[PPUSPL] = V; } PPU[3]++; @@ -903,17 +1059,21 @@ static DECLFW(B2004) { } } -static DECLFW(B2005) { +static DECLFW(B2005) +{ uint32 tmp = TempAddr; FCEUPPU_LineUpdate(); PPUGenLatch = V; - if (!vtoggle) { + if (!vtoggle) + { tmp &= 0xFFE0; tmp |= V >> 3; XOffset = V & 7; ppur._ht = V >> 3; ppur.fh = V & 7; - } else { + } + else + { tmp &= 0x8C1F; tmp |= ((V & ~0x7) << 2); tmp |= (V & 7) << 12; @@ -924,12 +1084,13 @@ static DECLFW(B2005) { vtoggle ^= 1; } - -static DECLFW(B2006) { +static DECLFW(B2006) +{ FCEUPPU_LineUpdate(); PPUGenLatch = V; - if (!vtoggle) { + if (!vtoggle) + { TempAddr &= 0x00FF; TempAddr |= (V & 0x3f) << 8; @@ -938,7 +1099,9 @@ static DECLFW(B2006) { ppur._h = (V >> 2) & 1; ppur._v = (V >> 3) & 1; ppur._fv = (V >> 4) & 3; - } else { + } + else + { TempAddr &= 0xFF00; TempAddr |= V; @@ -957,39 +1120,54 @@ static DECLFW(B2006) { vtoggle ^= 1; } -static DECLFW(B2007) { +static DECLFW(B2007) +{ uint32 tmp = RefreshAddr & 0x3FFF; - if (debug_loggingCD) { - if(!cdloggerVideoDataSize && (tmp < 0x2000)) + if (debug_loggingCD) + { + if (!cdloggerVideoDataSize && (tmp < 0x2000)) cdloggervdata[tmp] = 0; } - if (newppu) { + if (newppu) + { PPUGenLatch = V; RefreshAddr = ppur.get_2007access() & 0x3FFF; CALL_PPUWRITE(RefreshAddr, V); ppur.increment2007(ppur.status.sl >= 0 && ppur.status.sl < 241 && PPUON, INC32 != 0); RefreshAddr = ppur.get_2007access(); - } else { + } + else + { PPUGenLatch = V; - if (tmp < 0x2000) { - if (PPUCHRRAM & (1 << (tmp >> 10))) - VPage[tmp >> 10][tmp] = V; - } else if (tmp < 0x3F00) { - if (QTAIHack && (qtaintramreg & 1)) { + if (tmp < 0x2000) + { + if (PPUCHRRAM & (1 << (tmp >> 9))) + VPage[tmp >> 9][tmp] = V; + } + else if (tmp < 0x3F00) + { + if (QTAIHack && (qtaintramreg & 1)) + { QTAINTRAM[((((tmp & 0xF00) >> 10) >> ((qtaintramreg >> 1)) & 1) << 10) | (tmp & 0x3FF)] = V; - } else { + } + else + { if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; } - } else { - if (!(tmp & 3)) { + } + else + { + if (!(tmp & 3)) + { if (!(tmp & 0xC)) PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = V & 0x3F; else UPALRAM[((tmp & 0xC) >> 2) - 1] = V & 0x3F; - } else + } + else PALRAM[tmp & 0x1F] = V & 0x3F; } if (INC32) @@ -1001,7 +1179,8 @@ static DECLFW(B2007) { } } -static DECLFW(B4014) { +static DECLFW(B4014) +{ uint32 t = V << 8; int x; @@ -1010,16 +1189,17 @@ static DECLFW(B4014) { SpriteDMA = V; } -#define PAL(c) ((c) + cc) +#define PAL(c) ((c) + cc) -#define GETLASTPIXEL (PAL ? ((timestamp * 48 - linestartts) / 15) : ((timestamp * 48 - linestartts) >> 4)) +#define GETLASTPIXEL (PAL ? ((timestamp * 48 - linestartts) / 15) : ((timestamp * 48 - linestartts) >> 4)) static uint8 *Pline, *Plinef; static int firsttile; -int linestartts; //no longer static so the debugger can see it +int linestartts; // no longer static so the debugger can see it static int tofix = 0; -static void ResetRL(uint8 *target) { +static void ResetRL(uint8 *target) +{ memset(target, 0xFF, 256); InputScanlineHook(0, 0, 0, 0); Plinef = target; @@ -1033,34 +1213,39 @@ static void ResetRL(uint8 *target) { static uint8 sprlinebuf[256 + 8]; -void FCEUPPU_LineUpdate(void) { +void FCEUPPU_LineUpdate(void) +{ if (newppu) return; #ifdef FCEUDEF_DEBUGGER if (!fceuindbg) #endif - if (Pline) { - int l = GETLASTPIXEL; - RefreshLine(l); - } + if (Pline) + { + int l = GETLASTPIXEL; + RefreshLine(l); + } } static bool rendersprites = true, renderbg = true; -void FCEUI_SetRenderPlanes(bool sprites, bool bg) { +void FCEUI_SetRenderPlanes(bool sprites, bool bg) +{ rendersprites = sprites; renderbg = bg; } -void FCEUI_GetRenderPlanes(bool& sprites, bool& bg) { +void FCEUI_GetRenderPlanes(bool &sprites, bool &bg) +{ sprites = rendersprites; bg = renderbg; } static void CheckSpriteHit(int p); -static void EndRL(void) { +static void EndRL(void) +{ RefreshLine(272); if (tofix) Fixit1(); @@ -1071,14 +1256,18 @@ static void EndRL(void) { static int32 sphitx; static uint8 sphitdata; -static void CheckSpriteHit(int p) { +static void CheckSpriteHit(int p) +{ int l = p - 16; int x; - if (sphitx == 0x100) return; + if (sphitx == 0x100) + return; - for (x = sphitx; x < (sphitx + 8) && x < l; x++) { - if ((sphitdata & (0x80 >> (x - sphitx))) && !(Plinef[x] & 64) && x < 255) { + for (x = sphitx; x < (sphitx + 8) && x < l; x++) + { + if ((sphitdata & (0x80 >> (x - sphitx))) && !(Plinef[x] & 64) && x < 255) + { PPU_status |= 0x40; sphitx = 0x100; break; @@ -1086,50 +1275,56 @@ static void CheckSpriteHit(int p) { } } -//spork the world. Any sprites on this line? Then this will be set to 1. -//Needed for zapper emulation and *gasp* sprite emulation. +// spork the world. Any sprites on this line? Then this will be set to 1. +// Needed for zapper emulation and *gasp* sprite emulation. static int spork = 0; // lasttile is really "second to last tile." -static void RefreshLine(int lastpixel) { +static void RefreshLine(int lastpixel) +{ static uint32 pshift[2]; static uint32 atlatch; uint32 smorkus = RefreshAddr; - #define RefreshAddr smorkus +#define RefreshAddr smorkus uint32 vofs; int X1; uint8 *P = Pline; int lasttile = lastpixel >> 3; int numtiles; - static int norecurse = 0; // Yeah, recursion would be bad. - // PPU_hook() functions can call - // mirroring/chr bank switching functions, - // which call FCEUPPU_LineUpdate, which call this - // function. - if (norecurse) return; + static int norecurse = 0; // Yeah, recursion would be bad. + // PPU_hook() functions can call + // mirroring/chr bank switching functions, + // which call FCEUPPU_LineUpdate, which call this + // function. + if (norecurse) + return; - if (sphitx != 0x100 && !(PPU_status & 0x40)) { + if (sphitx != 0x100 && !(PPU_status & 0x40)) + { if ((sphitx < (lastpixel - 16)) && !(sphitx < ((lasttile - 2) * 8))) lasttile++; } - if (lasttile > 34) lasttile = 34; + if (lasttile > 34) + lasttile = 34; numtiles = lasttile - firsttile; - if (numtiles <= 0) return; + if (numtiles <= 0) + return; P = Pline; vofs = 0; - if(PEC586Hack) + if (PEC586Hack) vofs = ((RefreshAddr & 0x200) << 3) | ((RefreshAddr >> 12) & 7); else vofs = ((PPU[0] & 0x10) << 8) | ((RefreshAddr >> 12) & 7); - if (!ScreenON && !SpriteON) { + if (!ScreenON && !SpriteON) + { uint32 tem; tem = READPAL(0) | (READPAL(0) << 8) | (READPAL(0) << 16) | (READPAL(0) << 24); tem |= 0x40404040; @@ -1139,98 +1334,131 @@ static void RefreshLine(int lastpixel) { firsttile = lasttile; - #define TOFIXNUM (272 - 0x4) - if (lastpixel >= TOFIXNUM && tofix) { +#define TOFIXNUM (272 - 0x4) + if (lastpixel >= TOFIXNUM && tofix) + { Fixit1(); tofix = 0; } - if ((lastpixel - 16) >= 0) { + if ((lastpixel - 16) >= 0) + { InputScanlineHook(Plinef, spork ? sprlinebuf : 0, linestartts, lasttile * 8 - 16); } return; } - //Priority bits, needed for sprite emulation. + // Priority bits, needed for sprite emulation. PALRAM[0] |= 64; PALRAM[4] |= 64; PALRAM[8] |= 64; PALRAM[0xC] |= 64; - //This high-level graphics MMC5 emulation code was written for MMC5 carts in "CL" mode. - //It's probably not totally correct for carts in "SL" mode. + // This high-level graphics MMC5 emulation code was written for MMC5 carts in "CL" mode. + // It's probably not totally correct for carts in "SL" mode. #define PPUT_MMC5 - if (MMC5Hack && geniestage != 1) { - if (MMC5HackCHRMode == 0 && (MMC5HackSPMode & 0x80)) { + if (MMC5Hack && geniestage != 1) + { + if (MMC5HackCHRMode == 0 && (MMC5HackSPMode & 0x80)) + { int tochange = MMC5HackSPMode & 0x1F; tochange -= firsttile; - for (X1 = firsttile; X1 < lasttile; X1++) { - if ((tochange <= 0 && MMC5HackSPMode & 0x40) || (tochange > 0 && !(MMC5HackSPMode & 0x40))) { - #define PPUT_MMC5SP - #include "pputile.inc" - #undef PPUT_MMC5SP - } else { - #include "pputile.inc" + for (X1 = firsttile; X1 < lasttile; X1++) + { + if ((tochange <= 0 && MMC5HackSPMode & 0x40) || (tochange > 0 && !(MMC5HackSPMode & 0x40))) + { +#define PPUT_MMC5SP +#include "pputile.inc" +#undef PPUT_MMC5SP + } + else + { +#include "pputile.inc" } tochange--; } - } else if (MMC5HackCHRMode == 1 && (MMC5HackSPMode & 0x80)) { + } + else if (MMC5HackCHRMode == 1 && (MMC5HackSPMode & 0x80)) + { int tochange = MMC5HackSPMode & 0x1F; tochange -= firsttile; - #define PPUT_MMC5SP - #define PPUT_MMC5CHR1 - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" +#define PPUT_MMC5SP +#define PPUT_MMC5CHR1 + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } - #undef PPUT_MMC5CHR1 - #undef PPUT_MMC5SP - } else if (MMC5HackCHRMode == 1) { - #define PPUT_MMC5CHR1 - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" +#undef PPUT_MMC5CHR1 +#undef PPUT_MMC5SP + } + else if (MMC5HackCHRMode == 1) + { +#define PPUT_MMC5CHR1 + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } - #undef PPUT_MMC5CHR1 - } else { - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" +#undef PPUT_MMC5CHR1 + } + else + { + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } } } - #undef PPUT_MMC5 - else if (PPU_hook) { +#undef PPUT_MMC5 + else if (PPU_hook) + { norecurse = 1; - #define PPUT_HOOK - if (PEC586Hack) { - #define PPU_BGFETCH - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" +#define PPUT_HOOK + if (PEC586Hack) + { +#define PPU_BGFETCH + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } - #undef PPU_BGFETCH - } else { - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" +#undef PPU_BGFETCH + } + else + { + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } } - #undef PPUT_HOOK +#undef PPUT_HOOK norecurse = 0; - } else { - if (PEC586Hack) { - #define PPU_BGFETCH - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" + } + else + { + if (PEC586Hack) + { +#define PPU_BGFETCH + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } - #undef PPU_BGFETCH - } if (QTAIHack) { - #define PPU_VRC5FETCH - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" +#undef PPU_BGFETCH + } + if (QTAIHack) + { +#define PPU_VRC5FETCH + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } - #undef PPU_VRC5FETCH - } else { - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" +#undef PPU_VRC5FETCH + } + else + { + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } } } @@ -1238,21 +1466,23 @@ static void RefreshLine(int lastpixel) { #undef vofs #undef RefreshAddr - //Reverse changes made before. + // Reverse changes made before. PALRAM[0] &= 63; PALRAM[4] &= 63; PALRAM[8] &= 63; PALRAM[0xC] &= 63; RefreshAddr = smorkus; - if (firsttile <= 2 && 2 < lasttile && !(PPU[1] & 2)) { + if (firsttile <= 2 && 2 < lasttile && !(PPU[1] & 2)) + { uint32 tem; tem = READPAL(0) | (READPAL(0) << 8) | (READPAL(0) << 16) | (READPAL(0) << 24); tem |= 0x40404040; - *(uint32*)Plinef = *(uint32*)(Plinef + 4) = tem; + *(uint32 *)Plinef = *(uint32 *)(Plinef + 4) = tem; } - if (!ScreenON) { + if (!ScreenON) + { uint32 tem; int tstart, tcount; tem = READPAL(0) | (READPAL(0) << 8) | (READPAL(0) << 16) | (READPAL(0) << 24); @@ -1260,7 +1490,8 @@ static void RefreshLine(int lastpixel) { tcount = lasttile - firsttile; tstart = firsttile - 2; - if (tstart < 0) { + if (tstart < 0) + { tcount += tstart; tstart = 0; } @@ -1268,23 +1499,27 @@ static void RefreshLine(int lastpixel) { FCEU_dwmemset(Plinef + tstart * 8, tem, tcount * 8); } - if (lastpixel >= TOFIXNUM && tofix) { + if (lastpixel >= TOFIXNUM && tofix) + { Fixit1(); tofix = 0; } - //This only works right because of a hack earlier in this function. + // This only works right because of a hack earlier in this function. CheckSpriteHit(lastpixel); - if ((lastpixel - 16) >= 0) { + if ((lastpixel - 16) >= 0) + { InputScanlineHook(Plinef, spork ? sprlinebuf : 0, linestartts, lasttile * 8 - 16); } Pline = P; firsttile = lasttile; } -static INLINE void Fixit2(void) { - if (ScreenON || SpriteON) { +static INLINE void Fixit2(void) +{ + if (ScreenON || SpriteON) + { uint32 rad = RefreshAddr; rad &= 0xFBE0; rad |= TempAddr & 0x041f; @@ -1292,11 +1527,14 @@ static INLINE void Fixit2(void) { } } -static void Fixit1(void) { - if (ScreenON || SpriteON) { +static void Fixit1(void) +{ + if (ScreenON || SpriteON) + { uint32 rad = RefreshAddr; - if ((rad & 0x7000) == 0x7000) { + if ((rad & 0x7000) == 0x7000) + { rad ^= 0x7000; if ((rad & 0x3E0) == 0x3A0) rad ^= 0xBA0; @@ -1304,15 +1542,18 @@ static void Fixit1(void) { rad ^= 0x3e0; else rad += 0x20; - } else + } + else rad += 0x1000; RefreshAddr = rad; } } -void MMC5_hb(int); //Ugh ugh ugh. -static void DoLine(void) { - if (scanline >= 240 && scanline != totalscanlines) { +void MMC5_hb(int); // Ugh ugh ugh. +static void DoLine(void) +{ + if (scanline >= 240 && scanline != totalscanlines) + { X6502_Run(256 + 69); scanline++; X6502_Run(16); @@ -1321,64 +1562,73 @@ static void DoLine(void) { int x; uint8 *target = XBuf + ((scanline < 240 ? scanline : 240) << 8); - u8* dtarget = XDBuf + ((scanline < 240 ? scanline : 240) << 8); + u8 *dtarget = XDBuf + ((scanline < 240 ? scanline : 240) << 8); - if (MMC5Hack) MMC5_hb(scanline); + if (MMC5Hack) + MMC5_hb(scanline); X6502_Run(256); EndRL(); - if (!renderbg) {// User asked to not display background data. + if (!renderbg) + { // User asked to not display background data. uint32 tem; uint8 col; if (gNoBGFillColor == 0xFF) col = READPAL(0); - else col = gNoBGFillColor; + else + col = gNoBGFillColor; tem = col | (col << 8) | (col << 16) | (col << 24); - tem |= 0x40404040; + tem |= 0x40404040; FCEU_dwmemset(target, tem, 256); } if (SpriteON) CopySprites(target); - //greyscale handling (mask some bits off the color) ? ? ? + // greyscale handling (mask some bits off the color) ? ? ? if (ScreenON || SpriteON) { - if (PPU[1] & 0x01) { + if (PPU[1] & 0x01) + { for (x = 63; x >= 0; x--) - *(uint32*)&target[x << 2] = (*(uint32*)&target[x << 2]) & 0x30303030; + *(uint32 *)&target[x << 2] = (*(uint32 *)&target[x << 2]) & 0x30303030; } } - //some pathetic attempts at deemph - if ((PPU[1] >> 5) == 0x7) { + // some pathetic attempts at deemph + if ((PPU[1] >> 5) == 0x7) + { for (x = 63; x >= 0; x--) - *(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0xc0c0c0c0; - } else if (PPU[1] & 0xE0) + *(uint32 *)&target[x << 2] = ((*(uint32 *)&target[x << 2]) & 0x3f3f3f3f) | 0xc0c0c0c0; + } + else if (PPU[1] & 0xE0) for (x = 63; x >= 0; x--) - *(uint32*)&target[x << 2] = (*(uint32*)&target[x << 2]) | 0x40404040; + *(uint32 *)&target[x << 2] = (*(uint32 *)&target[x << 2]) | 0x40404040; else for (x = 63; x >= 0; x--) - *(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0x80808080; + *(uint32 *)&target[x << 2] = ((*(uint32 *)&target[x << 2]) & 0x3f3f3f3f) | 0x80808080; - //write the actual deemph + // write the actual deemph for (x = 63; x >= 0; x--) - *(uint32*)&dtarget[x << 2] = ((PPU[1]>>5)<<0)|((PPU[1]>>5)<<8)|((PPU[1]>>5)<<16)|((PPU[1]>>5)<<24); + *(uint32 *)&dtarget[x << 2] = ((PPU[1] >> 5) << 0) | ((PPU[1] >> 5) << 8) | ((PPU[1] >> 5) << 16) | ((PPU[1] >> 5) << 24); sphitx = 0x100; if (ScreenON || SpriteON) FetchSpriteData(); - if (GameHBIRQHook && (ScreenON || SpriteON) && ((PPU[0] & 0x38) != 0x18)) { + if (GameHBIRQHook && (ScreenON || SpriteON) && ((PPU[0] & 0x38) != 0x18)) + { X6502_Run(6); Fixit2(); X6502_Run(4); GameHBIRQHook(); X6502_Run(85 - 16 - 10); - } else { - X6502_Run(6); // Tried 65, caused problems with Slalom(maybe others) + } + else + { + X6502_Run(6); // Tried 65, caused problems with Slalom(maybe others) Fixit2(); X6502_Run(85 - 6 - 16); @@ -1394,30 +1644,35 @@ static void DoLine(void) { if (GameHBIRQHook2 && (ScreenON || SpriteON)) GameHBIRQHook2(); scanline++; - if (scanline < 240) { + if (scanline < 240) + { ResetRL(XBuf + (scanline << 8)); } X6502_Run(16); } -#define V_FLIP 0x80 -#define H_FLIP 0x40 +#define V_FLIP 0x80 +#define H_FLIP 0x40 #define SP_BACK 0x20 -typedef struct { +typedef struct +{ uint8 y, no, atr, x; } SPR; -typedef struct { +typedef struct +{ uint8 ca[2], atr, x; } SPRB; -void FCEUI_DisableSpriteLimitation(int a) { +void FCEUI_DisableSpriteLimitation(int a) +{ maxsprites = a ? 64 : 8; } static uint8 numsprites, SpriteBlurp; -static void FetchSpriteData(void) { +static void FetchSpriteData(void) +{ uint8 ns, sb; SPR *spr; uint8 H; @@ -1425,7 +1680,7 @@ static void FetchSpriteData(void) { int vofs; uint8 P0 = PPU[0]; - spr = (SPR*)SPRAM; + spr = (SPR *)SPRAM; H = 8; ns = sb = 0; @@ -1434,10 +1689,14 @@ static void FetchSpriteData(void) { H += (P0 & 0x20) >> 2; if (!PPU_hook) - for (n = 63; n >= 0; n--, spr++) { - if ((uint32)(scanline - spr->y) >= H) continue; - if (ns < maxsprites) { - if (n == 63) sb = 1; + for (n = 63; n >= 0; n--, spr++) + { + if ((uint32)(scanline - spr->y) >= H) + continue; + if (ns < maxsprites) + { + if (n == 63) + sb = 1; { SPRB dst; @@ -1452,12 +1711,15 @@ static void FetchSpriteData(void) { else vadr = (spr->no << 4) + vofs; - if (spr->atr & V_FLIP) { + if (spr->atr & V_FLIP) + { vadr += 7; vadr -= t; vadr += (P0 & 0x20) >> 1; vadr -= t & 8; - } else { + } + else + { vadr += t; vadr += t & 8; } @@ -1477,21 +1739,27 @@ static void FetchSpriteData(void) { dst.x = spr->x; dst.atr = spr->atr; - *(uint32*)&SPRBUF[ns << 2] = *(uint32*)&dst; + *(uint32 *)&SPRBUF[ns << 2] = *(uint32 *)&dst; } ns++; - } else { + } + else + { PPU_status |= 0x20; break; } } else - for (n = 63; n >= 0; n--, spr++) { - if ((uint32)(scanline - spr->y) >= H) continue; + for (n = 63; n >= 0; n--, spr++) + { + if ((uint32)(scanline - spr->y) >= H) + continue; - if (ns < maxsprites) { - if (n == 63) sb = 1; + if (ns < maxsprites) + { + if (n == 63) + sb = 1; { SPRB dst; @@ -1506,12 +1774,15 @@ static void FetchSpriteData(void) { else vadr = (spr->no << 4) + vofs; - if (spr->atr & V_FLIP) { + if (spr->atr & V_FLIP) + { vadr += 7; vadr -= t; vadr += (P0 & 0x20) >> 1; vadr -= t & 8; - } else { + } + else + { vadr += t; vadr += t & 8; } @@ -1523,7 +1794,8 @@ static void FetchSpriteData(void) { if (SpriteON) RENDER_LOGP(C); dst.ca[0] = C[0]; - if (ns < 8) { + if (ns < 8) + { PPU_hook(0x2000); PPU_hook(vadr); } @@ -1533,21 +1805,25 @@ static void FetchSpriteData(void) { dst.x = spr->x; dst.atr = spr->atr; - - *(uint32*)&SPRBUF[ns << 2] = *(uint32*)&dst; + *(uint32 *)&SPRBUF[ns << 2] = *(uint32 *)&dst; } ns++; - } else { + } + else + { PPU_status |= 0x20; break; } } - //Handle case when >8 sprites per scanline option is enabled. - if (ns > 8) PPU_status |= 0x20; - else if (PPU_hook) { - for (n = 0; n < (8 - ns); n++) { + // Handle case when >8 sprites per scanline option is enabled. + if (ns > 8) + PPU_status |= 0x20; + else if (PPU_hook) + { + for (n = 0; n < (8 - ns); n++) + { PPU_hook(0x2000); PPU_hook(vofs); } @@ -1556,18 +1832,21 @@ static void FetchSpriteData(void) { SpriteBlurp = sb; } -static void RefreshSprites(void) { +static void RefreshSprites(void) +{ int n; SPRB *spr; spork = 0; - if (!numsprites) return; + if (!numsprites) + return; FCEU_dwmemset(sprlinebuf, 0x80808080, 256); numsprites--; - spr = (SPRB*)SPRBUF + numsprites; + spr = (SPRB *)SPRBUF + numsprites; - for (n = numsprites; n >= 0; n--, spr--) { + for (n = numsprites; n >= 0; n--, spr--) + { uint32 pixdata; uint8 J, atr; @@ -1579,91 +1858,134 @@ static void RefreshSprites(void) { J = spr->ca[0] | spr->ca[1]; atr = spr->atr; - if (J) { - if (n == 0 && SpriteBlurp && !(PPU_status & 0x40)) { + if (J) + { + if (n == 0 && SpriteBlurp && !(PPU_status & 0x40)) + { sphitx = x; sphitdata = J; if (atr & H_FLIP) sphitdata = ((J << 7) & 0x80) | - ((J << 5) & 0x40) | - ((J << 3) & 0x20) | - ((J << 1) & 0x10) | - ((J >> 1) & 0x08) | - ((J >> 3) & 0x04) | - ((J >> 5) & 0x02) | - ((J >> 7) & 0x01); + ((J << 5) & 0x40) | + ((J << 3) & 0x20) | + ((J << 1) & 0x10) | + ((J >> 1) & 0x08) | + ((J >> 3) & 0x04) | + ((J >> 5) & 0x02) | + ((J >> 7) & 0x01); } C = sprlinebuf + x; VB = (0x10) + ((atr & 3) << 2); - if (atr & SP_BACK) { - if (atr & H_FLIP) { - if (J & 0x80) C[7] = READPAL(VB | (pixdata & 3)) | 0x40; + if (atr & SP_BACK) + { + if (atr & H_FLIP) + { + if (J & 0x80) + C[7] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x40) C[6] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x40) + C[6] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x20) C[5] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x20) + C[5] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x10) C[4] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x10) + C[4] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x08) C[3] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x08) + C[3] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x04) C[2] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x04) + C[2] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x02) C[1] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x02) + C[1] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x01) C[0] = READPAL(VB | pixdata) | 0x40; - } else { - if (J & 0x80) C[0] = READPAL(VB | (pixdata & 3)) | 0x40; - pixdata >>= 4; - if (J & 0x40) C[1] = READPAL(VB | (pixdata & 3)) | 0x40; - pixdata >>= 4; - if (J & 0x20) C[2] = READPAL(VB | (pixdata & 3)) | 0x40; - pixdata >>= 4; - if (J & 0x10) C[3] = READPAL(VB | (pixdata & 3)) | 0x40; - pixdata >>= 4; - if (J & 0x08) C[4] = READPAL(VB | (pixdata & 3)) | 0x40; - pixdata >>= 4; - if (J & 0x04) C[5] = READPAL(VB | (pixdata & 3)) | 0x40; - pixdata >>= 4; - if (J & 0x02) C[6] = READPAL(VB | (pixdata & 3)) | 0x40; - pixdata >>= 4; - if (J & 0x01) C[7] = READPAL(VB | pixdata) | 0x40; + if (J & 0x01) + C[0] = READPAL(VB | pixdata) | 0x40; } - } else { - if (atr & H_FLIP) { - if (J & 0x80) C[7] = READPAL(VB | (pixdata & 3)); + else + { + if (J & 0x80) + C[0] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x40) C[6] = READPAL(VB | (pixdata & 3)); + if (J & 0x40) + C[1] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x20) C[5] = READPAL(VB | (pixdata & 3)); + if (J & 0x20) + C[2] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x10) C[4] = READPAL(VB | (pixdata & 3)); + if (J & 0x10) + C[3] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x08) C[3] = READPAL(VB | (pixdata & 3)); + if (J & 0x08) + C[4] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x04) C[2] = READPAL(VB | (pixdata & 3)); + if (J & 0x04) + C[5] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x02) C[1] = READPAL(VB | (pixdata & 3)); + if (J & 0x02) + C[6] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x01) C[0] = READPAL(VB | pixdata); - } else { - if (J & 0x80) C[0] = READPAL(VB | (pixdata & 3)); + if (J & 0x01) + C[7] = READPAL(VB | pixdata) | 0x40; + } + } + else + { + if (atr & H_FLIP) + { + if (J & 0x80) + C[7] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x40) C[1] = READPAL(VB | (pixdata & 3)); + if (J & 0x40) + C[6] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x20) C[2] = READPAL(VB | (pixdata & 3)); + if (J & 0x20) + C[5] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x10) C[3] = READPAL(VB | (pixdata & 3)); + if (J & 0x10) + C[4] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x08) C[4] = READPAL(VB | (pixdata & 3)); + if (J & 0x08) + C[3] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x04) C[5] = READPAL(VB | (pixdata & 3)); + if (J & 0x04) + C[2] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x02) C[6] = READPAL(VB | (pixdata & 3)); + if (J & 0x02) + C[1] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x01) C[7] = READPAL(VB | pixdata); + if (J & 0x01) + C[0] = READPAL(VB | pixdata); + } + else + { + if (J & 0x80) + C[0] = READPAL(VB | (pixdata & 3)); + pixdata >>= 4; + if (J & 0x40) + C[1] = READPAL(VB | (pixdata & 3)); + pixdata >>= 4; + if (J & 0x20) + C[2] = READPAL(VB | (pixdata & 3)); + pixdata >>= 4; + if (J & 0x10) + C[3] = READPAL(VB | (pixdata & 3)); + pixdata >>= 4; + if (J & 0x08) + C[4] = READPAL(VB | (pixdata & 3)); + pixdata >>= 4; + if (J & 0x04) + C[5] = READPAL(VB | (pixdata & 3)); + pixdata >>= 4; + if (J & 0x02) + C[6] = READPAL(VB | (pixdata & 3)); + pixdata >>= 4; + if (J & 0x01) + C[7] = READPAL(VB | pixdata); } } } @@ -1672,53 +1994,64 @@ static void RefreshSprites(void) { spork = 1; } -static void CopySprites(uint8 *target) { +static void CopySprites(uint8 *target) +{ uint8 *P = target; - if (!spork) return; + if (!spork) + return; spork = 0; - if (!rendersprites) return; //User asked to not display sprites. + if (!rendersprites) + return; // User asked to not display sprites. - if(!SpriteON) return; - - int start=8; - if(PPU[1] & 0x04) + if (!SpriteON) + return; + + int start = 8; + if (PPU[1] & 0x04) start = 0; - for(int i=start;i<256;i++) + for (int i = start; i < 256; i++) { uint8 t = sprlinebuf[i]; - if(!(t&0x80)) - if (!(t & 0x40) || (P[i] & 0x40)) // Normal sprite || behind bg sprite + if (!(t & 0x80)) + if (!(t & 0x40) || (P[i] & 0x40)) // Normal sprite || behind bg sprite P[i] = t; } } -void FCEUPPU_SetVideoSystem(int w) { - if (w) { - scanlines_per_frame = dendy ? 262: 312; +void FCEUPPU_SetVideoSystem(int w) +{ + if (w) + { + scanlines_per_frame = dendy ? 262 : 312; FSettings.FirstSLine = FSettings.UsrFirstSLine[1]; FSettings.LastSLine = FSettings.UsrLastSLine[1]; - //paldeemphswap = 1; // dendy has pal ppu, and pal ppu has these swapped - } else { + // paldeemphswap = 1; // dendy has pal ppu, and pal ppu has these swapped + } + else + { scanlines_per_frame = 262; FSettings.FirstSLine = FSettings.UsrFirstSLine[0]; FSettings.LastSLine = FSettings.UsrLastSLine[0]; - //paldeemphswap = 0; + // paldeemphswap = 0; } } -//Initializes the PPU -void FCEUPPU_Init(void) { +// Initializes the PPU +void FCEUPPU_Init(void) +{ makeppulut(); } -void PPU_ResetHooks() { +void PPU_ResetHooks() +{ FFCEUX_PPURead = FFCEUX_PPURead_Default; } -void FCEUPPU_Reset(void) { +void FCEUPPU_Reset(void) +{ VRAMBuffer = PPU[0] = PPU[1] = PPU_status = PPU[3] = 0; PPUSPL = 0; PPUGenLatch = 0; @@ -1731,7 +2064,8 @@ void FCEUPPU_Reset(void) { new_ppu_reset = true; // delay reset of ppur/spr_read until it's ready to start a new frame } -void FCEUPPU_Power(void) { +void FCEUPPU_Power(void) +{ int x; // initialize PPU memory regions according to settings @@ -1739,7 +2073,8 @@ void FCEUPPU_Power(void) { FCEU_MemoryRand(PALRAM, 0x20, true); FCEU_MemoryRand(SPRAM, 0x100, true); // palettes can only store values up to $3F, and PALRAM X4/X8/XC are mirrors of X0 for rendering purposes (UPALRAM is used for $2007 readback) - for (x = 0; x < 0x20; ++x) PALRAM[x] &= 0x3F; + for (x = 0; x < 0x20; ++x) + PALRAM[x] &= 0x3F; UPALRAM[0] = PALRAM[0x04]; UPALRAM[1] = PALRAM[0x08]; UPALRAM[2] = PALRAM[0x0C]; @@ -1747,7 +2082,8 @@ void FCEUPPU_Power(void) { PALRAM[0x1C] = PALRAM[0x18] = PALRAM[0x14] = PALRAM[0x10]; FCEUPPU_Reset(); - for (x = 0x2000; x < 0x4000; x += 8) { + for (x = 0x2000; x < 0x4000; x += 8) + { ARead[x] = A200x; BWrite[x] = B2000; ARead[x + 1] = A200x; @@ -1768,37 +2104,45 @@ void FCEUPPU_Power(void) { BWrite[0x4014] = B4014; } -int FCEUPPU_Loop(int skip) { - if ((newppu) && (GameInfo->type != GIT_NSF)) { +int FCEUPPU_Loop(int skip) +{ + if ((newppu) && (GameInfo->type != GIT_NSF)) + { int FCEUX_PPU_Loop(int skip); return FCEUX_PPU_Loop(skip); } - //Needed for Knight Rider, possibly others. - if (ppudead) { + // Needed for Knight Rider, possibly others. + if (ppudead) + { memset(XBuf, 0x80, 256 * 240); X6502_Run(scanlines_per_frame * (256 + 85)); ppudead--; - } else { + } + else + { X6502_Run(256 + 85); PPU_status |= 0x80; - //Not sure if this is correct. According to Matt Conte and my own tests, it is. - //Timing is probably off, though. - //NOTE: Not having this here breaks a Super Donkey Kong game. + // Not sure if this is correct. According to Matt Conte and my own tests, it is. + // Timing is probably off, though. + // NOTE: Not having this here breaks a Super Donkey Kong game. PPU[3] = PPUSPL = 0; - //I need to figure out the true nature and length of this delay. + // I need to figure out the true nature and length of this delay. X6502_Run(12); if (GameInfo->type == GIT_NSF) DoNSFFrame(); - else { + else + { if (VBlankON) TriggerNMI(); } X6502_Run((scanlines_per_frame - 242) * (256 + 85) - 12); - if (overclock_enabled && vblankscanlines) { - if (!DMC_7bit || !skip_7bit_overclocking) { + if (overclock_enabled && vblankscanlines) + { + if (!DMC_7bit || !skip_7bit_overclocking) + { overclocking = 1; X6502_Run(vblankscanlines * (256 + 85) - 12); overclocking = 0; @@ -1810,23 +2154,28 @@ int FCEUPPU_Loop(int skip) { { int x; - if (ScreenON || SpriteON) { + if (ScreenON || SpriteON) + { if (GameHBIRQHook && ((PPU[0] & 0x38) != 0x18)) GameHBIRQHook(); if (PPU_hook) - for (x = 0; x < 42; x++) { - PPU_hook(0x2000); PPU_hook(0); + for (x = 0; x < 42; x++) + { + PPU_hook(0x2000); + PPU_hook(0); } if (GameHBIRQHook2) GameHBIRQHook2(); } X6502_Run(85 - 16); - if (ScreenON || SpriteON) { + if (ScreenON || SpriteON) + { RefreshAddr = TempAddr; - if (PPU_hook) PPU_hook(RefreshAddr & 0x3fff); + if (PPU_hook) + PPU_hook(RefreshAddr & 0x3fff); } - //Clean this stuff up later. + // Clean this stuff up later. spork = numsprites = 0; ResetRL(XBuf); @@ -1835,31 +2184,40 @@ int FCEUPPU_Loop(int skip) { } if (GameInfo->type == GIT_NSF) X6502_Run((256 + 85) * normalscanlines); - #ifdef FRAMESKIP - else if (skip) { +#ifdef FRAMESKIP + else if (skip) + { int y; y = SPRAM[0]; y++; - PPU_status |= 0x20; // Fixes "Bee 52". Does it break anything? - if (GameHBIRQHook) { + PPU_status |= 0x20; // Fixes "Bee 52". Does it break anything? + if (GameHBIRQHook) + { X6502_Run(256); - for (scanline = 0; scanline < 240; scanline++) { + for (scanline = 0; scanline < 240; scanline++) + { if (ScreenON || SpriteON) GameHBIRQHook(); - if (scanline == y && SpriteON) PPU_status |= 0x40; + if (scanline == y && SpriteON) + PPU_status |= 0x40; X6502_Run((scanline == 239) ? 85 : (256 + 85)); } - } else if (y < 240) { + } + else if (y < 240) + { X6502_Run((256 + 85) * y); - if (SpriteON) PPU_status |= 0x40; // Quick and very dirty hack. + if (SpriteON) + PPU_status |= 0x40; // Quick and very dirty hack. X6502_Run((256 + 85) * (240 - y)); - } else + } + else X6502_Run((256 + 85) * 240); } - #endif - else { +#endif + else + { deemp = PPU[1] >> 5; // manual samples can't play correctly with overclocking @@ -1868,7 +2226,8 @@ int FCEUPPU_Loop(int skip) { else totalscanlines = normalscanlines + (overclock_enabled ? postrenderscanlines : 0); - for (scanline = 0; scanline < totalscanlines; ) { //scanline is incremented in DoLine. Evil. :/ + for (scanline = 0; scanline < totalscanlines;) + { // scanline is incremented in DoLine. Evil. :/ deempcnt[deemp]++; if (scanline < 240) @@ -1878,7 +2237,8 @@ int FCEUPPU_Loop(int skip) { if (scanline < normalscanlines || scanline == totalscanlines) overclocking = 0; - else { + else + { if (DMC_7bit && skip_7bit_overclocking) // 7bit sample started after 240th line break; overclocking = 1; @@ -1886,12 +2246,15 @@ int FCEUPPU_Loop(int skip) { } DMC_7bit = 0; - if (MMC5Hack) MMC5_hb(scanline); + if (MMC5Hack) + MMC5_hb(scanline); - //deemph nonsense, kept for complicated reasons (see SetNESDeemph_OldHacky implementation) + // deemph nonsense, kept for complicated reasons (see SetNESDeemph_OldHacky implementation) int maxref = 0; - for (int x = 1, max = 0; x < 7; x++) { - if (deempcnt[x] > max) { + for (int x = 1, max = 0; x < 7; x++) + { + if (deempcnt[x] > max) + { max = deempcnt[x]; maxref = x; } @@ -1899,16 +2262,18 @@ int FCEUPPU_Loop(int skip) { } SetNESDeemph_OldHacky(maxref, 0); } - } //else... to if(ppudead) + } // else... to if(ppudead) - #ifdef FRAMESKIP - if (skip) { - FCEU_PutImageDummy(); - return(0); - } else - #endif +#ifdef FRAMESKIP + if (skip) { - return(1); + FCEU_PutImageDummy(); + return (0); + } + else +#endif + { + return (1); } } @@ -1916,64 +2281,64 @@ int (*PPU_MASTER)(int skip) = FCEUPPU_Loop; static uint16 TempAddrT, RefreshAddrT; -void FCEUPPU_LoadState(int version) { +void FCEUPPU_LoadState(int version) +{ TempAddr = TempAddrT; RefreshAddr = RefreshAddrT; } SFORMAT FCEUPPU_STATEINFO[] = { - { NTARAM, 0x800, "NTAR" }, - { PALRAM, 0x20, "PRAM" }, - { SPRAM, 0x100, "SPRA" }, - { PPU, 0x4, "PPUR" }, - { &kook, 1, "KOOK" }, - { &ppudead, 1, "DEAD" }, - { &PPUSPL, 1, "PSPL" }, - { &XOffset, 1, "XOFF" }, - { &vtoggle, 1, "VTGL" }, - { &RefreshAddrT, 2 | FCEUSTATE_RLSB, "RADD" }, - { &TempAddrT, 2 | FCEUSTATE_RLSB, "TADD" }, - { &VRAMBuffer, 1, "VBUF" }, - { &PPUGenLatch, 1, "PGEN" }, - { 0 } -}; + {NTARAM, 0x800, "NTAR"}, + {PALRAM, 0x20, "PRAM"}, + {SPRAM, 0x100, "SPRA"}, + {PPU, 0x4, "PPUR"}, + {&kook, 1, "KOOK"}, + {&ppudead, 1, "DEAD"}, + {&PPUSPL, 1, "PSPL"}, + {&XOffset, 1, "XOFF"}, + {&vtoggle, 1, "VTGL"}, + {&RefreshAddrT, 2 | FCEUSTATE_RLSB, "RADD"}, + {&TempAddrT, 2 | FCEUSTATE_RLSB, "TADD"}, + {&VRAMBuffer, 1, "VBUF"}, + {&PPUGenLatch, 1, "PGEN"}, + {0}}; SFORMAT FCEU_NEWPPU_STATEINFO[] = { - { &idleSynch, 1, "IDLS" }, - { &spr_read.num, 4 | FCEUSTATE_RLSB, "SR_0" }, - { &spr_read.count, 4 | FCEUSTATE_RLSB, "SR_1" }, - { &spr_read.fetch, 4 | FCEUSTATE_RLSB, "SR_2" }, - { &spr_read.found, 4 | FCEUSTATE_RLSB, "SR_3" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx0" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx1" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx2" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx3" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx4" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx5" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx6" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx7" }, - { &spr_read.ret, 4 | FCEUSTATE_RLSB, "SR_4" }, - { &spr_read.last, 4 | FCEUSTATE_RLSB, "SR_5" }, - { &spr_read.mode, 4 | FCEUSTATE_RLSB, "SR_6" }, - { &ppur.fv, 4 | FCEUSTATE_RLSB, "PFVx" }, - { &ppur.v, 4 | FCEUSTATE_RLSB, "PVxx" }, - { &ppur.h, 4 | FCEUSTATE_RLSB, "PHxx" }, - { &ppur.vt, 4 | FCEUSTATE_RLSB, "PVTx" }, - { &ppur.ht, 4 | FCEUSTATE_RLSB, "PHTx" }, - { &ppur._fv, 4 | FCEUSTATE_RLSB, "P_FV" }, - { &ppur._v, 4 | FCEUSTATE_RLSB, "P_Vx" }, - { &ppur._h, 4 | FCEUSTATE_RLSB, "P_Hx" }, - { &ppur._vt, 4 | FCEUSTATE_RLSB, "P_VT" }, - { &ppur._ht, 4 | FCEUSTATE_RLSB, "P_HT" }, - { &ppur.fh, 4 | FCEUSTATE_RLSB, "PFHx" }, - { &ppur.s, 4 | FCEUSTATE_RLSB, "PSxx" }, - { &ppur.status.sl, 4 | FCEUSTATE_RLSB, "PST0" }, - { &ppur.status.cycle, 4 | FCEUSTATE_RLSB, "PST1" }, - { &ppur.status.end_cycle, 4 | FCEUSTATE_RLSB, "PST2" }, - { 0 } -}; + {&idleSynch, 1, "IDLS"}, + {&spr_read.num, 4 | FCEUSTATE_RLSB, "SR_0"}, + {&spr_read.count, 4 | FCEUSTATE_RLSB, "SR_1"}, + {&spr_read.fetch, 4 | FCEUSTATE_RLSB, "SR_2"}, + {&spr_read.found, 4 | FCEUSTATE_RLSB, "SR_3"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx0"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx1"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx2"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx3"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx4"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx5"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx6"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx7"}, + {&spr_read.ret, 4 | FCEUSTATE_RLSB, "SR_4"}, + {&spr_read.last, 4 | FCEUSTATE_RLSB, "SR_5"}, + {&spr_read.mode, 4 | FCEUSTATE_RLSB, "SR_6"}, + {&ppur.fv, 4 | FCEUSTATE_RLSB, "PFVx"}, + {&ppur.v, 4 | FCEUSTATE_RLSB, "PVxx"}, + {&ppur.h, 4 | FCEUSTATE_RLSB, "PHxx"}, + {&ppur.vt, 4 | FCEUSTATE_RLSB, "PVTx"}, + {&ppur.ht, 4 | FCEUSTATE_RLSB, "PHTx"}, + {&ppur._fv, 4 | FCEUSTATE_RLSB, "P_FV"}, + {&ppur._v, 4 | FCEUSTATE_RLSB, "P_Vx"}, + {&ppur._h, 4 | FCEUSTATE_RLSB, "P_Hx"}, + {&ppur._vt, 4 | FCEUSTATE_RLSB, "P_VT"}, + {&ppur._ht, 4 | FCEUSTATE_RLSB, "P_HT"}, + {&ppur.fh, 4 | FCEUSTATE_RLSB, "PFHx"}, + {&ppur.s, 4 | FCEUSTATE_RLSB, "PSxx"}, + {&ppur.status.sl, 4 | FCEUSTATE_RLSB, "PST0"}, + {&ppur.status.cycle, 4 | FCEUSTATE_RLSB, "PST1"}, + {&ppur.status.end_cycle, 4 | FCEUSTATE_RLSB, "PST2"}, + {0}}; -void FCEUPPU_SaveState(void) { +void FCEUPPU_SaveState(void) +{ TempAddrT = TempAddr; RefreshAddrT = RefreshAddr; } @@ -1994,7 +2359,8 @@ int totpputime = 0; const int kLineTime = 341; const int kFetchTime = 2; -void runppu(int x) { +void runppu(int x) +{ ppur.status.cycle = (ppur.status.cycle + x) % ppur.status.end_cycle; if (!new_ppu_reset) // if resetting, suspend CPU until the first frame { @@ -2002,17 +2368,21 @@ void runppu(int x) { } } -//todo - consider making this a 3 or 4 slot fifo to keep from touching so much memory -struct BGData { - struct Record { +// todo - consider making this a 3 or 4 slot fifo to keep from touching so much memory +struct BGData +{ + struct Record + { uint8 nt, pecnt, at, pt[2], qtnt; uint8 ppu1[8]; - INLINE void Read() { + INLINE void Read() + { NTRefreshAddr = RefreshAddr = ppur.get_ntread(); if (PEC586Hack) ppur.s = (RefreshAddr & 0x200) >> 9; - else if (QTAIHack) { + else if (QTAIHack) + { qtnt = QTAINTRAM[((((RefreshAddr >> 10) & 3) >> ((qtaintramreg >> 1)) & 1) << 10) | (RefreshAddr & 0x3FF)]; ppur.s = qtnt & 0x3F; } @@ -2023,21 +2393,22 @@ struct BGData { ppu1[1] = PPU[1]; runppu(1); - - RefreshAddr = ppur.get_atread(); at = CALL_PPUREAD(RefreshAddr); - //modify at to get appropriate palette shift - if (ppur.vt & 2) at >>= 4; - if (ppur.ht & 2) at >>= 2; + // modify at to get appropriate palette shift + if (ppur.vt & 2) + at >>= 4; + if (ppur.ht & 2) + at >>= 2; at &= 0x03; at <<= 2; - //horizontal scroll clocked at cycle 3 and then - //vertical scroll at 251 + // horizontal scroll clocked at cycle 3 and then + // vertical scroll at 251 ppu1[2] = PPU[1]; runppu(1); - if (PPUON) { + if (PPUON) + { ppur.increment_hsc(); if (ppur.status.cycle == 251) ppur.increment_vs(); @@ -2047,7 +2418,8 @@ struct BGData { ppur.par = nt; RefreshAddr = ppur.get_ptread(); - if (PEC586Hack) { + if (PEC586Hack) + { pt[0] = CALL_PPUREAD(RefreshAddr | pecnt); ppu1[4] = PPU[1]; runppu(1); @@ -2058,7 +2430,9 @@ struct BGData { runppu(1); ppu1[7] = PPU[1]; runppu(1); - } else if (QTAIHack && (qtnt & 0x40)) { + } + else if (QTAIHack && (qtnt & 0x40)) + { pt[0] = *(CHRptr[0] + RefreshAddr); ppu1[4] = PPU[1]; runppu(1); @@ -2070,7 +2444,9 @@ struct BGData { runppu(1); ppu1[7] = PPU[1]; runppu(1); - } else { + } + else + { if (ScreenON) RENDER_LOG(RefreshAddr); pt[0] = CALL_PPUREAD(RefreshAddr); @@ -2090,10 +2466,11 @@ struct BGData { } }; - Record main[34]; //one at the end is junk, it can never be rendered + Record main[34]; // one at the end is junk, it can never be rendered } bgdata; -static inline int PaletteAdjustPixel(int pixel) { +static inline int PaletteAdjustPixel(int pixel) +{ if ((PPU[1] >> 5) == 0x7) return (pixel & 0x3f) | 0xc0; else if (PPU[1] & 0xE0) @@ -2103,7 +2480,8 @@ static inline int PaletteAdjustPixel(int pixel) { } int framectr = 0; -int FCEUX_PPU_Loop(int skip) { +int FCEUX_PPU_Loop(int skip) +{ if (new_ppu_reset) // first frame since reset, time to initialize { @@ -2112,8 +2490,9 @@ int FCEUX_PPU_Loop(int skip) { new_ppu_reset = false; } - //262 scanlines - if (ppudead) { + // 262 scanlines + if (ppudead) + { // not quite emulating all the NES power up behavior // since it is known that the NES ignores writes to some // register before around a full frame, but no games @@ -2134,53 +2513,54 @@ int FCEUX_PPU_Loop(int skip) { PPU_status |= 0x80; ppuphase = PPUPHASE_VBL; - //Not sure if this is correct. According to Matt Conte and my own tests, it is. - //Timing is probably off, though. - //NOTE: Not having this here breaks a Super Donkey Kong game. + // Not sure if this is correct. According to Matt Conte and my own tests, it is. + // Timing is probably off, though. + // NOTE: Not having this here breaks a Super Donkey Kong game. PPU[3] = PPUSPL = 0; - const int delay = 20; //fceu used 12 here but I couldnt get it to work in marble madness and pirates. + const int delay = 20; // fceu used 12 here but I couldnt get it to work in marble madness and pirates. - ppur.status.sl = 241; //for sprite reads + ppur.status.sl = 241; // for sprite reads - //formerly: runppu(delay); - for(int dot=0;dot 0 || SpriteLeft8); const bool renderbgnow = ScreenON && (xt > 0 || BGLeft8); - for (int xp = 0; xp < 8; xp++, rasterpos++, g_rasterpos++) { - //bg pos is different from raster pos due to its offsetability. - //so adjust for that here + for (int xp = 0; xp < 8; xp++, rasterpos++, g_rasterpos++) + { + // bg pos is different from raster pos due to its offsetability. + // so adjust for that here const int bgpos = rasterpos + ppur.fh; const int bgpx = bgpos & 7; const int bgtile = bgpos >> 3; @@ -2243,7 +2626,7 @@ int FCEUX_PPU_Loop(int skip) { uint8 pixel = 0; uint8 pixelcolor = blank; - //according to qeed's doc, use palette 0 or $2006's value if it is & 0x3Fxx + // according to qeed's doc, use palette 0 or $2006's value if it is & 0x3Fxx if (!ScreenON && !SpriteON) { // if there's anything wrong with how we're doing this, someone please chime in @@ -2255,54 +2638,63 @@ int FCEUX_PPU_Loop(int skip) { pixelcolor = READPAL_MOTHEROFALL(pixel); } - //generate the BG data - if (renderbgnow) { - uint8* pt = bgdata.main[bgtile].pt; + // generate the BG data + if (renderbgnow) + { + uint8 *pt = bgdata.main[bgtile].pt; pixel = ((pt[0] >> (7 - bgpx)) & 1) | (((pt[1] >> (7 - bgpx)) & 1) << 1) | bgdata.main[bgtile].at; } if (renderbg) pixelcolor = READPALNOGS(pixel); - //look for a sprite to be drawn + // look for a sprite to be drawn bool havepixel = false; - for (int s = 0; s < oamcount; s++) { - uint8* oam = oams[renderslot][s]; + for (int s = 0; s < oamcount; s++) + { + uint8 *oam = oams[renderslot][s]; int x = oam[3]; - if (rasterpos >= x && rasterpos < x + 8) { - //build the pixel. - //fetch the LSB of the patterns + if (rasterpos >= x && rasterpos < x + 8) + { + // build the pixel. + // fetch the LSB of the patterns uint8 spixel = oam[4] & 1; spixel |= (oam[5] & 1) << 1; - //shift down the patterns so the next pixel is in the LSB + // shift down the patterns so the next pixel is in the LSB oam[4] >>= 1; oam[5] >>= 1; - if (!renderspritenow) continue; + if (!renderspritenow) + continue; - //bail out if we already have a pixel from a higher priority sprite - if (havepixel) continue; + // bail out if we already have a pixel from a higher priority sprite + if (havepixel) + continue; - //transparent pixel bailout - if (spixel == 0) continue; + // transparent pixel bailout + if (spixel == 0) + continue; - //spritehit: - //1. is it sprite#0? - //2. is the bg pixel nonzero? - //then, it is spritehit. + // spritehit: + // 1. is it sprite#0? + // 2. is the bg pixel nonzero? + // then, it is spritehit. if (oam[6] == 0 && (pixel & 3) != 0 && - rasterpos < 255) { + rasterpos < 255) + { PPU_status |= 0x40; } havepixel = true; - //priority handling - if (oam[2] & 0x20) { - //behind background: - if ((pixel & 3) != 0) continue; + // priority handling + if (oam[2] & 0x20) + { + // behind background: + if ((pixel & 3) != 0) + continue; } - //bring in the palette bits and palettize + // bring in the palette bits and palettize spixel |= (oam[2] & 3) << 2; if (rendersprites) @@ -2310,173 +2702,190 @@ int FCEUX_PPU_Loop(int skip) { } } - //apply grayscale.. kind of clunky - //really we need to read the entire palette instead of just ppu1 - //this will be needed for special color effects probably (very fine rainbows and whatnot?) - //are you allowed to chang the palette mid-line anyway? well you can definitely change the grayscale flag as we know from the FF1 "polygon" effect - if(bgdata.main[xt+2].ppu1[xp]&1) + // apply grayscale.. kind of clunky + // really we need to read the entire palette instead of just ppu1 + // this will be needed for special color effects probably (very fine rainbows and whatnot?) + // are you allowed to chang the palette mid-line anyway? well you can definitely change the grayscale flag as we know from the FF1 "polygon" effect + if (bgdata.main[xt + 2].ppu1[xp] & 1) pixelcolor &= 0x30; - //this does deemph stuff inside it.. which is probably wrong... + // this does deemph stuff inside it.. which is probably wrong... *ptr = PaletteAdjustPixel(pixelcolor); ptr++; - //grab deemph.. - //I guess this works the same way as the grayscale, ideally? - *dptr++ = bgdata.main[xt+2].ppu1[xp]>>5; + // grab deemph.. + // I guess this works the same way as the grayscale, ideally? + *dptr++ = bgdata.main[xt + 2].ppu1[xp] >> 5; } } } - //look for sprites (was supposed to run concurrent with bg rendering) + // look for sprites (was supposed to run concurrent with bg rendering) oamcounts[scanslot] = 0; oamcount = 0; const int spriteHeight = Sprite16 ? 16 : 8; - for (int i = 0; i < 64; i++) { + for (int i = 0; i < 64; i++) + { oams[scanslot][oamcount][7] = 0; - uint8* spr = SPRAM + i * 4; - if (yp >= spr[0] && yp < spr[0] + spriteHeight) { - //if we already have maxsprites, then this new one causes an overflow, - //set the flag and bail out. - if (oamcount >= 8 && PPUON) { + uint8 *spr = SPRAM + i * 4; + if (yp >= spr[0] && yp < spr[0] + spriteHeight) + { + // if we already have maxsprites, then this new one causes an overflow, + // set the flag and bail out. + if (oamcount >= 8 && PPUON) + { PPU_status |= 0x20; if (maxsprites == 8) break; } - //just copy some bytes into the internal sprite buffer + // just copy some bytes into the internal sprite buffer for (int j = 0; j < 4; j++) oams[scanslot][oamcount][j] = spr[j]; oams[scanslot][oamcount][7] = 1; - //note that we stuff the oam index into [6]. - //i need to turn this into a struct so we can have fewer magic numbers + // note that we stuff the oam index into [6]. + // i need to turn this into a struct so we can have fewer magic numbers oams[scanslot][oamcount][6] = (uint8)i; oamcount++; } } oamcounts[scanslot] = oamcount; - //FV is clocked by the PPU's horizontal blanking impulse, and therefore will increment every scanline. - //well, according to (which?) tests, maybe at the end of hblank. - //but, according to what it took to get crystalis working, it is at the beginning of hblank. + // FV is clocked by the PPU's horizontal blanking impulse, and therefore will increment every scanline. + // well, according to (which?) tests, maybe at the end of hblank. + // but, according to what it took to get crystalis working, it is at the beginning of hblank. - //this is done at cycle 251 - //rendering scanline, it doesn't need to be scanline 0, - //because on the first scanline when the increment is 0, the vs_scroll is reloaded. - //if(PPUON && sl != 0) + // this is done at cycle 251 + // rendering scanline, it doesn't need to be scanline 0, + // because on the first scanline when the increment is 0, the vs_scroll is reloaded. + // if(PPUON && sl != 0) // ppur.increment_vs(); - //todo - think about clearing oams to a predefined value to force deterministic behavior + // todo - think about clearing oams to a predefined value to force deterministic behavior ppuphase = PPUPHASE_OBJ; - //fetch sprite patterns - for (int s = 0; s < maxsprites; s++) { - //if we have hit our eight sprite pattern and we dont have any more sprites, then bail + // fetch sprite patterns + for (int s = 0; s < maxsprites; s++) + { + // if we have hit our eight sprite pattern and we dont have any more sprites, then bail if (s == oamcount && s >= 8) break; - //if this is a real sprite sprite, then it is not above the 8 sprite limit. - //this is how we support the no 8 sprite limit feature. - //not that at some point we may need a virtual CALL_PPUREAD which just peeks and doesnt increment any counters - //this could be handy for the debugging tools also + // if this is a real sprite sprite, then it is not above the 8 sprite limit. + // this is how we support the no 8 sprite limit feature. + // not that at some point we may need a virtual CALL_PPUREAD which just peeks and doesnt increment any counters + // this could be handy for the debugging tools also const bool realSprite = (s < 8); - uint8* const oam = oams[scanslot][s]; + uint8 *const oam = oams[scanslot][s]; uint32 line = yp - oam[0]; - if (oam[2] & 0x80) //vflip + if (oam[2] & 0x80) // vflip line = spriteHeight - line - 1; uint32 patternNumber = oam[1]; uint32 patternAddress; - //create deterministic dummy fetch pattern - if (!oam[7]) { + // create deterministic dummy fetch pattern + if (!oam[7]) + { patternNumber = 0; line = 0; } - //8x16 sprite handling: - if (Sprite16) { + // 8x16 sprite handling: + if (Sprite16) + { uint32 bank = (patternNumber & 1) << 12; patternNumber = patternNumber & ~1; patternNumber |= (line >> 3); patternAddress = (patternNumber << 4) | bank; - } else { + } + else + { patternAddress = (patternNumber << 4) | (SpAdrHI << 9); } - //offset into the pattern for the current line. - //tricky: tall sprites have already had lines>8 taken care of by getting a new pattern number above. - //so we just need the line offset for the second pattern + // offset into the pattern for the current line. + // tricky: tall sprites have already had lines>8 taken care of by getting a new pattern number above. + // so we just need the line offset for the second pattern patternAddress += line & 7; - //garbage nametable fetches + // garbage nametable fetches int garbage_todo = 2; if (PPUON) { if (sl == 0 && ppur.status.cycle == 304) { runppu(1); - if (PPUON) ppur.install_latches(); + if (PPUON) + ppur.install_latches(); runppu(1); garbage_todo = 0; } if ((sl != 0 && sl < 241) && ppur.status.cycle == 256) { runppu(1); - //at 257: 3d world runner is ugly if we do this at 256 - if (PPUON) ppur.install_h_latches(); + // at 257: 3d world runner is ugly if we do this at 256 + if (PPUON) + ppur.install_h_latches(); runppu(1); garbage_todo = 0; } } - if (realSprite) runppu(garbage_todo); + if (realSprite) + runppu(garbage_todo); - //Dragon's Lair (Europe version mapper 4) - //does not set SpriteON in the beginning but it does - //set the bg on so if using the conditional SpriteON the MMC3 counter - //the counter will never count and no IRQs will be fired so use PPUON - if (((PPU[0] & 0x38) != 0x18) && s == 2 && PPUON) { + // Dragon's Lair (Europe version mapper 4) + // does not set SpriteON in the beginning but it does + // set the bg on so if using the conditional SpriteON the MMC3 counter + // the counter will never count and no IRQs will be fired so use PPUON + if (((PPU[0] & 0x38) != 0x18) && s == 2 && PPUON) + { //(The MMC3 scanline counter is based entirely on PPU A12, triggered on rising edges (after the line remains low for a sufficiently long period of time)) - //http://nesdevwiki.org/wiki/index.php/Nintendo_MMC3 - //test cases for timing: SMB3, Crystalis - //crystalis requires deferring this til somewhere in sprite [1,3] - //kirby requires deferring this til somewhere in sprite [2,5.. - //if (PPUON && GameHBIRQHook) { - if (GameHBIRQHook) { + // http://nesdevwiki.org/wiki/index.php/Nintendo_MMC3 + // test cases for timing: SMB3, Crystalis + // crystalis requires deferring this til somewhere in sprite [1,3] + // kirby requires deferring this til somewhere in sprite [2,5.. + // if (PPUON && GameHBIRQHook) { + if (GameHBIRQHook) + { GameHBIRQHook(); } } - //blind attempt to replicate old ppu functionality - if(s == 2 && PPUON) + // blind attempt to replicate old ppu functionality + if (s == 2 && PPUON) { - if (GameHBIRQHook2) { + if (GameHBIRQHook2) + { GameHBIRQHook2(); } } - if (realSprite) runppu(kFetchTime); + if (realSprite) + runppu(kFetchTime); - - //pattern table fetches + // pattern table fetches RefreshAddr = patternAddress; if (SpriteON) RENDER_LOG(RefreshAddr); oam[4] = CALL_PPUREAD(RefreshAddr); - if (realSprite) runppu(kFetchTime); + if (realSprite) + runppu(kFetchTime); RefreshAddr += 8; if (SpriteON) RENDER_LOG(RefreshAddr); oam[5] = CALL_PPUREAD(RefreshAddr); - if (realSprite) runppu(kFetchTime); + if (realSprite) + runppu(kFetchTime); - //hflip - if (!(oam[2] & 0x40)) { + // hflip + if (!(oam[2] & 0x40)) + { oam[4] = bitrevlut[oam[4]]; oam[5] = bitrevlut[oam[5]]; } @@ -2484,40 +2893,43 @@ int FCEUX_PPU_Loop(int skip) { ppuphase = PPUPHASE_BG; - //fetch BG: two tiles for next line + // fetch BG: two tiles for next line for (int xt = 0; xt < 2; xt++) bgdata.main[xt].Read(); - //I'm unclear of the reason why this particular access to memory is made. - //The nametable address that is accessed 2 times in a row here, is also the - //same nametable address that points to the 3rd tile to be rendered on the - //screen (or basically, the first nametable address that will be accessed when - //the PPU is fetching background data on the next scanline). + // I'm unclear of the reason why this particular access to memory is made. + // The nametable address that is accessed 2 times in a row here, is also the + // same nametable address that points to the 3rd tile to be rendered on the + // screen (or basically, the first nametable address that will be accessed when + // the PPU is fetching background data on the next scanline). //(not implemented yet) runppu(kFetchTime); - if (sl == 0) { + if (sl == 0) + { if (idleSynch && PPUON && !PAL) ppur.status.end_cycle = 340; else ppur.status.end_cycle = 341; idleSynch ^= 1; - } else + } + else ppur.status.end_cycle = 341; runppu(kFetchTime); - //After memory access 170, the PPU simply rests for 4 cycles (or the - //equivelant of half a memory access cycle) before repeating the whole - //pixel/scanline rendering process. If the scanline being rendered is the very - //first one on every second frame, then this delay simply doesn't exist. + // After memory access 170, the PPU simply rests for 4 cycles (or the + // equivelant of half a memory access cycle) before repeating the whole + // pixel/scanline rendering process. If the scanline being rendered is the very + // first one on every second frame, then this delay simply doesn't exist. if (ppur.status.end_cycle == 341) runppu(1); - } //scanline loop + } // scanline loop DMC_7bit = 0; - if (MMC5Hack) MMC5_hb(240); + if (MMC5Hack) + MMC5_hb(240); - //idle for one line + // idle for one line runppu(kLineTime); framectr++; } diff --git a/src/ppu.h b/src/ppu.h index b96694fd..cadd920c 100644 --- a/src/ppu.h +++ b/src/ppu.h @@ -16,7 +16,7 @@ void newppu_hacky_emergency_reset(); /* For cart.c and banksw.h, mostly */ extern uint8 NTARAM[0x800], *vnapage[4]; extern uint8 PPUNTARAM; -extern uint8 PPUCHRRAM; +extern uint16 PPUCHRRAM; void FCEUPPU_SaveState(void); void FCEUPPU_LoadState(int version); diff --git a/src/unif.h b/src/unif.h index bbef9ab6..a4e1bda0 100644 --- a/src/unif.h +++ b/src/unif.h @@ -63,6 +63,7 @@ void QTAi_Init(CartInfo *info); void NROM_Init(CartInfo *info); void Novel_Init(CartInfo *info); void RAINBOW13_Init(CartInfo *info); +void RAINBOW2_Init(CartInfo *info); void S74LS374NA_Init(CartInfo *info); void S74LS374N_Init(CartInfo *info); void S8259A_Init(CartInfo *info); diff --git a/vc/vc14_fceux.vcxproj b/vc/vc14_fceux.vcxproj index d599d8c4..e49dd4df 100644 --- a/vc/vc14_fceux.vcxproj +++ b/vc/vc14_fceux.vcxproj @@ -505,6 +505,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" + diff --git a/vc/vc14_fceux.vcxproj.filters b/vc/vc14_fceux.vcxproj.filters index 0234b90c..db19d9b6 100644 --- a/vc/vc14_fceux.vcxproj.filters +++ b/vc/vc14_fceux.vcxproj.filters @@ -1142,6 +1142,9 @@ boards + + boards +