improve input handling
authornotaz <notasas@gmail.com>
Sat, 17 Aug 2013 00:04:15 +0000 (03:04 +0300)
committernotaz <notasas@gmail.com>
Sat, 17 Aug 2013 00:38:47 +0000 (03:38 +0300)
12 files changed:
pico/memory.c
pico/memory_arm.s
pico/pico.c
pico/pico.h
pico/pico_cmn.c
pico/pico_int.h
platform/common/emu.c
platform/common/emu.h
platform/common/menu_pico.c
platform/common/menu_pico.h
platform/libretro.c
platform/win32/plat.c

index 88d43f0..664fd72 100644 (file)
@@ -186,62 +186,119 @@ void cyclone_crashed(u32 pc, struct Cyclone *context)
 // -----------------------------------------------------------------\r
 // memmap helpers\r
 \r
-#ifndef _ASM_MEMORY_C\r
-static\r
-#endif\r
-int PadRead(int i)\r
+static u32 read_pad_3btn(int i, u32 out_bits)\r
 {\r
-  int pad,value,data_reg;\r
-  pad=~PicoPadInt[i]; // Get inverse of pad MXYZ SACB RLDU\r
-  data_reg=Pico.ioports[i+1];\r
+  u32 pad = ~PicoPadInt[i]; // Get inverse of pad MXYZ SACB RLDU\r
+  u32 value;\r
 \r
-  // orr the bits, which are set as output\r
-  value = data_reg&(Pico.ioports[i+4]|0x80);\r
+  if (out_bits & 0x40) // TH\r
+    value = pad & 0x3f;                      // ?1CB RLDU\r
+  else\r
+    value = ((pad & 0xc0) >> 2) | (pad & 3); // ?0SA 00DU\r
 \r
-  if (PicoOpt & POPT_6BTN_PAD)\r
-  {\r
-    int phase = Pico.m.padTHPhase[i];\r
-\r
-    if(phase == 2 && !(data_reg&0x40)) { // TH\r
-      value|=(pad&0xc0)>>2;              // ?0SA 0000\r
-      return value;\r
-    } else if(phase == 3) {\r
-      if(data_reg&0x40)\r
-        value|=(pad&0x30)|((pad>>8)&0xf);  // ?1CB MXYZ\r
-      else\r
-        value|=((pad&0xc0)>>2)|0x0f;       // ?0SA 1111\r
-      return value;\r
-    }\r
+  value |= out_bits & 0x40;\r
+  return value;\r
+}\r
+\r
+static u32 read_pad_6btn(int i, u32 out_bits)\r
+{\r
+  u32 pad = ~PicoPadInt[i]; // Get inverse of pad MXYZ SACB RLDU\r
+  int phase = Pico.m.padTHPhase[i];\r
+  u32 value;\r
+\r
+  if (phase == 2 && !(out_bits & 0x40)) {\r
+    value = (pad & 0xc0) >> 2;                   // ?0SA 0000\r
+    goto out;\r
+  }\r
+  else if(phase == 3) {\r
+    if (out_bits & 0x40)\r
+      return (pad & 0x30) | ((pad >> 8) & 0xf);  // ?1CB MXYZ\r
+    else\r
+      return ((pad & 0xc0) >> 2) | 0x0f;         // ?0SA 1111\r
+    goto out;\r
   }\r
 \r
-  if(data_reg&0x40) // TH\r
-       value|=(pad&0x3f);              // ?1CB RLDU\r
-  else value|=((pad&0xc0)>>2)|(pad&3); // ?0SA 00DU\r
+  if (out_bits & 0x40) // TH\r
+    value = pad & 0x3f;                          // ?1CB RLDU\r
+  else\r
+    value = ((pad & 0xc0) >> 2) | (pad & 3);     // ?0SA 00DU\r
 \r
-  return value; // will mirror later\r
+out:\r
+  value |= out_bits & 0x40;\r
+  return value;\r
 }\r
 \r
-#ifndef _ASM_MEMORY_C\r
+static u32 read_nothing(int i, u32 out_bits)\r
+{\r
+  return 0xff;\r
+}\r
+\r
+typedef u32 (port_read_func)(int index, u32 out_bits);\r
+\r
+static port_read_func *port_readers[3] = {\r
+  read_pad_3btn,\r
+  read_pad_3btn,\r
+  read_nothing\r
+};\r
 \r
-static u32 io_ports_read(u32 a)\r
+static NOINLINE u32 port_read(int i)\r
+{\r
+  u32 data_reg = Pico.ioports[i + 1];\r
+  u32 ctrl_reg = Pico.ioports[i + 4] | 0x80;\r
+  u32 in, out;\r
+\r
+  out = data_reg & ctrl_reg;\r
+  out |= 0x7f & ~ctrl_reg; // pull-ups\r
+\r
+  in = port_readers[i](i, out);\r
+\r
+  return (in & ~ctrl_reg) | (data_reg & ctrl_reg);\r
+}\r
+\r
+void PicoSetInputDevice(int port, enum input_device device)\r
+{\r
+  port_read_func *func;\r
+\r
+  if (port < 0 || port > 2)\r
+    return;\r
+\r
+  switch (device) {\r
+  case PICO_INPUT_PAD_3BTN:\r
+    func = read_pad_3btn;\r
+    break;\r
+\r
+  case PICO_INPUT_PAD_6BTN:\r
+    func = read_pad_6btn;\r
+    break;\r
+\r
+  default:\r
+    func = read_nothing;\r
+    break;\r
+  }\r
+\r
+  port_readers[port] = func;\r
+}\r
+\r
+NOINLINE u32 io_ports_read(u32 a)\r
 {\r
   u32 d;\r
   a = (a>>1) & 0xf;\r
   switch (a) {\r
     case 0:  d = Pico.m.hardware; break; // Hardware value (Version register)\r
-    case 1:  d = PadRead(0); break;\r
-    case 2:  d = PadRead(1); break;\r
+    case 1:  d = port_read(0); break;\r
+    case 2:  d = port_read(1); break;\r
+    case 3:  d = port_read(2); break;\r
     default: d = Pico.ioports[a]; break; // IO ports can be used as RAM\r
   }\r
   return d;\r
 }\r
 \r
-static void NOINLINE io_ports_write(u32 a, u32 d)\r
+NOINLINE void io_ports_write(u32 a, u32 d)\r
 {\r
   a = (a>>1) & 0xf;\r
 \r
   // 6 button gamepad: if TH went from 0 to 1, gamepad changes state\r
-  if (1 <= a && a <= 2 && (PicoOpt & POPT_6BTN_PAD))\r
+  if (1 <= a && a <= 2)\r
   {\r
     Pico.m.padDelay[a - 1] = 0;\r
     if (!(Pico.ioports[a] & 0x40) && (d & 0x40))\r
@@ -252,8 +309,6 @@ static void NOINLINE io_ports_write(u32 a, u32 d)
   Pico.ioports[a] = d;\r
 }\r
 \r
-#endif // _ASM_MEMORY_C\r
-\r
 void NOINLINE ctl_write_z80busreq(u32 d)\r
 {\r
   d&=1; d^=1;\r
@@ -1177,3 +1232,4 @@ static void z80_mem_setup(void)
 #endif\r
 }\r
 \r
+// vim:shiftwidth=2:ts=2:expandtab\r
index be2fa99..f6d7f79 100644 (file)
@@ -9,7 +9,6 @@
 .equ SRR_MAPPED,    (1 <<  0)\r
 .equ SRR_READONLY,  (1 <<  1)\r
 .equ SRF_EEPROM,    (1 <<  1)\r
-.equ POPT_6BTN_PAD, (1 <<  5)\r
 .equ POPT_EN_32X,   (1 << 20)\r
 \r
 .text\r
@@ -67,24 +66,7 @@ m_read8_eeprom:
 PicoRead8_io: @ u32 a, u32 d\r
     bic     r2, r0, #0x001f   @ most commonly we get i/o port read,\r
     cmp     r2, #0xa10000     @ so check for it first\r
-    bne     m_read8_not_io\r
-\r
-m_read8_misc_io:\r
-    ands    r0, r0, #0x1e\r
-    beq     m_read8_misc_hwreg\r
-    cmp     r0, #4\r
-    movlt   r0, #0\r
-    moveq   r0, #1\r
-    ble     PadRead\r
-    ldr     r3, =(Pico+0x22000)\r
-    mov     r0, r0, lsr #1  @ other IO ports (Pico.ioports[a])\r
-    ldrb    r0, [r3, r0]\r
-    bx      lr\r
-\r
-m_read8_misc_hwreg:\r
-    ldr     r3, =(Pico+0x22200)\r
-    ldrb    r0, [r3, #0x0f] @ Pico.m.hardware\r
-    bx      lr\r
+    beq     io_ports_read\r
 \r
 m_read8_not_io:\r
     and     r2, r0, #0xfc00\r
@@ -161,7 +143,7 @@ PicoRead16_io: @ u32 a, u32 d
     cmp     r2, #0xa10000     @ so check for it first\r
     bne     m_read16_not_io\r
     stmfd   sp!,{lr}\r
-    bl      m_read8_misc_io   @ same as read8\r
+    bl      io_ports_read     @ same as read8\r
     orr     r0, r0, r0, lsl #8 @ only has bytes mirrored\r
     ldmfd   sp!,{pc}\r
 \r
@@ -201,37 +183,7 @@ PicoWrite8_io: @ u32 a, u32 d
     bic     r2, r0, #0x1e       @ most commonly we get i/o port write,\r
     eor     r2, r2, #0xa10000   @ so check for it first\r
     eors    r2, r2, #1\r
-    bne     m_write8_not_io\r
-\r
-m_write8_io:\r
-    ldr     r2, =PicoOpt\r
-    and     r0, r0, #0x1e\r
-    ldr     r2, [r2]\r
-    ldr     r3, =(Pico+0x22000) @ Pico.ioports\r
-    tst     r2, #POPT_6BTN_PAD\r
-    beq     m_write8_io_done\r
-    cmp     r0, #2\r
-    cmpne   r0, #4\r
-    bne     m_write8_io_done @ not likely to happen\r
-    add     r2, r3, #0x200   @ Pico+0x22200\r
-    mov     r12,#0\r
-    cmp     r0, #2\r
-    streqb  r12,[r2,#0x18]\r
-    strneb  r12,[r2,#0x19]   @ Pico.m.padDelay[i] = 0\r
-    tst     r1, #0x40        @ TH\r
-    beq     m_write8_io_done\r
-    ldrb    r12,[r3, r0, lsr #1]\r
-    tst     r12,#0x40\r
-    bne     m_write8_io_done\r
-    cmp     r0, #2\r
-    ldreqb  r12,[r2,#0x0a]\r
-    ldrneb  r12,[r2,#0x0b]   @ Pico.m.padTHPhase\r
-    add     r12,r12,#1\r
-    streqb  r12,[r2,#0x0a]\r
-    strneb  r12,[r2,#0x0b]   @ Pico.m.padTHPhase\r
-m_write8_io_done:\r
-    strb    r1, [r3, r0, lsr #1]\r
-    bx      lr\r
+    beq     io_ports_write\r
 \r
 m_write8_not_io:\r
     tst     r0, #1\r
@@ -270,7 +222,7 @@ m_write8_not_sreg:
 PicoWrite16_io: @ u32 a, u32 d\r
     bic     r2, r0, #0x1f    @ most commonly we get i/o port write,\r
     cmp     r2, #0xa10000    @ so check for it first\r
-    beq     m_write8_io\r
+    beq     io_ports_write\r
 \r
 m_write16_not_io:\r
     and     r2, r0, #0xff00\r
index 7c7a93e..859935e 100644 (file)
@@ -70,6 +70,9 @@ void PicoPower(void)
   Pico.video.pending_ints=0;\r
   z80_reset();\r
 \r
+  // my MD1 VA6 console has this in IO\r
+  Pico.ioports[1] = Pico.ioports[2] = Pico.ioports[3] = 0xff;\r
+\r
   // default VDP register values (based on Fusion)\r
   Pico.video.reg[0] = Pico.video.reg[1] = 0x04;\r
   Pico.video.reg[0xc] = 0x81;\r
index 0422dfd..c0aa6da 100644 (file)
@@ -52,7 +52,7 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
 #define POPT_EN_Z80         (1<< 2)\r
 #define POPT_EN_STEREO      (1<< 3)\r
 #define POPT_ALT_RENDERER   (1<< 4) // 00 00x0\r
-#define POPT_6BTN_PAD       (1<< 5)\r
+// unused                   (1<< 5)\r
 // unused                   (1<< 6)\r
 #define POPT_ACC_SPRITES    (1<< 7)\r
 #define POPT_DIS_32C_BORDER (1<< 8) // 00 0x00\r
@@ -248,6 +248,14 @@ int PicoCdCheck(const char *fname_in, int *pregion);
 \r
 extern unsigned char media_id_header[0x100];\r
 \r
+// memory.c\r
+enum input_device {\r
+  PICO_INPUT_NOTHING,\r
+  PICO_INPUT_PAD_3BTN,\r
+  PICO_INPUT_PAD_6BTN,\r
+};\r
+void PicoSetInputDevice(int port, enum input_device device);\r
+\r
 #ifdef __cplusplus\r
 } // End of extern "C"\r
 #endif\r
index 2b558c1..f4e20d2 100644 (file)
 #define CYCLES_S68K_ASD      241
 
 // pad delay (for 6 button pads)
-#define PAD_DELAY \
-  if (PicoOpt&POPT_6BTN_PAD) { \
-    if(Pico.m.padDelay[0]++ > 25) Pico.m.padTHPhase[0]=0; \
-    if(Pico.m.padDelay[1]++ > 25) Pico.m.padTHPhase[1]=0; \
-  }
+#define PAD_DELAY() { \
+  if(Pico.m.padDelay[0]++ > 25) Pico.m.padTHPhase[0]=0; \
+  if(Pico.m.padDelay[1]++ > 25) Pico.m.padTHPhase[1]=0; \
+}
 
 // CPUS_RUN
 #ifndef CPUS_RUN
@@ -114,7 +113,7 @@ static int PicoFrameHints(void)
       Pico.video.status|=0x200;
     }
 
-    PAD_DELAY
+    PAD_DELAY();
 #ifdef PICO_CD
     check_cd_dma();
 #endif
@@ -187,7 +186,7 @@ static int PicoFrameHints(void)
   Pico.video.status|=0x200;
 
   memcpy(PicoPadInt, PicoPad, sizeof(PicoPadInt));
-  PAD_DELAY
+  PAD_DELAY();
 #ifdef PICO_CD
   check_cd_dma();
 #endif
@@ -257,7 +256,7 @@ static int PicoFrameHints(void)
       pv->v_counter = (pv->v_counter << 1) | 1;
     pv->v_counter &= 0xff;
 
-    PAD_DELAY
+    PAD_DELAY();
 #ifdef PICO_CD
     check_cd_dma();
 #endif
index bb8fde7..8a760c6 100644 (file)
@@ -598,7 +598,6 @@ unsigned int PicoRead8_io(unsigned int a);
 unsigned int PicoRead16_io(unsigned int a);\r
 void PicoWrite8_io(unsigned int a, unsigned int d);\r
 void PicoWrite16_io(unsigned int a, unsigned int d);\r
-void p32x_dreq1_trigger(void);\r
 \r
 // pico/memory.c\r
 PICO_INTERNAL void PicoMemSetupPico(void);\r
index 1573d12..5807c1b 100644 (file)
@@ -455,9 +455,11 @@ int emu_reload_rom(const char *rom_fname_in)
        // additional movie stuff\r
        if (movie_data)\r
        {\r
-               if (movie_data[0x14] == '6')\r
-                    PicoOpt |=  POPT_6BTN_PAD; // 6 button pad\r
-               else PicoOpt &= ~POPT_6BTN_PAD;\r
+               enum input_device indev = (movie_data[0x14] == '6') ?\r
+                       PICO_INPUT_PAD_6BTN : PICO_INPUT_PAD_3BTN;\r
+               PicoSetInputDevice(0, indev);\r
+               PicoSetInputDevice(1, indev);\r
+\r
                PicoOpt |= POPT_DIS_VDP_FIFO; // no VDP fifo timing\r
                if (movie_data[0xF] >= 'A') {\r
                        if (movie_data[0x16] & 0x80) {\r
@@ -550,6 +552,8 @@ void emu_prep_defconfig(void)
        defaultConfig.s_PicoCDBuffers = 0;\r
        defaultConfig.confirm_save = EOPT_CONFIRM_SAVE;\r
        defaultConfig.Frameskip = -1; // auto\r
+       defaultConfig.input_dev0 = PICO_INPUT_PAD_3BTN;\r
+       defaultConfig.input_dev1 = PICO_INPUT_PAD_3BTN;\r
        defaultConfig.volume = 50;\r
        defaultConfig.gamma = 100;\r
        defaultConfig.scaling = 0;\r
index 836d7d4..5138754 100644 (file)
@@ -57,6 +57,8 @@ typedef struct _currentConfig_t {
        int s_PicoAutoRgnOrder;
        int s_PicoCDBuffers;
        int Frameskip;
+       int input_dev0;
+       int input_dev1;
        int confirm_save;
        int CPUclock;
        int volume;
index 0745352..4e9e594 100644 (file)
@@ -355,12 +355,15 @@ static const char *mgn_dev_name(int id, int *offs)
 static int mh_saveloadcfg(int id, int keys);
 static const char *mgn_saveloadcfg(int id, int *offs);
 
+const char *indev_names[] = { "none", "3 button pad", "6 button pad", NULL };
+
 static menu_entry e_menu_keyconfig[] =
 {
        mee_handler_id("Player 1",          MA_CTRL_PLAYER1,    key_config_loop_wrap),
        mee_handler_id("Player 2",          MA_CTRL_PLAYER2,    key_config_loop_wrap),
        mee_handler_id("Emulator controls", MA_CTRL_EMU,        key_config_loop_wrap),
-       mee_onoff     ("6 button pad",      MA_OPT_6BUTTON_PAD, PicoOpt, POPT_6BTN_PAD),
+       mee_enum      ("Input device 1",    MA_OPT_INPUT_DEV0,  currentConfig.input_dev0, indev_names),
+       mee_enum      ("Input device 2",    MA_OPT_INPUT_DEV1,  currentConfig.input_dev1, indev_names),
        mee_range     ("Turbo rate",        MA_CTRL_TURBO_RATE, currentConfig.turbo_rate, 1, 30),
        mee_range     ("Analog deadzone",   MA_CTRL_DEADZONE,   currentConfig.analog_deadzone, 1, 99),
        mee_cust_nosave("Save global config",       MA_OPT_SAVECFG, mh_saveloadcfg, mgn_saveloadcfg),
@@ -383,6 +386,10 @@ static int menu_loop_keyconfig(int id, int keys)
 
        me_enable(e_menu_keyconfig, MA_OPT_SAVECFG_GAME, PicoGameLoaded);
        me_loop(e_menu_keyconfig, &sel);
+
+       PicoSetInputDevice(0, currentConfig.input_dev0);
+       PicoSetInputDevice(1, currentConfig.input_dev1);
+
        return 0;
 }
 
index c609e83..9558ff5 100644 (file)
@@ -24,7 +24,8 @@ typedef enum
        MA_OPT_ENABLE_SOUND,
        MA_OPT_SOUND_QUALITY,
        MA_OPT_ARM940_SOUND,
-       MA_OPT_6BUTTON_PAD,
+       MA_OPT_INPUT_DEV0,
+       MA_OPT_INPUT_DEV1,
        MA_OPT_REGION,
        MA_OPT_SRAM_STATES,
        MA_OPT_CONFIRM_STATES,
index d46cc4a..3ae8974 100644 (file)
@@ -183,6 +183,8 @@ void retro_set_environment(retro_environment_t cb)
 {
        static const struct retro_variable vars[] = {
                //{ "region", "Region; Auto|NTSC|PAL" },
+               { "picodrive_input1", "Input device 1; 3 button pad|6 button pad|None" },
+               { "picodrive_input2", "Input device 2; 3 button pad|6 button pad|None" },
                { NULL, NULL },
        };
 
@@ -545,7 +547,7 @@ bool retro_load_game(const struct retro_game_info *info)
 
        enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
        if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) {
-               lprintf("RGB565 suppot required, sorry\n");
+               lprintf("RGB565 support required, sorry\n");
                return false;
        }
 
@@ -660,13 +662,41 @@ static void snd_write(int len)
        audio_batch_cb(PsndOut, len / 4);
 }
 
+static enum input_device input_name_to_val(const char *name)
+{
+       if (strcmp(name, "3 button pad") == 0)
+               return PICO_INPUT_PAD_3BTN;
+       if (strcmp(name, "6 button pad") == 0)
+               return PICO_INPUT_PAD_6BTN;
+       if (strcmp(name, "None") == 0)
+               return PICO_INPUT_NOTHING;
+
+       lprintf("invalid picodrive_input: '%s'\n", name);
+       return PICO_INPUT_PAD_3BTN;
+}
+
+static void update_variables(void)
+{
+       struct retro_variable var;
+
+       var.value = NULL;
+       var.key = "picodrive_input1";
+       if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+               PicoSetInputDevice(0, input_name_to_val(var.value));
+
+       var.value = NULL;
+       var.key = "picodrive_input2";
+       if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+               PicoSetInputDevice(1, input_name_to_val(var.value));
+}
+
 void retro_run(void) 
 {
        bool updated = false;
        int pad, i;
 
        if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
-               ; //update_variables(true);
+               update_variables();
 
        input_poll_cb();
 
@@ -720,6 +750,8 @@ void retro_init(void)
        //PicoMessage = plat_status_msg_busy_next;
        PicoMCDopenTray = disk_tray_open;
        PicoMCDcloseTray = disk_tray_close;
+
+       update_variables();
 }
 
 void retro_deinit(void)
index aa3a7f2..e8f5389 100644 (file)
@@ -64,7 +64,6 @@ int plat_wait_event(int *fds_hnds, int count, int timeout_ms)
 void pemu_prep_defconfig(void)
 {
        memset(&defaultConfig, 0, sizeof(defaultConfig));
-       defaultConfig.s_PicoOpt|= POPT_6BTN_PAD; // for xmen proto
        defaultConfig.s_PicoCDBuffers = 0;
        defaultConfig.Frameskip = 0;
 }