frontend: update libpicofe, fix missed callbacks
[pcsx_rearmed.git] / frontend / plugin_lib.c
index 8a6b6ad..324fede 100644 (file)
 #include "psemu_plugin_defs.h"
 #include "../libpcsxcore/new_dynarec/new_dynarec.h"
 #include "../libpcsxcore/psxmem_map.h"
+#include "../libpcsxcore/gpu.h"
+#include "../libpcsxcore/r3000a.h"
+#include "../libpcsxcore/psxcounters.h"
+#include "arm_features.h"
 
 #define HUD_HEIGHT 10
 
@@ -41,17 +45,22 @@ int multitap1;
 int multitap2;
 int in_analog_left[8][2] = {{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 }};
 int in_analog_right[8][2] = {{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 }};
-int in_adev[2] = { -1, -1 }, in_adev_axis[2][2] = {{ 0, 1 }, { 0, 1 }};
+int in_adev[2] = { -1, -1 };
+int in_adev_axis[2][2] =
+#ifdef PANDORA
+  {{ 0, 1 }, { 0, 1 }};
+#else
+  {{ 0, 1 }, { 2, 3 }};
+#endif
 int in_adev_is_nublike[2];
 unsigned short in_keystate[8];
 int in_mouse[8][2];
-int in_state_gun;
 int in_enable_vibration;
 void *tsdev;
 void *pl_vout_buf;
 int g_layer_x, g_layer_y, g_layer_w, g_layer_h;
 static int pl_vout_w, pl_vout_h, pl_vout_bpp; /* output display/layer */
-static int pl_vout_scale_w, pl_vout_scale_h, pl_vout_yoffset;
+static int pl_vout_scale_w, pl_vout_scale_h;
 static int psx_w, psx_h, psx_bpp;
 static int vsync_cnt;
 static int is_pal, frame_interval, frame_interval1024;
@@ -133,11 +142,11 @@ static __attribute__((noinline)) void draw_active_chans(int vout_w, int vout_h)
 
        static const unsigned short colors[2] = { 0x1fe3, 0x0700 };
        unsigned short *dest = (unsigned short *)pl_vout_buf +
-               vout_w * (vout_h - HUD_HEIGHT) + vout_w / 2 - 192/2;
+               pl_vout_w * (vout_h - HUD_HEIGHT) + pl_vout_w / 2 - 192/2;
        unsigned short *d, p;
        int c, x, y;
 
-       if (dest == NULL || pl_vout_bpp != 16)
+       if (pl_vout_buf == NULL || pl_vout_bpp != 16)
                return;
 
        spu_get_debug_info(&live_chans, &run_chans, &fmod_chans, &noise_chans);
@@ -148,7 +157,7 @@ static __attribute__((noinline)) void draw_active_chans(int vout_w, int vout_h)
                     (fmod_chans & (1<<c)) ? 0xf000 :
                     (noise_chans & (1<<c)) ? 0x001f :
                     colors[c & 1];
-               for (y = 0; y < 8; y++, d += vout_w)
+               for (y = 0; y < 8; y++, d += pl_vout_w)
                        for (x = 0; x < 8; x++)
                                d[x] = p;
        }
@@ -175,7 +184,7 @@ static void print_hud(int x, int w, int h)
 }
 
 /* update scaler target size according to user settings */
-static void update_layer_size(int w, int h)
+void pl_update_layer_size(int w, int h, int fw, int fh)
 {
        float mult;
        int imult;
@@ -187,51 +196,57 @@ static void update_layer_size(int w, int h)
 
        case SCALE_2_2:
                g_layer_w = w; g_layer_h = h;
-               if (w * 2 <= g_menuscreen_w)
+               if (w * 2 <= fw)
                        g_layer_w = w * 2;
-               if (h * 2 <= g_menuscreen_h)
+               if (h * 2 <= fh)
                        g_layer_h = h * 2;
                break;
 
        case SCALE_4_3v2:
-               if (h > g_menuscreen_h || (240 < h && h <= 360))
-                       goto fractional_4_3;
+#ifdef PANDORA
+               if (h <= fh && !(240 < h && h <= 360))
+               {
+#endif
 
                // 4:3 that prefers integer scaling
-               imult = g_menuscreen_h / h;
+               imult = fh / h;
+               if (imult < 1)
+                       imult = 1;
                g_layer_w = w * imult;
                g_layer_h = h * imult;
                mult = (float)g_layer_w / (float)g_layer_h;
                if (mult < 1.25f || mult > 1.666f)
                        g_layer_w = 4.0f/3.0f * (float)g_layer_h;
-               printf("  -> %dx%d %.1f\n", g_layer_w, g_layer_h, mult);
+               //printf("  -> %dx%d %.1f\n", g_layer_w, g_layer_h, mult);
                break;
+#ifdef PANDORA
+               }
+#endif
 
-       fractional_4_3:
        case SCALE_4_3:
                mult = 240.0f / (float)h * 4.0f / 3.0f;
                if (h > 256)
                        mult *= 2.0f;
-               g_layer_w = mult * (float)g_menuscreen_h;
-               g_layer_h = g_menuscreen_h;
-               printf("  -> %dx%d %.1f\n", g_layer_w, g_layer_h, mult);
+               g_layer_w = mult * (float)fh;
+               g_layer_h = fh;
+               //printf("  -> %dx%d %.1f\n", g_layer_w, g_layer_h, mult);
                break;
 
        case SCALE_FULLSCREEN:
-               g_layer_w = g_menuscreen_w;
-               g_layer_h = g_menuscreen_h;
+               g_layer_w = fw;
+               g_layer_h = fh;
                break;
 
        default:
                break;
        }
 
-       g_layer_x = g_menuscreen_w / 2 - g_layer_w / 2;
-       g_layer_y = g_menuscreen_h / 2 - g_layer_h / 2;
-       if (g_layer_x < 0) g_layer_x = 0;
-       if (g_layer_y < 0) g_layer_y = 0;
-       if (g_layer_w > g_menuscreen_w) g_layer_w = g_menuscreen_w;
-       if (g_layer_h > g_menuscreen_h) g_layer_h = g_menuscreen_h;
+       if (g_scaler != SCALE_CUSTOM) {
+               g_layer_x = fw / 2 - g_layer_w / 2;
+               g_layer_y = fh / 2 - g_layer_h / 2;
+       }
+       if (g_layer_w > fw * 2) g_layer_w = fw * 2;
+       if (g_layer_h > fh * 2) g_layer_h = fh * 2;
 }
 
 // XXX: this is platform specific really
@@ -243,7 +258,6 @@ static inline int resolution_ok(int w, int h)
 static void pl_vout_set_mode(int w, int h, int raw_w, int raw_h, int bpp)
 {
        int vout_w, vout_h, vout_bpp;
-       int buf_yoffset = 0;
 
        // special h handling, Wipeout likes to change it by 1-6
        static int vsync_cnt_ms_prev;
@@ -263,7 +277,7 @@ static void pl_vout_set_mode(int w, int h, int raw_w, int raw_h, int bpp)
        assert(vout_h >= 192);
 
        pl_vout_scale_w = pl_vout_scale_h = 1;
-#ifdef __ARM_NEON__
+#ifdef HAVE_NEON32
        if (soft_filter) {
                if (resolution_ok(w * 2, h * 2) && bpp == 16) {
                        pl_vout_scale_w = 2;
@@ -282,7 +296,7 @@ static void pl_vout_set_mode(int w, int h, int raw_w, int raw_h, int bpp)
        vout_w *= pl_vout_scale_w;
        vout_h *= pl_vout_scale_h;
 
-       update_layer_size(vout_w, vout_h);
+       pl_update_layer_size(vout_w, vout_h, g_menuscreen_w, g_menuscreen_h);
 
        pl_vout_buf = plat_gvideo_set_mode(&vout_w, &vout_h, &vout_bpp);
        if (pl_vout_buf == NULL && pl_plat_blit == NULL)
@@ -292,24 +306,28 @@ static void pl_vout_set_mode(int w, int h, int raw_w, int raw_h, int bpp)
                pl_vout_w = vout_w;
                pl_vout_h = vout_h;
                pl_vout_bpp = vout_bpp;
-               pl_vout_yoffset = buf_yoffset;
        }
-       if (pl_vout_buf != NULL)
-               pl_vout_buf = (char *)pl_vout_buf
-                       + pl_vout_yoffset * pl_vout_w * pl_vout_bpp / 8;
 
        menu_notify_mode_change(pl_vout_w, pl_vout_h, pl_vout_bpp);
 }
 
-static void pl_vout_flip(const void *vram, int stride, int bgr24,
+static int flip_clear_counter;
+
+void pl_force_clear(void)
+{
+       flip_clear_counter = 2;
+}
+
+static void pl_vout_flip(const void *vram_, int vram_ofs, int bgr24,
        int x, int y, int w, int h, int dims_changed)
 {
-       static int clear_counter;
        unsigned char *dest = pl_vout_buf;
-       const unsigned short *src = vram;
+       const unsigned char *vram = vram_;
        int dstride = pl_vout_w, h1 = h;
-       int h_full = pl_vout_h - pl_vout_yoffset;
+       int h_full = pl_vout_h;
+       int enhres = w > psx_w;
        int xoffs = 0, doffs;
+       int hwrapped;
 
        pcnt_start(PCNT_BLIT);
 
@@ -328,23 +346,23 @@ static void pl_vout_flip(const void *vram, int stride, int bgr24,
 
        // offset
        xoffs = x * pl_vout_scale_w;
-       doffs = xoffs + y * dstride;
+       doffs = xoffs + y * pl_vout_scale_h * dstride;
 
        if (dims_changed)
-               clear_counter = 2;
+               flip_clear_counter = 3;
 
-       if (clear_counter > 0) {
+       if (flip_clear_counter > 0) {
                if (pl_plat_clear)
                        pl_plat_clear();
                else
                        memset(pl_vout_buf, 0,
                                dstride * h_full * pl_vout_bpp / 8);
-               clear_counter--;
+               flip_clear_counter--;
        }
 
        if (pl_plat_blit)
        {
-               pl_plat_blit(doffs, src, w, h, stride, bgr24);
+               pl_plat_blit(doffs, vram + vram_ofs, w, h, 1024, bgr24);
                goto out_hud;
        }
 
@@ -355,54 +373,94 @@ static void pl_vout_flip(const void *vram, int stride, int bgr24,
 
        if (bgr24)
        {
+               hwrapped = (vram_ofs & 2047) + w * 3 - 2048;
                if (pl_rearmed_cbs.only_16bpp) {
-                       for (; h1-- > 0; dest += dstride * 2, src += stride)
-                       {
-                               bgr888_to_rgb565(dest, src, w * 3);
+                       for (; h1-- > 0; dest += dstride * 2) {
+                               bgr888_to_rgb565(dest, vram + vram_ofs, w * 3);
+                               vram_ofs = (vram_ofs + 2048) & 0xfffff;
+                       }
+
+                       if (hwrapped > 0) {
+                               // this is super-rare so just fix-up
+                               vram_ofs = (vram_ofs - h * 2048) & 0xff800;
+                               dest -= dstride * 2 * h;
+                               dest += (w - hwrapped / 3) * 2;
+                               for (h1 = h; h1-- > 0; dest += dstride * 2) {
+                                       bgr888_to_rgb565(dest, vram + vram_ofs, hwrapped);
+                                       vram_ofs = (vram_ofs + 2048) & 0xfffff;
+                               }
                        }
                }
                else {
                        dest -= doffs * 2;
                        dest += (doffs / 8) * 24;
 
-                       for (; h1-- > 0; dest += dstride * 3, src += stride)
-                       {
-                               bgr888_to_rgb888(dest, src, w * 3);
+                       for (; h1-- > 0; dest += dstride * 3) {
+                               bgr888_to_rgb888(dest, vram + vram_ofs, w * 3);
+                               vram_ofs = (vram_ofs + 2048) & 0xfffff;
+                       }
+
+                       if (hwrapped > 0) {
+                               vram_ofs = (vram_ofs - h * 2048) & 0xff800;
+                               dest -= dstride * 3 * h;
+                               dest += w * 3 - hwrapped;
+                               for (h1 = h; h1-- > 0; dest += dstride * 3) {
+                                       bgr888_to_rgb888(dest, vram + vram_ofs, hwrapped);
+                                       vram_ofs = (vram_ofs + 2048) & 0xfffff;
+                               }
                        }
                }
        }
-#ifdef __ARM_NEON__
+#ifdef HAVE_NEON32
        else if (soft_filter == SOFT_FILTER_SCALE2X && pl_vout_scale_w == 2)
        {
-               neon_scale2x_16_16(src, (void *)dest, w,
-                       stride * 2, dstride * 2, h);
+               neon_scale2x_16_16((const void *)(vram + vram_ofs), (void *)dest, w,
+                       2048, dstride * 2, h);
        }
        else if (soft_filter == SOFT_FILTER_EAGLE2X && pl_vout_scale_w == 2)
        {
-               neon_eagle2x_16_16(src, (void *)dest, w,
-                       stride * 2, dstride * 2, h);
+               neon_eagle2x_16_16((const void *)(vram + vram_ofs), (void *)dest, w,
+                       2048, dstride * 2, h);
        }
        else if (scanlines != 0 && scanline_level != 100)
        {
-               int l = scanline_level * 2048 / 100;
-               int stride_0 = pl_vout_scale_h >= 2 ? 0 : stride;
+               int h2, l = scanline_level * 2048 / 100;
+               int stride_0 = pl_vout_scale_h >= 2 ? 0 : 2048;
 
                h1 *= pl_vout_scale_h;
-               for (; h1 >= 2; h1 -= 2)
+               while (h1 > 0)
                {
-                       bgr555_to_rgb565(dest, src, w * 2);
-                       dest += dstride * 2, src += stride_0;
+                       for (h2 = scanlines; h2 > 0 && h1 > 0; h2--, h1--) {
+                               bgr555_to_rgb565(dest, vram + vram_ofs, w * 2);
+                               vram_ofs = (vram_ofs + stride_0) & 0xfffff;
+                               dest += dstride * 2;
+                       }
 
-                       bgr555_to_rgb565_b(dest, src, w * 2, l);
-                       dest += dstride * 2, src += stride;
+                       for (h2 = scanlines; h2 > 0 && h1 > 0; h2--, h1--) {
+                               bgr555_to_rgb565_b(dest, vram + vram_ofs, w * 2, l);
+                               vram_ofs = (vram_ofs + 2048) & 0xfffff;
+                               dest += dstride * 2;
+                       }
                }
        }
 #endif
        else
        {
-               for (; h1-- > 0; dest += dstride * 2, src += stride)
-               {
-                       bgr555_to_rgb565(dest, src, w * 2);
+               unsigned int vram_mask = enhres ? ~0 : 0xfffff;
+               for (; h1-- > 0; dest += dstride * 2) {
+                       bgr555_to_rgb565(dest, vram + vram_ofs, w * 2);
+                       vram_ofs = (vram_ofs + 2048) & vram_mask;
+               }
+
+               hwrapped = (vram_ofs & 2047) + w * 2 - 2048;
+               if (!enhres && hwrapped > 0) {
+                       vram_ofs = (vram_ofs - h * 2048) & 0xff800;
+                       dest -= dstride * 2 * h;
+                       dest += w * 2 - hwrapped;
+                       for (h1 = h; h1-- > 0; dest += dstride * 2) {
+                               bgr555_to_rgb565(dest, vram + vram_ofs, hwrapped);
+                               vram_ofs = (vram_ofs + 2048) & 0xfffff;
+                       }
                }
        }
 
@@ -414,9 +472,6 @@ out:
 
        // let's flip now
        pl_vout_buf = plat_gvideo_flip();
-       if (pl_vout_buf != NULL)
-               pl_vout_buf = (char *)pl_vout_buf
-                       + pl_vout_yoffset * pl_vout_w * pl_vout_bpp / 8;
 
        pl_rearmed_cbs.flip_cnt++;
 }
@@ -470,7 +525,6 @@ static int dispmode_default(void)
        return 1;
 }
 
-#ifdef BUILTIN_GPU_NEON
 static int dispmode_doubleres(void)
 {
        if (!(pl_rearmed_cbs.gpu_caps & GPU_CAP_SUPPORTS_2X)
@@ -482,9 +536,8 @@ static int dispmode_doubleres(void)
        snprintf(hud_msg, sizeof(hud_msg), "double resolution");
        return 1;
 }
-#endif
 
-#ifdef __ARM_NEON__
+#ifdef HAVE_NEON32
 static int dispmode_scale2x(void)
 {
        if (!resolution_ok(psx_w * 2, psx_h * 2) || psx_bpp != 16)
@@ -510,10 +563,8 @@ static int dispmode_eagle2x(void)
 
 static int (*dispmode_switchers[])(void) = {
        dispmode_default,
-#ifdef BUILTIN_GPU_NEON
        dispmode_doubleres,
-#endif
-#ifdef __ARM_NEON__
+#ifdef HAVE_NEON32
        dispmode_scale2x,
        dispmode_eagle2x,
 #endif
@@ -598,16 +649,29 @@ static void update_analogs(void)
        }
 }
 
+static void emu_set_action(enum sched_action action_)
+{
+       extern enum sched_action emu_action, emu_action_old;
+
+       if (action_ == SACTION_NONE)
+               emu_action_old = 0;
+       else if (action_ != emu_action_old)
+               psxRegs.stop++;
+       emu_action = action_;
+}
+
 static void update_input(void)
 {
        int actions[IN_BINDTYPE_COUNT] = { 0, };
        unsigned int emu_act;
+       int in_state_gun;
+       int i;
 
        in_update(actions);
        if (in_type[0] == PSE_PAD_TYPE_ANALOGJOY || in_type[0] == PSE_PAD_TYPE_ANALOGPAD)
                update_analogs();
        emu_act = actions[IN_BINDTYPE_EMU];
-       in_state_gun = (emu_act & SACTION_GUN_MASK) >> SACTION_GUN_TRIGGER;
+       in_state_gun = emu_act & SACTION_GUN_MASK;
 
        emu_act &= ~SACTION_GUN_MASK;
        if (emu_act) {
@@ -618,12 +682,35 @@ static void update_input(void)
        }
        emu_set_action(emu_act);
 
-       in_keystate[0] = actions[IN_BINDTYPE_PLAYER12];
+       in_keystate[0] = actions[IN_BINDTYPE_PLAYER12] & 0xffff;
+       in_keystate[1] = (actions[IN_BINDTYPE_PLAYER12] >> 16) & 0xffff;
 
-       // fixme
-       //if (in_type[0] == PSE_PAD_TYPE_GUNCON && tsdev)
-       //      pl_gun_ts_update(tsdev, xn, yn, in);
-       //      in_analog_left[0][0] = xn
+       if (tsdev) for (i = 0; i < 2; i++) {
+               int in = 0, x = 0, y = 0, trigger;;
+               if (in_type[i] != PSE_PAD_TYPE_GUN
+                   && in_type[i] != PSE_PAD_TYPE_GUNCON)
+                       continue;
+               trigger = in_type[i] == PSE_PAD_TYPE_GUN
+                       ? (1 << DKEY_SQUARE) : (1 << DKEY_CIRCLE);
+
+               pl_gun_ts_update(tsdev, &x, &y, &in);
+               in_analog_left[i][0] = 65536;
+               in_analog_left[i][1] = 65536;
+               if (in && !(in_state_gun & (1 << SACTION_GUN_TRIGGER2))) {
+                       in_analog_left[i][0] = x;
+                       in_analog_left[i][1] = y;
+                       if (!(g_opts & OPT_TSGUN_NOTRIGGER))
+                               in_state_gun |= (1 << SACTION_GUN_TRIGGER);
+               }
+               in_keystate[i] = 0;
+               if (in_state_gun & ((1 << SACTION_GUN_TRIGGER)
+                                       | (1 << SACTION_GUN_TRIGGER2)))
+                       in_keystate[i] |= trigger;
+               if (in_state_gun & (1 << SACTION_GUN_A))
+                       in_keystate[i] |= (1 << DKEY_START);
+               if (in_state_gun & (1 << SACTION_GUN_B))
+                       in_keystate[i] |= (1 << DKEY_CROSS);
+       }
 }
 #else /* MAEMO */
 extern void update_input(void);
@@ -631,6 +718,13 @@ extern void update_input(void);
 
 void pl_gun_byte2(int port, unsigned char byte)
 {
+       if (!tsdev || in_type[port] != PSE_PAD_TYPE_GUN || !(byte & 0x10))
+               return;
+       if (in_analog_left[port][0] == 65536)
+               return;
+
+       psxScheduleIrq10(4, in_analog_left[port][0] * 1629 / 1024,
+               in_analog_left[port][1] * psx_h / 1024);
 }
 
 #define MAX_LAG_FRAMES 3
@@ -720,14 +814,14 @@ void pl_frame_limit(void)
 
                // recompilation is not that fast and may cause frame skip on
                // loading screens and such, resulting in flicker or glitches
-               if (new_dynarec_did_compile) {
+               if (ndrc_g.did_compile) {
                        if (drc_active_vsyncs < 32)
                                pl_rearmed_cbs.fskip_advice = 0;
                        drc_active_vsyncs++;
                }
                else
                        drc_active_vsyncs = 0;
-               new_dynarec_did_compile = 0;
+               ndrc_g.did_compile = 0;
        }
 
        pcnt_start(PCNT_ALL);
@@ -735,18 +829,20 @@ void pl_frame_limit(void)
 
 void pl_timing_prepare(int is_pal_)
 {
+       double fps;
        pl_rearmed_cbs.fskip_advice = 0;
        pl_rearmed_cbs.flips_per_sec = 0;
        pl_rearmed_cbs.cpu_usage = 0;
 
        is_pal = is_pal_;
-       frame_interval = is_pal ? 20000 : 16667;
-       frame_interval1024 = is_pal ? 20000*1024 : 17066667;
+       fps = psxGetFps();
+       frame_interval = (int)(1000000.0 / fps);
+       frame_interval1024 = (int)(1000000.0 * 1024.0 / fps);
 
        // used by P.E.Op.S. frameskip code
-       pl_rearmed_cbs.gpu_peops.fFrameRateHz = is_pal ? 50.0f : 59.94f;
+       pl_rearmed_cbs.gpu_peops.fFrameRateHz = (float)fps;
        pl_rearmed_cbs.gpu_peops.dwFrameRateTicks =
-               (100000*100 / (unsigned long)(pl_rearmed_cbs.gpu_peops.fFrameRateHz*100));
+               (100000*100 / (int)(pl_rearmed_cbs.gpu_peops.fFrameRateHz*100));
 }
 
 static void pl_get_layer_pos(int *x, int *y, int *w, int *h)
@@ -770,6 +866,7 @@ struct rearmed_cbs pl_rearmed_cbs = {
        .mmap = pl_mmap,
        .munmap = pl_munmap,
        .pl_set_gpu_caps = pl_set_gpu_caps,
+       .gpu_state_change = gpu_state_change,
 };
 
 /* watchdog */
@@ -779,15 +876,11 @@ static void *watchdog_thread(void *unused)
        int seen_dead = 0;
        int sleep_time = 5;
 
-#if !defined(NDEBUG) || defined(DRC_DBG)
-       // don't interfere with debug
-       return NULL;
-#endif
        while (1)
        {
                sleep(sleep_time);
 
-               if (stop) {
+               if (psxRegs.stop) {
                        seen_dead = 0;
                        sleep_time = 5;
                        continue;
@@ -805,6 +898,7 @@ static void *watchdog_thread(void *unused)
                        fprintf(stderr, "watchdog: seen_dead %d\n", seen_dead);
                if (seen_dead > 4) {
                        fprintf(stderr, "watchdog: lockup detected, aborting\n");
+                       fflush(stderr);
                        // we can't do any cleanup here really, the main thread is
                        // likely touching resources and would crash anyway
                        abort();
@@ -814,9 +908,25 @@ static void *watchdog_thread(void *unused)
 
 void pl_start_watchdog(void)
 {
+#if defined(NDEBUG) && !defined(DRC_DBG)
        pthread_attr_t attr;
        pthread_t tid;
        int ret;
+#ifdef __linux__
+       int tpid = 0;
+       char buf[256];
+       FILE *f = fopen("/proc/self/status", "r");
+       if (f) {
+               while (fgets(buf, sizeof(buf), f))
+                       if (buf[0] == 'T' && sscanf(buf, "TracerPid: %d", &tpid) == 1)
+                               break;
+               fclose(f);
+       }
+       if (tpid) {
+               printf("no watchdog to tracer %d\n", tpid);
+               return;
+       }
+#endif
        
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
@@ -824,12 +934,15 @@ void pl_start_watchdog(void)
        ret = pthread_create(&tid, &attr, watchdog_thread, NULL);
        if (ret != 0)
                fprintf(stderr, "could not start watchdog: %d\n", ret);
+#endif
+       (void)watchdog_thread;
 }
 
-static void *pl_emu_mmap(unsigned long addr, size_t size, int is_fixed,
-       enum psxMapTag tag)
+static void *pl_emu_mmap(unsigned long addr, size_t size,
+       enum psxMapTag tag, int *can_retry_addr)
 {
-       return plat_mmap(addr, size, 0, is_fixed);
+       *can_retry_addr = 1;
+       return plat_mmap(addr, size, 0, 0);
 }
 
 static void pl_emu_munmap(void *ptr, size_t size, enum psxMapTag tag)
@@ -839,7 +952,8 @@ static void pl_emu_munmap(void *ptr, size_t size, enum psxMapTag tag)
 
 static void *pl_mmap(unsigned int size)
 {
-       return psxMapHook(0, size, 0, MAP_TAG_VRAM);
+       int can_retry_addr;
+       return psxMapHook(0, size, MAP_TAG_VRAM, &can_retry_addr);
 }
 
 static void pl_munmap(void *ptr, unsigned int size)