~registry/dolphin-emu/triforce

« back to all changes in this revision

Viewing changes to Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp

  • Committer: Sérgio Benjamim
  • Date: 2015-02-13 05:54:40 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20150213055440-ey2rt3sjpy27km78
Dolphin Triforce branch from code.google, commit b957980 (4.0-315).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2013 Dolphin Emulator Project
 
2
// Licensed under GPLv2
 
3
// Refer to the license.txt file included.
 
4
 
 
5
/*
 
6
This is the main Wii IPC file that handles all incoming IPC calls and directs them
 
7
to the right function.
 
8
 
 
9
IPC basics (IOS' usage):
 
10
 
 
11
Return values for file handles: All IPC calls will generate a return value to 0x04,
 
12
in case of success they are
 
13
        Open: DeviceID
 
14
        Close: 0
 
15
        Read: Bytes read
 
16
        Write: Bytes written
 
17
        Seek: Seek position
 
18
        Ioctl: 0 (in addition to that there may be messages to the out buffers)
 
19
        Ioctlv: 0 (in addition to that there may be messages to the out buffers)
 
20
They will also generate a true or false return for UpdateInterrupts() in WII_IPC.cpp.
 
21
*/
 
22
 
 
23
#include <map>
 
24
#include <string>
 
25
#include <list>
 
26
 
 
27
#include "Common.h"
 
28
#include "CommonPaths.h"
 
29
#include "Thread.h"
 
30
#include "WII_IPC_HLE.h"
 
31
#include "WII_IPC_HLE_Device.h"
 
32
#include "WII_IPC_HLE_Device_DI.h"
 
33
#include "WII_IPC_HLE_Device_FileIO.h"
 
34
#include "WII_IPC_HLE_Device_stm.h"
 
35
#include "WII_IPC_HLE_Device_fs.h"
 
36
#include "WII_IPC_HLE_Device_net.h"
 
37
#include "WII_IPC_HLE_Device_net_ssl.h"
 
38
#include "WII_IPC_HLE_Device_es.h"
 
39
#include "WII_IPC_HLE_Device_usb.h"
 
40
#include "WII_IPC_HLE_Device_usb_kbd.h"
 
41
#include "WII_IPC_HLE_Device_sdio_slot0.h"
 
42
 
 
43
#if defined(__LIBUSB__) || defined (_WIN32)
 
44
        #include "WII_IPC_HLE_Device_hid.h"
 
45
#endif
 
46
 
 
47
#include "FileUtil.h" // For Copy
 
48
#include "../ConfigManager.h"
 
49
#include "../HW/CPU.h"
 
50
#include "../HW/Memmap.h"
 
51
#include "../HW/WII_IPC.h"
 
52
#include "../Debugger/Debugger_SymbolMap.h"
 
53
#include "../PowerPC/PowerPC.h"
 
54
#include "../HW/SystemTimers.h"
 
55
#include "CoreTiming.h"
 
56
 
 
57
 
 
58
namespace WII_IPC_HLE_Interface
 
