From 423d9ba00dc608df40faa0a264f0ea96f0f19cba Mon Sep 17 00:00:00 2001
From: Tim Allen <screwtape@froup.com>
Date: Sat, 13 Aug 2011 13:51:29 +1000
Subject: [PATCH] Update to v081r01 release.

byuu says:

- EI takes an extra cycle to raise IME; fixes Bubble Bobble [for the
  Gameboy], and likely many more games [Jonas Quinn]
- nall/gameboy/cartridge.hpp descrambles MMM01 images (header can be at
  top or bottom of image now)
- screenshot timestamps use filename-yyyy-mm-dd hh.mm.ss.bmp format; so
  that they can save on Windows
- closing the emulator will switch to windowed mode first, so that
  geometry is preserved
---
 bsnes/gameboy/cartridge/mmm01/mmm01.cpp |  2 +-
 bsnes/gameboy/cpu/core/core.cpp         |  3 ++-
 bsnes/gameboy/cpu/cpu.cpp               |  1 +
 bsnes/gameboy/cpu/cpu.hpp               |  1 +
 bsnes/gameboy/cpu/serialization.cpp     |  1 +
 bsnes/gameboy/cpu/timing/opcode.cpp     | 10 ++++++++++
 bsnes/gameboy/cpu/timing/timing.hpp     |  1 +
 bsnes/nall/gameboy/cartridge.hpp        | 18 ++++++++++++++++--
 bsnes/snes/profile-performance.hpp      |  4 ++++
 bsnes/snes/snes.hpp                     |  2 +-
 bsnes/ui/interface.cpp                  |  7 ++++---
 bsnes/ui/main.cpp                       |  1 +
 12 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/bsnes/gameboy/cartridge/mmm01/mmm01.cpp b/bsnes/gameboy/cartridge/mmm01/mmm01.cpp
