cdrom: change pause timing again
[pcsx_rearmed.git] / frontend / plugin_lib.c
index fff8401..9b6faf4 100644 (file)
@@ -16,6 +16,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <pthread.h>
+#include <assert.h>
 
 #include "libpicofe/fonts.h"
 #include "libpicofe/input.h"
 #include "plat.h"
 #include "pcnt.h"
 #include "pl_gun_ts.h"
+#include "cspace.h"
 #include "psemu_plugin_defs.h"
 #include "../libpcsxcore/new_dynarec/new_dynarec.h"
 #include "../libpcsxcore/psxmem_map.h"
-#include "../plugins/gpulib/cspace.h"
-#include "../plugins/dfinput/externals.h"
+#include "../libpcsxcore/gpu.h"
+#include "../libpcsxcore/r3000a.h"
+#include "../libpcsxcore/psxcounters.h"
 
-int in_type1, in_type2;
-int in_a1[2] = { 127, 127 }, in_a2[2] = { 127, 127 };
+#define HUD_HEIGHT 10
+
+int in_type[8];
+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_is_nublike[2];
-int in_keystate, in_state_gun;
+unsigned short in_keystate[8];
+int in_mouse[8][2];
 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, pl_vout_yoffset;
+static int pl_vout_scale_w, pl_vout_scale_h, pl_vout_yoffset;
 static int psx_w, psx_h, psx_bpp;
 static int vsync_cnt;
 static int is_pal, frame_interval, frame_interval1024;
@@ -101,20 +110,20 @@ static void hud_printf(void *fb, int w, int x, int y, const char *texto, ...)
 
 static void print_msg(int h, int border)
 {
-       hud_print(pl_vout_buf, pl_vout_w, border + 2, h - 10, hud_msg);
+       hud_print(pl_vout_buf, pl_vout_w, border + 2, h - HUD_HEIGHT, hud_msg);
 }
 
 static void print_fps(int h, int border)
 {
-       hud_printf(pl_vout_buf, pl_vout_w, border + 2, h - 10,
+       hud_printf(pl_vout_buf, pl_vout_w, border + 2, h - HUD_HEIGHT,
                "%2d %4.1f", pl_rearmed_cbs.flips_per_sec,
                pl_rearmed_cbs.vsps_cur);
 }
 
-static void print_cpu_usage(int w, int h, int border)
+static void print_cpu_usage(int x, int h)
 {
-       hud_printf(pl_vout_buf, pl_vout_w, pl_vout_w - border - 28, h - 10,
-               "%3d", pl_rearmed_cbs.cpu_usage);
+       hud_printf(pl_vout_buf, pl_vout_w, x - 28,
+               h - HUD_HEIGHT, "%3d", pl_rearmed_cbs.cpu_usage);
 }
 
 // draw 192x8 status of 24 sound channels
@@ -126,11 +135,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 - 10) + 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);
@@ -141,19 +150,17 @@ 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;
        }
 }
 
-static void print_hud(int w, int h, int xborder)
+static void print_hud(int x, int w, int h)
 {
-       if (h < 16)
+       if (h < 192)
                return;
 
-       if (w < pl_vout_w)
-               xborder += (pl_vout_w - w) / 2;
        if (h > pl_vout_h)
                h = pl_vout_h;
 
@@ -161,12 +168,12 @@ static void print_hud(int w, int h, int xborder)
                draw_active_chans(w, h);
 
        if (hud_msg[0] != 0)
-               print_msg(h, xborder);
+               print_msg(h, x);
        else if (g_opts & OPT_SHOWFPS)
-               print_fps(h, xborder);
+               print_fps(h, x);
 
        if (g_opts & OPT_SHOWCPU)
-               print_cpu_usage(w, h, xborder);
+               print_cpu_usage(x + w, h);
 }
 
 /* update scaler target size according to user settings */
@@ -180,6 +187,14 @@ static void update_layer_size(int w, int h)
                g_layer_w = w; g_layer_h = h;
                break;
 
+       case SCALE_2_2:
+               g_layer_w = w; g_layer_h = h;
+               if (w * 2 <= g_menuscreen_w)
+                       g_layer_w = w * 2;
+               if (h * 2 <= g_menuscreen_h)
+                       g_layer_h = h * 2;
+               break;
+
        case SCALE_4_3v2:
                if (h > g_menuscreen_h || (240 < h && h <= 360))
                        goto fractional_4_3;
@@ -213,16 +228,16 @@ static void update_layer_size(int w, int h)
                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 = g_menuscreen_w / 2 - g_layer_w / 2;
