home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / GBAinline.h < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  10.7 KB  |  421 lines

  1. // -*- C++ -*-
  2. // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
  3. // Copyright (C) 1999-2003 Forgotten
  4. // Copyright (C) 2004 Forgotten and the VBA development team
  5.  
  6. // This program is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation; either version 2, or(at your option)
  9. // any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with this program; if not, write to the Free Software Foundation,
  18. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19.  
  20. #ifndef VBA_GBAinline_H
  21. #define VBA_GBAinline_H
  22.  
  23. #include "System.h"
  24. #include "Port.h"
  25. #include "RTC.h"
  26.  
  27. extern bool cpuSramEnabled;
  28. extern bool cpuFlashEnabled;
  29. extern bool cpuEEPROMEnabled;
  30. extern bool cpuEEPROMSensorEnabled;
  31.  
  32. #define CPUReadByteQuick(addr) \
  33.   map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
  34.  
  35. #define CPUReadHalfWordQuick(addr) \
  36.   READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
  37.  
  38. #define CPUReadMemoryQuick(addr) \
  39.   READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
  40.  
  41. inline u32 CPUReadMemory(u32 address)
  42. {
  43.  
  44. #ifdef DEV_VERSION
  45.   if(address & 3) {  
  46.     if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
  47.       log("Unaligned word read: %08x at %08x\n", address, armMode ?
  48.           armNextPC - 4 : armNextPC - 2);
  49.     }
  50.   }
  51. #endif
  52.   
  53.   u32 value;
  54.   switch(address >> 24) {
  55.   case 0:
  56.     if(reg[15].I >> 24) {
  57.       if(address < 0x4000) {
  58. #ifdef DEV_VERSION
  59.         if(systemVerbose & VERBOSE_ILLEGAL_READ) {
  60.           log("Illegal word read: %08x at %08x\n", address, armMode ?
  61.               armNextPC - 4 : armNextPC - 2);
  62.         }
  63. #endif
  64.         
  65.         value = READ32LE(((u32 *)&biosProtected));
  66.       }
  67.       else goto unreadable;
  68.     } else
  69.       value = READ32LE(((u32 *)&bios[address & 0x3FFC]));
  70.     break;
  71.   case 2:
  72.     value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC]));
  73.     break;
  74.   case 3:
  75.     value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC]));
  76.     break;
  77.   case 4:
  78.     if((address < 0x4000400) && ioReadable[address & 0x3fc]) {
  79.       if(ioReadable[(address & 0x3fc) + 2])
  80.         value = READ32LE(((u32 *)&ioMem[address & 0x3fC]));
  81.       else
  82.         value = READ16LE(((u16 *)&ioMem[address & 0x3fc]));
  83.     } else goto unreadable;
  84.     break;
  85.   case 5:
  86.     value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC]));
  87.     break;
  88.   case 6:
  89.     value = READ32LE(((u32 *)&vram[address & 0x1fffc]));
  90.     break;
  91.   case 7:
  92.     value = READ32LE(((u32 *)&oam[address & 0x3FC]));
  93.     break;
  94.   case 8:
  95.   case 9:
  96.   case 10:
  97.   case 11:
  98.   case 12:
  99.     value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
  100.     break;    
  101.   case 13:
  102.     if(cpuEEPROMEnabled)
  103.       // no need to swap this
  104.       return eepromRead(address);
  105.     goto unreadable;
  106.   case 14:
  107.     if(cpuFlashEnabled | cpuSramEnabled)
  108.       // no need to swap this
  109.       return flashRead(address);
  110.     // default
  111.   default:
  112.   unreadable:
  113. #ifdef DEV_VERSION
  114.     if(systemVerbose & VERBOSE_ILLEGAL_READ) {
  115.       log("Illegal word read: %08x at %08x\n", address, armMode ?
  116.           armNextPC - 4 : armNextPC - 2);
  117.     }
  118. #endif
  119.     
  120.     //    if(ioMem[0x205] & 0x40) {
  121.       if(armState) {
  122.         value = CPUReadMemoryQuick(reg[15].I);
  123.       } else {
  124.         value = CPUReadHalfWordQuick(reg[15].I) |
  125.           CPUReadHalfWordQuick(reg[15].I) << 16;
  126.       }
  127.       //  } else {
  128.       //      value = *((u32 *)&bios[address & 0x3ffc]);
  129.       //    }
  130.       //        return 0xFFFFFFFF;
  131.   }
  132.  
  133.   if(address & 3) {
  134. #ifdef C_CORE
  135.     int shift = (address & 3) << 3;
  136.     value = (value >> shift) | (value << (32 - shift));
  137. #else    
  138. #ifdef __GNUC__
  139.     asm("and $3, %%ecx;"
  140.         "shl $3 ,%%ecx;"
  141.         "ror %%cl, %0"
  142.         : "=r" (value)
  143.         : "r" (value), "c" (address));
  144. #else
  145.     __asm {
  146.       mov ecx, address;
  147.       and ecx, 3;
  148.       shl ecx, 3;
  149.       ror [dword ptr value], cl;
  150.     }
  151. #endif
  152. #endif
  153.   }
  154.   return value;
  155. }
  156.  
  157. extern u32 myROM[];
  158.  
  159. inline u32 CPUReadHalfWord(u32 address)
  160. {
  161. #ifdef DEV_VERSION      
  162.   if(address & 1) {
  163.     if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
  164.       log("Unaligned halfword read: %08x at %08x\n", address, armMode ?
  165.           armNextPC - 4 : armNextPC - 2);
  166.     }
  167.   }
  168. #endif
  169.   
  170.   u32 value;
  171.   
  172.   switch(address >> 24) {
  173.   case 0:
  174.     if (reg[15].I >> 24) {
  175.       if(address < 0x4000) {
  176. #ifdef DEV_VERSION
  177.         if(systemVerbose & VERBOSE_ILLEGAL_READ) {
  178.           log("Illegal halfword read: %08x at %08x\n", address, armMode ?
  179.               armNextPC - 4 : armNextPC - 2);
  180.         }
  181. #endif
  182.         value = READ16LE(((u16 *)&biosProtected[address&2]));
  183.       } else goto unreadable;
  184.     } else
  185.       value = READ16LE(((u16 *)&bios[address & 0x3FFE]));
  186.     break;
  187.   case 2:
  188.     value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE]));
  189.     break;
  190.   case 3:
  191.     value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe]));
  192.     break;
  193.   case 4:
  194.     if((address < 0x4000400) && ioReadable[address & 0x3fe])
  195.       value =  READ16LE(((u16 *)&ioMem[address & 0x3fe]));
  196.     else goto unreadable;
  197.     break;
  198.   case 5:
  199.     value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe]));
  200.     break;
  201.   case 6:
  202.     value = READ16LE(((u16 *)&vram[address & 0x1fffe]));
  203.     break;
  204.   case 7:
  205.     value = READ16LE(((u16 *)&oam[address & 0x3fe]));
  206.     break;
  207.   case 8:
  208.   case 9:
  209.   case 10:
  210.   case 11:
  211.   case 12:
  212.     if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
  213.       value = rtcRead(address);
  214.     else
  215.       value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
  216.     break;    
  217.   case 13:
  218.     if(cpuEEPROMEnabled)
  219.       // no need to swap this
  220.       return  eepromRead(address);
  221.     goto unreadable;
  222.   case 14:
  223.     if(cpuFlashEnabled | cpuSramEnabled)
  224.       // no need to swap this
  225.       return flashRead(address);
  226.     // default
  227.   default:
  228.   unreadable:
  229. #ifdef DEV_VERSION
  230.     if(systemVerbose & VERBOSE_ILLEGAL_READ) {
  231.       log("Illegal halfword read: %08x at %08x\n", address, armMode ?
  232.           armNextPC - 4 : armNextPC - 2);
  233.     }
  234. #endif
  235.     extern bool cpuDmaHack;
  236.     extern u32 cpuDmaLast;
  237.     extern int cpuDmaCount;
  238.     if(cpuDmaHack && cpuDmaCount) {
  239.       value = (u16)cpuDmaLast;
  240.     } else {
  241.       if(armState) {
  242.         value = CPUReadHalfWordQuick(reg[15].I + (address & 2));
  243.       } else {
  244.         value = CPUReadHalfWordQuick(reg[15].I);
  245.       }
  246.     }
  247.     //    return value;
  248.     //    if(address & 1)
  249.     //      value = (value >> 8) | ((value & 0xFF) << 24);
  250.     //    return 0xFFFF;
  251.     break;
  252.   }
  253.  
  254.   if(address & 1) {
  255.     value = (value >> 8) | (value << 24);
  256.   }
  257.   
  258.   return value;
  259. }
  260.  
  261. inline u16 CPUReadHalfWordSigned(u32 address)
  262. {
  263.   u16 value = CPUReadHalfWord(address);
  264.   if((address & 1))
  265.     value = (s8)value;
  266.   return value;
  267. }
  268.  
  269. inline u8 CPUReadByte(u32 address)
  270. {
  271.   switch(address >> 24) {
  272.   case 0:
  273.     if (reg[15].I >> 24) {
  274.       if(address < 0x4000) {
  275. #ifdef DEV_VERSION
  276.         if(systemVerbose & VERBOSE_ILLEGAL_READ) {
  277.           log("Illegal byte read: %08x at %08x\n", address, armMode ?
  278.               armNextPC - 4 : armNextPC - 2);
  279.         }
  280. #endif
  281.         return biosProtected[address & 3];
  282.       } else goto unreadable;
  283.     }
  284.     return bios[address & 0x3FFF];
  285.   case 2:
  286.     return workRAM[address & 0x3FFFF];
  287.   case 3:
  288.     return internalRAM[address & 0x7fff];
  289.   case 4:
  290.     if((address < 0x4000400) && ioReadable[address & 0x3ff])
  291.       return ioMem[address & 0x3ff];
  292.     else goto unreadable;
  293.   case 5:
  294.     return paletteRAM[address & 0x3ff];
  295.   case 6:
  296.     return vram[address & 0x1ffff];
  297.   case 7:
  298.     return oam[address & 0x3ff];
  299.   case 8:
  300.   case 9:
  301.   case 10:
  302.   case 11:
  303.   case 12:
  304.     return rom[address & 0x1FFFFFF];        
  305.   case 13:
  306.     if(cpuEEPROMEnabled)
  307.       return eepromRead(address);
  308.     goto unreadable;
  309.   case 14:
  310.     if(cpuSramEnabled | cpuFlashEnabled)
  311.       return flashRead(address);
  312.     if(cpuEEPROMSensorEnabled) {
  313.       switch(address & 0x00008f00) {
  314.       case 0x8200:
  315.         return systemGetSensorX() & 255;
  316.       case 0x8300:
  317.         return (systemGetSensorX() >> 8)|0x80;
  318.       case 0x8400:
  319.         return systemGetSensorY() & 255;
  320.       case 0x8500:
  321.         return systemGetSensorY() >> 8;
  322.       }
  323.     }
  324.     // default
  325.   default:
  326.   unreadable:
  327. #ifdef DEV_VERSION
  328.         if(systemVerbose & VERBOSE_ILLEGAL_READ) {
  329.           log("Illegal byte read: %08x at %08x\n", address, armMode ?
  330.               armNextPC - 4 : armNextPC - 2);
  331.         }
  332. #endif
  333.     
  334.     if(armState) {
  335.       return CPUReadByteQuick(reg[15].I+(address & 3));
  336.     } else {
  337.       return CPUReadByteQuick(reg[15].I+(address & 1));
  338.     }
  339.     //    return 0xFF;
  340.     break;
  341.   }
  342. }
  343.  
  344. inline void CPUWriteMemory(u32 address, u32 value)
  345. {
  346. #ifdef DEV_VERSION
  347.   if(address & 3) {
  348.     if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
  349.       log("Unaliagned word write: %08x to %08x from %08x\n",
  350.           value,
  351.           address,
  352.           armMode ? armNextPC - 4 : armNextPC - 2);
  353.     }
  354.   }
  355. #endif
  356.   
  357.   switch(address >> 24) {
  358.   case 0x02:
  359. #ifdef SDL
  360.     if(*((u32 *)&freezeWorkRAM[address & 0x3FFFC]))
  361.       cheatsWriteMemory((u32 *)&workRAM[address & 0x3FFFC],
  362.                         value,
  363.                         *((u32 *)&freezeWorkRAM[address & 0x3FFFC]));
  364.     else
  365. #endif
  366.       WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value);
  367.     break;
  368.   case 0x03:
  369. #ifdef SDL
  370.     if(*((u32 *)&freezeInternalRAM[address & 0x7ffc]))
  371.       cheatsWriteMemory((u32 *)&internalRAM[address & 0x7FFC],
  372.                         value,
  373.                         *((u32 *)&freezeInternalRAM[address & 0x7ffc]));
  374.     else
  375. #endif
  376.       WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value);
  377.     break;
  378.   case 0x04:
  379.     CPUUpdateRegister((address & 0x3FC), value & 0xFFFF);
  380.     CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16));
  381.     break;
  382.   case 0x05:
  383.     WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value);
  384.     break;
  385.   case 0x06:
  386.     if(address & 0x10000)
  387.       WRITE32LE(((u32 *)&vram[address & 0x17ffc]), value);
  388.     else
  389.       WRITE32LE(((u32 *)&vram[address & 0x1fffc]), value);
  390.     break;
  391.   case 0x07:
  392.     WRITE32LE(((u32 *)&oam[address & 0x3fc]), value);
  393.     break;
  394.   case 0x0D:
  395.     if(cpuEEPROMEnabled) {
  396.       eepromWrite(address, value);
  397.       break;
  398.     }
  399.     goto unwritable;
  400.   case 0x0E:
  401.     if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) {
  402.       (*cpuSaveGameFunc)(address, (u8)value);
  403.       break;
  404.     }
  405.     // default
  406.   default:
  407.   unwritable:
  408. #ifdef DEV_VERSION
  409.     if(systemVerbose & VERBOSE_ILLEGAL_WRITE) {
  410.       log("Illegal word write: %08x to %08x from %08x\n",
  411.           value,
  412.           address,
  413.           armMode ? armNextPC - 4 : armNextPC - 2);
  414.     }
  415. #endif
  416.     break;
  417.   }
  418. }
  419.  
  420. #endif //VBA_GBAinline_H
  421.