Initial joypad+buttons input support. Some games are quasi-playable now ;)
authorU-OMMADAWN\slack <slack@OMMADAWN.(none)>
Wed, 17 Sep 2008 01:47:50 +0000 (03:47 +0200)
committerU-OMMADAWN\slack <slack@OMMADAWN.(none)>
Wed, 17 Sep 2008 01:47:50 +0000 (03:47 +0200)
GBMemory.cc
GBMemory.h
gbcore.cc
gbcore.h

index 5a8e118fd7a1cf6d028d9d71e4d0fbca5d1da101..25d86fe6673d2b2572767d7d43b265417e624728 100644 (file)
@@ -55,7 +55,11 @@ void GBMemory::write(u16 addr, u8 value, WatchpointControl watch)
        else if (addr < 0xE000) WRAM[addr - WRAM_BASE] = value;
        else if (addr < 0xFE00) write(addr-0x2000, value);
        else if (addr < 0xFEA0) core->video.write_OAM (addr, value);
-       else if (addr >= 0xFF00) {
+       else if (addr == 0xFF00) {
+               high[0] = (high[0] & 0xCF) | (value & 0x30);
+               core->update_JOYP();
+       }
+       else if (addr > 0xFF00) {
                high[addr-0xFF00] = value;
                if (addr == DIV) 
                {
index ba34be881b9f7e8bde91c90969e45d7d89714e48..6b9aa6878e188353cdc58075e21c50a6e1f25c0f 100644 (file)
@@ -85,6 +85,7 @@ class GBMemory
        void write (u16 addr, u8 value, WatchpointControl watch = WATCH);
        
        public:
+       static const u16 JOYP = 0xFF00; // Joypad               (R/W)
        static const u16 DIV  = 0xFF04; // Divider register     (R/W)
        static const u16 TIMA = 0xFF05; // Timer counter        (R/W)
        static const u16 TMA  = 0xFF06; // Timer modulo         (R/W)
@@ -105,6 +106,7 @@ class GBMemory
        static const u16 IE   = 0xFFFF; // Interrupt enable     (R/W)
 
        private:
+       static const u16 I_JOYP = 0xFF00 - IO_BASE; // Joypad               (R/W)
        static const u16 I_DIV  = 0xFF04 - IO_BASE; // Divider register     (R/W)
        static const u16 I_TIMA = 0xFF05 - IO_BASE; // Timer counter        (R/W)
        static const u16 I_TMA  = 0xFF06 - IO_BASE; // Timer modulo         (R/W)
index a744d18cb9bccbd8aa89a2afa99b25dfd2c91644..7e9d48dff920b92b0d7932682a560b9db8965797 100644 (file)
--- a/gbcore.cc
+++ b/gbcore.cc
@@ -70,6 +70,7 @@ void GameBoy::reset()
                memory.write(i, 0);
        }
 
+       memory.write(0xFF00, 0xFF);   // TIMA
        memory.write(0xFF05, 0x00);   // TIMA
        memory.write(0xFF06, 0x00);   // TMA
        memory.write(0xFF07, 0x00);   // TAC
@@ -105,6 +106,9 @@ void GameBoy::reset()
        memory.write(0xFF4A, 0x00);   // WY
        memory.write(0xFF4B, 0x00);   // WX
        memory.write(0xFFFF, 0x00);   // IE
+
+       for (int i=0; i<NUM_CONTROLS; i++)
+               controls[i]=false;
 }
 
 int GameBoy::set_breakpoint(u16 addr)
@@ -1408,6 +1412,13 @@ GameBoy::run_status GameBoy::run()
 {
        static const int CYCLES_PER_INPUT_CHECK = 40000;
        static int c=0;
+
+       bool must_update_JOYP  = false; // has any button changed state?
+
+       // needed for firing joypad interrupt
+       bool button_pressed    = false;
+       bool direction_pressed = false;
+
        SDL_Event ev;
 
        run_status status=NORMAL;
@@ -1428,14 +1439,90 @@ GameBoy::run_status GameBoy::run()
                                                                return PAUSED;
                                                        case SDLK_q:
                                                                return QUIT;
+                                                       case SDLK_UP:
+                                                               controls[PAD_UP]=true;
+                                                               direction_pressed=true;
+                                                               break;
+                                                       case SDLK_DOWN:
+                                                               controls[PAD_DOWN]=true;
+                                                               direction_pressed=true;
+                                                               break;
+                                                       case SDLK_LEFT:
+                                                               controls[PAD_LEFT]=true;
+                                                               direction_pressed=true;
+                                                               break;
+                                                       case SDLK_RIGHT:
+                                                               controls[PAD_RIGHT]=true;
+                                                               direction_pressed=true;
+                                                               break;
+                                                       case SDLK_z:
+                                                               controls[BUTTON_A]=true;
+                                                               button_pressed=true;
+                                                               break;
+                                                       case SDLK_x:
+                                                               controls[BUTTON_B]=true;
+                                                               button_pressed=true;
+                                                               break;
+                                                       case SDLK_SPACE:
+                                                               controls[BUTTON_START]=true;
+                                                               button_pressed=true;
+                                                               break;
+                                                       case SDLK_RETURN:
+                                                               controls[BUTTON_SELECT]=true;
+                                                               button_pressed=true;
+                                                               break;
                                                        default:
                                                                break;
                                                }
+                                               must_update_JOYP=true;
+                                               break;
+                                       case SDL_KEYUP:
+                                               switch(ev.key.keysym.sym)
+                                               {
+                                                       case SDLK_UP:
+                                                               controls[PAD_UP]=false;
+                                                               break;
+                                                       case SDLK_DOWN:
+                                                               controls[PAD_DOWN]=false;
+                                                               break;
+                                                       case SDLK_LEFT:
+                                                               controls[PAD_LEFT]=false;
+                                                               break;
+                                                       case SDLK_RIGHT:
+                                                               controls[PAD_RIGHT]=false;
+                                                               break;
+                                                       case SDLK_z:
+                                                               controls[BUTTON_A]=false;
+                                                               break;
+                                                       case SDLK_x:
+                                                               controls[BUTTON_B]=false;
+                                                               break;
+                                                       case SDLK_SPACE:
+                                                               controls[BUTTON_START]=false;
+                                                               break;
+                                                       case SDLK_RETURN:
+                                                               controls[BUTTON_SELECT]=false;
+                                                               break;
+                                                       default:
+                                                               break;
+                                               }
+                                               must_update_JOYP=true;
                                                break;
                                        case SDL_QUIT:
                                                return QUIT;
                                }
                        }
