libretro.cpp 136 KB
Newer Older
Themaister's avatar
Themaister committed
1
#include "mednafen/mednafen.h"
2
#include "mednafen/mempatcher.h"
Themaister's avatar
Themaister committed
3
4
#include "mednafen/git.h"
#include "mednafen/general.h"
5
#include "mednafen/settings.h"
Zapeth's avatar
Zapeth committed
6
#include <compat/msvc.h>
7
#include "mednafen/psx/gpu.h"
8
#ifdef NEED_DEINTERLACER
9
#include "mednafen/video/Deinterlacer.h"
10
#endif
11
#include <libretro.h>
12
#include <rthreads/rthreads.h>
13
#include <streams/file_stream.h>
14
#include <string/stdstring.h>
r5's avatar
r5 committed
15
#include <rhash.h>
16
#include "ugui_tools.h"
17
#include "rsx/rsx_intf.h"
18
#include "libretro_cbs.h"
ggdrt's avatar
ggdrt committed
19
#include "beetle_psx_globals.h"
radius's avatar
radius committed
20
#include "libretro_options.h"
21
#include "input.h"
22

stoofin's avatar
stoofin committed
23
24
25
#include "parallel-psx/custom-textures/dbg_input_callback.h"
retro_input_state_t dbg_input_state_cb = 0;

Libretro-Admin's avatar
Libretro-Admin committed
26
#include "mednafen/mednafen-endian.h"
27
#include "mednafen/mednafen-types.h"
28
#include "mednafen/psx/psx.h"
29
#include "mednafen/error.h"
Libretro-Admin's avatar
Libretro-Admin committed
30

31
#include "pgxp/pgxp_main.h"
iCatButler's avatar
iCatButler committed
32

33
34
35
#include <vector>
#define ISHEXDEC ((codeLine[cursor]>='0') && (codeLine[cursor]<='9')) || ((codeLine[cursor]>='a') && (codeLine[cursor]<='f')) || ((codeLine[cursor]>='A') && (codeLine[cursor]<='F'))

Zachary Cook's avatar
Zachary Cook committed
36
37
38
39
40
41
#ifdef HAVE_LIGHTREC
#include <sys/mman.h>

#ifdef HAVE_ASHMEM
#include <sys/ioctl.h>
#include <linux/ashmem.h>
42
#include <dlfcn.h>
Zachary Cook's avatar
Zachary Cook committed
43
44
#endif

Zachary Cook's avatar
Zachary Cook committed
45
#if defined(HAVE_SHM) || defined(HAVE_ASHMEM)
46
#include <sys/stat.h>
Zachary Cook's avatar
Zachary Cook committed
47
48
49
50
51
52
#include <fcntl.h>
#endif

#ifdef HAVE_WIN_SHM
#include <windows.h>
#endif
Zachary Cook's avatar
Zachary Cook committed
53
#endif /* HAVE_LIGHTREC */
Zachary Cook's avatar
Zachary Cook committed
54

Dwedit's avatar
Dwedit committed
55
56
57
58
//Fast Save States exclude string labels from variables in the savestate, and are at least 20% faster.
extern bool FastSaveStates;
const int DEFAULT_STATE_SIZE = 16 * 1024 * 1024;

59
static bool libretro_supports_option_categories = false;
Libretro-Admin's avatar
Libretro-Admin committed
60
static bool libretro_supports_bitmasks = false;
61
static unsigned libretro_msg_interface_version = 0;
Libretro-Admin's avatar
Libretro-Admin committed
62

63
64
65
66
67
68
69
struct retro_perf_callback perf_cb;
retro_get_cpu_features_t perf_get_cpu_features_cb = NULL;
retro_log_printf_t log_cb;
static retro_audio_sample_t audio_cb;
static retro_audio_sample_batch_t audio_batch_cb;
static retro_input_poll_t input_poll_cb;
static retro_input_state_t input_state_cb;
70
71
72
static unsigned frame_count = 0;
static unsigned internal_frame_count = 0;
static bool display_internal_framerate = false;
73
static bool allow_frame_duping = false;
Libretro-Admin's avatar
Libretro-Admin committed
74
static bool failed_init = false;
hizzlekizzle's avatar
hizzlekizzle committed
75
static unsigned image_offset = 0;
76
static unsigned image_crop = 0;
77
static bool enable_memcard1 = false;
78
static bool enable_variable_serialization_size = false;
79
80
81
82
static int frame_width = 0;
static int frame_height = 0;
static bool gui_inited = false;
static bool gui_show = false;
83
84
static char bios_path[4096];
static bool firmware_found = false;
85

86
87
88
89
90
91
// Switchable memory cards
static int memcard_left_index = 0;
static int memcard_left_index_old;
static int memcard_right_index = 1;
static int memcard_right_index_old;

92
unsigned cd_2x_speedup = 1;
93
bool cd_async = false;
94
95
bool cd_warned_slow = false;
int64 cd_slow_timeout = 8000; // microseconds
96

97
98
99
// If true, PAL games will run at 60fps
bool fast_pal = false;

Zachary Cook's avatar
Zachary Cook committed
100
101
102
#ifdef HAVE_LIGHTREC
enum DYNAREC psx_dynarec;
bool psx_dynarec_invalidate;
Zachary Cook's avatar
Zachary Cook committed
103
104
105
106
107
uint8 psx_mmap = 0;
uint8 *psx_mem = NULL;
uint8 *psx_bios = NULL;
uint8 *psx_scratch = NULL;
#if defined(HAVE_ASHMEM)
108
int memfd;
Zachary Cook's avatar
Zachary Cook committed
109
110
111
#endif
#endif

112
uint32 EventCycles = 128;
Zachary Cook's avatar
Zachary Cook committed
113

114
115
// CPU overclock factor (or 0 if disabled)
int32_t psx_overclock_factor = 0;
116
117
// GPU rasterizer overclock shift
unsigned psx_gpu_overclock_shift = 0;
118

