register_LCDC = value;
void  gbWriteMemory(register u16 address, register u8 value){  if(address < 0x8000) {#ifndef FINAL_VERSION        if(memorydebug && (address>0x3fff || address < 0x2000)) {      log("Memory register write %04x=%02x PC=%04x\n",          address,          value,          PC.W);    }#endif    if(mapper)      (*mapper)(address, value);    return;  }     if(address < 0xa000) {    gbMemoryMap[address>>12][address&0x0fff] = value;    return;  }    if(address < 0xc000) {#ifndef FINAL_VERSION    if(memorydebug) {      log("Memory register write %04x=%02x PC=%04x\n",          address,          value,          PC.W);    }#endif        if(mapper)      (*mapperRAM)(address, value);    return;  }    if(address < 0xfe00) {    gbMemoryMap[address>>12][address & 0x0fff] = value;    return;  }    if(address < 0xff00) {    gbMemory[address] = value;    return;  }    switch(address & 0x00ff) {  case 0x00: {    gbMemory[0xff00] = ((gbMemory[0xff00] & 0xcf) |                      (value & 0x30));    if(gbSgbMode) {      gbSgbDoBitTransfer(value);    }        return;  }  case 0x01: {    gbMemory[0xff01] = value;    return;  }      // serial control  case 0x02: {    gbSerialOn = (value & 0x80);    gbMemory[0xff02] = value;        if(gbSerialOn) {      gbSerialTicks = GBSERIAL_CLOCK_TICKS;#ifdef LINK_EMULATION      if(linkConnected) {        if(value & 1) {          linkSendByte(0x100|gbMemory[0xFF01]);          Sleep(5);        }      }#endif    }    gbSerialBits = 0;    return;  }    // DIV register resets on any write  case 0x04: {    register_DIV = 0;    return;  }  case 0x05:    register_TIMA = value;    return;  case 0x06:    register_TMA = value;    return;        // TIMER control  case 0x07: {    register_TAC = value;        gbTimerOn = (value & 4);    gbTimerMode = value & 3;    //    register_TIMA = register_TMA;    switch(gbTimerMode) {    case 0:      gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS;      break;    case 1:      gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_1_CLOCK_TICKS;      break;    case 2:      gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_2_CLOCK_TICKS;      break;    case 3:      gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_3_CLOCK_TICKS;      break;    }    return;  }  case 0x0f: {    register_IF = value;    gbInterrupt = value;    return;  }    case 0x10:  case 0x11:  case 0x12:  case 0x13:  case 0x14:  case 0x15:  case 0x16:  case 0x17:  case 0x18:  case 0x19:  case 0x1a:  case 0x1b:  case 0x1c:  case 0x1d:  case 0x1e:  case 0x1f:  case 0x20:  case 0x21:  case 0x22:  case 0x23:  case 0x24:  case 0x25:  case 0x26: {    SOUND_EVENT(address,value);    return;  }  case 0x40: {    int lcdChange = (register_LCDC & 0x80) ^ (value & 0x80);    register_LCDC = value;    if(lcdChange) {      if(value & 0x80) {        gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS;        gbLcdMode = 0;        register_STAT &= 0xfc;        register_LY = 0x00;      } else {        gbLcdTicks = 0;        gbLcdMode = 0;        register_STAT &= 0xfc;        register_LY = 0x00;      }      //      compareLYToLYC();    }    return;  }  // STAT  case 0x41: {    //register_STAT = (register_STAT & 0x87) |    //      (value & 0x7c);    register_STAT = (value & 0xf8) | (register_STAT & 0x07); // fix ?    return;  }  // SCY  case 0x42: {    register_SCY = value;    return;  }    // SCX  case 0x43: {    register_SCX = value;    return;  }    // LY  case 0x44: {    // read only    return;  }  // LYC  case 0x45: {    register_LYC = value;    gbCompareLYToLYC();    return;  }    // DMA!  case 0x46: {    int source = value * 0x0100;    gbCopyMemory(0xfe00,                 source,                 0xa0);    register_DMA = value;    return;  }    // BGP  case 0x47: {    gbBgp[0] = value & 0x03;    gbBgp[1] = (value & 0x0c)>>2;    gbBgp[2] = (value & 0x30)>>4;    gbBgp[3] = (value & 0xc0)>>6;    break;  }    // OBP0  case 0x48: {    gbObp0[0] = value & 0x03;    gbObp0[1] = (value & 0x0c)>>2;    gbObp0[2] = (value & 0x30)>>4;    gbObp0[3] = (value & 0xc0)>>6;    break;  }  // OBP1  case 0x49: {    gbObp1[0] = value & 0x03;    gbObp1[1] = (value & 0x0c)>>2;    gbObp1[2] = (value & 0x30)>>4;    gbObp1[3] = (value & 0xc0)>>6;    break;  }  case 0x4a:    register_WY = value;    return;      case 0x4b:    register_WX = value;    return;      // KEY1  case 0x4d: {    if(gbCgbMode) {      gbMemory[0xff4d] = (gbMemory[0xff4d] & 0x80) | (value & 1);      return;    }  }  break;      // VBK  case 0x4f: {    if(gbCgbMode) {      value = value & 1;      if(value == gbVramBank)        return;            int vramAddress = value * 0x2000;      gbMemoryMap[0x08] = &gbVram[vramAddress];      gbMemoryMap[0x09] = &gbVram[vramAddress + 0x1000];            gbVramBank = value;      register_VBK = value;    }    return;  }  break;  // HDMA1  case 0x51: {    if(gbCgbMode) {      if(value > 0x7f && value < 0xa0)        value = 0;            gbHdmaSource = (value << 8) | (register_HDMA2 & 0xf0);            register_HDMA1 = value;      return;    }  }  break;    // HDMA2  case 0x52: {    if(gbCgbMode) {      value = value & 0xf0;            gbHdmaSource = (register_HDMA1 << 8) | (value);            register_HDMA2 = value;      return;    }  }  break;  // HDMA3  case 0x53: {    if(gbCgbMode) {      value = value & 0x1f;      gbHdmaDestination = (value << 8) | (register_HDMA4 & 0xf0);      gbHdmaDestination += 0x8000;      register_HDMA3 = value;      return;    }  }  break;    // HDMA4  case 0x54: {    if(gbCgbMode) {      value = value & 0xf0;      gbHdmaDestination = ((register_HDMA3 & 0x1f) << 8) | value;      gbHdmaDestination += 0x8000;      register_HDMA4 = value;      return;    }  }  break;    // HDMA5  case 0x55: {    if(gbCgbMode) {      gbHdmaBytes = 16 + (value & 0x7f) * 16;      if(gbHdmaOn) {        if(value & 0x80) {          register_HDMA5 = (value & 0x7f);        } else {          register_HDMA5 = 0xff;          gbHdmaOn = 0;        }      } else {        if(value & 0x80) {          gbHdmaOn = 1;          register_HDMA5 = value & 0x7f;          if(gbLcdMode == 0)            gbDoHdma();        } else {          gbCopyMemory(gbHdmaDestination,                       gbHdmaSource,                       gbHdmaBytes);          gbHdmaDestination += gbHdmaBytes;          gbHdmaSource += gbHdmaBytes;                    register_HDMA3 = ((gbHdmaDestination - 0x8000) >> 8) & 0x1f;          register_HDMA4 = gbHdmaDestination & 0xf0;          register_HDMA1 = (gbHdmaSource >> 8) & 0xff;          register_HDMA2 = gbHdmaSource & 0xf0;        }      }      return;    }  }  break;    // BCPS  case 0x68: {     if(gbCgbMode) {      int paletteIndex = (value & 0x3f) >> 1;      int paletteHiLo   = (value & 0x01);            gbMemory[0xff68] = value;      gbMemory[0xff69] = (paletteHiLo ?                        (gbPalette[paletteIndex] >> 8) :                        (gbPalette[paletteIndex] & 0x00ff));      return;    }  }  break;    // BCPD  case 0x69: {    if(gbCgbMode) {      int v = gbMemory[0xff68];            int paletteIndex = (v & 0x3f) >> 1;      int paletteHiLo  = (v & 0x01);      gbMemory[0xff69] = value;      gbPalette[paletteIndex] = (paletteHiLo ?                                 ((value << 8) | (gbPalette[paletteIndex] & 0xff)) :                                 ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff;                                              if(gbMemory[0xff68] & 0x80) {        int index = ((gbMemory[0xff68] & 0x3f) + 1) & 0x3f;                gbMemory[0xff68] = (gbMemory[0xff68] & 0x80) | index;                gbMemory[0xff69] = (index & 1 ?                          (gbPalette[index>>1] >> 8) :                          (gbPalette[index>>1] & 0x00ff));              }      return;    }  }  break;    // OCPS   case 0x6a: {    if(gbCgbMode) {      int paletteIndex = (value & 0x3f) >> 1;      int paletteHiLo   = (value & 0x01);            paletteIndex += 32;            gbMemory[0xff6a] = value;      gbMemory[0xff6b] = (paletteHiLo ?                        (gbPalette[paletteIndex] >> 8) :                        (gbPalette[paletteIndex] & 0x00ff));      return;    }  }  break;    // OCPD  case 0x6b: {    if(gbCgbMode) {      int v = gbMemory[0xff6a];            int paletteIndex = (v & 0x3f) >> 1;      int paletteHiLo  = (v & 0x01);            paletteIndex += 32;            gbMemory[0xff6b] = value;      gbPalette[paletteIndex] = (paletteHiLo ?                                 ((value << 8) | (gbPalette[paletteIndex] & 0xff)) :                                 ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff;      if(gbMemory[0xff6a] & 0x80) {        int index = ((gbMemory[0xff6a] & 0x3f) + 1) & 0x3f;                gbMemory[0xff6a] = (gbMemory[0xff6a] & 0x80) | index;                gbMemory[0xff6b] = (index & 1 ?                          (gbPalette[(index>>1) + 32] >> 8) :                          (gbPalette[(index>>1) + 32] & 0x00ff));              }            return;    }  }  break;    // SVBK  case 0x70: {    if(gbCgbMode) {      value = value & 7;      int bank = value;      if(value == 0)        bank = 1;      if(bank == gbWramBank)        return;            int wramAddress = bank * 0x1000;      gbMemoryMap[0x0d] = &gbWram[wramAddress];            gbWramBank = bank;      register_SVBK = value;      return;    }  }  break;    case 0xff: {    register_IE = value;    register_IF &= value;    return;  }  }    gbMemory[address] = value;}