index 8eb0267c..4ad9fae0 100755
--- a/bsnes/gameboy/cartridge/mmm01/mmm01.cpp
+++ b/bsnes/gameboy/cartridge/mmm01/mmm01.cpp
@@ -55,7 +55,7 @@ void Cartridge::MMM01::mmio_write(uint16 addr, uint8 data) {
 
 void Cartridge::MMM01::power() {
   rom_mode = 0;
-  rom_base = 0x00;
+  rom_base = 0;
 
   ram_enable = false;
   rom_select = 0x01;
diff --git a/bsnes/gameboy/cpu/core/core.cpp b/bsnes/gameboy/cpu/core/core.cpp
index e1e226e2..04f72c96 100755
--- a/bsnes/gameboy/cpu/core/core.cpp
+++ b/bsnes/gameboy/cpu/core/core.cpp
@@ -580,7 +580,8 @@ void CPU::op_di() {
 }
 
 void CPU::op_ei() {
-  status.ime = 1;
+  status.ei = true;
+//status.ime = 1;
 }
 
 //jump commands
diff --git a/bsnes/gameboy/cpu/cpu.cpp b/bsnes/gameboy/cpu/cpu.cpp
index b78aac8b..d68a130d 100755
--- a/bsnes/gameboy/cpu/cpu.cpp
+++ b/bsnes/gameboy/cpu/cpu.cpp
@@ -114,6 +114,7 @@ void CPU::power() {
   status.clock = 0;
   status.halt = false;
   status.stop = false;
+  status.ei = false;
   status.ime = 0;
 
   status.p15 = 0;
diff --git a/bsnes/gameboy/cpu/cpu.hpp b/bsnes/gameboy/cpu/cpu.hpp
index cbfe193a..81d6337b 100755
--- a/bsnes/gameboy/cpu/cpu.hpp
+++ b/bsnes/gameboy/cpu/cpu.hpp
@@ -17,6 +17,7 @@ struct CPU : Processor, MMIO {
     unsigned clock;
     bool halt;
     bool stop;
+    bool ei;
     bool ime;
 
     //$ff00  JOYP
diff --git a/bsnes/gameboy/cpu/serialization.cpp b/bsnes/gameboy/cpu/serialization.cpp
index f122f97f..73eab0f6 100755
--- a/bsnes/gameboy/cpu/serialization.cpp
+++ b/bsnes/gameboy/cpu/serialization.cpp
@@ -21,6 +21,7 @@ void CPU::serialize(serializer &s) {
   s.integer(status.clock);
   s.integer(status.halt);
   s.integer(status.stop);
+  s.integer(status.ei);
   s.integer(status.ime);
 
   s.integer(status.p15);
diff --git a/bsnes/gameboy/cpu/timing/opcode.cpp b/bsnes/gameboy/cpu/timing/opcode.cpp
index b952e3d6..5774670b 100755
--- a/bsnes/gameboy/cpu/timing/opcode.cpp
+++ b/bsnes/gameboy/cpu/timing/opcode.cpp
@@ -1,18 +1,28 @@
 #ifdef CPU_CPP
 
 void CPU::op_io() {
+  cycle_edge();
   add_clocks(4);
 }
 
 uint8 CPU::op_read(uint16 addr) {
+  cycle_edge();
   uint8 r = bus.read(addr);
   add_clocks(4);
   return r;
 }
 
 void CPU::op_write(uint16 addr, uint8 data) {
+  cycle_edge();
   bus.write(addr, data);
   add_clocks(4);
 }
 
+void CPU::cycle_edge() {
+  if(status.ei) {
+    status.ei = false;
+    status.ime = 1;
+  }
+}
+
 #endif
diff --git a/bsnes/gameboy/cpu/timing/timing.hpp b/bsnes/gameboy/cpu/timing/timing.hpp
index 9fead0ea..04c1c5ce 100755
--- a/bsnes/gameboy/cpu/timing/timing.hpp
+++ b/bsnes/gameboy/cpu/timing/timing.hpp
@@ -9,3 +9,4 @@ void timer_4096hz();
 void op_io();
 uint8 op_read(uint16 addr);
 void op_write(uint16 addr, uint8 data);
+void cycle_edge();
diff --git a/bsnes/nall/gameboy/cartridge.hpp b/bsnes/nall/gameboy/cartridge.hpp
index 3ab00e34..af04e0bb 100755
--- a/bsnes/nall/gameboy/cartridge.hpp
+++ b/bsnes/nall/gameboy/cartridge.hpp
@@ -6,7 +6,7 @@ namespace nall {
 class GameBoyCartridge {
 public:
   string xml;
-  inline GameBoyCartridge(const uint8_t *data, unsigned size);
+  inline GameBoyCartridge(uint8_t *data, unsigned size);
 
 //private:
   struct Information {
@@ -21,7 +21,7 @@ public:
   } info;
 };
 
-GameBoyCartridge::GameBoyCartridge(const uint8_t *romdata, unsigned romsize) {
+GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
   xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
   if(romsize < 0x4000) return;
 
@@ -34,6 +34,20 @@ GameBoyCartridge::GameBoyCartridge(const uint8_t *romdata, unsigned romsize) {
   info.romsize = 0;
   info.ramsize = 0;
 
+  unsigned base = romsize - 0x8000;
+  if(romdata[base + 0x0104] == 0xce && romdata[base + 0x0105] == 0xed
+  && romdata[base + 0x0106] == 0x66 && romdata[base + 0x0107] == 0x66
+  && romdata[base + 0x0108] == 0xcc && romdata[base + 0x0109] == 0x0d
+  && romdata[base + 0x0147] >= 0x0b && romdata[base + 0x0147] <= 0x0d
+  ) {
+    //MMM01 stores header at bottom of image
+    //flip this around for consistency with all other mappers
+    uint8_t header[0x8000];
+    memcpy(header, romdata + base, 0x8000);
+    memmove(romdata + 0x8000, romdata, romsize - 0x8000);
+    memcpy(romdata, header, 0x8000);
+  }
+
   switch(romdata[0x0147]) {
     case 0x00: info.mapper = "none";  break;
     case 0x01: info.mapper = "MBC1";  break;
diff --git a/bsnes/snes/profile-performance.hpp b/bsnes/snes/profile-performance.hpp
index 791e7478..1d379fdc 100755
--- a/bsnes/snes/profile-performance.hpp
+++ b/bsnes/snes/profile-performance.hpp
@@ -2,6 +2,10 @@ namespace Info {
   static const char Profile[] = "Performance";
 }
 
+#if defined(DEBUGGER)
+  #error "bsnes: debugger not supported with performance profile."
+#endif
+
 #include <snes/alt/cpu/cpu.hpp>
 #include <snes/alt/smp/smp.hpp>
 #include <snes/alt/dsp/dsp.hpp>
diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp
index bf31da0f..593846eb 100755
--- a/bsnes/snes/snes.hpp
+++ b/bsnes/snes/snes.hpp
@@ -1,7 +1,7 @@
 namespace SNES {
   namespace Info {
     static const char Name[] = "bsnes";
-    static const char Version[] = "081";
+    static const char Version[] = "081.01";
     static const unsigned SerializerVersion = 21;
   }
 }
diff --git a/bsnes/ui/interface.cpp b/bsnes/ui/interface.cpp
index 23a8259b..9a9c1b0c 100755
--- a/bsnes/ui/interface.cpp
+++ b/bsnes/ui/interface.cpp
@@ -129,10 +129,11 @@ void Interface::video_refresh(const uint16_t *data, bool hires, bool interlace,
     tm *info = localtime(&currentTime);
     string filename = { "-",
       decimal<4, '0'>(info->tm_year + 1900), "-", decimal<2, '0'>(info->tm_mon + 1), "-", decimal<2, '0'>(info->tm_mday), " ",
-      decimal<2, '0'>(info->tm_hour), ":", decimal<2, '0'>(info->tm_min), ":", decimal<2, '0'>(info->tm_sec), ".bmp"
+      decimal<2, '0'>(info->tm_hour), ".", decimal<2, '0'>(info->tm_min), ".", decimal<2, '0'>(info->tm_sec), ".bmp"
     };
-    bmp::write(path(utility.slotPath(), filename), buffer, outwidth, outheight, outpitch, false);
-    utility.showMessage("Screenshot captured");
+    if(bmp::write(path(utility.slotPath(), filename), buffer, outwidth, outheight, outpitch, false)) {
+      utility.showMessage("Screenshot captured");
+    }
   }
 }
 
diff --git a/bsnes/ui/main.cpp b/bsnes/ui/main.cpp
index 1c2023ad..30e49cd1 100755
--- a/bsnes/ui/main.cpp
+++ b/bsnes/ui/main.cpp
@@ -144,6 +144,7 @@ void Application::main(int argc, char **argv) {
   }
 
   cartridge.unload();
+  utility.setFullScreen(false);
   saveGeometry();
   foreach(window, windows) window->setVisible(false);
   OS::processEvents();