119
120
121
// Sets how often (in number of output frames/retro_run invocations)
// the internal framerace counter should be updated if
// display_internal_framerate is true.
122
#define INTERNAL_FPS_SAMPLE_PERIOD 64
123

124
125
static int psx_skipbios;

126
bool psx_gte_overclock;
127
128
enum dither_mode psx_gpu_dither_mode;

iCatButler's avatar
iCatButler committed
129
130
//iCB: PGXP options
unsigned int psx_pgxp_mode;
JS Deck's avatar
JS Deck committed
131
int psx_pgxp_2d_tol;
iCatButler's avatar
iCatButler committed
132
133
unsigned int psx_pgxp_vertex_caching;
unsigned int psx_pgxp_texture_correction;
JS Deck's avatar
JS Deck committed
134
unsigned int psx_pgxp_nclip;
iCatButler's avatar
iCatButler committed
135
136
// \iCB

jdgleaver's avatar
jdgleaver committed
137
138
#define NEGCON_RANGE 0x7FFF

139
140
char retro_save_directory[4096];
char retro_base_directory[4096];
stoofin's avatar
stoofin committed
141
char retro_cd_base_directory[4096];
142
143
144
145
146
147
148
149
static char retro_cd_path[4096];
char retro_cd_base_name[4096];
#ifdef _WIN32
   static char retro_slash = '\\';
#else
   static char retro_slash = '/';
#endif

150
151
152
153
154
155
156
157
158
enum
{
   REGION_JP = 0,
   REGION_NA = 1,
   REGION_EU = 2,
};

static bool firmware_is_present(unsigned region)
{
r5's avatar
r5 committed
159
   static const size_t list_size = 10;
r5's avatar
r5 committed
160
   const char *bios_name_list[list_size];
161
   const char *bios_sha1 = NULL;
162

Libretro-Admin's avatar
Libretro-Admin committed
163
   log_cb(RETRO_LOG_INFO, "Checking if required firmware is present...\n");
164

r5's avatar
r5 committed
165
166
   /* SHA1 and alternate BIOS names sourced from
   https://github.com/mamedev/mame/blob/master/src/mame/drivers/psx.cpp */
167
168
   if (region == REGION_JP)
   {
r5's avatar
r5 committed
169
170
171
      bios_name_list[0] = "scph5500.bin";
      bios_name_list[1] = "SCPH5500.bin";
      bios_name_list[2] = "SCPH-5500.bin";
172
173
174
175
176
177
178
      bios_name_list[3] = NULL;
      bios_name_list[4] = NULL;
      bios_name_list[5] = NULL;
      bios_name_list[6] = NULL;
      bios_name_list[7] = NULL;
      bios_name_list[8] = NULL;
      bios_name_list[9] = NULL;
r5's avatar
r5 committed
179
      bios_sha1 = "B05DEF971D8EC59F346F2D9AC21FB742E3EB6917";
r5's avatar
r5 committed
180
   }
181
   else if (region == REGION_NA)
r5's avatar
r5 committed
182
183
184
185
186
187
188
189
190
191
   {
      bios_name_list[0] = "scph5501.bin";
      bios_name_list[1] = "SCPH5501.bin";
      bios_name_list[2] = "SCPH-5501.bin";
      bios_name_list[3] = "scph5503.bin";
      bios_name_list[4] = "SCPH5503.bin";
      bios_name_list[5] = "SCPH-5503.bin";
      bios_name_list[6] = "scph7003.bin";
      bios_name_list[7] = "SCPH7003.bin";
      bios_name_list[8] = "SCPH-7003.bin";
192
      bios_name_list[9] = NULL;
r5's avatar
r5 committed
193
      bios_sha1 = "0555C6FAE8906F3F09BAF5988F00E55F88E9F30B";
r5's avatar
r5 committed
194
   }
195
   else if (region == REGION_EU)
r5's avatar
r5 committed
196
197
198
199
200
201
202
   {
      bios_name_list[0] = "scph5502.bin";
      bios_name_list[1] = "SCPH5502.bin";
      bios_name_list[2] = "SCPH-5502.bin";
      bios_name_list[3] = "scph5552.bin";
      bios_name_list[4] = "SCPH5552.bin";
      bios_name_list[5] = "SCPH-5552.bin";
203
204
205
206
      bios_name_list[6] = NULL;
      bios_name_list[7] = NULL;
      bios_name_list[8] = NULL;
      bios_name_list[9] = NULL;
r5's avatar
r5 committed
207
      bios_sha1 = "F6BC2D1F5EB6593DE7D089C425AC681D6FFFD3F0";
r5's avatar
r5 committed
208
209
210
211
212
   }

   size_t i;
   for (i = 0; i < list_size; ++i)
   {
213
214
      if (!bios_name_list[i])
         break;
215

216
217
218
      int r = snprintf(bios_path, sizeof(bios_path), "%s%c%s", retro_base_directory, retro_slash, bios_name_list[i]);
      if (r >= 4096)
      {
219
         bios_path[4095] = '\0';
220
221
222
223
         log_cb(RETRO_LOG_ERROR, "Firmware path longer than 4095: %s\n", bios_path);
         break;
      }

224
      if (filestream_exists(bios_path))
r5's avatar
r5 committed
225
      {
226
         firmware_found = true;
r5's avatar
r5 committed
227
         break;
228
      }
r5's avatar
r5 committed
229
230
   }

231
   if (!firmware_found)
r5's avatar
r5 committed
232
   {
233
234
      char s[4096];

235
      log_cb(RETRO_LOG_ERROR, "Firmware is missing: %s\n", bios_name_list[0]);
236
      s[4095] = '\0';
237
238
239
240
241

      snprintf(s, sizeof(s), "Firmware is missing:\n\n%s", bios_name_list[0]);

      gui_set_message(s);
      gui_show = true;
242

243
      return false;
244
   }
r5's avatar
r5 committed
245
246
247

   char obtained_sha1[41];
   sha1_calculate(bios_path, obtained_sha1);
r5's avatar
r5 committed
248
   if (strcmp(obtained_sha1, bios_sha1))
r5's avatar
r5 committed
249
   {
250
251
252
253
254
      log_cb(RETRO_LOG_WARN, "Firmware found but has invalid SHA1: %s\n", bios_path);
      log_cb(RETRO_LOG_WARN, "Expected SHA1: %s\n", bios_sha1);
      log_cb(RETRO_LOG_WARN, "Obtained SHA1: %s\n", obtained_sha1);
      log_cb(RETRO_LOG_WARN, "Unsupported firmware may cause emulation glitches.\n");
      return true;
r5's avatar
r5 committed
255
256
   }

r5's avatar
r5 committed
257
   log_cb(RETRO_LOG_INFO, "Firmware found: %s\n", bios_path);
258
   log_cb(RETRO_LOG_INFO, "Firmware SHA1: %s\n", obtained_sha1);
259

rz5's avatar
rz5 committed
260
   return true;
261
262
}

