PCem

changeset 133:24b744b9a632

ViRGE S3D triangle rendering now uses worker thread. Fixed clipping bug on ViRGE. Fixed status window crash.
author TomW
date Tue Jul 22 21:10:39 2014 +0100
parents 2b9cea0be424
children ffe477b4639f
files src/device.c src/device.h src/sound_sb.c src/sound_sb_dsp.c src/sound_sb_dsp.h src/vid_ati18800.c src/vid_ati28800.c src/vid_ati_mach64.c src/vid_cl5429.c src/vid_et4000.c src/vid_et4000w32.c src/vid_oti067.c src/vid_paradise.c src/vid_s3.c src/vid_s3_virge.c src/vid_svga.c src/vid_svga.h src/vid_tgui9440.c src/vid_tvga.c src/vid_vga.c src/win-status.c src/win.c
diffstat 22 files changed, 462 insertions(+), 305 deletions(-) [+]
line diff
     1.1 --- a/src/device.c	Wed Jul 16 20:44:29 2014 +0100
     1.2 +++ b/src/device.c	Tue Jul 22 21:10:39 2014 +0100
     1.3 @@ -95,18 +95,12 @@
     1.4  {
     1.5          int c;
     1.6          
     1.7 -        s += strlen(s);
     1.8 -        
     1.9          for (c = 0; c < 256; c++)
    1.10          {
    1.11                  if (devices[c] != NULL)
    1.12                  {
    1.13                          if (devices[c]->add_status_info != NULL)
    1.14 -                        {
    1.15 -                                int len = devices[c]->add_status_info(s, max_len, device_priv[c]);
    1.16 -                                s += len;
    1.17 -                                max_len -= len;
    1.18 -                        }
    1.19 +                                devices[c]->add_status_info(s, max_len, device_priv[c]);
    1.20                  }
    1.21          }
    1.22  }
     2.1 --- a/src/device.h	Wed Jul 16 20:44:29 2014 +0100
     2.2 +++ b/src/device.h	Tue Jul 22 21:10:39 2014 +0100
     2.3 @@ -28,7 +28,7 @@
     2.4          int  (*available)();
     2.5          void (*speed_changed)(void *p);
     2.6          void (*force_redraw)(void *p);
     2.7 -        int  (*add_status_info)(char *s, int max_len, void *p);
     2.8 +        void (*add_status_info)(char *s, int max_len, void *p);
     2.9          device_config_t *config;
    2.10  } device_t;
    2.11  
     3.1 --- a/src/sound_sb.c	Wed Jul 16 20:44:29 2014 +0100
     3.2 +++ b/src/sound_sb.c	Tue Jul 22 21:10:39 2014 +0100
     3.3 @@ -444,7 +444,7 @@
     3.4          sb_dsp_speed_changed(&sb->dsp);
     3.5  }
     3.6  
     3.7 -int sb_add_status_info(char *s, int max_len, void *p)
     3.8 +void sb_add_status_info(char *s, int max_len, void *p)
     3.9  {
    3.10          sb_t *sb = (sb_t *)p;
    3.11          
     4.1 --- a/src/sound_sb_dsp.c	Wed Jul 16 20:44:29 2014 +0100
     4.2 +++ b/src/sound_sb_dsp.c	Tue Jul 22 21:10:39 2014 +0100
     4.3 @@ -910,10 +910,9 @@
     4.4          *r = dsp->sbdatr;
     4.5  }
     4.6  
     4.7 -int sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp)
     4.8 +void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp)
     4.9  {
    4.10          char temps[128];
    4.11 -        int cur_len = max_len;
    4.12          int len;
    4.13          int freq;
    4.14  
    4.15 @@ -967,15 +966,11 @@
    4.16          }
    4.17          else
    4.18                  strcpy(temps, "SB playback stopped\n");
    4.19 -        strncat(s, temps, cur_len);
    4.20 -        cur_len -= strlen(temps);
    4.21 +        strncat(s, temps, max_len);
    4.22  
    4.23          if ((dsp->sb_8_enable && dsp->sb_8_output) || (dsp->sb_16_enable && dsp->sb_16_output))
    4.24          {
    4.25                  sprintf(temps, "SB playback frequency : %iHz\n", freq);
    4.26 -                strncat(s, temps, cur_len);
    4.27 -                cur_len -= strlen(temps);
    4.28 +                strncat(s, temps, max_len);
    4.29          }
    4.30 -        
    4.31 -        return max_len - cur_len;
    4.32  }
     5.1 --- a/src/sound_sb_dsp.h	Wed Jul 16 20:44:29 2014 +0100
     5.2 +++ b/src/sound_sb_dsp.h	Tue Jul 22 21:10:39 2014 +0100
     5.3 @@ -68,4 +68,4 @@
     5.4  
     5.5  void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo);
     5.6  
     5.7 -int sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp);
     5.8 +void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp);
     6.1 --- a/src/vid_ati18800.c	Wed Jul 16 20:44:29 2014 +0100
     6.2 +++ b/src/vid_ati18800.c	Tue Jul 22 21:10:39 2014 +0100
     6.3 @@ -171,11 +171,11 @@
     6.4          ati18800->svga.fullchange = changeframecount;
     6.5  }
     6.6  
     6.7 -int ati18800_add_status_info(char *s, int max_len, void *p)
     6.8 +void ati18800_add_status_info(char *s, int max_len, void *p)
     6.9  {
    6.10          ati18800_t *ati18800 = (ati18800_t *)p;
    6.11          
    6.12 -        return svga_add_status_info(s, max_len, &ati18800->svga);
    6.13 +        svga_add_status_info(s, max_len, &ati18800->svga);
    6.14  }
    6.15  
    6.16  device_t ati18800_device =
     7.1 --- a/src/vid_ati28800.c	Wed Jul 16 20:44:29 2014 +0100
     7.2 +++ b/src/vid_ati28800.c	Tue Jul 22 21:10:39 2014 +0100
     7.3 @@ -192,11 +192,11 @@
     7.4          ati28800->svga.fullchange = changeframecount;
     7.5  }
     7.6  
     7.7 -int ati28800_add_status_info(char *s, int max_len, void *p)
     7.8 +void ati28800_add_status_info(char *s, int max_len, void *p)
     7.9  {
    7.10          ati28800_t *ati28800 = (ati28800_t *)p;
    7.11          
    7.12 -        return svga_add_status_info(s, max_len, &ati28800->svga);
    7.13 +        svga_add_status_info(s, max_len, &ati28800->svga);
    7.14  }
    7.15  
    7.16  device_t ati28800_device =
     8.1 --- a/src/vid_ati_mach64.c	Wed Jul 16 20:44:29 2014 +0100
     8.2 +++ b/src/vid_ati_mach64.c	Tue Jul 22 21:10:39 2014 +0100
     8.3 @@ -2278,10 +2278,9 @@
     8.4          mach64->svga.fullchange = changeframecount;
     8.5  }
     8.6  
     8.7 -int mach64_add_status_info(char *s, int max_len, void *p)
     8.8 +void mach64_add_status_info(char *s, int max_len, void *p)
     8.9  {
    8.10          mach64_t *mach64 = (mach64_t *)p;
    8.11 -        int cur_len = max_len;
    8.12  
    8.13          if (((mach64->crtc_gen_cntl >> 24) & 3) == 3)
    8.14          {
    8.15 @@ -2289,8 +2288,7 @@
    8.16                  char temps[128];
    8.17                  int bpp = 4;
    8.18                  
    8.19 -                strncat(s, "Mach64 in native mode\n", cur_len);
    8.20 -                cur_len -= strlen("Mach64 in native mode\n");
    8.21 +                strncat(s, "Mach64 in native mode\n", max_len);
    8.22  
    8.23                  switch ((mach64->crtc_gen_cntl >> 8) & 7)
    8.24                  {
    8.25 @@ -2303,25 +2301,19 @@
    8.26                  }
    8.27  
    8.28                  sprintf(temps, "Mach64 colour depth : %i bpp\n", bpp);
    8.29 -                strncat(s, temps, cur_len);
    8.30 -                cur_len -= strlen(temps);
    8.31 +                strncat(s, temps, max_len);
    8.32          
    8.33                  sprintf(temps, "Mach64 resolution : %i x %i\n", svga->hdisp, svga->dispend);
    8.34 -                strncat(s, temps, cur_len);
    8.35 -                cur_len -= strlen(temps);
    8.36 +                strncat(s, temps, max_len);
    8.37          
    8.38                  sprintf(temps, "Mach64 refresh rate : %i Hz\n\n", svga->frames);
    8.39                  svga->frames = 0;
    8.40 -                strncat(s, temps, cur_len);
    8.41 -                cur_len -= strlen(temps);
    8.42 -                
    8.43 -                return max_len - cur_len;
    8.44 +                strncat(s, temps, max_len);
    8.45          }
    8.46          else
    8.47          {
    8.48 -                strncat(s, "Mach64 in SVGA mode\n", cur_len);
    8.49 -                cur_len -= strlen("Mach64 in SVGA mode\n");
    8.50 -                return svga_add_status_info(s, cur_len, &mach64->svga);
    8.51 +                strncat(s, "Mach64 in SVGA mode\n", max_len);
    8.52 +                svga_add_status_info(s, max_len, &mach64->svga);
    8.53          }
    8.54  }
    8.55  
     9.1 --- a/src/vid_cl5429.c	Wed Jul 16 20:44:29 2014 +0100
     9.2 +++ b/src/vid_cl5429.c	Tue Jul 22 21:10:39 2014 +0100
     9.3 @@ -870,11 +870,11 @@
     9.4          gd5429->svga.fullchange = changeframecount;
     9.5  }
     9.6  
     9.7 -int gd5429_add_status_info(char *s, int max_len, void *p)
     9.8 +void gd5429_add_status_info(char *s, int max_len, void *p)
     9.9  {
    9.10          gd5429_t *gd5429 = (gd5429_t *)p;
    9.11          
    9.12 -        return svga_add_status_info(s, max_len, &gd5429->svga);
    9.13 +        svga_add_status_info(s, max_len, &gd5429->svga);
    9.14  }
    9.15  
    9.16  device_t gd5429_device =
    10.1 --- a/src/vid_et4000.c	Wed Jul 16 20:44:29 2014 +0100
    10.2 +++ b/src/vid_et4000.c	Tue Jul 22 21:10:39 2014 +0100
    10.3 @@ -174,11 +174,11 @@
    10.4          et4000->svga.fullchange = changeframecount;
    10.5  }
    10.6  
    10.7 -int et4000_add_status_info(char *s, int max_len, void *p)
    10.8 +void et4000_add_status_info(char *s, int max_len, void *p)
    10.9  {
   10.10          et4000_t *et4000 = (et4000_t *)p;
   10.11          
   10.12 -        return svga_add_status_info(s, max_len, &et4000->svga);
   10.13 +        svga_add_status_info(s, max_len, &et4000->svga);
   10.14  }
   10.15  
   10.16  device_t et4000_device =
    11.1 --- a/src/vid_et4000w32.c	Wed Jul 16 20:44:29 2014 +0100
    11.2 +++ b/src/vid_et4000w32.c	Tue Jul 22 21:10:39 2014 +0100
    11.3 @@ -1077,11 +1077,11 @@
    11.4          et4000w32p->svga.fullchange = changeframecount;
    11.5  }
    11.6  
    11.7 -int et4000w32p_add_status_info(char *s, int max_len, void *p)
    11.8 +void et4000w32p_add_status_info(char *s, int max_len, void *p)
    11.9  {
   11.10          et4000w32p_t *et4000w32p = (et4000w32p_t *)p;
   11.11          
   11.12 -        return svga_add_status_info(s, max_len, &et4000w32p->svga);
   11.13 +        svga_add_status_info(s, max_len, &et4000w32p->svga);
   11.14  }
   11.15  
   11.16  static device_config_t et4000w32p_config[] =
    12.1 --- a/src/vid_oti067.c	Wed Jul 16 20:44:29 2014 +0100
    12.2 +++ b/src/vid_oti067.c	Tue Jul 22 21:10:39 2014 +0100
    12.3 @@ -187,11 +187,11 @@
    12.4          oti067->svga.fullchange = changeframecount;
    12.5  }
    12.6  
    12.7 -int oti067_add_status_info(char *s, int max_len, void *p)
    12.8 +void oti067_add_status_info(char *s, int max_len, void *p)
    12.9  {
   12.10          oti067_t *oti067 = (oti067_t *)p;
   12.11          
   12.12 -        return svga_add_status_info(s, max_len, &oti067->svga);
   12.13 +        svga_add_status_info(s, max_len, &oti067->svga);
   12.14  }
   12.15  
   12.16  static device_config_t oti067_config[] =
    13.1 --- a/src/vid_paradise.c	Wed Jul 16 20:44:29 2014 +0100
    13.2 +++ b/src/vid_paradise.c	Tue Jul 22 21:10:39 2014 +0100
    13.3 @@ -372,11 +372,11 @@
    13.4          paradise->svga.fullchange = changeframecount;
    13.5  }
    13.6  
    13.7 -int paradise_add_status_info(char *s, int max_len, void *p)
    13.8 +void paradise_add_status_info(char *s, int max_len, void *p)
    13.9  {
   13.10          paradise_t *paradise = (paradise_t *)p;
   13.11          
   13.12 -        return svga_add_status_info(s, max_len, &paradise->svga);
   13.13 +        svga_add_status_info(s, max_len, &paradise->svga);
   13.14  }
   13.15  
   13.16  device_t paradise_pvga1a_pc2086_device =
    14.1 --- a/src/vid_s3.c	Wed Jul 16 20:44:29 2014 +0100
    14.2 +++ b/src/vid_s3.c	Tue Jul 22 21:10:39 2014 +0100
    14.3 @@ -2055,11 +2055,11 @@
    14.4          s3->svga.fullchange = changeframecount;
    14.5  }
    14.6  
    14.7 -int s3_add_status_info(char *s, int max_len, void *p)
    14.8 +void s3_add_status_info(char *s, int max_len, void *p)
    14.9  {
   14.10          s3_t *s3 = (s3_t *)p;
   14.11          
   14.12 -        return svga_add_status_info(s, max_len, &s3->svga);
   14.13 +        svga_add_status_info(s, max_len, &s3->svga);
   14.14  }
   14.15  
   14.16  static device_config_t s3_bahamas64_config[] =
    15.1 --- a/src/vid_s3_virge.c	Wed Jul 16 20:44:29 2014 +0100
    15.2 +++ b/src/vid_s3_virge.c	Tue Jul 22 21:10:39 2014 +0100
    15.3 @@ -6,6 +6,7 @@
    15.4  #include "mem.h"
    15.5  #include "pci.h"
    15.6  #include "rom.h"
    15.7 +#include "thread.h"
    15.8  #include "video.h"
    15.9  #include "vid_s3_virge.h"
   15.10  #include "vid_svga.h"
   15.11 @@ -13,7 +14,7 @@
   15.12  
   15.13  static uint64_t virge_time = 0;
   15.14  static uint64_t status_time = 0;
   15.15 -static int reg_writes = 0;
   15.16 +static int reg_writes = 0, reg_reads = 0;
   15.17  
   15.18  static int dither[4][4] =
   15.19  {
   15.20 @@ -23,6 +24,54 @@
   15.21          7,  3,  6,  2,
   15.22  };
   15.23  
   15.24 +#define RB_SIZE 256
   15.25 +#define RB_MASK (RB_SIZE - 1)
   15.26 +
   15.27 +#define RB_ENTRIES (virge->s3d_write_idx - virge->s3d_read_idx)
   15.28 +#define RB_FULL (RB_ENTRIES == RB_SIZE)
   15.29 +#define RB_EMPTY (!RB_ENTRIES)
   15.30 +
   15.31 +typedef struct s3d_t
   15.32 +{
   15.33 +        uint32_t cmd_set;
   15.34 +        int clip_l, clip_r, clip_t, clip_b;
   15.35 +                
   15.36 +        uint32_t dest_base;
   15.37 +        uint32_t dest_str;
   15.38 +        
   15.39 +        uint32_t z_base;
   15.40 +        uint32_t z_str;
   15.41 +
   15.42 +        uint32_t tex_base;
   15.43 +        uint32_t tex_bdr_clr;
   15.44 +        uint32_t tbv, tbu;
   15.45 +        int32_t TdVdX, TdUdX;
   15.46 +        int32_t TdVdY, TdUdY;
   15.47 +        uint32_t tus, tvs;
   15.48 +
   15.49 +        int32_t TdZdX, TdZdY;
   15.50 +        uint32_t tzs;
   15.51 +
   15.52 +        int32_t TdWdX, TdWdY;
   15.53 +        uint32_t tws;
   15.54 +                
   15.55 +        int32_t TdDdX, TdDdY;
   15.56 +        uint32_t tds;
   15.57 +                
   15.58 +        int16_t TdGdX, TdBdX, TdRdX, TdAdX;
   15.59 +        int16_t TdGdY, TdBdY, TdRdY, TdAdY;
   15.60 +        uint32_t tgs, tbs, trs, tas;
   15.61 +                                
   15.62 +        uint32_t TdXdY12;
   15.63 +        uint32_t txend12;
   15.64 +        uint32_t TdXdY01;
   15.65 +        uint32_t txend01;
   15.66 +        uint32_t TdXdY02;
   15.67 +        uint32_t txs;
   15.68 +        uint32_t tys;
   15.69 +        int ty01, ty12, tlr;
   15.70 +} s3d_t;
   15.71 +        
   15.72  typedef struct virge_t
   15.73  {
   15.74          mem_mapping_t   linear_mapping;
   15.75 @@ -51,6 +100,11 @@
   15.76          int memory_size;
   15.77          
   15.78          int pixel_count, tri_count;
   15.79 +        
   15.80 +        thread_t *render_thread;
   15.81 +        event_t *wake_render_thread;
   15.82 +        event_t *wake_main_thread;
   15.83 +        event_t *not_full_event;
   15.84                          
   15.85          struct
   15.86          {
   15.87 @@ -86,41 +140,14 @@
   15.88                  uint32_t pattern_8[8*8];
   15.89                  uint32_t pattern_16[8*8];
   15.90                  uint32_t pattern_32[8*8];
   15.91 -                
   15.92 -                
   15.93 -                uint32_t z_base;
   15.94 -                uint32_t z_str;
   15.95 -
   15.96 -                uint32_t tex_base;
   15.97 -                uint32_t tex_bdr_clr;
   15.98 -                uint32_t tbv, tbu;
   15.99 -                int32_t TdVdX, TdUdX;
  15.100 -                int32_t TdVdY, TdUdY;
  15.101 -                uint32_t tus, tvs;
  15.102 -
  15.103 -                int32_t TdZdX, TdZdY;
  15.104 -                uint32_t tzs;
  15.105 -
  15.106 -                int32_t TdWdX, TdWdY;
  15.107 -                uint32_t tws;
  15.108 -                
  15.109 -                int32_t TdDdX, TdDdY;
  15.110 -                uint32_t tds;
  15.111 -                
  15.112 -                int16_t TdGdX, TdBdX, TdRdX, TdAdX;
  15.113 -                int16_t TdGdY, TdBdY, TdRdY, TdAdY;
  15.114 -                uint32_t tgs, tbs, trs, tas;
  15.115 -                                
  15.116 -                uint32_t TdXdY12;
  15.117 -                uint32_t txend12;
  15.118 -                uint32_t TdXdY01;
  15.119 -                uint32_t txend01;
  15.120 -                uint32_t TdXdY02;
  15.121 -                uint32_t txs;
  15.122 -                uint32_t tys;
  15.123 -                int ty01, ty12, tlr;
  15.124          } s3d;
  15.125          
  15.126 +        s3d_t s3d_tri;
  15.127 +
  15.128 +        s3d_t s3d_buffer[RB_SIZE];
  15.129 +        int s3d_read_idx, s3d_write_idx;
  15.130 +        int s3d_busy;
  15.131 +                
  15.132          struct
  15.133          {
  15.134                  uint32_t pri_ctrl;
  15.135 @@ -154,13 +181,13 @@
  15.136          } streams;
  15.137  } virge_t;
  15.138  
  15.139 +static void queue_triangle(virge_t *virge);
  15.140 +
  15.141  static void s3_virge_recalctimings(svga_t *svga);
  15.142  static void s3_virge_updatemapping(virge_t *virge);
  15.143  
  15.144  static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat);
  15.145  
  15.146 -static void s3_virge_triangle(virge_t *virge);
  15.147 -
  15.148  static uint8_t  s3_virge_mmio_read(uint32_t addr, void *p);
  15.149  static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p);
  15.150  static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p);
  15.151 @@ -598,7 +625,7 @@
  15.152  
  15.153  static uint8_t s3_virge_mmio_read(uint32_t addr, void *p)
  15.154  {
  15.155 -        reg_writes++;
  15.156 +        reg_reads++;
  15.157  //        pclog("New MMIO readb %08X\n", addr);
  15.158          switch (addr & 0xffff)
  15.159          {
  15.160 @@ -620,7 +647,7 @@
  15.161  }
  15.162  static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p)
  15.163  {
  15.164 -        reg_writes++;
  15.165 +        reg_reads++;
  15.166  //        pclog("New MMIO readw %08X\n", addr);
  15.167          switch (addr & 0xfffe)
  15.168          {
  15.169 @@ -633,7 +660,7 @@
  15.170  {
  15.171          virge_t *virge = (virge_t *)p;
  15.172          uint32_t ret = 0xffffffff;
  15.173 -        reg_writes++;
  15.174 +        reg_reads++;
  15.175  //        pclog("New MMIO readl %08X %04X(%08X):%08X  ", addr, CS, cs, pc);
  15.176          switch (addr & 0xfffc)
  15.177          {
  15.178 @@ -705,7 +732,11 @@
  15.179                  break;
  15.180                  
  15.181                  case 0x8504:
  15.182 -                ret = (0x10 << 8) | (1 << 13);
  15.183 +                if (virge->s3d_busy)
  15.184 +                        ret = (0x10 << 8);
  15.185 +                else
  15.186 +                        ret = (0x10 << 8) | (1 << 13);
  15.187 +//                pclog("Read status %04x %i\n", ret, virge->s3d_busy);
  15.188                  break;
  15.189                  case 0xa4d4:
  15.190                  ret = virge->s3d.src_base;
  15.191 @@ -756,7 +787,7 @@
  15.192                  default:
  15.193                  ret = s3_virge_mmio_read_w(addr, p) | (s3_virge_mmio_read_w(addr + 2, p) << 16);
  15.194          }
  15.195 -//        pclog("%02x\n", ret);
  15.196 +//        /*if ((addr & 0xfffc) != 0x8504) */pclog("%02x\n", ret);
  15.197          return ret;
  15.198  }
  15.199  static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p)
  15.200 @@ -856,11 +887,13 @@
  15.201                  virge->streams.blend_ctrl = val;
  15.202                  break;
  15.203                  case 0x81c0:
  15.204 +//                        pclog("Write pri_fb0 %08x\n", val);
  15.205                  virge->streams.pri_fb0 = val & 0x3fffff;
  15.206                  s3_virge_recalctimings(svga);
  15.207                  svga->fullchange = changeframecount;
  15.208                  break;
  15.209                  case 0x81c4:
  15.210 +//                        pclog("Write pri_fb1 %08x\n", val);
  15.211                  virge->streams.pri_fb1 = val & 0x3fffff;
  15.212                  s3_virge_recalctimings(svga);
  15.213                  svga->fullchange = changeframecount;
  15.214 @@ -871,9 +904,10 @@
  15.215                  svga->fullchange = changeframecount;
  15.216                  break;
  15.217                  case 0x81cc:
  15.218 -                        pclog("Write buffer_ctrl %08x\n", val);
  15.219 +//                        pclog("Write buffer_ctrl %08x\n", val);
  15.220                  virge->streams.buffer_ctrl = val;
  15.221                  s3_virge_recalctimings(svga);
  15.222 +                svga->fullchange = changeframecount;
  15.223                  break;
  15.224                  case 0x81d0:
  15.225                  virge->streams.sec_fb0 = val;
  15.226 @@ -991,22 +1025,21 @@
  15.227                  }
  15.228                  break;
  15.229  
  15.230 -
  15.231                  case 0xa4d4: case 0xa8d4:
  15.232                  virge->s3d.src_base = val & 0x3ffff8;
  15.233                  break;
  15.234 -                case 0xa4d8: case 0xa8d8: case 0xb4d8:
  15.235 +                case 0xa4d8: case 0xa8d8:
  15.236                  virge->s3d.dest_base = val & 0x3ffff8;
  15.237                  break;
  15.238 -                case 0xa4dc: case 0xa8dc: case 0xb4dc:
  15.239 +                case 0xa4dc: case 0xa8dc:
  15.240                  virge->s3d.clip_l = (val >> 16) & 0x7ff;
  15.241                  virge->s3d.clip_r = val & 0x7ff;
  15.242                  break;
  15.243 -                case 0xa4e0: case 0xa8e0: case 0xb4e0:
  15.244 +                case 0xa4e0: case 0xa8e0:
  15.245                  virge->s3d.clip_t = (val >> 16) & 0x7ff;
  15.246                  virge->s3d.clip_b = val & 0x7ff;
  15.247                  break;
  15.248 -                case 0xa4e4: case 0xa8e4: case 0xb4e4:
  15.249 +                case 0xa4e4: case 0xa8e4:
  15.250                  virge->s3d.dest_str = (val >> 16) & 0xff8;
  15.251                  virge->s3d.src_str = val & 0xff8;
  15.252                  break;
  15.253 @@ -1068,125 +1101,151 @@
  15.254                  break;
  15.255                  
  15.256                  case 0xb4d4:
  15.257 -                virge->s3d.z_base = val & 0x3ffff8;
  15.258 +                virge->s3d_tri.z_base = val & 0x3ffff8;
  15.259 +                break;
  15.260 +                case 0xb4d8:
  15.261 +                virge->s3d_tri.dest_base = val & 0x3ffff8;
  15.262 +                break;
  15.263 +                case 0xb4dc:
  15.264 +                virge->s3d_tri.clip_l = (val >> 16) & 0x7ff;
  15.265 +                virge->s3d_tri.clip_r = val & 0x7ff;
  15.266 +                break;
  15.267 +                case 0xb4e0:
  15.268 +                virge->s3d_tri.clip_t = (val >> 16) & 0x7ff;
  15.269 +                virge->s3d_tri.clip_b = val & 0x7ff;
  15.270 +                break;
  15.271 +                case 0xb4e4:
  15.272 +                virge->s3d_tri.dest_str = (val >> 16) & 0xff8;
  15.273 +                virge->s3d.src_str = val & 0xff8;
  15.274                  break;
  15.275                  case 0xb4e8:
  15.276 -                virge->s3d.z_str = val & 0xff8;
  15.277 +                virge->s3d_tri.z_str = val & 0xff8;
  15.278                  break;
  15.279                  case 0xb4ec:
  15.280 -                virge->s3d.tex_base = val & 0x3ffff8;
  15.281 +                virge->s3d_tri.tex_base = val & 0x3ffff8;
  15.282                  break;
  15.283                  case 0xb4f0:
  15.284 -                virge->s3d.tex_bdr_clr = val & 0xffffff;
  15.285 +                virge->s3d_tri.tex_bdr_clr = val & 0xffffff;
  15.286                  break;
  15.287                  case 0xb500:
  15.288 -                virge->s3d.cmd_set = val;
  15.289 +                virge->s3d_tri.cmd_set = val;
  15.290                  if (!(val & CMD_SET_AE))
  15.291 -                        s3_virge_triangle(virge);
  15.292 +                        queue_triangle(virge);
  15.293 +/*                {
  15.294 +                        thread_set_event(virge->wake_render_thread);
  15.295 +                        thread_wait_event(virge->wake_main_thread, -1);
  15.296 +                }                        */
  15.297 +//                        s3_virge_triangle(virge);
  15.298                  break;
  15.299                  case 0xb504:
  15.300 -                virge->s3d.tbv = val & 0xfffff;
  15.301 +                virge->s3d_tri.tbv = val & 0xfffff;
  15.302                  break;
  15.303                  case 0xb508:
  15.304 -                virge->s3d.tbu = val & 0xfffff;
  15.305 +                virge->s3d_tri.tbu = val & 0xfffff;
  15.306                  break;
  15.307                  case 0xb50c:
  15.308 -                virge->s3d.TdWdX = val;
  15.309 +                virge->s3d_tri.TdWdX = val;
  15.310                  break;
  15.311                  case 0xb510:
  15.312 -                virge->s3d.TdWdY = val;
  15.313 +                virge->s3d_tri.TdWdY = val;
  15.314                  break;
  15.315                  case 0xb514:
  15.316 -                virge->s3d.tws = val;
  15.317 +                virge->s3d_tri.tws = val;
  15.318                  break;
  15.319                  case 0xb518:
  15.320 -                virge->s3d.TdDdX = val;
  15.321 +                virge->s3d_tri.TdDdX = val;
  15.322                  break;
  15.323                  case 0xb51c:
  15.324 -                virge->s3d.TdVdX = val;
  15.325 +                virge->s3d_tri.TdVdX = val;
  15.326                  break;
  15.327                  case 0xb520:
  15.328 -                virge->s3d.TdUdX = val;
  15.329 +                virge->s3d_tri.TdUdX = val;
  15.330                  break;
  15.331                  case 0xb524:
  15.332 -                virge->s3d.TdDdY = val;
  15.333 +                virge->s3d_tri.TdDdY = val;
  15.334                  break;
  15.335                  case 0xb528:
  15.336 -                virge->s3d.TdVdY = val;
  15.337 +                virge->s3d_tri.TdVdY = val;
  15.338                  break;
  15.339                  case 0xb52c:
  15.340 -                virge->s3d.TdUdY = val;
  15.341 +                virge->s3d_tri.TdUdY = val;
  15.342                  break;
  15.343                  case 0xb530:
  15.344 -                virge->s3d.tds = val;
  15.345 +                virge->s3d_tri.tds = val;
  15.346                  break;
  15.347                  case 0xb534:
  15.348 -                virge->s3d.tvs = val;
  15.349 +                virge->s3d_tri.tvs = val;
  15.350                  break;
  15.351                  case 0xb538:
  15.352 -                virge->s3d.tus = val;
  15.353 +                virge->s3d_tri.tus = val;
  15.354                  break;
  15.355                  case 0xb53c:
  15.356 -                virge->s3d.TdGdX = val >> 16;
  15.357 -                virge->s3d.TdBdX = val & 0xffff;
  15.358 +                virge->s3d_tri.TdGdX = val >> 16;
  15.359 +                virge->s3d_tri.TdBdX = val & 0xffff;
  15.360                  break;
  15.361                  case 0xb540:
  15.362 -                virge->s3d.TdAdX = val >> 16;
  15.363 -                virge->s3d.TdRdX = val & 0xffff;
  15.364 +                virge->s3d_tri.TdAdX = val >> 16;
  15.365 +                virge->s3d_tri.TdRdX = val & 0xffff;
  15.366                  break;
  15.367                  case 0xb544:
  15.368 -                virge->s3d.TdGdY = val >> 16;
  15.369 -                virge->s3d.TdBdY = val & 0xffff;
  15.370 +                virge->s3d_tri.TdGdY = val >> 16;
  15.371 +                virge->s3d_tri.TdBdY = val & 0xffff;
  15.372                  break;
  15.373                  case 0xb548:
  15.374 -                virge->s3d.TdAdY = val >> 16;
  15.375 -                virge->s3d.TdRdY = val & 0xffff;
  15.376 +                virge->s3d_tri.TdAdY = val >> 16;
  15.377 +                virge->s3d_tri.TdRdY = val & 0xffff;
  15.378                  break;
  15.379                  case 0xb54c:
  15.380 -                virge->s3d.tgs = (val >> 16) & 0xffff;
  15.381 -                virge->s3d.tbs = val & 0xffff;
  15.382 +                virge->s3d_tri.tgs = (val >> 16) & 0xffff;
  15.383 +                virge->s3d_tri.tbs = val & 0xffff;
  15.384                  break;
  15.385                  case 0xb550:
  15.386 -                virge->s3d.tas = (val >> 16) & 0xffff;
  15.387 -                virge->s3d.trs = val & 0xffff;
  15.388 +                virge->s3d_tri.tas = (val >> 16) & 0xffff;
  15.389 +                virge->s3d_tri.trs = val & 0xffff;
  15.390                  break;
  15.391                  
  15.392                  case 0xb554:
  15.393 -                virge->s3d.TdZdX = val;
  15.394 +                virge->s3d_tri.TdZdX = val;
  15.395                  break;
  15.396                  case 0xb558:
  15.397 -                virge->s3d.TdZdY = val;
  15.398 +                virge->s3d_tri.TdZdY = val;
  15.399                  break;
  15.400                  case 0xb55c:
  15.401 -                virge->s3d.tzs = val;
  15.402 +                virge->s3d_tri.tzs = val;
  15.403                  break;
  15.404                  case 0xb560:
  15.405 -                virge->s3d.TdXdY12 = val;
  15.406 +                virge->s3d_tri.TdXdY12 = val;
  15.407                  break;
  15.408                  case 0xb564:
  15.409 -                virge->s3d.txend12 = val;
  15.410 +                virge->s3d_tri.txend12 = val;
  15.411                  break;
  15.412                  case 0xb568:
  15.413 -                virge->s3d.TdXdY01 = val;
  15.414 +                virge->s3d_tri.TdXdY01 = val;
  15.415                  break;
  15.416                  case 0xb56c:
  15.417 -                virge->s3d.txend01 = val;
  15.418 +                virge->s3d_tri.txend01 = val;
  15.419                  break;
  15.420                  case 0xb570:
  15.421 -                virge->s3d.TdXdY02 = val;
  15.422 +                virge->s3d_tri.TdXdY02 = val;
  15.423                  break;
  15.424                  case 0xb574:
  15.425 -                virge->s3d.txs = val;
  15.426 +                virge->s3d_tri.txs = val;
  15.427                  break;
  15.428                  case 0xb578:
  15.429 -                virge->s3d.tys = val;
  15.430 +                virge->s3d_tri.tys = val;
  15.431                  break;
  15.432                  case 0xb57c:
  15.433 -                virge->s3d.ty01 = (val >> 16) & 0x7ff;
  15.434 -                virge->s3d.ty12 = val & 0x7ff;
  15.435 -                virge->s3d.tlr = val >> 31;
  15.436 -                if (virge->s3d.cmd_set & CMD_SET_AE)
  15.437 -                        s3_virge_triangle(virge);
  15.438 +                virge->s3d_tri.ty01 = (val >> 16) & 0x7ff;
  15.439 +                virge->s3d_tri.ty12 = val & 0x7ff;
  15.440 +                virge->s3d_tri.tlr = val >> 31;
  15.441 +                if (virge->s3d_tri.cmd_set & CMD_SET_AE)
  15.442 +                        queue_triangle(virge);
  15.443 +/*                {
  15.444 +                        thread_set_event(virge->wake_render_thread);
  15.445 +                        thread_wait_event(virge->wake_main_thread, -1);
  15.446 +                }*/
  15.447 +
  15.448 +//                        s3_virge_triangle(virge);
  15.449                  break;
  15.450          }
  15.451  }
  15.452 @@ -1210,24 +1269,35 @@
  15.453  
  15.454  #define Z_READ(addr) *(uint16_t *)&vram[addr & 0x3fffff]
  15.455  
  15.456 -#define Z_WRITE(addr, val) if (!(virge->s3d.cmd_set & CMD_SET_ZB_MODE)) *(uint16_t *)&vram[addr & 0x3fffff] = val
  15.457 +#define Z_WRITE(addr, val) if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) *(uint16_t *)&vram[addr & 0x3fffff] = val
  15.458  
  15.459  #define CLIP(x, y)                                              \
  15.460          do                                                      \
  15.461          {                                                       \
  15.462 -                if ((virge->s3d.cmd_set & CMD_SET_HC) &&        \
  15.463 -                    (x < virge->s3d.clip_l ||                   \
  15.464 -                     x > virge->s3d.clip_r ||                   \
  15.465 -                     y < virge->s3d.clip_t ||                   \
  15.466 -                     y > virge->s3d.clip_b))                    \
  15.467 +                if ((virge->s3d.cmd_set & CMD_SET_HC) &&     \
  15.468 +                    (x < virge->s3d.clip_l ||                \
  15.469 +                     x > virge->s3d.clip_r ||                \
  15.470 +                     y < virge->s3d.clip_t ||                \
  15.471 +                     y > virge->s3d.clip_b))                 \
  15.472 +                        update = 0;                             \
  15.473 +        } while (0)
  15.474 +
  15.475 +#define CLIP_3D(x, y)                                           \
  15.476 +        do                                                      \
  15.477 +        {                                                       \
  15.478 +                if ((s3d_tri->cmd_set & CMD_SET_HC) &&        \
  15.479 +                    (x < s3d_tri->clip_l ||                   \
  15.480 +                     x > s3d_tri->clip_r ||                   \
  15.481 +                     y < s3d_tri->clip_t ||                   \
  15.482 +                     y > s3d_tri->clip_b))                    \
  15.483                          update = 0;                             \
  15.484          } while (0)
  15.485  
  15.486  #define Z_CLIP(Zzb, Zs)                                                 \
  15.487          do                                                              \
  15.488          {                                                               \
  15.489 -                if (!(virge->s3d.cmd_set & CMD_SET_ZB_MODE))            \
  15.490 -                switch ((virge->s3d.cmd_set >> 20) & 7)                 \
  15.491 +                if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE))            \
  15.492 +                switch ((s3d_tri->cmd_set >> 20) & 7)                 \
  15.493                  {                                                       \
  15.494                          case 0: update = 0; break;                      \
  15.495                          case 1: if (Zs <= Zzb) update = 0; else Zzb = Zs; break;       \
  15.496 @@ -2208,51 +2278,53 @@
  15.497                  state->dest_rgba.a = a;
  15.498  }
  15.499  
  15.500 -static void tri(virge_t *virge, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2)
  15.501 +static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2)
  15.502  {
  15.503          uint8_t *vram = virge->svga.vram;
  15.504  
  15.505 -        int x_dir = virge->s3d.tlr ? 1 : -1;
  15.506 +        int x_dir = s3d_tri->tlr ? 1 : -1;
  15.507          
  15.508 -        int use_z = !(virge->s3d.cmd_set & CMD_SET_ZB_MODE);
  15.509 +        int use_z = !(s3d_tri->cmd_set & CMD_SET_ZB_MODE);
  15.510  
  15.511          int y_count = yc;
  15.512          
  15.513 -        int bpp = (virge->s3d.cmd_set >> 2) & 7;
  15.514 +        int bpp = (s3d_tri->cmd_set >> 2) & 7;
  15.515          
  15.516          uint32_t dest_offset, z_offset;
  15.517  
  15.518 -        if (virge->s3d.cmd_set & CMD_SET_HC)
  15.519 +        if (s3d_tri->cmd_set & CMD_SET_HC)
  15.520          {
  15.521 -                if (state->y < virge->s3d.clip_t)
  15.522 +                if (state->y < s3d_tri->clip_t)
  15.523                          return;
  15.524 -                if (state->y > virge->s3d.clip_b)
  15.525 +                if (state->y > s3d_tri->clip_b)
  15.526                  {
  15.527 -                        int diff_y = state->y - virge->s3d.clip_b;
  15.528 +                        int diff_y = state->y - s3d_tri->clip_b;
  15.529                          
  15.530                          if (diff_y > y_count)
  15.531                                  diff_y = y_count;
  15.532                          
  15.533 -                        state->base_u += (virge->s3d.TdUdY * diff_y);
  15.534 -                        state->base_v += (virge->s3d.TdVdY * diff_y);
  15.535 -                        state->base_z += (virge->s3d.TdZdY * diff_y);
  15.536 -                        state->base_r += (virge->s3d.TdRdY * diff_y);
  15.537 -                        state->base_g += (virge->s3d.TdGdY * diff_y);
  15.538 -                        state->base_b += (virge->s3d.TdBdY * diff_y);
  15.539 -                        state->base_a += (virge->s3d.TdAdY * diff_y);
  15.540 -                        state->base_d += (virge->s3d.TdDdY * diff_y);
  15.541 -                        state->base_w += (virge->s3d.TdWdY * diff_y);
  15.542 +                        state->base_u += (s3d_tri->TdUdY * diff_y);
  15.543 +                        state->base_v += (s3d_tri->TdVdY * diff_y);
  15.544 +                        state->base_z += (s3d_tri->TdZdY * diff_y);
  15.545 +                        state->base_r += (s3d_tri->TdRdY * diff_y);
  15.546 +                        state->base_g += (s3d_tri->TdGdY * diff_y);
  15.547 +                        state->base_b += (s3d_tri->TdBdY * diff_y);
  15.548 +                        state->base_a += (s3d_tri->TdAdY * diff_y);
  15.549 +                        state->base_d += (s3d_tri->TdDdY * diff_y);
  15.550 +                        state->base_w += (s3d_tri->TdWdY * diff_y);
  15.551                          state->x1 += (dx1 * diff_y);
  15.552                          state->x2 += (dx2 * diff_y);
  15.553                          state->y -= diff_y;
  15.554 -                        dest_offset -= virge->s3d.dest_str;
  15.555 -                        z_offset -= virge->s3d.z_str;
  15.556 +                        dest_offset -= s3d_tri->dest_str;
  15.557 +                        z_offset -= s3d_tri->z_str;
  15.558                          y_count -= diff_y;
  15.559                  }
  15.560 +                if ((state->y - y_count) < s3d_tri->clip_t)
  15.561 +                        y_count = state->y - s3d_tri->clip_t;
  15.562          }
  15.563  
  15.564 -        dest_offset = virge->s3d.dest_base + (state->y * virge->s3d.dest_str);
  15.565 -        z_offset = virge->s3d.z_base + (state->y * virge->s3d.z_str);
  15.566 +        dest_offset = s3d_tri->dest_base + (state->y * s3d_tri->dest_str);
  15.567 +        z_offset = s3d_tri->z_base + (state->y * s3d_tri->z_str);
  15.568          
  15.569          for (; y_count > 0; y_count--)
  15.570          {
  15.571 @@ -2273,68 +2345,68 @@
  15.572                          int xz_offset = x_dir << 1;
  15.573                          if (x_dir > 0)
  15.574                                  dx += 1;
  15.575 -                        state->r = state->base_r + ((virge->s3d.TdRdX * dx) >> 5);
  15.576 -                        state->g = state->base_g + ((virge->s3d.TdGdX * dx) >> 5);
  15.577 -                        state->b = state->base_b + ((virge->s3d.TdBdX * dx) >> 5);
  15.578 -                        state->a = state->base_a + ((virge->s3d.TdAdX * dx) >> 5);
  15.579 -                        state->u = state->base_u + ((virge->s3d.TdUdX * dx) >> 5);
  15.580 -                        state->v = state->base_v + ((virge->s3d.TdVdX * dx) >> 5);
  15.581 -                        state->w = state->base_w + ((virge->s3d.TdWdX * dx) >> 5);
  15.582 -                        state->d = state->base_d + ((virge->s3d.TdDdX * dx) >> 5);
  15.583 -                        z += ((virge->s3d.TdZdX * dx) >> 5);
  15.584 +                        state->r = state->base_r + ((s3d_tri->TdRdX * dx) >> 5);
  15.585 +                        state->g = state->base_g + ((s3d_tri->TdGdX * dx) >> 5);
  15.586 +                        state->b = state->base_b + ((s3d_tri->TdBdX * dx) >> 5);
  15.587 +                        state->a = state->base_a + ((s3d_tri->TdAdX * dx) >> 5);
  15.588 +                        state->u = state->base_u + ((s3d_tri->TdUdX * dx) >> 5);
  15.589 +                        state->v = state->base_v + ((s3d_tri->TdVdX * dx) >> 5);
  15.590 +                        state->w = state->base_w + ((s3d_tri->TdWdX * dx) >> 5);
  15.591 +                        state->d = state->base_d + ((s3d_tri->TdDdX * dx) >> 5);
  15.592 +                        z += ((s3d_tri->TdZdX * dx) >> 5);
  15.593  
  15.594  //                        pclog("Draw Y=%i X=%i to XE=%i  %i   %08x %08x %08x %08x  %08x %08x %08x %08x  %i %08x\n", state->y, x, xe, dx, state->x1, state->x2, dx1, virge->s3d.TdWdX, state->u, state->v, virge->s3d.TdUdX, virge->s3d.TdUdY, dx, (virge->s3d.TdUdX * dx) >> 4);
  15.595  
  15.596 -                        if (virge->s3d.cmd_set & CMD_SET_HC)
  15.597 +                        if (s3d_tri->cmd_set & CMD_SET_HC)
  15.598                          {
  15.599                                  if (x_dir > 0)
  15.600                                  {
  15.601 -                                        if (x > virge->s3d.clip_r)
  15.602 +                                        if (x > s3d_tri->clip_r)
  15.603                                                  goto tri_skip_line;
  15.604 -                                        if (xe < virge->s3d.clip_l)
  15.605 +                                        if (xe < s3d_tri->clip_l)
  15.606                                                  goto tri_skip_line;
  15.607 -                                        if (xe > virge->s3d.clip_r)
  15.608 -                                                xe = virge->s3d.clip_r;
  15.609 -                                        if (x < virge->s3d.clip_l)
  15.610 +                                        if (xe > s3d_tri->clip_r)
  15.611 +                                                xe = s3d_tri->clip_r;
  15.612 +                                        if (x < s3d_tri->clip_l)
  15.613                                          {
  15.614 -                                                int diff_x = virge->s3d.clip_l - x;
  15.615 +                                                int diff_x = s3d_tri->clip_l - x;
  15.616                                                  
  15.617 -                                                z += (virge->s3d.TdZdX * diff_x);
  15.618 -                                                state->u += (virge->s3d.TdUdX * diff_x);
  15.619 -                                                state->v += (virge->s3d.TdVdX * diff_x);
  15.620 -                                                state->r += (virge->s3d.TdRdX * diff_x);
  15.621 -                                                state->g += (virge->s3d.TdGdX * diff_x);
  15.622 -                                                state->b += (virge->s3d.TdBdX * diff_x);
  15.623 -                                                state->a += (virge->s3d.TdAdX * diff_x);
  15.624 -                                                state->d += (virge->s3d.TdDdX * diff_x);
  15.625 -                                                state->w += (virge->s3d.TdWdX * diff_x);
  15.626 +                                                z += (s3d_tri->TdZdX * diff_x);
  15.627 +                                                state->u += (s3d_tri->TdUdX * diff_x);
  15.628 +                                                state->v += (s3d_tri->TdVdX * diff_x);
  15.629 +                                                state->r += (s3d_tri->TdRdX * diff_x);
  15.630 +                                                state->g += (s3d_tri->TdGdX * diff_x);
  15.631 +                                                state->b += (s3d_tri->TdBdX * diff_x);
  15.632 +                                                state->a += (s3d_tri->TdAdX * diff_x);
  15.633 +                                                state->d += (s3d_tri->TdDdX * diff_x);
  15.634 +                                                state->w += (s3d_tri->TdWdX * diff_x);
  15.635                                                  
  15.636 -                                                x = virge->s3d.clip_l;
  15.637 +                                                x = s3d_tri->clip_l;
  15.638                                          }
  15.639                                  }
  15.640                                  else
  15.641                                  {
  15.642 -                                        if (x < virge->s3d.clip_l)
  15.643 +                                        if (x < s3d_tri->clip_l)
  15.644                                                  goto tri_skip_line;
  15.645 -                                        if (xe > virge->s3d.clip_r)
  15.646 +                                        if (xe > s3d_tri->clip_r)
  15.647                                                  goto tri_skip_line;
  15.648 -                                        if (xe < virge->s3d.clip_l)
  15.649 -                                                xe = virge->s3d.clip_l;
  15.650 -                                        if (x > virge->s3d.clip_r)
  15.651 +                                        if (xe < s3d_tri->clip_l)
  15.652 +                                                xe = s3d_tri->clip_l;
  15.653 +                                        if (x > s3d_tri->clip_r)
  15.654                                          {
  15.655 -                                                int diff_x = x - virge->s3d.clip_r;
  15.656 +                                                int diff_x = x - s3d_tri->clip_r;
  15.657                                                  
  15.658 -                                                z += (virge->s3d.TdZdX * diff_x);
  15.659 -                                                state->u += (virge->s3d.TdUdX * diff_x);
  15.660 -                                                state->v += (virge->s3d.TdVdX * diff_x);
  15.661 -                                                state->r += (virge->s3d.TdRdX * diff_x);
  15.662 -                                                state->g += (virge->s3d.TdGdX * diff_x);
  15.663 -                                                state->b += (virge->s3d.TdBdX * diff_x);
  15.664 -                                                state->a += (virge->s3d.TdAdX * diff_x);
  15.665 -                                                state->d += (virge->s3d.TdDdX * diff_x);
  15.666 -                                                state->w += (virge->s3d.TdWdX * diff_x);
  15.667 +                                                z += (s3d_tri->TdZdX * diff_x);
  15.668 +                                                state->u += (s3d_tri->TdUdX * diff_x);
  15.669 +                                                state->v += (s3d_tri->TdVdX * diff_x);
  15.670 +                                                state->r += (s3d_tri->TdRdX * diff_x);
  15.671 +                                                state->g += (s3d_tri->TdGdX * diff_x);
  15.672 +                                                state->b += (s3d_tri->TdBdX * diff_x);
  15.673 +                                                state->a += (s3d_tri->TdAdX * diff_x);
  15.674 +                                                state->d += (s3d_tri->TdDdX * diff_x);
  15.675 +                                                state->w += (s3d_tri->TdWdX * diff_x);
  15.676                                                  
  15.677 -                                                x = virge->s3d.clip_r;
  15.678 +                                                x = s3d_tri->clip_r;
  15.679                                          }
  15.680                                  }
  15.681                          }
  15.682 @@ -2362,7 +2434,7 @@
  15.683  
  15.684                                          dest_pixel(state);
  15.685  
  15.686 -                                        if (virge->s3d.cmd_set & CMD_SET_ABC_ENABLE)
  15.687 +                                        if (s3d_tri->cmd_set & CMD_SET_ABC_ENABLE)
  15.688                                          {
  15.689                                                  uint32_t src_col;
  15.690                                                  int src_r, src_g, src_b;
  15.691 @@ -2404,19 +2476,19 @@
  15.692                                                  break;
  15.693                                          }
  15.694  
  15.695 -                                        if (use_z && (virge->s3d.cmd_set & CMD_SET_ZUP))
  15.696 +                                        if (use_z && (s3d_tri->cmd_set & CMD_SET_ZUP))
  15.697                                                  Z_WRITE(z_addr, src_z);
  15.698                                  }
  15.699  
  15.700 -                                z += virge->s3d.TdZdX;
  15.701 -                                state->u += virge->s3d.TdUdX;
  15.702 -                                state->v += virge->s3d.TdVdX;
  15.703 -                                state->r += virge->s3d.TdRdX;
  15.704 -                                state->g += virge->s3d.TdGdX;
  15.705 -                                state->b += virge->s3d.TdBdX;
  15.706 -                                state->a += virge->s3d.TdAdX;
  15.707 -                                state->d += virge->s3d.TdDdX;
  15.708 -                                state->w += virge->s3d.TdWdX;
  15.709 +                                z += s3d_tri->TdZdX;
  15.710 +                                state->u += s3d_tri->TdUdX;
  15.711 +                                state->v += s3d_tri->TdVdX;
  15.712 +                                state->r += s3d_tri->TdRdX;
  15.713 +                                state->g += s3d_tri->TdGdX;
  15.714 +                                state->b += s3d_tri->TdBdX;
  15.715 +                                state->a += s3d_tri->TdAdX;
  15.716 +                                state->d += s3d_tri->TdDdX;
  15.717 +                                state->w += s3d_tri->TdWdX;
  15.718                                  dest_addr += x_offset;
  15.719                                  z_addr += xz_offset;
  15.720                                  virge->pixel_count++;
  15.721 @@ -2425,18 +2497,18 @@
  15.722  tri_skip_line:
  15.723                  state->x1 += dx1;
  15.724                  state->x2 += dx2;
  15.725 -                state->base_u += virge->s3d.TdUdY;
  15.726 -                state->base_v += virge->s3d.TdVdY;
  15.727 -                state->base_z += virge->s3d.TdZdY;
  15.728 -                state->base_r += virge->s3d.TdRdY;
  15.729 -                state->base_g += virge->s3d.TdGdY;
  15.730 -                state->base_b += virge->s3d.TdBdY;
  15.731 -                state->base_a += virge->s3d.TdAdY;
  15.732 -                state->base_d += virge->s3d.TdDdY;
  15.733 -                state->base_w += virge->s3d.TdWdY;
  15.734 +                state->base_u += s3d_tri->TdUdY;
  15.735 +                state->base_v += s3d_tri->TdVdY;
  15.736 +                state->base_z += s3d_tri->TdZdY;
  15.737 +                state->base_r += s3d_tri->TdRdY;
  15.738 +                state->base_g += s3d_tri->TdGdY;
  15.739 +                state->base_b += s3d_tri->TdBdY;
  15.740 +                state->base_a += s3d_tri->TdAdY;
  15.741 +                state->base_d += s3d_tri->TdDdY;
  15.742 +                state->base_w += s3d_tri->TdWdY;
  15.743                  state->y--;
  15.744 -                dest_offset -= virge->s3d.dest_str;
  15.745 -                z_offset -= virge->s3d.z_str;
  15.746 +                dest_offset -= s3d_tri->dest_str;
  15.747 +                z_offset -= s3d_tri->z_str;
  15.748          }
  15.749  }
  15.750  
  15.751 @@ -2452,7 +2524,7 @@
  15.752          1*2
  15.753  };
  15.754  
  15.755 -static void s3_virge_triangle(virge_t *virge)
  15.756 +static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri)
  15.757  {
  15.758          s3d_state_t state;
  15.759  
  15.760 @@ -2462,34 +2534,34 @@
  15.761          uint64_t start_time = timer_read();
  15.762          uint64_t end_time;
  15.763  
  15.764 -        state.tbu = virge->s3d.tbu << 11;
  15.765 -        state.tbv = virge->s3d.tbv << 11;
  15.766 +        state.tbu = s3d_tri->tbu << 11;
  15.767 +        state.tbv = s3d_tri->tbv << 11;
  15.768          
  15.769 -        state.max_d = (virge->s3d.cmd_set >> 8) & 15;
  15.770 +        state.max_d = (s3d_tri->cmd_set >> 8) & 15;
  15.771          
  15.772 -        state.tex_bdr_clr = virge->s3d.tex_bdr_clr;
  15.773 +        state.tex_bdr_clr = s3d_tri->tex_bdr_clr;
  15.774          
  15.775 -        state.cmd_set = virge->s3d.cmd_set;
  15.776 +        state.cmd_set = s3d_tri->cmd_set;
  15.777  
  15.778 -        state.base_u = virge->s3d.tus;
  15.779 -        state.base_v = virge->s3d.tvs;
  15.780 -        state.base_z = virge->s3d.tzs;
  15.781 -        state.base_r = (int32_t)virge->s3d.trs;
  15.782 -        state.base_g = (int32_t)virge->s3d.tgs;
  15.783 -        state.base_b = (int32_t)virge->s3d.tbs;
  15.784 -        state.base_a = (int32_t)virge->s3d.tas;
  15.785 -        state.base_d = virge->s3d.tds;
  15.786 -        state.base_w = virge->s3d.tws;
  15.787 +        state.base_u = s3d_tri->tus;
  15.788 +        state.base_v = s3d_tri->tvs;
  15.789 +        state.base_z = s3d_tri->tzs;
  15.790 +        state.base_r = (int32_t)s3d_tri->trs;
  15.791 +        state.base_g = (int32_t)s3d_tri->tgs;
  15.792 +        state.base_b = (int32_t)s3d_tri->tbs;
  15.793 +        state.base_a = (int32_t)s3d_tri->tas;
  15.794 +        state.base_d = s3d_tri->tds;
  15.795 +        state.base_w = s3d_tri->tws;
  15.796          
  15.797 -        tex_base = virge->s3d.tex_base;
  15.798 +        tex_base = s3d_tri->tex_base;
  15.799          for (c = 9; c >= 0; c--)
  15.800          {
  15.801                  state.texture[c] = (uint16_t *)&virge->svga.vram[tex_base];
  15.802                  if (c <= state.max_d)
  15.803 -                        tex_base += ((1 << (c*2)) * tex_size[(virge->s3d.cmd_set >> 5) & 7]) / 2;
  15.804 +                        tex_base += ((1 << (c*2)) * tex_size[(s3d_tri->cmd_set >> 5) & 7]) / 2;
  15.805          }
  15.806  
  15.807 -        switch ((virge->s3d.cmd_set >> 27) & 0xf)
  15.808 +        switch ((s3d_tri->cmd_set >> 27) & 0xf)
  15.809          {
  15.810                  case 0:
  15.811                  dest_pixel = dest_pixel_gouraud_shaded_triangle;
  15.812 @@ -2497,7 +2569,7 @@
  15.813                  break;
  15.814                  case 1:
  15.815                  case 5:
  15.816 -                switch ((virge->s3d.cmd_set >> 15) & 0x3)
  15.817 +                switch ((s3d_tri->cmd_set >> 15) & 0x3)
  15.818                  {
  15.819                          case 0:
  15.820                          dest_pixel = dest_pixel_lit_texture_reflection;
  15.821 @@ -2512,7 +2584,7 @@
  15.822  //                        pclog("dest_pixel_lit_texture_decal\n");
  15.823                          break;
  15.824                          default:
  15.825 -                        pclog("bad triangle type %x\n", (virge->s3d.cmd_set >> 27) & 0xf);
  15.826 +                        pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf);
  15.827                          return;
  15.828                  }
  15.829                  break;
  15.830 @@ -2522,11 +2594,11 @@
  15.831  //                pclog("dest_pixel_unlit_texture_triangle\n");
  15.832                  break;
  15.833                  default:
  15.834 -                pclog("bad triangle type %x\n", (virge->s3d.cmd_set >> 27) & 0xf);
  15.835 +                pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf);
  15.836                  return;
  15.837          }        
  15.838          
  15.839 -        switch (((virge->s3d.cmd_set >> 12) & 7) | ((virge->s3d.cmd_set & (1 << 29)) ? 8 : 0))
  15.840 +        switch (((s3d_tri->cmd_set >> 12) & 7) | ((s3d_tri->cmd_set & (1 << 29)) ? 8 : 0))
  15.841          {
  15.842                  case 0: case 1:
  15.843                  tex_sample = tex_sample_mipmap;
  15.844 @@ -2574,33 +2646,33 @@
  15.845                  break;
  15.846          }
  15.847          
  15.848 -        switch ((virge->s3d.cmd_set >> 5) & 7)
  15.849 +        switch ((s3d_tri->cmd_set >> 5) & 7)
  15.850          {
  15.851                  case 0:
  15.852 -                tex_read = (virge->s3d.cmd_set & CMD_SET_TWE) ? tex_ARGB8888 : tex_ARGB8888_nowrap;
  15.853 +                tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB8888 : tex_ARGB8888_nowrap;
  15.854                  break;
  15.855                  case 1:
  15.856 -                tex_read = (virge->s3d.cmd_set & CMD_SET_TWE) ? tex_ARGB4444 : tex_ARGB4444_nowrap;
  15.857 +                tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB4444 : tex_ARGB4444_nowrap;
  15.858  //                pclog("tex_ARGB4444\n");
  15.859                  break;
  15.860                  case 2:
  15.861 -                tex_read = (virge->s3d.cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap;
  15.862 -//                pclog("tex_ARGB1555 %i\n", (virge->s3d.cmd_set >> 5) & 7);
  15.863 +                tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap;
  15.864 +//                pclog("tex_ARGB1555 %i\n", (s3d_tri->cmd_set >> 5) & 7);
  15.865                  break;
  15.866                  default:
  15.867 -                pclog("bad texture type %i\n", (virge->s3d.cmd_set >> 5) & 7);
  15.868 -                tex_read = (virge->s3d.cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap;
  15.869 +                pclog("bad texture type %i\n", (s3d_tri->cmd_set >> 5) & 7);
  15.870 +                tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap;
  15.871                  break;
  15.872          }
  15.873          
  15.874 -//        pclog("Triangle %i %i,%i to %i,%i  %08x\n", y, x1 >> 20, y, virge->s3d.txend01 >> 20, y - (virge->s3d.ty01 + virge->s3d.ty12), state.cmd_set);
  15.875 +//        pclog("Triangle %i %i,%i to %i,%i  %08x\n", y, x1 >> 20, y, s3d_tri->txend01 >> 20, y - (s3d_tri->ty01 + s3d_tri->ty12), state.cmd_set);
  15.876  
  15.877 -        state.y  = virge->s3d.tys;
  15.878 -        state.x1 = virge->s3d.txs;
  15.879 -        state.x2 = virge->s3d.txend01;
  15.880 -        tri(virge, &state, virge->s3d.ty01, virge->s3d.TdXdY02, virge->s3d.TdXdY01);
  15.881 -        state.x2 = virge->s3d.txend12;
  15.882 -        tri(virge, &state, virge->s3d.ty12, virge->s3d.TdXdY02, virge->s3d.TdXdY12);
  15.883 +        state.y  = s3d_tri->tys;
  15.884 +        state.x1 = s3d_tri->txs;
  15.885 +        state.x2 = s3d_tri->txend01;
  15.886 +        tri(virge, s3d_tri, &state, s3d_tri->ty01, s3d_tri->TdXdY02, s3d_tri->TdXdY01);
  15.887 +        state.x2 = s3d_tri->txend12;
  15.888 +        tri(virge, s3d_tri, &state, s3d_tri->ty12, s3d_tri->TdXdY02, s3d_tri->TdXdY12);
  15.889  
  15.890          virge->tri_count++;
  15.891  
  15.892 @@ -2609,6 +2681,43 @@
  15.893          virge_time += end_time - start_time;
  15.894  }
  15.895  
  15.896 +static void render_thread(void *param)
  15.897 +{
  15.898 +        virge_t *virge = (virge_t *)param;
  15.899 +        
  15.900 +        while (1)
  15.901 +        {
  15.902 +                thread_wait_event(virge->wake_render_thread, -1);
  15.903 +                thread_reset_event(virge->wake_render_thread);
  15.904 +                virge->s3d_busy = 1;
  15.905 +                while (!RB_EMPTY)
  15.906 +                {
  15.907 +                        s3_virge_triangle(virge, &virge->s3d_buffer[virge->s3d_read_idx & RB_MASK]);
  15.908 +                        virge->s3d_read_idx++;
  15.909 +                        
  15.910 +                        if (RB_ENTRIES == RB_SIZE - 1)
  15.911 +                                thread_set_event(virge->not_full_event);
  15.912 +                }
  15.913 +                virge->s3d_busy = 0;
  15.914 +        }
  15.915 +}
  15.916 +
  15.917 +static void queue_triangle(virge_t *virge)
  15.918 +{
  15.919 +        int c;
  15.920 +//        pclog("queue_triangle: read=%i write=%i RB_ENTRIES=%i RB_FULL=%i\n", virge->s3d_read_idx, virge->s3d_write_idx, RB_ENTRIES, RB_FULL);
  15.921 +        if (RB_FULL)
  15.922 +        {
  15.923 +                thread_reset_event(virge->not_full_event);
  15.924 +                if (RB_FULL)
  15.925 +                        thread_wait_event(virge->not_full_event, -1); /*Wait for room in ringbuffer*/
  15.926 +        }
  15.927 +//        pclog("                add at read=%i write=%i %i\n", virge->s3d_read_idx, virge->s3d_write_idx, virge->s3d_write_idx & RB_MASK);
  15.928 +        virge->s3d_buffer[virge->s3d_write_idx & RB_MASK] = virge->s3d_tri;
  15.929 +        virge->s3d_write_idx++;
  15.930 +        if (!virge->s3d_busy)
  15.931 +                thread_set_event(virge->wake_render_thread); /*Wake up render thread if moving from idle*/
  15.932 +}
  15.933  
  15.934  static void s3_virge_hwcursor_draw(svga_t *svga, int displine)
  15.935  {
  15.936 @@ -3098,6 +3207,11 @@
  15.937          virge->is_375 = 0;
  15.938          
  15.939          pci_add(s3_virge_pci_read, s3_virge_pci_write, virge);
  15.940 +        
  15.941 +        virge->wake_render_thread = thread_create_event();
  15.942 +        virge->wake_main_thread = thread_create_event();
  15.943 +        virge->not_full_event = thread_create_event();
  15.944 +        virge->render_thread = thread_create(render_thread, virge);
  15.945   
  15.946          return virge;
  15.947  }
  15.948 @@ -3186,6 +3300,11 @@
  15.949          
  15.950          pci_add(s3_virge_pci_read, s3_virge_pci_write, virge);
  15.951   
  15.952 +        virge->wake_render_thread = thread_create_event();
  15.953 +        virge->wake_main_thread = thread_create_event();
  15.954 +        virge->not_full_event = thread_create_event();
  15.955 +        virge->render_thread = thread_create(render_thread, virge);
  15.956 + 
  15.957          return virge;
  15.958  }
  15.959  
  15.960 @@ -3196,6 +3315,11 @@
  15.961          fwrite(virge->svga.vram, 4 << 20, 1, f);
  15.962          fclose(f);
  15.963  
  15.964 +        thread_kill(virge->render_thread);
  15.965 +        thread_destroy_event(virge->not_full_event);
  15.966 +        thread_destroy_event(virge->wake_main_thread);
  15.967 +        thread_destroy_event(virge->wake_render_thread);
  15.968 +        
  15.969          svga_close(&virge->svga);
  15.970          
  15.971          free(virge);
  15.972 @@ -3225,12 +3349,10 @@
  15.973          virge->svga.fullchange = changeframecount;
  15.974  }
  15.975  
  15.976 -static int s3_virge_add_status_info(char *s, int max_len, void *p)
  15.977 +static void s3_virge_add_status_info(char *s, int max_len, void *p)
  15.978  {
  15.979          virge_t *virge = (virge_t *)p;
  15.980 -        int cur_len;
  15.981          char temps[256];
  15.982 -
  15.983          uint64_t new_time = timer_read();
  15.984          uint64_t status_diff = new_time - status_time;
  15.985          status_time = new_time;
  15.986 @@ -3238,15 +3360,14 @@
  15.987          if (!status_diff)
  15.988                  status_diff = 1;
  15.989  
  15.990 -        cur_len = svga_add_status_info(s, cur_len, &virge->svga);
  15.991 -        sprintf(temps, "%f Mpixels/sec\n%f ktris/sec\n%f%% CPU\n%f%% CPU (real)\n%d writes", (double)virge->pixel_count/1000000.0, (double)virge->tri_count/1000.0, ((double)virge_time * 100.0) / timer_freq, ((double)virge_time * 100.0) / status_diff, reg_writes);
  15.992 -        strncat(s, temps, cur_len);
  15.993 -        cur_len -= strlen(temps);
  15.994 +        svga_add_status_info(s, max_len, &virge->svga);
  15.995 +        sprintf(temps, "%f Mpixels/sec\n%f ktris/sec\n%f%% CPU\n%f%% CPU (real)\n%d writes %i reads\n\n", (double)virge->pixel_count/1000000.0, (double)virge->tri_count/1000.0, ((double)virge_time * 100.0) / timer_freq, ((double)virge_time * 100.0) / status_diff, reg_writes, reg_reads);
  15.996 +        strncat(s, temps, max_len);
  15.997 +
  15.998          virge->pixel_count = virge->tri_count = 0;
  15.999          virge_time = 0;
 15.1000 +        reg_reads = 0;
 15.1001          reg_writes = 0;
 15.1002 -        
 15.1003 -        return max_len - cur_len;
 15.1004  }
 15.1005  
 15.1006  static device_config_t s3_virge_config[] =
    16.1 --- a/src/vid_svga.c	Wed Jul 16 20:44:29 2014 +0100
    16.2 +++ b/src/vid_svga.c	Tue Jul 22 21:10:39 2014 +0100
    16.3 @@ -1181,8 +1181,6 @@
    16.4  void svga_writew(uint32_t addr, uint16_t val, void *p)
    16.5  {
    16.6          svga_t *svga = (svga_t *)p;
    16.7 -        if (!svga)
    16.8 -                exit(-1);
    16.9          if (!svga->fast)
   16.10          {
   16.11                  svga_write(addr, val, p);
   16.12 @@ -1363,30 +1361,23 @@
   16.13  }
   16.14  
   16.15  
   16.16 -int svga_add_status_info(char *s, int max_len, void *p)
   16.17 +void svga_add_status_info(char *s, int max_len, void *p)
   16.18  {
   16.19          svga_t *svga = (svga_t *)p;
   16.20          char temps[128];
   16.21 -        int cur_len = max_len;
   16.22          
   16.23          if (svga->chain4) strcpy(temps, "SVGA chained (possibly mode 13h)\n");
   16.24          else              strcpy(temps, "SVGA unchained (possibly mode-X)\n");
   16.25 -        strncat(s, temps, cur_len);
   16.26 -        cur_len -= strlen(temps);
   16.27 +        strncat(s, temps, max_len);
   16.28  
   16.29          if (!svga->video_bpp) strcpy(temps, "SVGA in text mode\n");
   16.30          else                  sprintf(temps, "SVGA colour depth : %i bpp\n", svga->video_bpp);
   16.31 -        strncat(s, temps, cur_len);
   16.32 -        cur_len -= strlen(temps);
   16.33 +        strncat(s, temps, max_len);
   16.34          
   16.35          sprintf(temps, "SVGA resolution : %i x %i\n", svga->video_res_x, svga->video_res_y);
   16.36 -        strncat(s, temps, cur_len);
   16.37 -        cur_len -= strlen(temps);
   16.38 +        strncat(s, temps, max_len);
   16.39          
   16.40          sprintf(temps, "SVGA refresh rate : %i Hz\n\n", svga->frames);
   16.41          svga->frames = 0;
   16.42 -        strncat(s, temps, cur_len);
   16.43 -        cur_len -= strlen(temps);
   16.44 -        
   16.45 -        return max_len - cur_len;
   16.46 +        strncat(s, temps, max_len);
   16.47  }
    17.1 --- a/src/vid_svga.h	Wed Jul 16 20:44:29 2014 +0100
    17.2 +++ b/src/vid_svga.h	Tue Jul 22 21:10:39 2014 +0100
    17.3 @@ -128,7 +128,7 @@
    17.4  void     svga_writew_linear(uint32_t addr, uint16_t val, void *p);
    17.5  void     svga_writel_linear(uint32_t addr, uint32_t val, void *p);
    17.6  
    17.7 -int svga_add_status_info(char *s, int max_len, void *p);
    17.8 +void svga_add_status_info(char *s, int max_len, void *p);
    17.9  
   17.10  extern uint8_t svga_rotate[8][256];
   17.11  
    18.1 --- a/src/vid_tgui9440.c	Wed Jul 16 20:44:29 2014 +0100
    18.2 +++ b/src/vid_tgui9440.c	Tue Jul 22 21:10:39 2014 +0100
    18.3 @@ -1111,11 +1111,11 @@
    18.4  	tgui_accel_command(32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24), tgui);
    18.5  }
    18.6  
    18.7 -int tgui_add_status_info(char *s, int max_len, void *p)
    18.8 +void tgui_add_status_info(char *s, int max_len, void *p)
    18.9  {
   18.10          tgui_t *tgui = (tgui_t *)p;
   18.11          
   18.12 -        return svga_add_status_info(s, max_len, &tgui->svga);
   18.13 +        svga_add_status_info(s, max_len, &tgui->svga);
   18.14  }
   18.15  
   18.16  static device_config_t tgui9440_config[] =
    19.1 --- a/src/vid_tvga.c	Wed Jul 16 20:44:29 2014 +0100
    19.2 +++ b/src/vid_tvga.c	Tue Jul 22 21:10:39 2014 +0100
    19.3 @@ -300,11 +300,11 @@
    19.4          tvga->svga.fullchange = changeframecount;
    19.5  }
    19.6  
    19.7 -int tvga_add_status_info(char *s, int max_len, void *p)
    19.8 +void tvga_add_status_info(char *s, int max_len, void *p)
    19.9  {
   19.10          tvga_t *tvga = (tvga_t *)p;
   19.11          
   19.12 -        return svga_add_status_info(s, max_len, &tvga->svga);
   19.13 +        svga_add_status_info(s, max_len, &tvga->svga);
   19.14  }
   19.15  
   19.16  static device_config_t tvga_config[] =
    20.1 --- a/src/vid_vga.c	Wed Jul 16 20:44:29 2014 +0100
    20.2 +++ b/src/vid_vga.c	Tue Jul 22 21:10:39 2014 +0100
    20.3 @@ -125,11 +125,11 @@
    20.4          vga->svga.fullchange = changeframecount;
    20.5  }
    20.6  
    20.7 -int vga_add_status_info(char *s, int max_len, void *p)
    20.8 +void vga_add_status_info(char *s, int max_len, void *p)
    20.9  {
   20.10          vga_t *vga = (vga_t *)p;
   20.11          
   20.12 -        return svga_add_status_info(s, max_len, &vga->svga);
   20.13 +        svga_add_status_info(s, max_len, &vga->svga);
   20.14  }
   20.15  
   20.16  device_t vga_device =
    21.1 --- a/src/win-status.c	Wed Jul 16 20:44:29 2014 +0100
    21.2 +++ b/src/win-status.c	Tue Jul 22 21:10:39 2014 +0100
    21.3 @@ -13,10 +13,8 @@
    21.4  int status_is_open = 0;
    21.5  
    21.6  extern int sreadlnum, swritelnum, segareads, segawrites, scycles_lost;
    21.7 -
    21.8  static BOOL CALLBACK status_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
    21.9  {
   21.10 -        char s[256];
   21.11          char device_s[4096];
   21.12          switch (message)
   21.13          {
   21.14 @@ -28,7 +26,7 @@
   21.15                          "FPU speed : %f MFLOPS\n\n"
   21.16                          "Cache misses (read) : %i/sec\n"
   21.17                          "Cache misses (write) : %i/sec\n\n"
   21.18 -                        "Video throughput (read) : %i bytes/sec\n\n"
   21.19 +                        "Video throughput (read) : %i bytes/sec\n"
   21.20                          "Video throughput (write) : %i bytes/sec\n\n"
   21.21                          "Effective clockspeed : %iHz\n\n"
   21.22                          "Timer 0 frequency : %fHz\n\n",
   21.23 @@ -57,6 +55,7 @@
   21.24                  }
   21.25                  break;
   21.26          }
   21.27 +
   21.28          return FALSE;
   21.29  }
   21.30  
    22.1 --- a/src/win.c	Wed Jul 16 20:44:29 2014 +0100
    22.2 +++ b/src/win.c	Tue Jul 22 21:10:39 2014 +0100
    22.3 @@ -21,6 +21,7 @@
    22.4  #include "model.h"
    22.5  #include "nvr.h"
    22.6  #include "sound.h"
    22.7 +#include "thread.h"
    22.8  
    22.9  #include "plat-midi.h"
   22.10  #include "plat-keyboard.h"
   22.11 @@ -183,6 +184,70 @@
   22.12          }
   22.13  }
   22.14  
   22.15 +void *thread_create(void (*thread_rout)(void *param), void *param)
   22.16 +{
   22.17 +        return (void *)_beginthread(thread_rout, 0, param);
   22.18 +}
   22.19 +
   22.20 +void thread_kill(void *handle)
   22.21 +{
   22.22 +        TerminateThread(handle, 0);
   22.23 +}
   22.24 +
   22.25 +void thread_sleep(int t)
   22.26 +{
   22.27 +        Sleep(t);
   22.28 +}
   22.29 +
   22.30 +typedef struct win_event_t
   22.31 +{
   22.32 +        HANDLE handle;
   22.33 +} win_event_t;
   22.34 +
   22.35 +event_t *thread_create_event()
   22.36 +{
   22.37 +        win_event_t *event = malloc(sizeof(win_event_t));
   22.38 +        
   22.39 +        event->handle = CreateEvent(NULL, FALSE, FALSE, NULL);
   22.40 +        
   22.41 +        return (event_t *)event;
   22.42 +}
   22.43 +
   22.44 +void thread_set_event(event_t *_event)
   22.45 +{
   22.46 +        win_event_t *event = (win_event_t *)_event;
   22.47 +        
   22.48 +        SetEvent(event->handle);
   22.49 +}
   22.50 +
   22.51 +void thread_reset_event(event_t *_event)
   22.52 +{
   22.53 +        win_event_t *event = (win_event_t *)_event;
   22.54 +        
   22.55 +        ResetEvent(event->handle);
   22.56 +}
   22.57 +
   22.58 +int thread_wait_event(event_t *_event, int timeout)
   22.59 +{
   22.60 +        win_event_t *event = (win_event_t *)_event;
   22.61 +        
   22.62 +        if (timeout == -1)
   22.63 +                timeout = INFINITE;
   22.64 +        
   22.65 +        if (WaitForSingleObject(event->handle, timeout))
   22.66 +                return 1;
   22.67 +        return 0;
   22.68 +}
   22.69 +
   22.70 +void thread_destroy_event(event_t *_event)
   22.71 +{
   22.72 +        win_event_t *event = (win_event_t *)_event;
   22.73 +        
   22.74 +        CloseHandle(event->handle);
   22.75 +        
   22.76 +        free(event);
   22.77 +}
   22.78 +
   22.79  static void initmenu(void)
   22.80  {
   22.81          int c;