Advertisement
xiahanlu

控制器

Oct 13th, 2018
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.94 KB | None | 0 0
  1. /* controller (PL0-PL5, with DAN215)
  2.  * Game boy's joypad information read and write
  3.  *
  4.  * Copyright (C) 2018 moecmks
  5.  * This file is part of KS3578.
  6.  *
  7.  * do What The Fuck you want to Public License
  8.  *
  9.  * Version 1.0, March 2000
  10.  * Copyright (C) 2000 Banlu Kemiyatorn (]d).
  11.  * 136 Nives 7 Jangwattana 14 Laksi Bangkok
  12.  * Everyone is permitted to copy and distribute verbatim copies
  13.  * of this license document, but changing it is not allowed.
  14.  *
  15.  * Ok, the purpose of this license is simple
  16.  * and you just
  17.  *
  18.  * DO WHAT THE FUCK YOU WANT TO.
  19.  */
  20.  
  21. #include "gameboy.h"
  22. #include "internal.h"
  23.  
  24. /* for internal call */
  25. #define joypad_hostdrv ubdata_user
  26.  
  27. /* Assert IRQ_5 Interrupt Gen MACRO */
  28. #ifndef IRQ_5
  29. # define IRQ_5 0x10
  30. #endif
  31.  
  32. #ifndef JOYPAD_INTERRUPT_GEN_ENABLE
  33. # undef IRQ_5
  34. # define IRQ_5 0
  35. #endif
  36.  
  37. static
  38. void default_update (struct controller *ctl, void *obj, struct controller_pad *gb_infos, struct controller_pad *host_infos) {
  39.   printf ("%s:%s please set joypad callback( controller_setupdate function)\n", __FILE__, __LINE__);
  40.   assert (0);
  41. }
  42.  
  43. void controller_write (struct controller *ctl, ks_uint8 value) {
  44.   ctl->reg00_P1 = value & 0x30;
  45. }
  46.  
  47. /* Gameboy Joypad Infos:http://gbdev.gg8.se/files/docs/mirrors/pandocs.html#joypadinput */
  48. ks_uint8 controller_read (struct controller *ctl) {
  49.   ks_uint8 value =ctl->reg00_P1 & 0x30;
  50.   switch (value) {
  51.   case 0x00: /* maybe result direction | action ??*/
  52.     value = ctl->reg00_P1 & 0xF0;
  53.     value|= 0x0F;
  54. #if (JOYPAD_LOAD_ACTION_IN_P1415_ALLOPEN == 0)
  55.     if (ctl->gb_pad.right || ctl->gb_pad.a) value &= ~0x01; /*Right ||A*/
  56.     if (ctl->gb_pad.left || ctl->gb_pad.b) value &= ~0x02; /*Left ||B */
  57.     if (ctl->gb_pad.up || ctl->gb_pad.select) value &= ~0x04; /*Up ||Select */
  58.     if (ctl->gb_pad.down || ctl->gb_pad.start) value &= ~0x08; /*Down || Start*/
  59. #elif (JOYPAD_LOAD_ACTION_IN_P1415_ALLOPEN == 1)
  60.     if (ctl->gb_pad.right && ctl->gb_pad.a) value &= ~0x01; /*Right ||A*/
  61.     if (ctl->gb_pad.left && ctl->gb_pad.b) value &= ~0x02; /*Left ||B */
  62.     if (ctl->gb_pad.up && ctl->gb_pad.select) value &= ~0x04; /*Up ||Select */
  63.     if (ctl->gb_pad.down && ctl->gb_pad.start) value &= ~0x08; /*Down || Start*/
  64. #elif (JOYPAD_LOAD_ACTION_IN_P1415_ALLOPEN == 2)
  65.     if ((!!ctl->gb_pad.right) ^ !!ctl->gb_pad.a) value &= ~0x01; /*Right ||A*/
  66.     if ((!!ctl->gb_pad.left) ^ !!ctl->gb_pad.b) value &= ~0x02; /*Left ||B */
  67.     if ((!!ctl->gb_pad.up) ^ !!ctl->gb_pad.select) value &= ~0x04; /*Up ||Select */
  68.     if ((!!ctl->gb_pad.down) ^ !!ctl->gb_pad.start) value &= ~0x08; /*Down || Start*/
  69. #elif (JOYPAD_LOAD_ACTION_IN_P1415_ALLOPEN == 3)
  70.     if (!(ctl->gb_pad.right && ctl->gb_pad.a)) value &= ~0x01; /*Right ||A*/
  71.     if (!(ctl->gb_pad.left && ctl->gb_pad.b)) value &= ~0x02; /*Left ||B */
  72.     if (!(ctl->gb_pad.up && ctl->gb_pad.select)) value &= ~0x04; /*Up ||Select */
  73.     if (!(ctl->gb_pad.down && ctl->gb_pad.start)) value &= ~0x08; /*Down || Start*/
  74. #else
  75. # error "JOYPAD_LOAD_ACTION_IN_P1415_ALLOPEN define error."
  76. #endif
  77.     break;
  78.   case 0x30: /* reset device ?*/
  79.     return 0xFF;
  80.   case 0x20: /* p14 out, set button, active low*/
  81.     value = ctl->reg00_P1 & 0xF0;
  82.     value|= 0x0F;
  83.     if (ctl->gb_pad.right) value &= ~0x01; /*Right */
  84.     if (ctl->gb_pad.left) value &= ~0x02; /*Left */
  85.     if (ctl->gb_pad.up) value &= ~0x04; /*Up */
  86.     if (ctl->gb_pad.down) value &= ~0x08; /*Down */
  87.     break;
  88.   case 0x10: /* p15 out, set direction, active low */
  89.     value = ctl->reg00_P1 & 0xF0;
  90.     value|= 0x0F;
  91.     if (ctl->gb_pad.a) value &= ~0x01; /*A */
  92.     if (ctl->gb_pad.b) value &= ~0x02; /*B */
  93.     if (ctl->gb_pad.select) value &= ~0x04; /*Select */
  94.     if (ctl->gb_pad.start) value &= ~0x08; /*Start */
  95.     break;
  96.   }
  97.   return value;
  98. }
  99.  
  100. void controller_uninit (struct controller **ctl) {
  101.   struct controller *ctl_;
  102.   assert (ctl != ks_null);
  103.   ctl_ = *ctl;
  104.   *ctl = ks_null;
  105.   if (ctl_ != ks_null)
  106.     free (ctl_);
  107.   else ;
  108. }
  109.  
  110. void controller_setupdate_ (struct controller *ctl, void (*update)
  111.              (struct controller *,
  112.              void *,
  113.                 struct controller_pad *, /* self */
  114.              struct controller_pad * /* host edge */), void *obj){
  115.   assert (ctl != ks_null);
  116.   assert (update != ks_null);
  117.   ctl->joypad_hostdrv = update;
  118.   ctl->obj = obj;
  119. }
  120.  
  121. static
  122. void controller_update_hostdrv (struct controller *ctl) {
  123.  
  124.   if (ctl->gb->cpu_clks_joypad > ctl->gb->mach_tools->joypad_gen_freq) {
  125.     ks_bool edge_gen =ks_false;
  126.     /* temrp cache for check edge (high to low*/
  127.     struct controller_pad edge;
  128.     assert (ctl != ks_null);
  129.     memset (& edge, 0, sizeof (edge));
  130.     /*call hostdrv*/
  131.     ((void (*)(struct controller *, void *,
  132.                   struct controller_pad *,
  133.          struct controller_pad *))(ctl->joypad_hostdrv)) (ctl, ctl->obj, & ctl->gb_pad, & edge);
  134.     ctl->gb->cpu_clks_joypad -= ctl->gb->mach_tools->joypad_gen_freq; /* sub a clk block */
  135.     /* there is a bouncing phenomenon similar to electrical components flutter in real gameboy,
  136.        making joypad interrupt very difficult to use. */
  137.     /* check register */
  138.     switch (ctl->reg00_P1 & 0x30) {
  139.     case 0x30: /* close device*/
  140.       return ;
  141.     case 0x00: /* any button press will cause interrupt requested, resume stop command */
  142.       if (edge.right || edge.a) edge_gen = ks_true; /*Right ||A*/
  143.       if (edge.left || edge.b) edge_gen = ks_true; /*Left ||B */
  144.       if (edge.up || edge.select) edge_gen = ks_true; /*Up ||Select */
  145.       if (edge.down || edge.start) edge_gen = ks_true; /*Down || Start*/
  146.     case 0x20: /* p14 out, button, */
  147.       if (edge.right) edge_gen = ks_true; /*Right */
  148.       if (edge.left) edge_gen = ks_true; /*Left */
  149.       if (edge.up) edge_gen = ks_true; /*Up */
  150.       if (edge.down) edge_gen = ks_true; /*Down */
  151.       break;
  152.     case 0x10: /* p15 out, direction */
  153.       if (edge.a) edge_gen = ks_true; /*A */
  154.       if (edge.b) edge_gen = ks_true; /*B */
  155.       if (edge.select) edge_gen = ks_true; /*Select */
  156.       if (edge.start) edge_gen = ks_true; /*Start */
  157.       break;
  158.     }
  159.     if (edge_gen != ks_false) {
  160.       /* Set interrupt flags */
  161.   #   if 1
  162.       /* try resume gameboy from stop,  (if stop) */
  163.       if (ctl->gb->lr35902->stop != ks_false) {
  164.         ctl->gb->lr35902->stop = ks_false;
  165.         ctl->gb->reg0F_IF |= IRQ_5;
  166.       }
  167.   #   else
  168.       /* IRQ_5 is the lowest priority interruption.*/
  169.       ctl->gb->reg0F_IF |= IRQ_5;
  170.       /* try resume gameboy from stop,  (if stop) */
  171.       gameboy_resume_ifstop (ctl->gb);
  172.   #   endif
  173.     }
  174.   }
  175. }
  176.  
  177. int controller_init (struct controller **ctl) {
  178.   struct controller *ctl_ =ks_null;
  179.   assert (ctl != ks_null);
  180.  
  181.   ctl_ = (struct controller *)
  182.      calloc (sizeof (struct controller), 1);
  183.   ctl_->joypad_hostdrv = default_update;
  184.   ctl_->obj = ks_null;
  185.   ctl_->clks = controller_update_hostdrv;
  186.   assert (ctl_ != ks_null);
  187.   // memset (& ctl_->gb_pad, 0x01, sizeof (ctl_->gb_pad));
  188.   * ctl = ctl_;
  189.   return 0;
  190. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement