From: slack Date: Wed, 22 Aug 2007 02:06:22 +0000 (+0000) Subject: Preparando las cosas para empezar con el video X-Git-Tag: v0.1~65 X-Git-Url: http://slack.codemaniacs.com/git/?a=commitdiff_plain;h=8ed8af5eb6a18c6ef7a04d8e87642b8c688fdbf5;p=wenboi.git Preparando las cosas para empezar con el video git-svn-id: http://slack.codemaniacs.com/wenboi@14 0666ae3d-8926-0410-aeff-ae84559ff337 --- diff --git a/GBMemory.cc b/GBMemory.cc index 17b4ef4..26994ef 100644 --- a/GBMemory.cc +++ b/GBMemory.cc @@ -9,12 +9,12 @@ void GBMemory::write(int addr, u8 value) { if (addr < 0x8000) mbc->write(addr, value); - else if (addr < 0xA000) VRAM [addr - VRAM_BASE] = value; + else if (addr < 0xA000) core->video->write_VRAM(addr, value); else if (addr < 0xC000) mbc->write(addr, value); else if (addr < 0xD000) WRAM0[addr - WRAM0_BASE] = value; else if (addr < 0xE000) WRAM1[addr - WRAM1_BASE] = value; else if (addr < 0xFDFF) write(addr-0x2000, value); - else if (addr < 0xFEA0) OAM [addr - OAM_BASE] = value; + else if (addr < 0xFEA0) core->video->write_OAM (addr, value); else if (addr >= 0xFF00 && addr <= 0xFF7F) { IO.write(addr,value); } @@ -33,15 +33,16 @@ void GBMemory::write(int addr, u8 value) u8 GBMemory::read(int addr) const { if (addr < 0x8000) return mbc->read(addr); - else if (addr < 0xA000) return VRAM [addr - VRAM_BASE]; + else if (addr < 0xA000) return core->video->read_VRAM(addr); else if (addr < 0xC000) return mbc->read(addr); else if (addr < 0xD000) return WRAM0[addr - WRAM0_BASE]; else if (addr < 0xE000) return WRAM1[addr - WRAM1_BASE]; else if (addr < 0xFDFF) return read(addr-0x2000); - else if (addr < 0xFEA0) return OAM [addr - OAM_BASE]; + else if (addr < 0xFEA0) return core->video->read_OAM (addr); else if (addr >= 0xFF00 && addr <= 0xFF7F) return IO.read(addr); else if (addr >= 0xFF80 && addr <= 0xFFFE) return HRAM[addr - HRAM_BASE]; + else if (addr == 0xFFFF) return IE; else { std::ostringstream errmsg; errmsg << "Invalid read address 0x" << diff --git a/GBMemory.h b/GBMemory.h index 7591513..562d9b0 100644 --- a/GBMemory.h +++ b/GBMemory.h @@ -24,12 +24,12 @@ class GBMemory MBC *mbc; // 0000-3FFF: ROM Bank 0 (in cart) // 4000-7FFF: Switchable ROM Bank (in cart) - u8 VRAM[8192]; // 8000-9FFF: Video RAM + // 8000-9FFF: Video RAM // A000-BFFF: External RAM (in cart, switchable) u8 WRAM0[4096]; // C000-CFFF: Work RAM Bank 0 u8 WRAM1[4096]; // D000-DFFF: Work RAM Bank 1 (TODO: In GBC mode switchable bank 1-7) // E000-FDFF: ECHO: Same as C000-DDFF - u8 OAM[160]; // FE00-FE9F: Sprite Attribute Table + // FE00-FE9F: Sprite Attribute Table GBIO IO; // FF00-FF7F: IO ports u8 HRAM[126]; // FF80-FFFE: High RAM diff --git a/Makefile b/Makefile index 09ed32e..846df43 100644 --- a/Makefile +++ b/Makefile @@ -2,9 +2,9 @@ CXXFLAGS=-g -Wall -Weffc++ -Wstrict-null-sentinel -Wold-style-cast \ -Woverloaded-virtual LDFLAGS=-g -all: gbcore.o MBC.o GBMemory.o Logger.o GBRom.o tests +all: gbcore.o MBC.o GBMemory.o Logger.o GBRom.o -tests: tests/test_gbrom +tests: tests/test_gbrom tests/test_core Logger.o: Logger.cc Logger.h g++ $(CXXFLAGS) -c -o $@ $< @@ -21,6 +21,9 @@ gbcore.o: gbcore.cc gbcore.h GBRom.h Logger.h MBC.h GBMemory.h tests/test_gbrom: GBRom.cc GBRom.h Logger.o g++ -DTEST_GBROM -o $@ GBRom.cc Logger.o +tests/test_core: tests/test_core.cc gbcore.o MBC.o GBMemory.o Logger.o GBRom.o + g++ -o $@ $^ + clean: rm -f *.o tests/test_gbrom diff --git a/gbcore.cc b/gbcore.cc index 515c9c5..dbd8bb8 100644 --- a/gbcore.cc +++ b/gbcore.cc @@ -77,6 +77,48 @@ void GameBoy::reset() void GameBoy::run_cycle() { + // Check for interrupts before opcode fetching + u8 IE; + if (IME && (IE=memory.read(0xFFFF))) + { + u8 IF = memory.read(0xFF0F); + if (IF) + { + if ((IF & IRQ_VBLANK) && (IE & IRQ_VBLANK)) + { + IME = 0; + IF &= (~IRQ_VBLANK); + do_call(0x40); + } + else if ((IF & IRQ_LCD_STAT) && (IE & IRQ_LCD_STAT)) + { + IME = 0; + IF &= (~IRQ_LCD_STAT); + IF do_call(0x48); + } + else if ((IF & IRQ_TIMER) && (IE & IRQ_TIMER)) + { + IME = 0; + IF &= (~IRQ_TIMER); + do_call(0x50); + } + else if ((IF & IRQ_SERIAL) && (IE & IRQ_SERIAL)) + { + IME = 0; + IF &= (~IRQ_SERIAL); + do_call(0x58); + } + else if ((IF & IRQ_JOYPAD) && (IE & IRQ_JOYPAD)) + { + IME = 0; + IF &= (~IRQ_JOYPAD); + do_call(0x60); + } + } + } + + + int prefix; int opcode; opcode = memory.read(regs.PC++); @@ -539,12 +581,12 @@ void GameBoy::run_cycle() for_each_register(0x1F, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, RR_reg) // RR (HL) (through carry) - case 0x16: { + case 0x1E: { u8 value = memory.read(regs.HL); u8 bit0 = value & 1; value = (value >> 1) | (check_flag(CARRY_FLAG) << 7); memory.write(regs.HL, value); - set_flag_if(bit7, CARRY_FLAG); + set_flag_if(bit0, CARRY_FLAG); set_flag_if(value == 0, ZERO_FLAG); reset_flag(ADD_SUB_FLAG); reset_flag(HALF_CARRY_FLAG); @@ -780,26 +822,18 @@ void GameBoy::run_cycle() // Calls // CALL nn case 0xCD: { - // push, then jump - u16 retaddr = regs.PC+2; - memory.write(regs.SP-1, retaddr >> 8); // high - memory.write(regs.SP-2, retaddr & 0xFF); // low - regs.SP -= 2; - - regs.PC = memory.read(regs.PC) | (memory.read(regs.PC+1)<<8); + u16 addr = memory.read(regs.PC) | (memory.read(regs.PC+1)<<8); + regs.PC += 2; + do_call(addr); break; } // CALL cc, nn case 0xC4: { // CALL NZ, nn if (!check_flag(ZERO_FLAG)) { - // push, then jump - u16 retaddr = regs.PC+2; - memory.write(regs.SP-1, retaddr >> 8); // high - memory.write(regs.SP-2, retaddr & 0xFF); // low - regs.SP -= 2; - - regs.PC = memory.read(regs.PC) | (memory.read(regs.PC+1)<<8); + u16 addr = memory.read(regs.PC) | (memory.read(regs.PC+1)<<8); + regs.PC += 2; + do_call(addr); } else { regs.PC += 2; // if !cc, skip 2 (nn) bytes } @@ -807,13 +841,9 @@ void GameBoy::run_cycle() case 0xCC: { // CALL Z, nn if (check_flag(ZERO_FLAG)) { - // push, then jump - u16 retaddr = regs.PC+2; - memory.write(regs.SP-1, retaddr >> 8); // high - memory.write(regs.SP-2, retaddr & 0xFF); // low - regs.SP -= 2; - - regs.PC = memory.read(regs.PC) | (memory.read(regs.PC+1)<<8); + u16 addr = memory.read(regs.PC) | (memory.read(regs.PC+1)<<8); + regs.PC += 2; + do_call(addr); } else { regs.PC += 2; // if !cc, skip 2 (nn) bytes } @@ -821,13 +851,9 @@ void GameBoy::run_cycle() case 0xD4: { // CALL NC, nn if (!check_flag(CARRY_FLAG)) { - // push, then jump - u16 retaddr = regs.PC+2; - memory.write(regs.SP-1, retaddr >> 8); // high - memory.write(regs.SP-2, retaddr & 0xFF); // low - regs.SP -= 2; - - regs.PC = memory.read(regs.PC) | (memory.read(regs.PC+1)<<8); + u16 addr = memory.read(regs.PC) | (memory.read(regs.PC+1)<<8); + regs.PC += 2; + do_call(addr); } else { regs.PC += 2; // if !cc, skip 2 (nn) bytes } @@ -835,13 +861,9 @@ void GameBoy::run_cycle() case 0xDC: { // CALL C, nn if (check_flag(CARRY_FLAG)) { - // push, then jump - u16 retaddr = regs.PC+2; - memory.write(regs.SP-1, retaddr >> 8); // high - memory.write(regs.SP-2, retaddr & 0xFF); // low - regs.SP -= 2; - - regs.PC = memory.read(regs.PC) | (memory.read(regs.PC+1)<<8); + u16 addr = memory.read(regs.PC) | (memory.read(regs.PC+1)<<8); + regs.PC += 2; + do_call(addr); } else { regs.PC += 2; // if !cc, skip 2 (nn) bytes } diff --git a/gbcore.h b/gbcore.h index 55c58c4..0929523 100644 --- a/gbcore.h +++ b/gbcore.h @@ -10,19 +10,27 @@ union GBRom; class GameBoy { enum GameBoyType { GAMEBOY, GAMEBOYCOLOR, SUPERGAMEBOY } gameboy_type; + enum InterruptRequest { + IRQ_VBLANK = 0x00, + IRQ_LCD_STAT = 0x10, + IRQ_TIMER = 0x20, + IRQ_SERIAL = 0x40, + IRQ_JOYPAD = 0x80 + }; + + enum Flag + { + ZERO_FLAG = 0x80, + ADD_SUB_FLAG = 0x40, + HALF_CARRY_FLAG = 0x20, + CARRY_FLAG = 0x10, + }; + friend class GBMemory; GBMemory memory; GBRom *rom; - enum flags_enum - { - ZERO_FLAG=0x80, - ADD_SUB_FLAG=0x40, - HALF_CARRY_FLAG=0x20, - CARRY_FLAG=0x10, - }; - // CPU Registers // ENDIANNESS WARNING! struct @@ -55,15 +63,25 @@ class GameBoy u8 IME; // Interrupt master enable flag u8 HALT; // Is the CPU halted waiting for an interrupt? + u32 cycle_count; + + inline void do_call(u16 addr) + { + memory.write(regs.SP-1, regs.PC >> 8); + memory.write(regs.SP-2, regs.PC & 0xFF); + regs.SP -= 2; + regs.PC = addr; + } - void set_flag(const u8 f) { regs.flags |= f; } - void reset_flag(const u8 f) { regs.flags &= (~f); } - bool check_flag(const u8 f) { return ((regs.flags & f) != 0); } + void set_flag (Flag f) { regs.flags |= f; } + void reset_flag(Flag f) { regs.flags &= (~f); } + bool check_flag(Flag f) { return ((regs.flags & f) != 0); } public: GameBoy(std::string rom_name, GameBoyType type=GAMEBOY); + void irq(InterruptRequest i) { memory.write(0xFFFF, memory.read(0xFFFF) | i); } void reset(); void run_cycle(); void run(); diff --git a/opcodes.h b/opcodes.h index d66382c..0a5ba75 100644 --- a/opcodes.h +++ b/opcodes.h @@ -212,10 +212,7 @@ #define RST(opcode, n) \ case opcode: \ - memory.write(regs.SP-1, regs.PC >> 8); \ - memory.write(regs.SP-2, regs.PC & 0xFF); \ - regs.SP -= 2; \ - regs.PC = n; \ + do_call(n); \ break; @@ -224,24 +221,24 @@ //set_flag_if(bit7, CARRY_FLAG); // #define RLC_reg(opcode, reg) \ - case opcode: {\ + case opcode: { \ u8 bit7 = regs.reg >> 7; \ regs.reg = (regs.reg << 1) | bit7; \ set_flag_if(regs.reg == 0, ZERO_FLAG); \ reset_flag(ADD_SUB_FLAG); \ reset_flag(HALF_CARRY_FLAG); \ - break; + break; \ } #define RL_reg(opcode, reg) \ - case opcode: { - u8 bit7 = regs.reg >> 7; - regs.reg = (regs.reg << 1) | check_flag(CARRY_FLAG); - set_flag_if(bit7, CARRY_FLAG); - set_flag_if(value == 0, ZERO_FLAG); - reset_flag(ADD_SUB_FLAG); - reset_flag(HALF_CARRY_FLAG); - break; + case opcode: { \ + u8 bit7 = regs.reg >> 7; \ + regs.reg = (regs.reg << 1) | check_flag(CARRY_FLAG); \ + set_flag_if(bit7, CARRY_FLAG); \ + set_flag_if(regs.reg == 0, ZERO_FLAG); \ + reset_flag(ADD_SUB_FLAG); \ + reset_flag(HALF_CARRY_FLAG); \ + break; \ } // TODO: Check which of GBCPUman.pdf or @@ -249,24 +246,24 @@ //set_flag_if(bit7, CARRY_FLAG); // #define RRC_reg(opcode, reg) \ - case opcode: {\ + case opcode: { \ u8 bit0 = regs.reg & 1; \ regs.reg = (regs.reg >> 1) | (bit0 << 7); \ set_flag_if(regs.reg == 0, ZERO_FLAG); \ reset_flag(ADD_SUB_FLAG); \ reset_flag(HALF_CARRY_FLAG); \ - break; + break; \ } #define RR_reg(opcode, reg) \ - case opcode: { - u8 bit0 = regs.reg & 1; - regs.reg = (regs.reg >> 1) | (check_flag(CARRY_FLAG) << 7); - set_flag_if(bit7, CARRY_FLAG); - set_flag_if(value == 0, ZERO_FLAG); - reset_flag(ADD_SUB_FLAG); - reset_flag(HALF_CARRY_FLAG); - break; + case opcode: { \ + u8 bit0 = regs.reg & 1; \ + regs.reg = (regs.reg >> 1) | (check_flag(CARRY_FLAG) << 7); \ + set_flag_if(bit0, CARRY_FLAG); \ + set_flag_if(regs.reg == 0, ZERO_FLAG); \ + reset_flag(ADD_SUB_FLAG); \ + reset_flag(HALF_CARRY_FLAG); \ + break; \ }