59
{
 
60
 
 
61
typedef std::map<u32, IWII_IPC_HLE_Device*> TDeviceMap;
 
62
TDeviceMap g_DeviceMap;
 
63
 
 
64
// STATE_TO_SAVE
 
65
typedef std::map<u32, std::string> TFileNameMap;
 
66
 
 
67
#define IPC_MAX_FDS 0x18
 
68
#define ES_MAX_COUNT 2
 
69
IWII_IPC_HLE_Device* g_FdMap[IPC_MAX_FDS];
 
70
bool es_inuse[ES_MAX_COUNT];
 
71
IWII_IPC_HLE_Device* es_handles[ES_MAX_COUNT];
 
72
 
 
73
 
 
74
typedef std::deque<u32> ipc_msg_queue;
 
75
static ipc_msg_queue request_queue;     // ppc -> arm
 
76
static ipc_msg_queue reply_queue;       // arm -> ppc
 
77
static std::mutex s_reply_queue;
 
78
 
 
79
static int enque_reply;
 
80
 
 
81
static u64 last_reply_time;
 
82
 
 
83
void EnqueReplyCallback(u64 userdata, int)
 
84
{
 
85
        std::lock_guard<std::mutex> lk(s_reply_queue);
 
86
        reply_queue.push_back(userdata);
 
87
}
 
88
 
 
89
void Init()
 
90
{
 
91
 
 
92
        _dbg_assert_msg_(WII_IPC_HLE, g_DeviceMap.empty(), "DeviceMap isn't empty on init");
 
93
        CWII_IPC_HLE_Device_es::m_ContentFile = "";
 
94
        u32 i;
 
95
        for (i=0; i<IPC_MAX_FDS; i++)
 
96
        {
 
97
                g_FdMap[i] = NULL;
 
98
        }
 
99
 
 
100
        i = 0;
 
101
        // Build hardware devices
 
102
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_usb_oh1_57e_305(i, std::string("/dev/usb/oh1/57e/305")); i++;
 
103
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_stm_immediate(i, std::string("/dev/stm/immediate")); i++;
 
104
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_stm_eventhook(i, std::string("/dev/stm/eventhook")); i++;
 
105
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_fs(i, std::string("/dev/fs")); i++;
 
106
 
 
107
        // IOS allows two ES devices at a time<
 
108
        u32 j;
 
109
        for (j=0; j<ES_MAX_COUNT; j++)
 
110
        {
 
111
                g_DeviceMap[i] = es_handles[j] = new CWII_IPC_HLE_Device_es(i, std::string("/dev/es")); i++;
 
112
                es_inuse[j] = false;
 
113
        }
 
114
 
 
115
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_di(i, std::string("/dev/di")); i++;
 
116
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_kd_request(i, std::string("/dev/net/kd/request")); i++;
 
117
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_kd_time(i, std::string("/dev/net/kd/time")); i++;
 
118
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_ncd_manage(i, std::string("/dev/net/ncd/manage")); i++;
 
119
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_wd_command(i, std::string("/dev/net/wd/command")); i++;
 
120
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_ip_top(i, std::string("/dev/net/ip/top")); i++;
 
121
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_ssl(i, std::string("/dev/net/ssl")); i++;
 
122
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_usb_kbd(i, std::string("/dev/usb/kbd")); i++;
 
123
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_sdio_slot0(i, std::string("/dev/sdio/slot0")); i++;
 
124
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, std::string("/dev/sdio/slot1")); i++;
 
125
        #if  defined(__LIBUSB__) || defined(_WIN32)
 
126
                g_DeviceMap[i] = new CWII_IPC_HLE_Device_hid(i, std::string("/dev/usb/hid")); i++;
 
127
        #else
 
128
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, std::string("/dev/usb/hid")); i++;
 
129
        #endif
 
130
        g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, std::string("/dev/usb/oh1")); i++;
 
131
        g_DeviceMap[i] = new IWII_IPC_HLE_Device(i, std::string("_Unimplemented_Device_")); i++;
 
132
 
 
133
        enque_reply = CoreTiming::RegisterEvent("IPCReply", EnqueReplyCallback);
 
134
}
 
135
 
 
136
void Reset(bool _bHard)
 
137
{
 
138
        CoreTiming::RemoveAllEvents(enque_reply);
 
139
 
 
140
        u32 i;
 
141
        for (i=0; i<IPC_MAX_FDS; i++)
 
142
        {
 
143
                if (g_FdMap[i] != NULL && !g_FdMap[i]->IsHardware())
 
144
                {
 
145
                        // close all files and delete their resources
 
146
                        g_FdMap[i]->Close(0, true);
 
147
                        delete g_FdMap[i];
 
148
                }
 
149
                g_FdMap[i] = NULL;
 
150
        }
 
151
 
 
152
        u32 j;
 
153
        for (j=0; j<ES_MAX_COUNT; j++)
 
154
        {
 
155
                es_inuse[j] = false;
 
156
        }
 
157
 
 
158
        TDeviceMap::iterator itr = g_DeviceMap.begin();
 
159
        while (itr != g_DeviceMap.end())
 
160
        {
 
161
                if (itr->second)
 
162
                {
 
163
                        // Force close
 
164
                        itr->second->Close(0, true);
 
165
                        // Hardware should not be deleted unless it is a hard reset
 
166
                        if (_bHard)
 
167
                                delete itr->second;
 
168
                }
 
169
                ++itr;
 
170
        }
 
171
        if (_bHard)
 
172
        {
 
173
                g_DeviceMap.erase(g_DeviceMap.begin(), g_DeviceMap.end());
 
174
        }
 
175
        request_queue.clear();
 
176
 
 
177
        // lock due to using reply_queue
 
178
        {
 
179
                std::lock_guard<std::mutex> lk(s_reply_queue);
 
180
                reply_queue.clear();
 
181
        }
 
182
        last_reply_time = 0;
 
183
}
 