263
264
265
266
267
268
269
270
271
272
273
static void extract_basename(char *buf, const char *path, size_t size)
{
   const char *base = strrchr(path, '/');
   if (!base)
      base = strrchr(path, '\\');
   if (!base)
      base = path;

   if (*base == '\\' || *base == '/')
      base++;

274
   strncpy(buf, base, size - strlen(buf) - 1);
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
   buf[size - 1] = '\0';

   char *ext = strrchr(buf, '.');
   if (ext)
      *ext = '\0';
}

static void extract_directory(char *buf, const char *path, size_t size)
{
   strncpy(buf, path, size - 1);
   buf[size - 1] = '\0';

   char *base = strrchr(buf, '/');
   if (!base)
      base = strrchr(buf, '\\');

   if (base)
      *base = '\0';
   else
      buf[0] = '\0';
}

297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
/* start of Mednafen psx.cpp */

/* Mednafen - Multi-system Emulator
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "mednafen/psx/psx.h"
#include "mednafen/psx/mdec.h"
#include "mednafen/psx/frontio.h"
#include "mednafen/psx/timer.h"
#include "mednafen/psx/sio.h"
#include "mednafen/psx/cdc.h"
#include "mednafen/psx/spu.h"
#include "mednafen/mempatcher.h"

#include <stdarg.h>
#include <ctype.h>

328
329
bool setting_apply_analog_toggle  = false;
bool use_mednafen_memcard0_method = false;
330

331
332
333
334
335
extern MDFNGI EmulatedPSX;

#if PSX_DBGPRINT_ENABLE
static unsigned psx_dbg_level = 0;

336
void PSX_DBG(unsigned level, const char *format, ...)
337
338
{
   if(psx_dbg_level >= level)
Libretro-Admin's avatar
Libretro-Admin committed
339
340
341
   {
      va_list ap;
      va_start(ap, format);
Libretro-Admin's avatar
Libretro-Admin committed
342
      vprintf(format, ap);
Libretro-Admin's avatar
Libretro-Admin committed
343
344
      va_end(ap);
   }
345
}
346
347
#else
static unsigned const psx_dbg_level = 0;
348
349
#endif

Libretro-Admin's avatar
Libretro-Admin committed
350
351
/* Based off(but not the same as) public-domain "JKISS" PRNG. */
struct MDFN_PseudoRNG
352
353
354
355
356
357
358
359
360
{
   uint32_t x,y,z,c;
   uint64_t lcgo;
};

static MDFN_PseudoRNG PSX_PRNG;

uint32_t PSX_GetRandU32(uint32_t mina, uint32_t maxa)
{
Libretro-Admin's avatar
Libretro-Admin committed
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
   uint32_t tmp;
   const uint32_t range_m1 = maxa - mina;
   uint32_t range_mask = range_m1;

   range_mask |= range_mask >> 1;
   range_mask |= range_mask >> 2;
   range_mask |= range_mask >> 4;
   range_mask |= range_mask >> 8;
   range_mask |= range_mask >> 16;

   do
   {
      uint64_t t = 4294584393ULL * PSX_PRNG.z + PSX_PRNG.c;

      PSX_PRNG.x = 314527869 * PSX_PRNG.x + 1234567;
      PSX_PRNG.y ^= PSX_PRNG.y << 5;
      PSX_PRNG.y ^= PSX_PRNG.y >> 7;
      PSX_PRNG.y ^= PSX_PRNG.y << 22;
      PSX_PRNG.c = t >> 32;
      PSX_PRNG.z = t;
      PSX_PRNG.lcgo = (19073486328125ULL * PSX_PRNG.lcgo) + 1;
      tmp = ((PSX_PRNG.x + PSX_PRNG.y + PSX_PRNG.z) ^ (PSX_PRNG.lcgo >> 16)) & range_mask;
   } while(tmp > range_m1);

   return(mina + tmp);
386
387
}

388
static std::vector<CDIF *> CDInterfaces;  // FIXME: Cleanup on error out.
389
390
static std::vector<CDIF*> *cdifs = NULL;
static std::vector<const char *> cdifs_scex_ids;
391
392
393

static bool eject_state;

394
static bool CD_TrayOpen;
395
396
397
398
int CD_SelectedDisc;     // -1 for no disc

static bool CD_IsPBP = false;
extern int PBP_DiscCount;
399
400
401
402
403
404
/* The global value PBP_DiscCount is set to
 * zero when loading single-disk PBP files.
 * We therefore have to maintain a separate
 * 'physical' disk count, otherwise the
 * frontend disk control interface will fail */
static int PBP_PhysicalDiscCount;
405

406
407
408
409
410
411
412
413
414
415
typedef struct
{
   unsigned initial_index;
   std::string initial_path;
   std::vector<std::string> image_paths;
   std::vector<std::string> image_labels;
} disk_control_ext_info_t;

static disk_control_ext_info_t disk_control_ext_info;

416
417
418
static uint64_t Memcard_PrevDC[8];
static int64_t Memcard_SaveDelay[8];

Libretro-Admin's avatar
Libretro-Admin committed
419
420
421
422
PS_CPU *PSX_CPU = NULL;
PS_SPU *PSX_SPU = NULL;
PS_CDC *PSX_CDC = NULL;
FrontIO *PSX_FIO = NULL;
423