+               g_layer_y = g_menuscreen_h / 2 - g_layer_h / 2;
+       }
+       if (g_layer_w > g_menuscreen_w * 2) g_layer_w = g_menuscreen_w * 2;
+       if (g_layer_h > g_menuscreen_h * 2) g_layer_h = g_menuscreen_h * 2;
 }
 
 // XXX: this is platform specific really
-static int resolution_ok(int w, int h)
+static inline int resolution_ok(int w, int h)
 {
        return w <= 1024 && h <= 512;
 }
@@ -240,37 +255,41 @@ static void pl_vout_set_mode(int w, int h, int raw_w, int raw_h, int bpp)
 
        psx_w = raw_w;
        psx_h = raw_h;
+       psx_bpp = bpp;
        vout_w = w;
        vout_h = h;
-       vout_bpp = psx_bpp = bpp;
+       vout_bpp = bpp;
+       if (pl_rearmed_cbs.only_16bpp)
+               vout_bpp = 16;
 
-       // don't use very low heights
-       if (vout_h < 192) {
-               buf_yoffset = (192 - vout_h) / 2;
-               vout_h = 192;
-       }
+       assert(vout_h >= 192);
 
-       pl_vout_scale = 1;
+       pl_vout_scale_w = pl_vout_scale_h = 1;
 #ifdef __ARM_NEON__
        if (soft_filter) {
                if (resolution_ok(w * 2, h * 2) && bpp == 16) {
-                       vout_w *= 2;
-                       vout_h *= 2;
-                       pl_vout_scale = 2;
+                       pl_vout_scale_w = 2;
+                       pl_vout_scale_h = 2;
                }
                else {
                        // filter unavailable
                        hud_msg[0] = 0;
                }
        }
+       else if (scanlines != 0 && scanline_level != 100 && bpp == 16) {
+               if (h <= 256)
+                       pl_vout_scale_h = 2;
+       }
 #endif
+       vout_w *= pl_vout_scale_w;
+       vout_h *= pl_vout_scale_h;
 
        update_layer_size(vout_w, vout_h);
 
        pl_vout_buf = plat_gvideo_set_mode(&vout_w, &vout_h, &vout_bpp);
        if (pl_vout_buf == NULL && pl_plat_blit == NULL)
                fprintf(stderr, "failed to set mode %dx%d@%d\n",
-                       vout_w, vout_h, psx_bpp);
+                       vout_w, vout_h, vout_bpp);
        else {
                pl_vout_w = vout_w;
                pl_vout_h = vout_h;
@@ -284,13 +303,21 @@ static void pl_vout_set_mode(int w, int h, int raw_w, int raw_h, int bpp)
        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, int w, int h)
+static int flip_clear_counter;
+
+void pl_force_clear(void)
+{
+       flip_clear_counter = 2;
+}
+
+static void pl_vout_flip(const void *vram, int stride, int bgr24,
+       int x, int y, int w, int h, int dims_changed)
 {
-       static int doffs_old, clear_counter;
        unsigned char *dest = pl_vout_buf;
        const unsigned short *src = vram;
        int dstride = pl_vout_w, h1 = h;
-       int doffs;
+       int h_full = pl_vout_h - pl_vout_yoffset;
+       int xoffs = 0, doffs;
 
        pcnt_start(PCNT_BLIT);
 
@@ -300,24 +327,27 @@ static void pl_vout_flip(const void *vram, int stride, int bgr24, int w, int h)
                        pl_plat_clear();
                else
                        memset(pl_vout_buf, 0,
-                               dstride * pl_vout_h * pl_vout_bpp / 8);
+                               dstride * h_full * pl_vout_bpp / 8);
                goto out_hud;
        }
 
-       // borders
-       doffs = (dstride - w * pl_vout_scale) / 2 & ~1;
+       assert(x + w <= pl_vout_w);
+       assert(y + h <= pl_vout_h);
+
+       // offset
+       xoffs = x * pl_vout_scale_w;
+       doffs = xoffs + y * dstride;
 
-       if (doffs > doffs_old)
-               clear_counter = 2;
-       doffs_old = doffs;
+       if (dims_changed)
+               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 * pl_vout_h * pl_vout_bpp / 8);
-               clear_counter--;
+                               dstride * h_full * pl_vout_bpp / 8);
+               flip_clear_counter--;
        }
 
        if (pl_plat_blit)
@@ -350,16 +380,35 @@ static void pl_vout_flip(const void *vram, int stride, int bgr24, int w, int h)
                }
        }
 #ifdef __ARM_NEON__
-       else if (soft_filter == SOFT_FILTER_SCALE2X && pl_vout_scale == 2)
+       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);
        }
-       else if (soft_filter == SOFT_FILTER_EAGLE2X && pl_vout_scale == 2)
+       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);
        }
