Preparando las cosas para empezar con el video
authorslack <slack@0666ae3d-8926-0410-aeff-ae84559ff337>
Wed, 22 Aug 2007 02:06:22 +0000 (02:06 +0000)
committerslack <slack@0666ae3d-8926-0410-aeff-ae84559ff337>
Wed, 22 Aug 2007 02:06:22 +0000 (02:06 +0000)
git-svn-id: http://slack.codemaniacs.com/wenboi@14 0666ae3d-8926-0410-aeff-ae84559ff337

GBMemory.cc
GBMemory.h
Makefile
gbcore.cc
gbcore.h
opcodes.h

index 17b4ef4217a48c47e0024f4182e7cfc00b5edd1b..26994ef31ebe8fada29dcaf0ae2fdd3588ce2c31 100644 (file)
@@ -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" << 
index 75915132c5082a18e197191f6182e15a6b138a4e..562d9b0a75ae18c67b2da14c8b87555be1c2b68e 100644 (file)
@@ -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
index 09ed32e7fed5c7f5f9876dbbe9868c04a382add1..846df438fdaf390ef7f36e6046048974f80a5de3 100644 (file)
--- 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
 
index 515c9c58435acdfabf690632a02bf139b32557b9..dbd8bb8ec9846539aa310f4762f9a7b5a2e604b8 100644 (file)
--- 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
                        }
index 55c58c4f017833800501afaa62d3eaeb9aac9bec..09295232252ef0ccbf433e6c9ad7fac34d12c364 100644 (file)
--- 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();
index d66382c2fd3fbe79a42e3095e3dd99ccb5344cbb..0a5ba751f8e1fcab983d32092390ea8528dc96f3 100644 (file)
--- a/opcodes.h
+++ b/opcodes.h
 
 #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;
 
 
 //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
 //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; \
        }