Zachary Cook's avatar
Zachary Cook committed
424
425
MultiAccessSizeMem<512 * 1024, uint32, false> *BIOSROM = NULL;
MultiAccessSizeMem<65536, uint32, false> *PIOMem = NULL;
426
MultiAccessSizeMem<2048 * 1024, uint32, false> *MainRAM = NULL;
Zachary Cook's avatar
Zachary Cook committed
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
MultiAccessSizeMem<1024, uint32, false> *ScratchRAM = NULL;

#ifdef HAVE_LIGHTREC
/* Size of Expansion 1 (8MB) */
#define PSX_EXPANSION1_SIZE        0x800000U
/* Base address of Expansion 1 */
#define PSX_EXPANSION1_BASE        0x1F000000U

/* Mednafen splits the expansion in two buffers (PIOMem and TextMem). That's not
 * super convenient for us so I'm going to copy both of them in one contiguous
 * buffer */
const uint8_t *PSX_LoadExpansion1(void) {
   static uint8_t *expansion1 = NULL;

   if (expansion1 == NULL) {
      expansion1 = new uint8_t[PSX_EXPANSION1_SIZE];
   }

   /* Let's read 32bits at a time to speed things up a bit */
   uint32_t *p = reinterpret_cast<uint32_t *>(expansion1);
447

Zachary Cook's avatar
Zachary Cook committed
448
449
450
451
452
453
454
   for (unsigned i = 0; i < PSX_EXPANSION1_SIZE / 4; i++) {
      p[i] = PSX_MemPeek32(PSX_EXPANSION1_BASE + i * 4);
   }

   return expansion1;
}
#endif
455
456
457
458
459

static uint32_t TextMem_Start;
static std::vector<uint8> TextMem;

static const uint32_t SysControl_Mask[9] = { 0x00ffffff, 0x00ffffff, 0xffffffff, 0x2f1fffff,
460
461
                                             0xffffffff, 0x2f1fffff, 0x2f1fffff, 0xffffffff,
                                             0x0003ffff };
462
463

static const uint32_t SysControl_OR[9] = { 0x1f000000, 0x1f000000, 0x00000000, 0x00000000,
464
465
                                           0x00000000, 0x00000000, 0x00000000, 0x00000000,
                                           0x00000000 };
466
467
468

static struct
{
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
   union
   {
      struct
      {
         uint32_t PIO_Base;   // 0x1f801000  // BIOS Init: 0x1f000000, Writeable bits: 0x00ffffff(assumed, verify), FixedOR = 0x1f000000
         uint32_t Unknown0;   // 0x1f801004  // BIOS Init: 0x1f802000, Writeable bits: 0x00ffffff, FixedOR = 0x1f000000
         uint32_t Unknown1;   // 0x1f801008  // BIOS Init: 0x0013243f, ????
         uint32_t Unknown2;   // 0x1f80100c  // BIOS Init: 0x00003022, Writeable bits: 0x2f1fffff, FixedOR = 0x00000000

         uint32_t BIOS_Mapping;  // 0x1f801010  // BIOS Init: 0x0013243f, ????
         uint32_t SPU_Delay;  // 0x1f801014  // BIOS Init: 0x200931e1, Writeable bits: 0x2f1fffff, FixedOR = 0x00000000 - Affects bus timing on access to SPU
         uint32_t CDC_Delay;  // 0x1f801018  // BIOS Init: 0x00020843, Writeable bits: 0x2f1fffff, FixedOR = 0x00000000
         uint32_t Unknown4;   // 0x1f80101c  // BIOS Init: 0x00070777, ????
         uint32_t Unknown5;   // 0x1f801020  // BIOS Init: 0x00031125(but rewritten with other values often), Writeable bits: 0x0003ffff, FixedOR = 0x00000000 -- Possibly CDC related
      };
      uint32_t Regs[9];
   };
486
487
} SysControl;

488
489
490
491
492
493
494
495
496
static unsigned DMACycleSteal = 0;   // Doesn't need to be saved in save states, since it's calculated in the ForceEventUpdates() call chain.

void PSX_SetDMACycleSteal(unsigned stealage)
{
   if (stealage > 200) // Due to 8-bit limitations in the CPU core.
      stealage = 200;

   DMACycleSteal = stealage;
}
497
498
499
500
501

//
// Event stuff
//

502
static int32_t Running; // Set to -1 when not desiring exit, and 0 when we are.
503
504
505

struct event_list_entry
{
506
507
508
509
   uint32_t which;
   int32_t event_time;
   event_list_entry *prev;
   event_list_entry *next;
510
511
512
513
514
515
516
517
518
519
520
521
};

static event_list_entry events[PSX_EVENT__COUNT];

static void EventReset(void)
{
   unsigned i;
   for(i = 0; i < PSX_EVENT__COUNT; i++)
   {
      events[i].which = i;

      if(i == PSX_EVENT__SYNFIRST)
522
        events[i].event_time = (int32_t)0x80000000;
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
      else if(i == PSX_EVENT__SYNLAST)
         events[i].event_time = 0x7FFFFFFF;
      else
         events[i].event_time = PSX_EVENT_MAXTS;

      events[i].prev = (i > 0) ? &events[i - 1] : NULL;
      events[i].next = (i < (PSX_EVENT__COUNT - 1)) ? &events[i + 1] : NULL;
   }
}

//static void RemoveEvent(event_list_entry *e)
//{
// e->prev->next = e->next;
// e->next->prev = e->prev;
//}

539
static void RebaseTS(const int32_t timestamp)
540
541
542
543
544
545
546
547
548
549
550
{
   unsigned i;
   for(i = 0; i < PSX_EVENT__COUNT; i++)
   {
      if(i == PSX_EVENT__SYNFIRST || i == PSX_EVENT__SYNLAST)
         continue;

      assert(events[i].event_time > timestamp);
      events[i].event_time -= timestamp;
   }

Libretro-Admin's avatar
Libretro-Admin committed
551
   PSX_CPU->SetEventNT(events[PSX_EVENT__SYNFIRST].next->event_time);
552
553
}