+
+                       if (must_update_JOYP)
+                               update_JOYP();
+
+                       if (button_pressed || direction_pressed)
+                       {
+                               u8 JOYP = memory.read(GBMemory::JOYP, GBMemory::DONT_WATCH);
+                               if ((check_bit(JOYP,5)==false && button_pressed) ||
+                                               (check_bit(JOYP,4)==false && direction_pressed))
+                                       irq(IRQ_JOYPAD);
+                       }
                }
                status = run_cycle();
        }
@@ -1469,3 +1556,34 @@ std::string GameBoy::status_string()
        return result.str();
 }
 
+void GameBoy::update_JOYP()
+{
+       u8 JOYP = memory.high[GBMemory::I_JOYP];
+
+       // Check if writing D-Pad status to JOYP
+       if (check_bit(JOYP,4)==false)
+       {
+               if (controls[PAD_DOWN])  JOYP=reset_bit(JOYP, 3);
+               else JOYP=set_bit(JOYP, 3);
+               if (controls[PAD_UP])    JOYP=reset_bit(JOYP, 2);
+               else JOYP=set_bit(JOYP, 2);
+               if (controls[PAD_LEFT])  JOYP=reset_bit(JOYP, 1);
+               else JOYP=set_bit(JOYP, 1);
+               if (controls[PAD_RIGHT]) JOYP=reset_bit(JOYP, 0);
+               else JOYP=set_bit(JOYP, 0);
+       }
+       else // Write button status
+       {
+               if (controls[BUTTON_START])  JOYP=reset_bit(JOYP, 3);
+               else JOYP=set_bit(JOYP, 3);
+               if (controls[BUTTON_SELECT]) JOYP=reset_bit(JOYP, 2);
+               else JOYP=set_bit(JOYP, 2);
+               if (controls[BUTTON_B])      JOYP=reset_bit(JOYP, 1);
+               else JOYP=set_bit(JOYP, 1);
+               if (controls[BUTTON_A])      JOYP=reset_bit(JOYP, 0);
+               else JOYP=set_bit(JOYP, 0);
+       }
+
+       memory.high[GBMemory::I_JOYP]=JOYP;
+}
+
index 7e86e5010d5e87e0dd564d34482aab45fdddc2a4..570dcd6cb364c4717fb018b50ab8d875b4c1dc73 100644 (file)
--- a/gbcore.h
+++ b/gbcore.h
@@ -29,12 +29,26 @@ class GameBoy
                CARRY_FLAG      = 0x10,
        };
 
+       enum Controls
+       {
+               BUTTON_A=0,
+               BUTTON_B,
+               BUTTON_START,
+               BUTTON_SELECT,
+               PAD_UP,
+               PAD_DOWN,
+               PAD_LEFT,
+               PAD_RIGHT,
+               NUM_CONTROLS
+       };
+
 
        friend class GBMemory;
        friend class GBVideo;
        GBMemory memory;
        GBVideo video;
        GBRom *rom;
+       bool controls[NUM_CONTROLS];
 
        // CPU Registers
        // ENDIANNESS WARNING!
@@ -120,6 +134,8 @@ class GameBoy
        private:
        GameBoy(const GameBoy&);
        GameBoy operator=(const GameBoy&);
+
+       void update_JOYP();
        
        // debug things
        struct Breakpoint {