184
 
 
185
void Shutdown()
 
186
{
 
187
        Reset(true);
 
188
}
 
189
 
 
190
void SetDefaultContentFile(const std::string& _rFilename)
 
191
{
 
192
        TDeviceMap::const_iterator itr = g_DeviceMap.begin();
 
193
        while (itr != g_DeviceMap.end())
 
194
        {
 
195
                if (itr->second && itr->second->GetDeviceName().find(std::string("/dev/es")) == 0)
 
196
                {
 
197
                        ((CWII_IPC_HLE_Device_es*)itr->second)->LoadWAD(_rFilename);
 
198
                }
 
199
                ++itr;
 
200
        }
 
201
}
 
202
 
 
203
void ES_DIVerify(u8 *_pTMD, u32 _sz)
 
204
{
 
205
        CWII_IPC_HLE_Device_es::ES_DIVerify(_pTMD, _sz);
 
206
}
 
207
 
 
208
void SDIO_EventNotify()
 
209
{
 
210
        CWII_IPC_HLE_Device_sdio_slot0 *pDevice =
 
211
                (CWII_IPC_HLE_Device_sdio_slot0*)GetDeviceByName(std::string("/dev/sdio/slot0"));
 
212
        if (pDevice)
 
213
                pDevice->EventNotify();
 
214
}
 
215
int getFreeDeviceId()
 
216
{
 
217
        u32 i;
 
218
        for (i=0; i<IPC_MAX_FDS; i++)
 
219
        {
 
220
                if (g_FdMap[i] == NULL)
 
221
                {
 
222
                        return i;
 
223
                }
 
224
        }
 
225
        return -1;
 
226
}
 
227
 
 
228
IWII_IPC_HLE_Device* GetDeviceByName(const std::string& _rDeviceName)
 
229
{
 
230
        TDeviceMap::const_iterator itr = g_DeviceMap.begin();
 
231
        while (itr != g_DeviceMap.end())
 
232
        {
 
233
                if (itr->second && itr->second->GetDeviceName() == _rDeviceName)
 
234
                        return itr->second;
 
235
                ++itr;
 
236
        }
 
237
 
 
238
        return NULL;
 
239
}
 
240
 
 
241
IWII_IPC_HLE_Device* AccessDeviceByID(u32 _ID)
 
242
{
 
243
        if (g_DeviceMap.find(_ID) != g_DeviceMap.end())
 
244
                return g_DeviceMap[_ID];
 
245
 
 
246
                return NULL;
 
247
}
 
248
 
 
249
// This is called from ExecuteCommand() COMMAND_OPEN_DEVICE
 
250
IWII_IPC_HLE_Device* CreateFileIO(u32 _DeviceID, const std::string& _rDeviceName)
 
251
{
 
252
        // scan device name and create the right one
 
253
        IWII_IPC_HLE_Device* pDevice = NULL;
 
254
 
 
255
        INFO_LOG(WII_IPC_FILEIO, "IOP: Create FileIO %s", _rDeviceName.c_str());
 
256
        pDevice = new CWII_IPC_HLE_Device_FileIO(_DeviceID, _rDeviceName);
 
257
 
 
258
        return pDevice;
 
259
}
 
260
 
 
261
 
 
262
void DoState(PointerWrap &p)
 
263
{
 
264
        std::lock_guard<std::mutex> lk(s_reply_queue);
 
265
 
 
266
        p.Do(request_queue);
 
267
        p.Do(reply_queue);
 
268
        p.Do(last_reply_time);
 
269
 
 
270
        TDeviceMap::const_iterator itr;
 
271
 
 
272
        itr = g_DeviceMap.begin();
 
273
        while (itr != g_DeviceMap.end())
 
274
        {
 
275
                        if (itr->second->IsHardware())
 
276
                        {
 
277
                                itr->second->DoState(p);
 
278
                        }
 
279
                        ++itr;
 
280
        }
 
281
 
 
282
        if (p.GetMode() == PointerWrap::MODE_READ)
 
283
        {
 
284
                u32 i;
 
285
                for (i=0; i<IPC_MAX_FDS; i++)
 
286
                {
 
287
                        u32 exists = 0;
 
288
                        p.Do(exists);
 
289
                        if (exists)
 
290
                        {
 
291
                                u32 isHw = 0;
 
292
                                p.Do(isHw);
 
293
                                if (isHw)
 
294
                                {
 
295
                                        u32 hwId = 0;
 
296
                                        p.Do(hwId);
 
297
                                        g_FdMap[i] = AccessDeviceByID(hwId);
 
298
                                }
 
299
                                else
 
300
                                {
 
301
                                        g_FdMap[i] = new CWII_IPC_HLE_Device_FileIO(i, "");
 
302
                                        g_FdMap[i]->DoState(p);
 
303
                                }
 
304
                        }
 
305
                        else
 
306
                        {
 
307
                                g_FdMap[i] = NULL;
 
308
                        }
 
309
                }
 
310
                for (i=0; i<ES_MAX_COUNT; i++)
 
311
                {
 
312
                        p.Do(es_inuse[i]);
 
313
                        u32 handleID = es_handles[i]->GetDeviceID();
 
314
                        p.Do(handleID);
 
315
 
 
316
                        es_handles[i] = AccessDeviceByID(handleID);
 
317
                }
 
318
        }
 
319
        else
 
320
        {
 
321
                u32 i;
 
322
                for (i=0; i<IPC_MAX_FDS; i++)
 
323
                {
 
324
                        u32 exists = g_FdMap[i] ? 1 : 0;
 
325
                        p.Do(exists);
 
326
                        if (exists)
 
327
                        {
 
328
                                u32 isHw = g_FdMap[i]->IsHardware() ? 1 : 0;
 
329
                                p.Do(isHw);
 
330
                                if (isHw)
 
331
                                {
 
332
                                        u32 hwId = g_FdMap[i]->GetDeviceID();
 
333
                                        p.Do(hwId);
 
334
                                }
 
335
                                else
 
336
                                {
 
337
                                        g_FdMap[i]->DoState(p);
 
338
                                }
 
339
                        }
 
340
                }
 
341
                for (i=0; i<ES_MAX_COUNT; i++)
 
342
                {
 
343
                        p.Do(es_inuse[i]);
 
344
                        u32 handleID = es_handles[i]->GetDeviceID();
 
345
                        p.Do(handleID);
 
346
                }
 
347
        }
 
348
}
 
349
 
 
350
void ExecuteCommand(u32 _Address)
 
351
{
 
352
        bool CmdSuccess = false;
 
353
 
 
354
        ECommandType Command = static_cast<ECommandType>(Memory::Read_U32(_Address));
 
355
        volatile s32 DeviceID = Memory::Read_U32(_Address + 8);
 
356
 
 
357
        IWII_IPC_HLE_Device* pDevice = (DeviceID >= 0 && DeviceID < IPC_MAX_FDS) ? g_FdMap[DeviceID] : NULL;
 
358
 
 
359
        INFO_LOG(WII_IPC_HLE, "-->> Execute Command Address: 0x%08x (code: %x, device: %x) %p", _Address, Command, DeviceID, pDevice);
 
360
 
 
361
        switch (Command)
 
362
        {
 
363
        case COMMAND_OPEN_DEVICE:
 
364
        {
 
365
                u32 Mode = Memory::Read_U32(_Address + 0x10);
 
366
                DeviceID = getFreeDeviceId();
 
367
 
 
368
                std::string DeviceName;
 
369
                Memory::GetString(DeviceName, Memory::Read_U32(_Address + 0xC));
 
370
 
 
371
 
 
372
                WARN_LOG(WII_IPC_HLE, "Trying to open %s as %d", DeviceName.c_str(), DeviceID);
 
373
                if (DeviceID >= 0)
 
374
                {
 
375
                        if (DeviceName.find("/dev/es") == 0)
 
376
                        {
 
377
                                u32 j;
 
378
                                for (j=0; j<ES_MAX_COUNT; j++)
 
379
                                {
 
380
                                        if (!es_inuse[j])
 
381
                                        {
 
382
                                                es_inuse[j] = true;
 
383
                                                g_FdMap[DeviceID] = es_handles[j];
 
384
                                                CmdSuccess = es_handles[j]->Open(_Address, Mode);
 
385
                                                Memory::Write_U32(DeviceID, _Address+4);
 
386
                                                break;
 
387
                                        }
 
388
                                }
 
389
                                if (j == ES_MAX_COUNT)
 
390
                                {
 
391
                                        Memory::Write_U32(FS_EESEXHAUSTED, _Address + 4);
 
392
                                        CmdSuccess = true;
 
393
                                }
 
394
 
 
395
                        }
 
396
                        else if (DeviceName.find("/dev/") == 0)
 
397
                        {
 
398
                                pDevice = GetDeviceByName(DeviceName);
 
399
                                if (pDevice)
 
400
                                {
 
401
                                        g_FdMap[DeviceID] = pDevice;
 
402
                                        CmdSuccess = pDevice->Open(_Address, Mode);
 
403
                                        INFO_LOG(WII_IPC_FILEIO, "IOP: ReOpen (Device=%s, DeviceID=%08x, Mode=%i)",
 
404
                                                pDevice->GetDeviceName().c_str(), DeviceID, Mode);
 
405
                                        Memory::Write_U32(DeviceID, _Address+4);
 
406
                                }
 
407
                                else
 
408
                                {
 
409
                                        WARN_LOG(WII_IPC_HLE, "Unimplemented device: %s", DeviceName.c_str());
 
410
                                        Memory::Write_U32(FS_ENOENT, _Address+4);
 
411
                                        CmdSuccess = true;
 
412
                                }
 
413
                        }
 
414
                        else
 
415
                        {
 
416
                                pDevice = CreateFileIO(DeviceID, DeviceName);
 
417
                                CmdSuccess = pDevice->Open(_Address, Mode);
 
418
 
 
419
                                INFO_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)",
 
420
                                                pDevice->GetDeviceName().c_str(), DeviceID, Mode);
 
421
                                if (Memory::Read_U32(_Address + 4) == (u32)DeviceID)
 
422
                                {
 
423
                                        g_FdMap[DeviceID] = pDevice;
 
424
                                }
 
425
                                else
 
426
                                {
 
427
                                        delete pDevice;
 
428
                                        pDevice = NULL;
 
429
                                }
 
430
                        }
 
431
 
 
432
                }
 
433
                else
 
434
                {
 
435
                        Memory::Write_U32(FS_EFDEXHAUSTED, _Address + 4);
 
436
                        CmdSuccess = true;
 
437
                }
 
438
                break;
 
439
        }
 