554
void PSX_SetEventNT(const int type, const int32_t next_timestamp)
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
{
   event_list_entry *e = &events[type];

   if(next_timestamp < e->event_time)
   {
      event_list_entry *fe = e;

      do
      {
         fe = fe->prev;
      }while(next_timestamp < fe->event_time);

      // Remove this event from the list, temporarily of course.
      e->prev->next = e->next;
      e->next->prev = e->prev;

      // Insert into the list, just after "fe".
      e->prev = fe;
      e->next = fe->next;
      fe->next->prev = e;
      fe->next = e;

      e->event_time = next_timestamp;
   }
   else if(next_timestamp > e->event_time)
   {
      event_list_entry *fe = e;

      do
      {
         fe = fe->next;
      } while(next_timestamp > fe->event_time);

      // Remove this event from the list, temporarily of course
      e->prev->next = e->next;
      e->next->prev = e->prev;

      // Insert into the list, just BEFORE "fe".
      e->prev = fe->prev;
      e->next = fe;
      fe->prev->next = e;
      fe->prev = e;

      e->event_time = next_timestamp;
   }

Libretro-Admin's avatar
Libretro-Admin committed
601
   PSX_CPU->SetEventNT(events[PSX_EVENT__SYNFIRST].next->event_time & Running);
602
603
604
}

// Called from debug.cpp too.
605
void ForceEventUpdates(const int32_t timestamp)
606
{
607
   PSX_SetEventNT(PSX_EVENT_GPU, GPU_Update(timestamp));
Libretro-Admin's avatar
Libretro-Admin committed
608
   PSX_SetEventNT(PSX_EVENT_CDC, PSX_CDC->Update(timestamp));
609
610
611
612
613

   PSX_SetEventNT(PSX_EVENT_TIMER, TIMER_Update(timestamp));

   PSX_SetEventNT(PSX_EVENT_DMA, DMA_Update(timestamp));

Libretro-Admin's avatar
Libretro-Admin committed
614
   PSX_SetEventNT(PSX_EVENT_FIO, PSX_FIO->Update(timestamp));
615

Libretro-Admin's avatar
Libretro-Admin committed
616
   PSX_CPU->SetEventNT(events[PSX_EVENT__SYNFIRST].next->event_time);
617
618
}

619
bool MDFN_FASTCALL PSX_EventHandler(const int32_t timestamp)
620
621
622
{
   event_list_entry *e = events[PSX_EVENT__SYNFIRST].next;

623
   while(timestamp >= e->event_time)   // If Running = 0, PSX_EventHandler() may be called even if there isn't an event per-se, so while() instead of do { ... } while
624
   {
625
      int32_t nt;
626
627
628
629
      event_list_entry *prev = e->prev;

      switch(e->which)
      {
Libretro-Admin's avatar
Changes    
Libretro-Admin committed
630
631
         default:
            abort();
632
         case PSX_EVENT_GPU:
633
            nt = GPU_Update(e->event_time);
Libretro-Admin's avatar
Changes    
Libretro-Admin committed
634
            break;
635
         case PSX_EVENT_CDC:
Libretro-Admin's avatar
Libretro-Admin committed
636
            nt = PSX_CDC->Update(e->event_time);
Libretro-Admin's avatar
Changes    
Libretro-Admin committed
637
            break;
638
         case PSX_EVENT_TIMER:
Libretro-Admin's avatar
Changes    
Libretro-Admin committed
639
640
            nt = TIMER_Update(e->event_time);
            break;
641
         case PSX_EVENT_DMA:
Libretro-Admin's avatar
Changes    
Libretro-Admin committed
642
643
            nt = DMA_Update(e->event_time);
            break;
644
         case PSX_EVENT_FIO:
Libretro-Admin's avatar
Libretro-Admin committed
645
            nt = PSX_FIO->Update(e->event_time);
Libretro-Admin's avatar
Changes    
Libretro-Admin committed
646
            break;
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
      }

      PSX_SetEventNT(e->which, nt);

      // Order of events can change due to calling PSX_SetEventNT(), this prev business ensures we don't miss an event due to reordering.
      e = prev->next;
   }

   return(Running);
}


void PSX_RequestMLExit(void)
{
   Running = 0;
Libretro-Admin's avatar
Libretro-Admin committed
662
   PSX_CPU->SetEventNT(0);
663
664
665
666
667
668
669
670
}


//
// End event stuff
//


