// Meteor - A Nintendo Gameboy Advance emulator // Copyright (C) 2009-2011 Philippe Daouadi // // 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 3 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, see . #ifndef __IO_H__ #define __IO_H__ #include #include #include namespace AMeteor { class Io { public : enum IoAddress { // LCD I/O Registers DISPCNT = 0x000, DISPSTAT = 0x004, VCOUNT = 0x006, BG0CNT = 0x008, BG1CNT = 0x00A, BG2CNT = 0x00C, BG3CNT = 0x00E, BG0HOFS = 0x010, BG0VOFS = 0x012, BG1HOFS = 0x014, BG1VOFS = 0x016, BG2HOFS = 0x018, BG2VOFS = 0x01A, BG3HOFS = 0x01C, BG3VOFS = 0x01E, BG2PA = 0x020, BG2PB = 0x022, BG2PC = 0x024, BG2PD = 0x026, BG2X_L = 0x028, BG2X_H = 0x02A, BG2Y_L = 0x02C, BG2Y_H = 0x02E, BG3PA = 0x030, BG3PB = 0x032, BG3PC = 0x034, BG3PD = 0x036, BG3X_L = 0x038, BG3X_H = 0x03A, BG3Y_L = 0x03C, BG3Y_H = 0x03E, WIN0H = 0x040, WIN1H = 0x042, WIN0V = 0x044, WIN1V = 0x046, WININ = 0x048, WINOUT = 0x04A, MOSAIC = 0x04C, BLDCNT = 0x050, BLDALPHA = 0x052, BLDY = 0x054, // Sound Registers SOUND1CNT_L = 0x060, NR10 = 0x060, SOUND1CNT_H = 0x062, NR11 = 0x062, NR12 = 0x063, SOUND1CNT_X = 0x064, NR13 = 0x064, NR14 = 0x065, SOUND2CNT_L = 0x068, NR21 = 0x068, NR22 = 0x069, SOUND2CNT_H = 0x06C, NR23 = 0x06C, NR24 = 0x06D, SOUND4CNT_L = 0x078, NR41 = 0x078, NR42 = 0x079, SOUND4CNT_H = 0x07C, NR43 = 0x07C, NR44 = 0x07D, SOUNDCNT_L = 0x080, NR50 = 0x080, NR51 = 0x081, SOUNDCNT_H = 0x082, SOUNDCNT_X = 0x084, NR52 = 0x084, SOUNDBIAS = 0x088, FIFO_A = 0x0A0, FIFO_B = 0x0A4, // DMA Transfer Channels DMA0SAD = 0x0B0, DMA0DAD = 0x0B4, DMA0CNT_L = 0x0B8, DMA0CNT_H = 0x0BA, DMA1SAD = 0x0BC, DMA1DAD = 0x0C0, DMA1CNT_L = 0x0C4, DMA1CNT_H = 0x0C6, DMA2SAD = 0x0C8, DMA2DAD = 0x0CC, DMA2CNT_L = 0x0D0, DMA2CNT_H = 0x0D2, DMA3SAD = 0x0D4, DMA3DAD = 0x0D8, DMA3CNT_L = 0x0DC, DMA3CNT_H = 0x0DE, // Timer Registers TM0CNT_L = 0x100, TM0CNT_H = 0x102, TM1CNT_L = 0x104, TM1CNT_H = 0x106, TM2CNT_L = 0x108, TM2CNT_H = 0x10A, TM3CNT_L = 0x10C, TM3CNT_H = 0x10E, // Keypad Input KEYINPUT = 0x130, KEYCNT = 0x132, // Serial Communication (2) RCNT = 0x134, // Interrupt, WaitState, and Power-Down Control IE = 0x200, IF = 0x202, WAITCNT = 0x204, IME = 0x208, POSTFLG = 0x300, HALTCNT = 0x301, DMA_CHANSIZE = 0x00C, TIMER_SIZE = 0x004, // TODO make tests and everything in Write*() functions so that we can // make IO_SIZE 0x804 (don't forget mirrors) IO_SIZE = 0x1000 }; Io (); ~Io (); void Reset (); void ClearSio (); void ClearSound (); void ClearOthers (); uint8_t Read8 (uint32_t add); uint16_t Read16 (uint32_t add); uint32_t Read32 (uint32_t add); void Write8 (uint32_t add, uint8_t val); void Write16 (uint32_t add, uint16_t val); void Write32 (uint32_t add, uint32_t val); // Direct read and write // Using theses functions will write directly on IO memory without // doing anything else (they won't call Dma::Check for example) // add must be the real address & 0xFFF // No check is done on the memory, these functions may segfault if // you give them wrong values ! uint8_t DRead8 (uint16_t add) { return m_iomem[add]; } uint16_t DRead16 (uint16_t add) { return *(uint16_t*)(m_iomem+add); } uint32_t DRead32 (uint16_t add) { return *(uint32_t*)(m_iomem+add); } void DWrite8 (uint16_t add, uint8_t val) { m_iomem[add] = val; } void DWrite16 (uint16_t add, uint16_t val) { *(uint16_t*)(m_iomem+add) = val; } void DWrite32 (uint16_t add, uint32_t val) { *(uint32_t*)(m_iomem+add) = val; } uint8_t& GetRef8 (uint16_t add) { return m_iomem[add]; } uint16_t& GetRef16 (uint16_t add) { return *(uint16_t*)(m_iomem+add); } uint32_t& GetRef32 (uint16_t add) { return *(uint32_t*)(m_iomem+add); } bool SaveState (std::ostream& stream); bool LoadState (std::istream& stream); // this should be considered very dangerous to use uint8_t* GetIoPointer() {return m_iomem;} private : uint8_t* m_iomem; }; } #endif