00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00020 #include <windows.h>
00021 #include <windowsx.h>
00022
00023 #include "viceremote.h"
00024
00026 #define DBG_USERMODE
00027
00029 #define DBG_PROGNAME "OPENCBM.DLL"
00030
00031 #include "debug.h"
00032
00033 #include <winioctl.h>
00034 #include "cbmioctl.h"
00035
00036 #include <stdlib.h>
00037
00039 #define DLL
00040 #include "i_opencbm.h"
00041 #include "archlib.h"
00042
00043 #include "arch.h"
00044 #include "vice_comm.h"
00045
00046 static REMOTECONTROL *ptr_mappedfile = 0;
00047 static HANDLE handle_mappedfile = 0;
00048
00049 static UINT buffernotowrite = -1;
00050
00051 static REMOTECONTROL_ONEMEMBUFFER *membuffertowrite = 0;
00052 static REMOTECONTROL_ONEREGBUFFER *regbuffertowrite = 0;
00053
00054 static REMOTECONTROL_ONEMEMBUFFER *membuffertoread = 0;
00055 static REMOTECONTROL_ONEREGBUFFER *regbuffertoread = 0;
00056
00057 int vicereadregister(viceregs which)
00058 {
00059 unsigned int value;
00060
00061 switch (which)
00062 {
00063 case reg_pc: value = regbuffertoread->OutRegs.PC; break;
00064 case reg_a: value = regbuffertoread->OutRegs.AC; break;
00065 case reg_x: value = regbuffertoread->OutRegs.XR; break;
00066 case reg_y: value = regbuffertoread->OutRegs.YR; break;
00067 case reg_sp: value = regbuffertoread->OutRegs.SP; break;
00068 case reg_flags: value = regbuffertoread->OutRegs.FLAGS; break;
00069 }
00070
00071 return value;
00072 }
00073
00074 void vicewriteregister(viceregs which, unsigned int value)
00075 {
00076 switch (which)
00077 {
00078 case reg_pc: regbuffertowrite->InRegsValid.PC = 1; regbuffertowrite->InRegs.PC = value; break;
00079 case reg_a: regbuffertowrite->InRegsValid.AC = 1; regbuffertowrite->InRegs.AC = value; break;
00080 case reg_x: regbuffertowrite->InRegsValid.XR = 1; regbuffertowrite->InRegs.XR = value; break;
00081 case reg_y: regbuffertowrite->InRegsValid.YR = 1; regbuffertowrite->InRegs.YR = value; break;
00082 case reg_sp: regbuffertowrite->InRegsValid.SP = 1; regbuffertowrite->InRegs.SP = value; break;
00083 case reg_flags: regbuffertowrite->InRegsValid.FLAGS = 1; regbuffertowrite->InRegs.FLAGS = value; break;
00084 }
00085 }
00086
00087 void vicewriteregister_when_at(unsigned int value)
00088 {
00089 ptr_mappedfile->regupdateaddress = value;
00090 }
00091
00092 void vicereadmemory(unsigned int address, unsigned int size, char *buffer)
00093 {
00094 if (ptr_mappedfile)
00095 {
00096 DBG_ASSERT(membuffertoread->read.perform == 0);
00097 DBG_ASSERT(membuffertoread->read.address == address);
00098 DBG_ASSERT(membuffertoread->read.size == size);
00099
00100 memcpy(buffer, ptr_mappedfile->data, size);
00101 }
00102 }
00103
00104 void vicepreparereadmemory(unsigned int address, unsigned int size)
00105 {
00106 if (ptr_mappedfile)
00107 {
00108 DBG_ASSERT(membuffertowrite->read.perform == 0);
00109
00110 membuffertowrite->read.perform = 1;
00111 membuffertowrite->read.address = address;
00112 membuffertowrite->read.size = size;
00113 }
00114 }
00115
00116 void vicewritememory(unsigned int address, unsigned int size, const char *buffer)
00117 {
00118 if (ptr_mappedfile)
00119 {
00120 DBG_ASSERT(membuffertowrite->write.perform == 0);
00121
00122 membuffertowrite->write.perform = 1;
00123 membuffertowrite->write.address = address;
00124 membuffertowrite->write.size = size;
00125
00126 memcpy(ptr_mappedfile->data, buffer, size);
00127 }
00128 }
00129
00130 void vicepause()
00131 {
00132 if (ptr_mappedfile)
00133 {
00134 membuffertoread = 0;
00135 regbuffertoread = 0;
00136
00137 buffernotowrite = (ptr_mappedfile->remotecontrollerbuffer + 1) & 1;
00138 membuffertowrite = &ptr_mappedfile->memorybuffer[buffernotowrite];
00139 regbuffertowrite = &ptr_mappedfile->regbuffer[buffernotowrite];
00140
00141
00142 memset(membuffertowrite, 0, sizeof(*membuffertowrite));
00143 memset(regbuffertowrite, 0, sizeof(*regbuffertowrite));
00144
00145 ptr_mappedfile->trapaddress = -1;
00146 ptr_mappedfile->regupdateaddress = -1;
00147 }
00148 }
00149
00150 void viceresume()
00151 {
00152 if (ptr_mappedfile)
00153 {
00154 DBG_ASSERT(ptr_mappedfile->remotecontrollerbuffer == ptr_mappedfile->vicebuffer);
00155
00156
00157 InterlockedIncrement(&ptr_mappedfile->remotecontrollerbuffer);
00158
00159 buffernotowrite = -1;
00160
00161 membuffertoread = membuffertowrite;
00162 regbuffertoread = regbuffertowrite;
00163
00164 membuffertowrite = 0;
00165 regbuffertowrite = 0;
00166 }
00167 }
00168
00169 void vicetrap(UINT address)
00170 {
00171 if (ptr_mappedfile)
00172 {
00173 ptr_mappedfile->trapaddress = address;
00174 }
00175 }
00176
00177 void vicereset(void)
00178 {
00179 if (ptr_mappedfile)
00180 {
00181 ptr_mappedfile->reset = 1;
00182 }
00183 }
00184
00185 void vicewaittrap(void)
00186 {
00187 if (ptr_mappedfile)
00188 {
00189 while (InterlockedExchangeAdd(&ptr_mappedfile->vicebuffer, 0)
00190 != InterlockedExchangeAdd(&ptr_mappedfile->remotecontrollerbuffer, 0))
00191 arch_usleep(1);
00192 }
00193 }
00194
00195 void vicerelease(void)
00196 {
00197 if (ptr_mappedfile)
00198 {
00199 vicepause();
00200 vicewriteregister(reg_pc, 0xe39d);
00201 viceresume();
00202
00203 vicewaittrap();
00204
00205 if (InterlockedExchangeAdd(&ptr_mappedfile->version, 0) == 1)
00206 InterlockedDecrement(&ptr_mappedfile->controllerAvailable);
00207
00208 UnmapViewOfFile(ptr_mappedfile);
00209 ptr_mappedfile = 0;
00210 }
00211
00212 if (handle_mappedfile)
00213 {
00214 CloseHandle(handle_mappedfile);
00215 handle_mappedfile = 0;
00216 }
00217 }
00218
00219 BOOLEAN viceinit(void)
00220 {
00221 static BOOLEAN success = FALSE;
00222
00223 do {
00224 #if 0
00225 handle_mappedfile =
00226 CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
00227 0, sizeof(*ptr_mappedfile), "VICE_REMOTE_CONTROL");
00228 #else
00229 handle_mappedfile =
00230 OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "VICE_REMOTE_CONTROL");
00231 #endif
00232
00233 if (!handle_mappedfile || handle_mappedfile == INVALID_HANDLE_VALUE)
00234 {
00235 handle_mappedfile = 0;
00236 break;
00237 }
00238
00239 ptr_mappedfile =
00240 MapViewOfFile(handle_mappedfile, FILE_MAP_ALL_ACCESS,
00241 0, 0, sizeof(*ptr_mappedfile));
00242
00243 if (!ptr_mappedfile)
00244 {
00245 break;
00246 }
00247 } while (0);
00248
00249 do {
00250 if (!ptr_mappedfile)
00251 break;
00252
00253 #ifdef MSVC_COMPILE
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 # define InterlockedCompareExchange(_a, _b, _c) \
00273 (LONG) InterlockedCompareExchange(_a, (PVOID)_b, (PVOID)_c)
00274
00275 #endif
00276
00277 if (InterlockedCompareExchange(
00278 (PVOID)&ptr_mappedfile->version, 1, 0)
00279 > 1)
00280 break;
00281
00282 #undef InterlockedCompareExchange
00283
00284 if (InterlockedIncrement(&ptr_mappedfile->controllerAvailable) > 1)
00285 break;
00286
00287 success = TRUE;
00288 } while (0);
00289
00290 if (!success)
00291 {
00292 vicerelease();
00293 }
00294
00295 return success;
00296 }