Libretro-Admin's avatar
Libretro-Admin committed
671
/* Remember to update MemPeek<>() and MemPoke<>() when we change address decoding in MemRW() */
672
template<typename T, bool IsWrite, bool Access24> static INLINE void MemRW(int32_t &timestamp, uint32_t A, uint32_t &V)
673
674
675
676
677
678
679
680
681
{
#if 0
   if(IsWrite)
      printf("Write%d: %08x(orig=%08x), %08x\n", (int)(sizeof(T) * 8), A & mask[A >> 29], A, V);
   else
      printf("Read%d: %08x(orig=%08x)\n", (int)(sizeof(T) * 8), A & mask[A >> 29], A);
#endif

   if(!IsWrite)
682
      timestamp += DMACycleSteal;
683
684
685
686
687
688
689
690

   //if(A == 0xa0 && IsWrite)
   // DBG_Break();

   if(A < 0x00800000)
   {
      if(IsWrite)
      {
691
         //timestamp++; // Best-case timing.
692
693
694
      }
      else
      {
695
         // Overclock: get rid of memory access latency
696
         if (!psx_gte_overclock)
697
            timestamp += 3;
698
699
700
701
702
      }

      if(Access24)
      {
         if(IsWrite)
703
            MainRAM->WriteU24(A & 0x1FFFFF, V);
704
         else
705
            V = MainRAM->ReadU24(A & 0x1FFFFF);
706
707
708
709
      }
      else
      {
         if(IsWrite)
710
            MainRAM->Write<T>(A & 0x1FFFFF, V);
711
         else
712
            V = MainRAM->Read<T>(A & 0x1FFFFF);
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
      }

      return;
   }

   if(A >= 0x1FC00000 && A <= 0x1FC7FFFF)
   {
      if(!IsWrite)
      {
         if(Access24)
            V = BIOSROM->ReadU24(A & 0x7FFFF);
         else
            V = BIOSROM->Read<T>(A & 0x7FFFF);
      }

      return;
   }

   if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time)
      PSX_EventHandler(timestamp);

   if(A >= 0x1F801000 && A <= 0x1F802FFF)
   {

      //if(IsWrite)
      // printf("HW Write%d: %08x %08x\n", (unsigned int)(sizeof(T)*8), (unsigned int)A, (unsigned int)V);
      //else
      // printf("HW Read%d: %08x\n", (unsigned int)(sizeof(T)*8), (unsigned int)A);

      if(A >= 0x1F801C00 && A <= 0x1F801FFF) // SPU
      {
         if(sizeof(T) == 4 && !Access24)
         {
            if(IsWrite)
            {
               //timestamp += 15;

               //if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time)
               // PSX_EventHandler(timestamp);

Libretro-Admin's avatar
Libretro-Admin committed
753
754
               PSX_SPU->Write(timestamp, A | 0, V);
               PSX_SPU->Write(timestamp, A | 2, V >> 16);
755
756
757
758
759
760
761
762
            }
            else
            {
               timestamp += 36;

               if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time)
                  PSX_EventHandler(timestamp);

Libretro-Admin's avatar
Libretro-Admin committed
763
               V = PSX_SPU->Read(timestamp, A) | (PSX_SPU->Read(timestamp, A | 2) << 16);
764
765
766
767
768
769
770
771
772
773
774
            }
         }
         else
         {
            if(IsWrite)
            {
               //timestamp += 8;

               //if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time)
               // PSX_EventHandler(timestamp);

Libretro-Admin's avatar
Libretro-Admin committed
775
               PSX_SPU->Write(timestamp, A & ~1, V);
776
777
778
779
780
781
782
783
            }
            else
            {
               timestamp += 16; // Just a guess, need to test.

               if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time)
                  PSX_EventHandler(timestamp);

Libretro-Admin's avatar
Libretro-Admin committed
784
               V = PSX_SPU->Read(timestamp, A & ~1);
785
786
787
            }
         }
         return;
788
      }     // End SPU
789
790
791
792
793


      // CDC: TODO - 8-bit access.
      if(A >= 0x1f801800 && A <= 0x1f80180F)
      {
radius's avatar
radius committed
794
         if(!IsWrite)
795
796
797
798
799
         {
            timestamp += 6 * sizeof(T); //24;
         }

         if(IsWrite)
Libretro-Admin's avatar
Libretro-Admin committed
800
            PSX_CDC->Write(timestamp, A & 0x3, V);
801
         else
Libretro-Admin's avatar
Libretro-Admin committed
802
            V = PSX_CDC->Read(timestamp, A & 0x3);
803
804
805
806
807
808
809
810
811
812

         return;
      }

      if(A >= 0x1F801810 && A <= 0x1F801817)
      {
         if(!IsWrite)
            timestamp++;

         if(IsWrite)
813
            GPU_Write(timestamp, A, V);
814
         else
815
            V = GPU_Read(timestamp, A);
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861

         return;
      }

      if(A >= 0x1F801820 && A <= 0x1F801827)
      {
         if(!IsWrite)
            timestamp++;

         if(IsWrite)
            MDEC_Write(timestamp, A, V);
         else
            V = MDEC_Read(timestamp, A);

         return;
      }

      if(A >= 0x1F801000 && A <= 0x1F801023)
      {
         unsigned index = (A & 0x1F) >> 2;

         if(!IsWrite)
            timestamp++;

         //if(A == 0x1F801014 && IsWrite)
         // fprintf(stderr, "%08x %08x\n",A,V);

         if(IsWrite)
         {
            V <<= (A & 3) * 8;
            SysControl.Regs[index] = V & SysControl_Mask[index];
         }
         else
         {
            V = SysControl.Regs[index] | SysControl_OR[index];
            V >>= (A & 3) * 8;
         }
         return;
      }

      if(A >= 0x1F801040 && A <= 0x1F80104F)
      {
         if(!IsWrite)
            timestamp++;

         if(IsWrite)
Libretro-Admin's avatar
Libretro-Admin committed
862
            PSX_FIO->Write(timestamp, A, V);
863
         else
Libretro-Admin's avatar
Libretro-Admin committed
864
            V = PSX_FIO->Read(timestamp, A);
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
         return;
      }

      if(A >= 0x1F801050 && A <= 0x1F80105F)
      {
         if(!IsWrite)
            timestamp++;

#if 0
         if(IsWrite)
         {
            PSX_WARNING("[SIO] Write: 0x%08x 0x%08x %u", A, V, (unsigned)sizeof(T));
         }
         else
         {
            PSX_WARNING("[SIO] Read: 0x%08x", A);
         }
#endif

         if(IsWrite)
            SIO_Write(timestamp, A, V);
         else
            V = SIO_Read(timestamp, A);
         return;
      }

#if 0
      if(A >= 0x1F801060 && A <= 0x1F801063)
      {
         if(IsWrite)
         {

         }
         else
         {

         }

         return;
      }
#endif

907
      if(A >= 0x1F801070 && A <= 0x1F801077) // IRQ
908
909
910
911
912
      {
         if(!IsWrite)
            timestamp++;

         if(IsWrite)
Libretro-Admin's avatar
Libretro-Admin committed
913
            ::IRQ_Write(A, V);
914
         else
Libretro-Admin's avatar
Libretro-Admin committed
915
            V = ::IRQ_Read(A);
916
917
918
         return;
      }

919
      if(A >= 0x1F801080 && A <= 0x1F8010FF)    // DMA
920
921
922
923
924
925
926
927
928
929
930
931
      {
         if(!IsWrite)
            timestamp++;

         if(IsWrite)
            DMA_Write(timestamp, A, V);
         else
            V = DMA_Read(timestamp, A);

         return;
      }

