/*
   --------------------------------------
   This file is part of the zBoy project.
   Copyright (C) Mateusz Viste 2010, 2011
   --------------------------------------

   * MBC3 short documentation *
   (zboy doesn't provide timer support!)

   This controller is similar to MBC1 except it accesses all 16 Mbits of ROM without requiring any writes to
   the 4000-5FFF area. Writing a value (XBBBBBBB - X = Don't care, B = bank select bits) into 2000-3FFF area
   will select an appropriate ROM bank at 4000-7FFF.
   Also, this MBC has a built-in battery-backed Real Time Clock (RTC) not found in any other MBC. Some MBC3
   carts do not support it (WarioLand II non color version) but some do (Harvest Moon/Japanese version.)

   Note: The content of the MBC1 RAM can be saved during poweroff if the cartridge comes with a battery.
*/


uint8_t MBC3_MemoryRead(int memaddr) {
  if ((memaddr >= 0xA000) && (memaddr < 0xC000)) {        /* RAM bank n */
    return(MemoryBankedRAM[(CurRamBank << 13) + memaddr]);     /* SHL 13 is the same than *8192 (but faster) */
  } else if ((memaddr >= 0x4000) && (memaddr < 0x8000)) {    /* ROM bank #n */
    /*IF RomInfos.RomSize = 32768 THEN */
    /*    RETURN MemoryROM(memaddr) */
    /*  ELSE */
        if ((CurRomBank == 0) || (RomInfos.RomSize == 32768)) {
            return(MemoryROM[memaddr]);
          } else {
            if (((CurRomBank << 14) + (memaddr - 0x4000)) > RomInfos.RomSize) {    /* SHL 14 is the same than *16384 (but faster) */
              PrintMsg("INVALID ROM ADDRESS!\nCURBANK=%u", CurRomBank);
              PressAnyKey();
              exit(0);
            }
            return(MemoryROM[(CurRomBank << 14) + (memaddr - 0x4000)]);    /* SHL 14 is the same than *16384 (but faster) */
        }
    /*END IF */
  } else {                                               /* Else it's something I don't know about */
    /*IF (memaddr > 0xFFFF) THEN */
    /*  PrintMsg("MMU FATAL ERROR!" & CHR(10) & "MEMORYREAD() -> INVALID MEMADDR! [" & HEX(memaddr) & "]") : PressAnyKey() : END */
    /*END IF */
    /*PRINT "MMU fatal error: Tried to read from an unknown memory address: " & HEX(memaddr) & "h" */
    /*SLEEP */
    /*QuitEmulator = 1 */
    return(MemoryMAP[memaddr]);
  }
}


void MBC3_MemoryWrite(int memaddr, uint8_t DataByte) {
  if (memaddr < 0x2000) {  /* Enables / disables current RAM bank (not supported yet) */
    /* Before using any RAM bank, you need to enable it by writing xxxx1010 into 0000-1FFF (writing there */
    /* any non-xxxx1010 value disables the RAM bank). */
    if ((DataByte & bx00001111) == bx00001010) {   /* Enables currently selected RAM bank */
      } else {  /* Disables currently selected RAM bank */
        /*UserMessage = "RAM BANK DISABLED" */
    }
  } else if ((memaddr >= 0x2000) && (memaddr < 0x4000)) {       /* Select current ROM bank on MBC3 */
    CurRomBank = (DataByte & bx01111111);
    CurRomBank &= RomInfos.RomAddrTrim; /* ROM address is incompletely decoded so games like Quarth can address bank 1 as "33" */
  } else if ((memaddr >= 0x4000) && (memaddr < 0x6000)) {       /* Select current RAM bank */
    CurRamBank = (DataByte & bx00000011);
    CurRamBank &= RomInfos.RamAddrTrim;
  } else if ((memaddr >= 0xA000) && (memaddr < 0xC000)) {       /* RAM bank n */
    MemoryBankedRAM[(CurRamBank << 13) + memaddr] = DataByte;   /* SHL 13 is the same than * 8192 (but faster) */
  } else if ((memaddr >= 0xFEA0) && (memaddr <= 0xFEFF)) {      /* This area is not usable, but some games writes to it... */
                                                                /* For example Dr. Mario tries to write to FEFF... who knows why? */
  } else if ((memaddr >= 0xFF4C) && (memaddr <= 0xFF7F)) {      /* This area is not usable, but some games writes to it... */
                                                                /* For example Dr. Mario tries to write to FF7F... who knows why? */
  } else {                                                      /* Else it's something I don't know about */
    /*PRINT "MMU fatal error: Tried to write to an unknown memory address: "; HEX(memaddr) */
    /*QuitEmulator = 1 */
    MemoryMAP[memaddr] = DataByte;
  }
}