forked from badman12345/osmose-rpi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
IOMapper.cpp
292 lines (275 loc) · 6.69 KB
/
IOMapper.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
/*****************************************************************************
*
* File: IOMapper.cpp
*
* Project: Osmose emulator.
*
* Description: This class will handle emulator input/output operation.
*
* Author: Vedder Bruno
* Date: 08/10/2004, 18h00
*
* URL: http://bcz.emu-france.com/
*****************************************************************************/
#include "IOMapper.h"
#include "Bits.h"
/* Constructor need VDP reference */
IOMapper::IOMapper(VDP & v, SN76489 & p) : vdp( v ), psg( p )
{
reset();
}
/*----------------------------------------------------------------------*/
/* This method resets ports. */
/*----------------------------------------------------------------------*/
void IOMapper::reset()
{
if (opt.inputType == DEFAULT_PAD)
{
port3F = 0xFF; // Active low
}
else
if (opt.inputType == PADDLE)
{
port3F = 0x30; // 00110000b
}
port3E = 0xA4;
portPAD1 = 0xFF;
portPAD2 = 0xFF;
paddleValue = 0;
flipFlop = false;
}
/*----------------------------------------------------------------------*/
/* Based on Charles MacDonald documentation, this method dispatches */
/* port write, depending on A7, A6 and A0 address line. */
/*----------------------------------------------------------------------*/
void IOMapper::out8(unsigned port, unsigned char value)
{
if (port <= 0x3F)
{
if (port & BIT0) // Write to port 3F
{
#ifdef AUTO_NAT_VERBOSE
cout << "AUTO_NAT port 0x3F written with value " << hex << setw(2) << setfill('0') << (int)value << endl;
#endif
port3F = value;
if ( (port3F & BIT0) && (port3F & BIT2) )
{
#ifdef AUTO_NAT_VERBOSE
cout << "Auto nationalisation asked." << endl;
#endif
if (opt.WorldVersion == EXPORT)
{
// Copy 3F bit7 to DD bit7
if (port3F & BIT7)
{
portPAD2 |= BIT7;
}
else
{
portPAD2 &= (0x7F);
}
// Copy 3F bit5 to DD bit6
if (port3F & BIT5)
{
portPAD2 |= BIT6;
}
else
{
portPAD2 &= 0xBF;
}
}
else
{
portPAD2 &= 0x3F;
}
if ( ((value & BIT0) && (value & BIT2))== 0 )
{
#ifdef AUTO_NAT_VERBOSE
cout << "Auto nationalisation reset asked." << endl;
#endif
}
}
if (port3F & BIT5)
{
// cout << "Selecting X7-X4 value on DC" << endl;
}
else
{
// cout << "Selecting X3-X0 value on DC" << endl;
}
return;
}
else // Write to port 3E
{
#ifdef MEM_CTRL_VERBOSE
cout << "MEM CTRL port 0x3E written with value " << hex << setw(2) << setfill('0') << (int)value << endl;
#endif
port3E = value;
#ifdef MEM_CTRL_VERBOSE
if (value & BIT2)
{
cout << "I/O chip Disable." << endl;
}
else
{
cout << "I/O chip Enabled." << endl;
}
if (value & BIT3)
{
cout << "BIOS ROM Disable." << endl;
}
else
{
cout << "BIOS ROM Enabled." << endl;
}
if (value & BIT4)
{
cout << "Work Ram Disable (For battery backed RAM ?)." << endl;
}
else
{
cout << "Work Ram Enable." << endl;
}
if (value & BIT5)
{
cout << "Card slot Disable." << endl;
}
else
{
cout << "Card slot Enable." << endl;
}
if (value & BIT6)
{
cout << "Cartridge slot Disable." << endl;
}
else
{
cout << "Cartridge slot Enable." << endl;
}
if (value & BIT7)
{
cout << "Expansion slot Disable." << endl;
}
else
{
cout << "Expansion slot Enable." << endl;
}
#endif
return;
}
}
if (port <= 0x7F)
{
psg.writePort(value);
return;
#ifdef PSG_VERBOSE
cout << "PSG port 0x7F written with value " << hex << setw(2) << setfill('0') << (int)value << endl;
#endif
return;
}
if (port <= 0xBF)
{
if (port & BIT0) // Write on VDP Ctrl Port 0xBF
{
#ifdef VDP_ACCESS
cout << "VDP_CTRL port 0xBF written with value " << hex << setw(2) << setfill('0') << (int)value << endl;
#endif
vdp.writeCtrlPort( value );
return;
}
else // Write on VDP Data Port 0xBE
{
#ifdef VDP_VERBOSE
cout << "VDP_DATA port 0xBE written with value " << hex << setw(2) << setfill('0') << (int)value << endl;
#endif
vdp.writeDataPort( value );
return;
}
}
#ifdef VDP_VERBOSE
cout << "Unkown port "<< hex << setw(2) << setfill('0') << (int)port << " written with value " << hex << setw(2) << setfill('0') << (int)value << endl;
#endif
}
/*----------------------------------------------------------------------*/
/* Based on Charles MacDonald documentation, this method dispatches */
/* port read, depending on A7, A6 and A0 address line. */
/*----------------------------------------------------------------------*/
unsigned char IOMapper::in8(unsigned port)
{
if (port == 0x3E)
{
return port3E;
//cout << "MEM CTRL Port 0x3E: Read, value is " << hex << setw(2) << setfill('0') << (int)port3E << endl;
}
if (port <= 0x3F)
{
//cout << "NOT IMPLEMENTED / EXPERIMENTAL: Read port <=0x3f" << endl;
return (port & 0xff);
}
if (port <= 0x7F)
{
if (port & BIT0) // Read H counter port.
{
//#ifdef VDP_VERBOSE
cout << "NOT IMPLEMENTED: VDP port H COUTNER 0x7F read."<< endl;
//#endif
return 0xFF;
}
else // Read on VDP Vertical counter
{
#ifdef VDP_VERBOSE
cout << "VDP, port V COUTNER 0x7E read."<< endl;
#endif
return vdp.v_counter;
}
}
if (port <= 0xBF) // Read VDP status flag
{
if (port & BIT0)
{
#ifdef VDP_VERBOSE
cout << "VDP status read."<< endl;
#endif
return vdp.readStatusFlag();
}
else // Read VDP Data port
{
#ifdef VDP_VERBOSE
cout << "CRAM/VRAM read."<< endl;
#endif
return vdp.readDataPort();
}
}
// Port is > 0xBF and < 0xFF
if (port & BIT0)
{
#ifdef PAD_VERBOSE
cout << "Port PAD2 0xDD read."<< endl;
#endif
return portPAD2;
}
else
{
#ifdef PAD_VERBOSE
cout << "Port PAD1 0xDC read."<< endl;
#endif
if (opt.inputType == PADDLE)
{
flipFlop^=1;
if (flipFlop == true)
{
portPAD1 |= BIT5;
portPAD1 &= 0xf0;
portPAD1 |= (paddleValue >> 4);
}
else
{
portPAD1 &= ~BIT5;
portPAD1 &= 0xf0;
portPAD1 |= (paddleValue & 0x0f);
}
}
return portPAD1;
}
cout << "Unkown port "<< hex << setw(2) << setfill('0') << (int)port << " read."<< endl;
}