+       else if (scanlines != 0 && scanline_level != 100)
+       {
+               int h2, l = scanline_level * 2048 / 100;
+               int stride_0 = pl_vout_scale_h >= 2 ? 0 : stride;
+
+               h1 *= pl_vout_scale_h;
+               while (h1 > 0)
+               {
+                       for (h2 = scanlines; h2 > 0 && h1 > 0; h2--, h1--) {
+                               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_b(dest, src, w * 2, l);
+                               dest += dstride * 2, src += stride;
+                       }
+               }
+       }
 #endif
        else
        {
@@ -370,7 +419,7 @@ static void pl_vout_flip(const void *vram, int stride, int bgr24, int w, int h)
        }
 
 out_hud:
-       print_hud(w * pl_vout_scale, h * pl_vout_scale, 0);
+       print_hud(xoffs, w * pl_vout_scale_w, (y + h) * pl_vout_scale_h);
 
 out:
        pcnt_end(PCNT_BLIT);
@@ -433,7 +482,8 @@ static int dispmode_default(void)
        return 1;
 }
 
-int dispmode_doubleres(void)
+#ifdef BUILTIN_GPU_NEON
+static int dispmode_doubleres(void)
 {
        if (!(pl_rearmed_cbs.gpu_caps & GPU_CAP_SUPPORTS_2X)
            || !resolution_ok(psx_w * 2, psx_h * 2) || psx_bpp != 16)
@@ -444,8 +494,10 @@ int dispmode_doubleres(void)
        snprintf(hud_msg, sizeof(hud_msg), "double resolution");
        return 1;
 }
+#endif
 
-int dispmode_scale2x(void)
+#ifdef __ARM_NEON__
+static int dispmode_scale2x(void)
 {
        if (!resolution_ok(psx_w * 2, psx_h * 2) || psx_bpp != 16)
                return 0;
@@ -456,7 +508,7 @@ int dispmode_scale2x(void)
        return 1;
 }
 
-int dispmode_eagle2x(void)
+static int dispmode_eagle2x(void)
 {
        if (!resolution_ok(psx_w * 2, psx_h * 2) || psx_bpp != 16)
                return 0;
@@ -466,11 +518,14 @@ int dispmode_eagle2x(void)
        snprintf(hud_msg, sizeof(hud_msg), "eagle2x");
        return 1;
 }
+#endif
 
 static int (*dispmode_switchers[])(void) = {
        dispmode_default,
-#ifdef __ARM_NEON__
+#ifdef BUILTIN_GPU_NEON
        dispmode_doubleres,
+#endif
+#ifdef __ARM_NEON__
        dispmode_scale2x,
        dispmode_eagle2x,
 #endif
@@ -525,7 +580,7 @@ static void update_analog_nub_adjust(int *x_, int *y_)
 
 static void update_analogs(void)
 {
-       int *nubp[2] = { in_a1, in_a2 };
+       int *nubp[2] = { in_analog_left[0], in_analog_right[0] };
        int vals[2];
        int i, a, v, ret;
 
@@ -553,19 +608,20 @@ static void update_analogs(void)
                }
 
        }
-       //printf("%4d %4d %4d %4d\n", in_a1[0], in_a1[1], in_a2[0], in_a2[1]);
 }
 
 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_type1 == PSE_PAD_TYPE_ANALOGPAD)
+       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) {
@@ -576,21 +632,49 @@ static void update_input(void)
        }
        emu_set_action(emu_act);
 
-       in_keystate = actions[IN_BINDTYPE_PLAYER12];
+       in_keystate[0] = actions[IN_BINDTYPE_PLAYER12] & 0xffff;
+       in_keystate[1] = (actions[IN_BINDTYPE_PLAYER12] >> 16) & 0xffff;
+
+       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 */
-static void update_input(void)
-{
-}
+extern void update_input(void);
 #endif
 
-void pl_update_gun(int *xn, int *yn, int *xres, int *yres, int *in)
+void pl_gun_byte2(int port, unsigned char byte)
 {
-       if (tsdev)
-               pl_gun_ts_update(tsdev, xn, yn, in);
+       if (!tsdev || in_type[port] != PSE_PAD_TYPE_GUN || !(byte & 0x10))
+               return;
+       if (in_analog_left[port][0] == 65536)
+               return;
 
-       *xres = psx_w;
-       *yres = psx_h;
+       psxScheduleIrq10(4, in_analog_left[port][0] * 1629 / 1024,
+               in_analog_left[port][1] * psx_h / 1024);
 }
 
 #define MAX_LAG_FRAMES 3
@@ -637,6 +721,7 @@ void pl_frame_limit(void)
                                hud_msg[0] = 0;
                }
                tv_old = now;
+               //new_dynarec_print_stats();
        }
 #ifdef PCNT
        static int ya_vsync_count;
@@ -694,18 +779,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)
@@ -729,6 +816,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 */