OSDN Git Service

[VM][General] Merge Upstream 2021-05-06. Some variants of PC-6001 are temporally...
[csp-qt/common_source_project-fm7.git] / source / src / vm / mz700 / joystick.cpp
1 /*
2         SHARP MZ-700 Emulator 'EmuZ-700'
3         SHARP MZ-1500 Emulator 'EmuZ-1500'
4
5         Author : Takeda.Toshiya
6         Date   : 2006.11.24 -
7
8         [ joystick ]
9 */
10
11 #include "joystick.h"
12
13 namespace MZ700 {
14
15 void JOYSTICK::initialize()
16 {
17         val_1x03 = 0x7e;
18         joy_stat = emu->get_joy_buffer();
19
20         // register event
21         register_vline_event(this);
22 }
23
24 //              __           _______________________
25 //      JA2       \_________/__y1___/__y0___/       \__ JA2は上下方向の状態をPWMする
26 //              __ _________ _______ _______ _______ __
27 //      JA1     __X____A____X___B___X___R___X___L___X__ JA1は左右とボタンの状態をそのまま送る
28 //
29 //                |←  38 →|← 30→|← 30→|← 30→|   (3.579545MHz)
30 //
31 //      y1y0    UD
32 //       0 0    01
33 //       0 1    10
34 //       1 1    11
35 //
36 uint32_t JOYSTICK::read_AM7J(int jnum)
37 {
38         uint32_t js;
39         uint32_t val = ~0;
40         uint32_t clk;
41         bool y0, y1;
42
43         clk = get_current_clock() & 0x007f;
44         js = joy_stat[jnum];
45         y0 = y1 = false;
46
47         switch (js & 0xc0) {
48                 case 0x40: // RUN
49                         y1 = true;
50                         y0 = true;
51                         js |= 0x0c;  // LEFT+RIGHT
52                         break;
53                 case 0x80: // SELECT
54                         y0 = true;
55                         js |= 0x0c;  // LEFT+RIGHT
56                         break;
57                 case 0xc0: // RUN+SELECT
58                         js |= 0x0c;  // LEFT+RIGHT
59                         break;
60                 default:
61                         switch (js & 0x03) {
62                                 case 0x01: // UP
63                                         break;
64                                 case 0x02: // DOWN
65                                         y0 = true;
66                                         break;
67                                 default: // center
68                                         y1 = true;
69                                         y0 = true;
70                                         break;
71                         }
72                         break;
73         }
74
75         if (clk < 38) {
76                 // JA2 = 0,  JA1 = TRG-A
77                 val &= ~0x10;
78                 if(js & 0x10) val &= ~0x08;  // trigger A
79         } else if (clk < 68) {
80                 // JA2 = y1,  JA1 = TRG-B
81                 if(!y1) val &= ~0x10;
82                 if(js & 0x20) val &= ~0x08;  // trigger B
83         } else if (clk < 98) {
84                 // JA2 = y0,  JA1 = RIGHT
85                 if(!y0) val &= ~0x10;
86                 if(js & 0x08) val &= ~0x08;  // right
87         } else {
88                 // JA2 = 1,  JA1 = LEFT
89                 if(js & 0x04) val &= ~0x08;  // left
90         }
91         if (jnum == 0) {
92                 val >>= 2;
93         }
94
95         return val;
96 }
97
98 uint32_t JOYSTICK::read_io8(uint32_t addr)
99 {
100         uint32_t val = 0x7e;
101
102         switch (config.joystick_type) {
103
104                 case DEVICE_JOYSTICK_1X03:              // SHARP MZ-1X03
105                         val = val_1x03;
106                         break;
107
108                 case DEVICE_JOYSTICK_JOY700:            // TSUKUMO JOY-700
109                         if(joy_stat[0] & 0x01) val &= ~0x10;  // up    : JB2
110                         if(joy_stat[0] & 0x02) val &= ~0x08;  // down  : JB1
111                         if(joy_stat[0] & 0x04) val &= ~0x02;  // left  : JA1
112                         if(joy_stat[0] & 0x08) val &= ~0x04;  // right : JA2
113                         if(joy_stat[0] & 0x10) val &= ~0x1e;  // trigger A : ALL
114                         if(joy_stat[0] & 0x20) val &= ~0x1e;  // trigger B : ALL
115                         break;
116
117                 case DEVICE_JOYSTICK_AM7J:              // AM7J ATARI Joystick adaptor
118                         val &= read_AM7J(0);
119                         val &= read_AM7J(1);
120                         break;
121
122                 default:
123                         break;
124         }
125
126         return val;
127 }
128
129 //
130 // MZ-1X03 は /VBLK=H でボタンの状態(押されていればL)
131 //            /VBLK=L でスティックの傾き(PWM, 127.841kHz, (0〜255)+10のLowパルス) を出力する
132 //            /VBLKが立ち下がってから 302 CPU clock待った後、28 CPU clock 単位のLowパルスを出力
133 //
134 uint64_t JOYSTICK::pulse_width_1x03(uint32_t js, uint32_t mmin, uint32_t mmax)
135 {
136         if (js & mmin) return 192;
137         if (js & mmax) return 10000;
138         return 4192;
139 }
140
141 void JOYSTICK::event_vline(int v, int clock)
142 {
143         if (config.joystick_type == DEVICE_JOYSTICK_1X03) {
144                 if (v == 0) {
145                         // trigger
146                         val_1x03 = 0x7e;
147                         if(joy_stat[0] & 0x10) val_1x03 &= ~0x02;
148                         if(joy_stat[0] & 0x20) val_1x03 &= ~0x04;
149                         if(joy_stat[1] & 0x10) val_1x03 &= ~0x08;
150                         if(joy_stat[1] & 0x20) val_1x03 &= ~0x10;
151                 } else if (v == 200) {
152                         // stick (PWM)
153                         val_1x03 &= ~(0x06 | 0x18);
154                         register_event_by_clock(this, EVENT_1X03_X1, pulse_width_1x03(joy_stat[0], 0x04, 0x08), false, NULL);
155                         register_event_by_clock(this, EVENT_1X03_Y1, pulse_width_1x03(joy_stat[0], 0x01, 0x02), false, NULL);
156                         register_event_by_clock(this, EVENT_1X03_X2, pulse_width_1x03(joy_stat[1], 0x04, 0x08), false, NULL);
157                         register_event_by_clock(this, EVENT_1X03_Y2, pulse_width_1x03(joy_stat[1], 0x01, 0x02), false, NULL);
158                 }
159         }
160 }
161
162 void JOYSTICK::event_callback(int event_id, int err)
163 {
164         switch (event_id) {
165                 case EVENT_1X03_X1:  val_1x03 |= 0x02; break;
166                 case EVENT_1X03_Y1:  val_1x03 |= 0x04; break;
167                 case EVENT_1X03_X2:  val_1x03 |= 0x08; break;
168                 case EVENT_1X03_Y2:  val_1x03 |= 0x10; break;
169         }
170 }
171
172 #define STATE_VERSION   2
173
174 bool JOYSTICK::process_state(FILEIO* state_fio, bool loading)
175 {
176         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
177                 return false;
178         }
179         if(!state_fio->StateCheckInt32(this_device_id)) {
180                 return false;
181         }
182         state_fio->StateValue(val_1x03);
183         return true;
184 }
185
186 }