440
        case COMMAND_CLOSE_DEVICE:
 
441
        {
 
442
                if (pDevice)
 
443
                {
 
444
                        CmdSuccess = pDevice->Close(_Address);
 
445
 
 
446
                        u32 j;
 
447
                        for (j=0; j<ES_MAX_COUNT; j++)
 
448
                        {
 
449
                                if (es_handles[j] == g_FdMap[DeviceID])
 
450
                                {
 
451
                                        es_inuse[j] = false;
 
452
                                }
 
453
                        }
 
454
 
 
455
                        g_FdMap[DeviceID] = NULL;
 
456
 
 
457
                        // Don't delete hardware
 
458
                        if (!pDevice->IsHardware())
 
459
                        {
 
460
                                delete pDevice;
 
461
                                pDevice = NULL;
 
462
                        }
 
463
                }
 
464
                else
 
465
                {
 
466
                        Memory::Write_U32(FS_EINVAL, _Address + 4);
 
467
                        CmdSuccess = true;
 
468
                }
 
469
                break;
 
470
        }
 
471
        case COMMAND_READ:
 
472
        {
 
473
                if (pDevice)
 
474
                {
 
475
                        CmdSuccess = pDevice->Read(_Address);
 
476
                }
 
477
                else
 
478
                {
 
479
                        Memory::Write_U32(FS_EINVAL, _Address + 4);
 
480
                        CmdSuccess = true;
 
481
                }
 
482
                break;
 
483
        }
 
484
        case COMMAND_WRITE:
 
485
        {
 
486
                if (pDevice)
 
487
                {
 
488
                        CmdSuccess = pDevice->Write(_Address);
 
489
                }
 
490
                else
 
491
                {
 
492
                        Memory::Write_U32(FS_EINVAL, _Address + 4);
 
493
                        CmdSuccess = true;
 
494
                }
 
495
                break;
 
496
        }
 
497
        case COMMAND_SEEK:
 
498
        {
 
499
                if (pDevice)
 
500
                {
 
501
                        CmdSuccess = pDevice->Seek(_Address);
 
502
                }
 
503
                else
 
504
                {
 
505
                        Memory::Write_U32(FS_EINVAL, _Address + 4);
 
506
                        CmdSuccess = true;
 
507
                }
 
508
                break;
 
509
        }
 
510
        case COMMAND_IOCTL:
 
511
        {
 
512
                if (pDevice)
 
513
                {
 
514
                        CmdSuccess = pDevice->IOCtl(_Address);
 
515
                }
 
516
                break;
 
517
        }
 
518
        case COMMAND_IOCTLV:
 