932
      if(A >= 0x1F801100 && A <= 0x1F80113F) // Root counters
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
      {
         if(!IsWrite)
            timestamp++;

         if(IsWrite)
            TIMER_Write(timestamp, A, V);
         else
            V = TIMER_Read(timestamp, A);

         return;
      }
   }


   if(A >= 0x1F000000 && A <= 0x1F7FFFFF)
   {
      if(!IsWrite)
      {
         //if((A & 0x7FFFFF) <= 0x84)
         //PSX_WARNING("[PIO] Read%d from 0x%08x at time %d", (int)(sizeof(T) * 8), A, timestamp);

954
         V = ~0U; // A game this affects:  Tetris with Cardcaptor Sakura
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971

         if(PIOMem)
         {
            if((A & 0x7FFFFF) < 65536)
            {
               if(Access24)
                  V = PIOMem->ReadU24(A & 0x7FFFFF);
               else
                  V = PIOMem->Read<T>(A & 0x7FFFFF);
            }
            else if((A & 0x7FFFFF) < (65536 + TextMem.size()))
            {
               if(Access24)
                  V = MDFN_de24lsb(&TextMem[(A & 0x7FFFFF) - 65536]);
               else switch(sizeof(T))
               {
                  case 1: V = TextMem[(A & 0x7FFFFF) - 65536]; break;
Lionel Flandrin's avatar
Lionel Flandrin committed
972
973
                  case 2: V = MDFN_de16lsb<false>(&TextMem[(A & 0x7FFFFF) - 65536]); break;
                  case 4: V = MDFN_de32lsb<false>(&TextMem[(A & 0x7FFFFF) - 65536]); break;
974
975
976
977
978
979
980
981
982
983
               }
            }
         }
      }
      return;
   }

   if(A == 0xFFFE0130) // Per tests on PS1, ignores the access(sort of, on reads the value is forced to 0 if not aligned) if not aligned to 4-bytes.
   {
      if(!IsWrite)
Libretro-Admin's avatar
Libretro-Admin committed
984
         V = PSX_CPU->GetBIU();
985
      else
Libretro-Admin's avatar
Libretro-Admin committed
986
         PSX_CPU->SetBIU(V);
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001

      return;
   }

   if(IsWrite)
   {
      PSX_WARNING("[MEM] Unknown write%d to %08x at time %d, =%08x(%d)", (int)(sizeof(T) * 8), A, timestamp, V, V);
   }
   else
   {
      V = 0;
      PSX_WARNING("[MEM] Unknown read%d from %08x at time %d", (int)(sizeof(T) * 8), A, timestamp);
   }
}

1002
void MDFN_FASTCALL PSX_MemWrite8(int32_t timestamp, uint32_t A, uint32_t V)
1003
1004
1005
1006
{
   MemRW<uint8, true, false>(timestamp, A, V);
}

1007
void MDFN_FASTCALL PSX_MemWrite16(int32_t timestamp, uint32_t A, uint32_t V)
1008
1009
1010
1011
{
   MemRW<uint16, true, false>(timestamp, A, V);
}

1012
void MDFN_FASTCALL PSX_MemWrite24(int32_t timestamp, uint32_t A, uint32_t V)
1013
{
1014
   MemRW<uint32, true, true>(timestamp, A, V);
1015
1016
}

1017
void MDFN_FASTCALL PSX_MemWrite32(int32_t timestamp, uint32_t A, uint32_t V)
1018
{
1019
   MemRW<uint32, true, false>(timestamp, A, V);
1020
1021
}

1022
uint8_t MDFN_FASTCALL PSX_MemRead8(int32_t &timestamp, uint32_t A)
1023
{
1024
   uint32_t V;
1025

1026
   MemRW<uint8, false, false>(timestamp, A, V);
1027

1028
   return(V);
1029
1030
}

1031
uint16_t MDFN_FASTCALL PSX_MemRead16(int32_t &timestamp, uint32_t A)
1032
{
1033
   uint32_t V;
1034

1035
   MemRW<uint16, false, false>(timestamp, A, V);
1036

1037
   return(V);
1038
1039
}

1040
uint32_t MDFN_FASTCALL PSX_MemRead24(int32_t &timestamp, uint32_t A)
1041
{
1042
   uint32_t V;
1043

1044
   MemRW<uint32, false, true>(timestamp, A, V);
1045

1046
   return(V);
1047
1048
}

1049
uint32_t MDFN_FASTCALL PSX_MemRead32(int32_t &timestamp, uint32_t A)
1050
{
1051
   uint32_t V;
1052

1053
   MemRW<uint32, false, false>(timestamp, A, V);
1054

1055
   return(V);
1056
1057
}