519
        {
 
520
                if (pDevice)
 
521
                {
 
522
                        CmdSuccess = pDevice->IOCtlV(_Address);
 
523
                }
 
524
                break;
 
525
        }
 
526
        default:
 
527
        {
 
528
                _dbg_assert_msg_(WII_IPC_HLE, 0, "Unknown IPC Command %i (0x%08x)", Command, _Address);
 
529
                break;
 
530
        }
 
531
        }
 
532
 
 
533
 
 
534
        if (CmdSuccess)
 
535
        {
 
536
                // It seems that the original hardware overwrites the command after it has been
 
537
                // executed. We write 8 which is not any valid command, and what IOS does
 
538
                Memory::Write_U32(8, _Address);
 
539
                // IOS seems to write back the command that was responded to
 
540
                Memory::Write_U32(Command, _Address + 8);
 
541
 
 
542
                // Ensure replies happen in order, fairly ugly
 
543
                // Without this, tons of games fail now that DI commands have different reply delays
 
544
                int reply_delay = pDevice ? pDevice->GetCmdDelay(_Address) : 0;
 
545
 
 
546
                const s64 ticks_til_last_reply = last_reply_time - CoreTiming::GetTicks();
 
547
 
 
548
                if (ticks_til_last_reply > 0)
 
549
                        reply_delay = ticks_til_last_reply;
 
550
 
 
551
                last_reply_time = CoreTiming::GetTicks() + reply_delay;
 
552
 
 
553
                // Generate a reply to the IPC command
 
554
                EnqReply(_Address, reply_delay);
 
555
        }
 
556
}
 
557
 
 
558
// Happens AS SOON AS IPC gets a new pointer!
 
559
void EnqRequest(u32 _Address)
 
560
{
 
561
        request_queue.push_back(_Address);
 
562
}
 
563
 
 
564
// Called when IOS module has some reply
 
565
void EnqReply(u32 _Address, int cycles_in_future)
 
566
{
 
567
        CoreTiming::ScheduleEvent(cycles_in_future, enque_reply, _Address);
 
568
}
 
569
 
 
570
// This is called every IPC_HLE_PERIOD from SystemTimers.cpp
 
571
// Takes care of routing ipc <-> ipc HLE
 
572
void Update()
 
573
{
 
574
        if (!WII_IPCInterface::IsReady())
 
575
                return;
 
576
 
 
577
        UpdateDevices();
 
578
 
 
579
        if (request_queue.size())
 
580
        {
 
581
                WII_IPCInterface::GenerateAck(request_queue.front());
 
582
                INFO_LOG(WII_IPC_HLE, "||-- Acknowledge IPC Request @ 0x%08x", request_queue.front());
 
583
                u32 command = request_queue.front();
 
584
                request_queue.pop_front();
 
585
                ExecuteCommand(command);
 
586
 
 
587
#if MAX_LOGLEVEL >= DEBUG_LEVEL
 
588
                Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HLE, LogTypes::LDEBUG);
 
589
#endif
 
590
        }
 
591
 
 
592
        // lock due to using reply_queue
 
593
        {
 
594
                std::lock_guard<std::mutex> lk(s_reply_queue);
 
595
                if (reply_queue.size())
 
596
                {
 
597
                        WII_IPCInterface::GenerateReply(reply_queue.front());
 
598
                        INFO_LOG(WII_IPC_HLE, "<<-- Reply to IPC Request @ 0x%08x", reply_queue.front());
 
599
                        reply_queue.pop_front();
 
600
                }
 
601
        }
 
602
}
 
603
 
 
604
void UpdateDevices()
 
605
{
 
606
        // Check if a hardware device must be updated
 
607
        for (TDeviceMap::const_iterator itr = g_DeviceMap.begin(); itr != g_DeviceMap.end(); ++itr)
 
608
        {
 
609
                if (itr->second->IsOpened() && itr->second->Update())
 
610
                {
 
611
                        break;
 
612
                }
 
613
        }
 
614
}
 
615
 
 
616
 
 
617
} // end of namespace WII_IPC_HLE_Interface
 
618
 
 
619
// TODO: create WII_IPC_HLE_Device.cpp ?
 
620
void IWII_IPC_HLE_Device::DoStateShared(PointerWrap& p)
 
621
{
 
622
        p.Do(m_Name);
 
623
        p.Do(m_DeviceID);
 
624
        p.Do(m_Hardware);
 
625
        p.Do(m_Active);
 
626
}