1058
template<typename T, bool Access24> static INLINE uint32_t MemPeek(int32_t timestamp, uint32_t A)
1059
1060
1061
1062
{
   if(A < 0x00800000)
   {
      if(Access24)
1063
1064
         return(MainRAM->ReadU24(A & 0x1FFFFF));
      return(MainRAM->Read<T>(A & 0x1FFFFF));
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
   }

   if(A >= 0x1FC00000 && A <= 0x1FC7FFFF)
   {
      if(Access24)
         return(BIOSROM->ReadU24(A & 0x7FFFF));
      return(BIOSROM->Read<T>(A & 0x7FFFF));
   }

   if(A >= 0x1F801000 && A <= 0x1F802FFF)
   {
      if(A >= 0x1F801C00 && A <= 0x1F801FFF) // SPU
      {
         // TODO

1080
      }     // End SPU
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120


      // CDC: TODO - 8-bit access.
      if(A >= 0x1f801800 && A <= 0x1f80180F)
      {
         // TODO

      }

      if(A >= 0x1F801810 && A <= 0x1F801817)
      {
         // TODO

      }

      if(A >= 0x1F801820 && A <= 0x1F801827)
      {
         // TODO

      }

      if(A >= 0x1F801000 && A <= 0x1F801023)
      {
         unsigned index = (A & 0x1F) >> 2;
         return((SysControl.Regs[index] | SysControl_OR[index]) >> ((A & 3) * 8));
      }

      if(A >= 0x1F801040 && A <= 0x1F80104F)
      {
         // TODO

      }

      if(A >= 0x1F801050 && A <= 0x1F80105F)
      {
         // TODO

      }


1121
      if(A >= 0x1F801070 && A <= 0x1F801077) // IRQ
1122
1123
1124
1125
1126
      {
         // TODO

      }

1127
      if(A >= 0x1F801080 && A <= 0x1F8010FF)    // DMA
1128
1129
1130
1131
1132
      {
         // TODO

      }

1133
      if(A >= 0x1F801100 && A <= 0x1F80113F) // Root counters
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
      {
         // TODO

      }
   }


   if(A >= 0x1F000000 && A <= 0x1F7FFFFF)
   {
      if(PIOMem)
      {
         if((A & 0x7FFFFF) < 65536)
         {
            if(Access24)
               return(PIOMem->ReadU24(A & 0x7FFFFF));
            return(PIOMem->Read<T>(A & 0x7FFFFF));
         }
         else if((A & 0x7FFFFF) < (65536 + TextMem.size()))
         {
            if(Access24)
               return(MDFN_de24lsb(&TextMem[(A & 0x7FFFFF) - 65536]));
            else switch(sizeof(T))
            {
               case 1:
                  return(TextMem[(A & 0x7FFFFF) - 65536]);
               case 2:
Lionel Flandrin's avatar
Lionel Flandrin committed
1160
                  return(MDFN_de16lsb<false>(&TextMem[(A & 0x7FFFFF) - 65536]));
1161
               case 4:
Lionel Flandrin's avatar
Lionel Flandrin committed
1162
                  return(MDFN_de32lsb<false>(&TextMem[(A & 0x7FFFFF) - 65536]));
1163
1164
1165
1166
1167
1168
1169
            }
         }
      }
      return(~0U);
   }

   if(A == 0xFFFE0130)
Libretro-Admin's avatar
Libretro-Admin committed
1170
      return PSX_CPU->GetBIU();
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194

   return(0);
}

uint8_t PSX_MemPeek8(uint32_t A)
{
   return MemPeek<uint8, false>(0, A);
}

uint16_t PSX_MemPeek16(uint32_t A)
{
   return MemPeek<uint16, false>(0, A);
}

uint32_t PSX_MemPeek32(uint32_t A)
{
   return MemPeek<uint32, false>(0, A);
}

// FIXME: Add PSX_Reset() and FrontIO::Reset() so that emulated input devices don't get power-reset on reset-button reset.
static void PSX_Power(void)
{
   unsigned i;

Libretro-Admin's avatar
Libretro-Admin committed
1195
1196
1197
1198
1199
   PSX_PRNG.x = 123456789;
   PSX_PRNG.y = 987654321;
   PSX_PRNG.z = 43219876;
   PSX_PRNG.c = 6543217;
   PSX_PRNG.lcgo = 0xDEADBEEFCAFEBABEULL;
1200

1201
1202
   cd_warned_slow = false;

1203
   memset(MainRAM->data32, 0, 2048 * 1024);
1204
1205
1206
1207

   for(i = 0; i < 9; i++)
      SysControl.Regs[i] = 0;

Libretro-Admin's avatar
Libretro-Admin committed
1208
   PSX_CPU->Power();
1209
1210
1211
1212
1213
1214
1215

   EventReset();

   TIMER_Power();

   DMA_Power();

Libretro-Admin's avatar
Libretro-Admin committed
1216
   PSX_FIO->Power();
1217
1218
1219
   SIO_Power();

   MDEC_Power();
Libretro-Admin's avatar
Libretro-Admin committed
1220
   PSX_CDC->Power();
1221
   GPU_Power();
1222
   //SPU->Power();   // Called from CDC->Power()
1223
1224
1225
1226
1227
   IRQ_Power();

   ForceEventUpdates(0);
}

Libretro-Admin's avatar
Libretro-Admin committed
1228
1229
1230
1231
1232
template<typename T, bool Access24> static INLINE void MemPoke(pscpu_timestamp_t timestamp, uint32 A, T V)
{
   if(A < 0x00800000)
   {
      if(Access24)
1233
         MainRAM->WriteU24(A & 0x1FFFFF, V);
Libretro-Admin's avatar
Libretro-Admin committed
1234
      else
1235
         MainRAM->Write<T>(A & 0x1FFFFF, V);
Libretro-Admin's avatar
Libretro-Admin committed
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261

      return;
   }

   if(A >= 0x1FC00000 && A <= 0x1FC7FFFF)
   {
      if(Access24)
         BIOSROM->WriteU24(A & 0x7FFFF, V);
      else
         BIOSROM->Write<T>(A & 0x7FFFF, V);

      return;
   }

   if(A >= 0x1F801000 && A <= 0x1F802FFF)
   {
      if(A >= 0x1F801000 && A <= 0x1F801023)
      {
         unsigned index = (A & 0x1F) >> 2;
         SysControl.Regs[index] = (V << ((A & 3) * 8)) & SysControl_Mask[index];
         return;
      }
   }

   if(A == 0xFFFE0130)
   {
Libretro-Admin's avatar
Libretro-Admin committed
1262
      PSX_CPU->SetBIU(V);
Libretro-Admin's avatar
Libretro-Admin committed
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
      return;
   }
}

void PSX_MemPoke8(uint32 A, uint8 V)
{
   MemPoke<uint8, false>(0, A, V);
}

void PSX_MemPoke16(uint32 A, uint16 V)
{
   MemPoke<uint16, false>(0, A, V);
}

void PSX_MemPoke32(uint32 A, uint32 V)
{
   MemPoke<uint32, false>(0, A, V);
}
1281

1282
void PSX_GPULineHook(const int32_t timestamp, const int32_t line_timestamp, bool vsync, uint32_t *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider, const unsigned surf_pitchinpix, const unsigned upscale_factor)
1283
{
1284