Pastebin
API
tools
faq
paste
Login
Sign up
Please fix the following errors:
New Paste
Syntax Highlighting
diff --git a/src/sound.c b/src/sound.c index 0bb5f92..b361f35 100644 --- a/src/sound.c +++ b/src/sound.c @@ -213,7 +213,7 @@ void sound_init() outbuffer = malloc(MAXSOUNDBUFLEN * 2 * sizeof(int32_t)); sound_cd_event = thread_create_event(); - sound_cd_thread_h = thread_create(sound_cd_thread, NULL); + //sound_cd_thread_h = thread_create(sound_cd_thread, NULL); } void sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p) diff --git a/src/vid_s3_virge.c b/src/vid_s3_virge.c index 3039969..d6e69e8 100644 --- a/src/vid_s3_virge.c +++ b/src/vid_s3_virge.c @@ -34,21 +34,6 @@ static int dither[4][4] = {7, 3, 6, 2}, }; -#define RB_SIZE 256 -#define RB_MASK (RB_SIZE - 1) - -#define RB_ENTRIES (virge->s3d_write_idx - virge->s3d_read_idx) -#define RB_FULL (RB_ENTRIES == RB_SIZE) -#define RB_EMPTY (!RB_ENTRIES) - -#define FIFO_SIZE 65536 -#define FIFO_MASK (FIFO_SIZE - 1) -#define FIFO_ENTRY_SIZE (1 << 31) - -#define FIFO_ENTRIES (virge->fifo_write_idx - virge->fifo_read_idx) -#define FIFO_FULL ((virge->fifo_write_idx - virge->fifo_read_idx) >= FIFO_SIZE) -#define FIFO_EMPTY (virge->fifo_read_idx == virge->fifo_write_idx) - #define FIFO_TYPE 0xff000000 #define FIFO_ADDR 0x00ffffff @@ -60,20 +45,14 @@ enum FIFO_WRITE_DWORD = (0x03 << 24), }; -typedef struct -{ - uint32_t addr_type; - uint32_t val; -} fifo_entry_t; - typedef struct s3d_t { uint32_t cmd_set; int clip_l, clip_r, clip_t, clip_b; - + uint32_t dest_base; uint32_t dest_str; - + uint32_t z_base; uint32_t z_str; @@ -89,14 +68,14 @@ typedef struct s3d_t int32_t TdWdX, TdWdY; uint32_t tws; - + int32_t TdDdX, TdDdY; uint32_t tds; - + int16_t TdGdX, TdBdX, TdRdX, TdAdX; int16_t TdGdY, TdBdY, TdRdY, TdAdY; uint32_t tgs, tbs, trs, tas; - + uint32_t TdXdY12; uint32_t txend12; uint32_t TdXdY01; @@ -106,17 +85,17 @@ typedef struct s3d_t uint32_t tys; int ty01, ty12, tlr; } s3d_t; - + typedef struct virge_t { mem_mapping_t linear_mapping; mem_mapping_t mmio_mapping; mem_mapping_t new_mmio_mapping; - + rom_t bios_rom; - + svga_t svga; - + uint8_t bank; uint8_t ma_ext; @@ -132,17 +111,12 @@ typedef struct virge_t int bilinear_enabled; int dithering_enabled; int memory_size; - + int pixel_count, tri_count; - - thread_t *render_thread; - event_t *wake_render_thread; - event_t *wake_main_thread; - event_t *not_full_event; - + uint32_t hwc_fg_col, hwc_bg_col; int hwc_col_stack_pos; - + struct { uint32_t src_base; @@ -159,21 +133,21 @@ typedef struct virge_t int r_width, r_height; int rsrc_x, rsrc_y; int rdest_x, rdest_y; - + int lxend0, lxend1; int32_t ldx; uint32_t lxstart, lystart; int lycnt; int line_dir; - + int src_x, src_y; int dest_x, dest_y; int w, h; uint8_t rop; - + int data_left_count; uint32_t data_left; - + uint32_t pattern_8[8*8]; uint32_t pattern_16[8*8]; uint32_t pattern_32[8*8]; @@ -186,13 +160,9 @@ typedef struct virge_t uint32_t pycnt; uint32_t dest_l, dest_r; } s3d; - + s3d_t s3d_tri; - s3d_t s3d_buffer[RB_SIZE]; - int s3d_read_idx, s3d_write_idx; - int s3d_busy; - struct { uint32_t pri_ctrl; @@ -218,30 +188,18 @@ typedef struct virge_t uint32_t pri_size; uint32_t sec_start; uint32_t sec_size; - + int sdif; - + int pri_x, pri_y, pri_w, pri_h; int sec_x, sec_y, sec_w, sec_h; } streams; - fifo_entry_t fifo[FIFO_SIZE]; - volatile int fifo_read_idx, fifo_write_idx; - - thread_t *fifo_thread; - event_t *wake_fifo_thread; - event_t *fifo_not_full_event; - int virge_busy; - + uint8_t subsys_stat, subsys_cntl; } virge_t; -static inline void wake_fifo_thread(virge_t *virge) -{ - thread_set_event(virge->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ -} - static void queue_triangle(virge_t *virge); static void s3_virge_recalctimings(svga_t *svga); @@ -260,29 +218,29 @@ enum { CMD_SET_AE = 1, CMD_SET_HC = (1 << 1), - + CMD_SET_FORMAT_MASK = (7 << 2), CMD_SET_FORMAT_8 = (0 << 2), CMD_SET_FORMAT_16 = (1 << 2), CMD_SET_FORMAT_24 = (2 << 2), - + CMD_SET_MS = (1 << 6), CMD_SET_IDS = (1 << 7), CMD_SET_MP = (1 << 8), CMD_SET_TP = (1 << 9), - + CMD_SET_ITA_MASK = (3 << 10), CMD_SET_ITA_BYTE = (0 << 10), CMD_SET_ITA_WORD = (1 << 10), CMD_SET_ITA_DWORD = (2 << 10), - + CMD_SET_ZUP = (1 << 23), - + CMD_SET_ZB_MODE = (3 << 24), CMD_SET_XP = (1 << 25), CMD_SET_YP = (1 << 26), - + CMD_SET_COMMAND_MASK = (15 << 27) }; @@ -320,9 +278,9 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) svga_t *svga = &virge->svga; uint8_t old; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; - + // pclog("S3 out %04X %02X %04X:%08X %04X %04X %i\n", addr, val, CS, pc, ES, BX, ins); switch (addr) @@ -340,7 +298,7 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) else svga->write_bank = svga->read_bank = virge->bank << 14; } break; - + //case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: // pclog("Write RAMDAC %04X %02X %04X:%04X\n", addr, val, CS, pc); //sdac_ramdac_out(addr,val); @@ -355,7 +313,7 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) val = (svga->crtc[7] & ~0x10) | (val & 0x10); - if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) + if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) return; if (svga->crtcreg >= 0x80) return; @@ -369,11 +327,11 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) case 0x32: s3_virge_update_irqs(virge); break; - + case 0x69: virge->ma_ext = val & 0x1f; break; - + case 0x35: virge->bank = (virge->bank & 0x70) | (val & 0xf); // pclog("CRTC write R35 %02X\n", val); @@ -392,11 +350,11 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16; else svga->write_bank = svga->read_bank = virge->bank << 14; break; - + case 0x3a: if (val & 0x10) svga->gdcreg[5] |= 0x40; /*Horrible cheat*/ break; - + case 0x45: svga->hwcursor.ena = val & 1; break; @@ -408,7 +366,7 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) svga->hwcursor.yoff = svga->crtc[0x4f] & 63; svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); break; - + case 0x4a: switch (virge->hwc_col_stack_pos) { @@ -444,7 +402,7 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) case 0x58: case 0x59: case 0x5a: s3_virge_updatemapping(virge); break; - + case 0x67: switch (val >> 4) { @@ -476,8 +434,8 @@ static uint8_t s3_virge_in(uint16_t addr, void *p) virge_t *virge = (virge_t *)p; svga_t *svga = &virge->svga; uint8_t ret; - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; // if (addr != 0x3da) pclog("S3 in %04X %04X:%08X ", addr, CS, pc); @@ -488,7 +446,7 @@ static uint8_t s3_virge_in(uint16_t addr, void *p) ret = 0xff; else ret = svga_in(addr, svga); - break; + break; //case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: // pclog("Read RAMDAC %04X %04X:%04X\n", addr, CS, pc); //return sdac_ramdac_in(addr); @@ -511,7 +469,7 @@ static uint8_t s3_virge_in(uint16_t addr, void *p) { case 0x2d: ret = virge->virge_id_high; break; /*Extended chip ID*/ case 0x2e: ret = virge->virge_id_low; break; /*New chip ID*/ - case 0x2f: ret = virge->virge_rev; break; + case 0x2f: ret = virge->virge_rev; break; case 0x30: ret = virge->virge_id; break; /*Chip ID*/ case 0x31: ret = (svga->crtc[0x31] & 0xcf) | ((virge->ma_ext & 3) << 4); break; case 0x35: ret = (svga->crtc[0x35] & 0xf0) | (virge->bank & 0xf); break; @@ -523,10 +481,10 @@ static uint8_t s3_virge_in(uint16_t addr, void *p) default: ret = svga->crtc[svga->crtcreg]; break; } break; - + default: ret = svga_in(addr, svga); - break; + break; } // if (addr != 0x3da) pclog("%02X\n", ret); return ret; @@ -557,24 +515,24 @@ static void s3_virge_recalctimings(svga_t *svga) { switch (svga->bpp) { - case 8: - svga->render = svga_render_8bpp_highres; + case 8: + svga->render = svga_render_8bpp_highres; break; - case 15: - svga->render = svga_render_15bpp_highres; + case 15: + svga->render = svga_render_15bpp_highres; break; - case 16: - svga->render = svga_render_16bpp_highres; + case 16: + svga->render = svga_render_16bpp_highres; break; - case 24: - svga->render = svga_render_24bpp_highres; + case 24: + svga->render = svga_render_24bpp_highres; break; - case 32: - svga->render = svga_render_32bpp_highres; + case 32: + svga->render = svga_render_32bpp_highres; break; } } - + // pclog("svga->rowoffset = %i bpp=%i\n", svga->rowoffset, svga->bpp); if (svga->bpp == 15 || svga->bpp == 16) { @@ -594,11 +552,11 @@ static void s3_virge_recalctimings(svga_t *svga) svga->ma_latch = virge->streams.pri_fb1 >> 2; else svga->ma_latch = virge->streams.pri_fb0 >> 2; - + svga->hdisp = virge->streams.pri_w + 1; if (virge->streams.pri_h < svga->dispend) svga->dispend = virge->streams.pri_h; - + svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x; svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y; svga->overlay.ysize = virge->streams.sec_h; @@ -616,21 +574,21 @@ static void s3_virge_recalctimings(svga_t *svga) switch ((virge->streams.pri_ctrl >> 24) & 0x7) { case 0: /*RGB-8 (CLUT)*/ - svga->render = svga_render_8bpp_highres; + svga->render = svga_render_8bpp_highres; break; - case 3: /*KRGB-16 (1.5.5.5)*/ + case 3: /*KRGB-16 (1.5.5.5)*/ svga->htotal >>= 1; - svga->render = svga_render_15bpp_highres; + svga->render = svga_render_15bpp_highres; break; - case 5: /*RGB-16 (5.6.5)*/ + case 5: /*RGB-16 (5.6.5)*/ svga->htotal >>= 1; - svga->render = svga_render_16bpp_highres; + svga->render = svga_render_16bpp_highres; break; - case 6: /*RGB-24 (8.8.8)*/ - svga->render = svga_render_24bpp_highres; + case 6: /*RGB-24 (8.8.8)*/ + svga->render = svga_render_24bpp_highres; break; case 7: /*XRGB-32 (X.8.8.8)*/ - svga->render = svga_render_32bpp_highres; + svga->render = svga_render_32bpp_highres; break; } svga->vram_display_mask = (virge->memory_size << 20) - 1; @@ -661,7 +619,7 @@ static void s3_virge_updatemapping(virge_t *virge) return; } - pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); + pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/ { case 0x0: /*128k at A0000*/ @@ -681,9 +639,9 @@ static void s3_virge_updatemapping(virge_t *virge) svga->banked_mask = 0x7fff; break; } - + virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); - + pclog("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10); if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/ { @@ -719,7 +677,7 @@ static void s3_virge_updatemapping(virge_t *virge) mem_mapping_disable(&virge->linear_mapping); svga->fb_only = 0; } - + pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18); if (svga->crtc[0x53] & 0x10) /*Old MMIO*/ { @@ -746,15 +704,6 @@ static void s3_virge_vblank_start(svga_t *svga) s3_virge_update_irqs(virge); } -static void s3_virge_wait_fifo_idle(virge_t *virge) -{ - while (!FIFO_EMPTY) - { - wake_fifo_thread(virge); - thread_wait_event(virge->fifo_not_full_event, 1); - } -} - static uint8_t s3_virge_mmio_read(uint32_t addr, void *p) { virge_t *virge = (virge_t *)p; @@ -765,14 +714,9 @@ static uint8_t s3_virge_mmio_read(uint32_t addr, void *p) switch (addr & 0xffff) { case 0x8505: - if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY) - ret = 0x10; - else - ret = 0x10 | (1 << 5); - if (!virge->virge_busy) - wake_fifo_thread(virge); + ret = 0x10 | (1 << 5); return ret; - + case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: @@ -874,78 +818,58 @@ static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p) case 0x81fc: ret = virge->streams.sec_size; break; - + case 0x8504: - if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY) - ret = (0x10 << 8); - else - ret = (0x10 << 8) | (1 << 13); + ret = (0x10 << 8) | (1 << 13); ret |= virge->subsys_stat; - if (!virge->virge_busy) - wake_fifo_thread(virge); // pclog("Read status %04x %i\n", ret, virge->s3d_busy); break; case 0xa4d4: - s3_virge_wait_fifo_idle(virge); ret = virge->s3d.src_base; break; case 0xa4d8: - s3_virge_wait_fifo_idle(virge); ret = virge->s3d.dest_base; break; case 0xa4dc: - s3_virge_wait_fifo_idle(virge); ret = (virge->s3d.clip_l << 16) | virge->s3d.clip_r; break; case 0xa4e0: - s3_virge_wait_fifo_idle(virge); ret = (virge->s3d.clip_t << 16) | virge->s3d.clip_b; break; case 0xa4e4: - s3_virge_wait_fifo_idle(virge); ret = (virge->s3d.dest_str << 16) | virge->s3d.src_str; break; case 0xa4e8: case 0xace8: - s3_virge_wait_fifo_idle(virge); ret = virge->s3d.mono_pat_0; break; case 0xa4ec: case 0xacec: - s3_virge_wait_fifo_idle(virge); ret = virge->s3d.mono_pat_1; break; case 0xa4f0: - s3_virge_wait_fifo_idle(virge); ret = virge->s3d.pat_bg_clr; break; case 0xa4f4: - s3_virge_wait_fifo_idle(virge); ret = virge->s3d.pat_fg_clr; break; case 0xa4f8: - s3_virge_wait_fifo_idle(virge); ret = virge->s3d.src_bg_clr; break; case 0xa4fc: - s3_virge_wait_fifo_idle(virge); ret = virge->s3d.src_fg_clr; break; case 0xa500: - s3_virge_wait_fifo_idle(virge); ret = virge->s3d.cmd_set; break; case 0xa504: - s3_virge_wait_fifo_idle(virge); ret = (virge->s3d.r_width << 16) | virge->s3d.r_height; break; case 0xa508: - s3_virge_wait_fifo_idle(virge); ret = (virge->s3d.rsrc_x << 16) | virge->s3d.rsrc_y; break; case 0xa50c: - s3_virge_wait_fifo_idle(virge); ret = (virge->s3d.rdest_x << 16) | virge->s3d.rdest_y; break; - + default: ret = s3_virge_mmio_read_w(addr, p) | (s3_virge_mmio_read_w(addr + 2, p) << 16); } @@ -953,388 +877,345 @@ static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p) return ret; } -static void fifo_thread(void *param) +static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) { - virge_t *virge = (virge_t *)param; - - while (1) + uint64_t start_time = timer_read(); + uint64_t end_time; + uint32_t addr_type = (addr & FIFO_ADDR) | type; + + switch (addr_type & FIFO_TYPE) { - thread_set_event(virge->fifo_not_full_event); - thread_wait_event(virge->wake_fifo_thread, -1); - thread_reset_event(virge->wake_fifo_thread); - virge->virge_busy = 1; - while (!FIFO_EMPTY) + case FIFO_WRITE_BYTE: + if (((addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) + s3_virge_bitblt(virge, 8, val); + break; + case FIFO_WRITE_WORD: + if (((addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) { - uint64_t start_time = timer_read(); - uint64_t end_time; - fifo_entry_t *fifo = &virge->fifo[virge->fifo_read_idx & FIFO_MASK]; - uint32_t val = fifo->val; - - switch (fifo->addr_type & FIFO_TYPE) + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16); + else + s3_virge_bitblt(virge, 16, val); + } + break; + case FIFO_WRITE_DWORD: + if (((addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) + { + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); + else + s3_virge_bitblt(virge, 32, val); + } + else + { + switch ((addr_type & FIFO_ADDR) & 0xfffc) { - case FIFO_WRITE_BYTE: - if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) - s3_virge_bitblt(virge, 8, val); - break; - case FIFO_WRITE_WORD: - if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) + case 0xa000: case 0xa004: case 0xa008: case 0xa00c: + case 0xa010: case 0xa014: case 0xa018: case 0xa01c: + case 0xa020: case 0xa024: case 0xa028: case 0xa02c: + case 0xa030: case 0xa034: case 0xa038: case 0xa03c: + case 0xa040: case 0xa044: case 0xa048: case 0xa04c: + case 0xa050: case 0xa054: case 0xa058: case 0xa05c: + case 0xa060: case 0xa064: case 0xa068: case 0xa06c: + case 0xa070: case 0xa074: case 0xa078: case 0xa07c: + case 0xa080: case 0xa084: case 0xa088: case 0xa08c: + case 0xa090: case 0xa094: case 0xa098: case 0xa09c: + case 0xa0a0: case 0xa0a4: case 0xa0a8: case 0xa0ac: + case 0xa0b0: case 0xa0b4: case 0xa0b8: case 0xa0bc: + case 0xa0c0: case 0xa0c4: case 0xa0c8: case 0xa0cc: + case 0xa0d0: case 0xa0d4: case 0xa0d8: case 0xa0dc: + case 0xa0e0: case 0xa0e4: case 0xa0e8: case 0xa0ec: + case 0xa0f0: case 0xa0f4: case 0xa0f8: case 0xa0fc: + case 0xa100: case 0xa104: case 0xa108: case 0xa10c: + case 0xa110: case 0xa114: case 0xa118: case 0xa11c: + case 0xa120: case 0xa124: case 0xa128: case 0xa12c: + case 0xa130: case 0xa134: case 0xa138: case 0xa13c: + case 0xa140: case 0xa144: case 0xa148: case 0xa14c: + case 0xa150: case 0xa154: case 0xa158: case 0xa15c: + case 0xa160: case 0xa164: case 0xa168: case 0xa16c: + case 0xa170: case 0xa174: case 0xa178: case 0xa17c: + case 0xa180: case 0xa184: case 0xa188: case 0xa18c: + case 0xa190: case 0xa194: case 0xa198: case 0xa19c: + case 0xa1a0: case 0xa1a4: case 0xa1a8: case 0xa1ac: + case 0xa1b0: case 0xa1b4: case 0xa1b8: case 0xa1bc: + case 0xa1c0: case 0xa1c4: case 0xa1c8: case 0xa1cc: + case 0xa1d0: case 0xa1d4: case 0xa1d8: case 0xa1dc: + case 0xa1e0: case 0xa1e4: case 0xa1e8: case 0xa1ec: + case 0xa1f0: case 0xa1f4: case 0xa1f8: case 0xa1fc: { - if (virge->s3d.cmd_set & CMD_SET_MS) - s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16); - else - s3_virge_bitblt(virge, 16, val); + int x = (addr_type & FIFO_ADDR) & 4; + int y = ((addr_type & FIFO_ADDR) >> 3) & 7; + virge->s3d.pattern_8[y*8 + x] = val & 0xff; + virge->s3d.pattern_8[y*8 + x + 1] = val >> 8; + virge->s3d.pattern_8[y*8 + x + 2] = val >> 16; + virge->s3d.pattern_8[y*8 + x + 3] = val >> 24; + + x = ((addr_type & FIFO_ADDR) >> 1) & 6; + y = ((addr_type & FIFO_ADDR) >> 4) & 7; + virge->s3d.pattern_16[y*8 + x] = val & 0xffff; + virge->s3d.pattern_16[y*8 + x + 1] = val >> 16; + + x = ((addr_type & FIFO_ADDR) >> 2) & 7; + y = ((addr_type & FIFO_ADDR) >> 5) & 7; + virge->s3d.pattern_32[y*8 + x] = val & 0xffffff; } break; - case FIFO_WRITE_DWORD: - if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) - { - if (virge->s3d.cmd_set & CMD_SET_MS) - s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); - else - s3_virge_bitblt(virge, 32, val); - } - else - { - switch ((fifo->addr_type & FIFO_ADDR) & 0xfffc) - { - case 0xa000: case 0xa004: case 0xa008: case 0xa00c: - case 0xa010: case 0xa014: case 0xa018: case 0xa01c: - case 0xa020: case 0xa024: case 0xa028: case 0xa02c: - case 0xa030: case 0xa034: case 0xa038: case 0xa03c: - case 0xa040: case 0xa044: case 0xa048: case 0xa04c: - case 0xa050: case 0xa054: case 0xa058: case 0xa05c: - case 0xa060: case 0xa064: case 0xa068: case 0xa06c: - case 0xa070: case 0xa074: case 0xa078: case 0xa07c: - case 0xa080: case 0xa084: case 0xa088: case 0xa08c: - case 0xa090: case 0xa094: case 0xa098: case 0xa09c: - case 0xa0a0: case 0xa0a4: case 0xa0a8: case 0xa0ac: - case 0xa0b0: case 0xa0b4: case 0xa0b8: case 0xa0bc: - case 0xa0c0: case 0xa0c4: case 0xa0c8: case 0xa0cc: - case 0xa0d0: case 0xa0d4: case 0xa0d8: case 0xa0dc: - case 0xa0e0: case 0xa0e4: case 0xa0e8: case 0xa0ec: - case 0xa0f0: case 0xa0f4: case 0xa0f8: case 0xa0fc: - case 0xa100: case 0xa104: case 0xa108: case 0xa10c: - case 0xa110: case 0xa114: case 0xa118: case 0xa11c: - case 0xa120: case 0xa124: case 0xa128: case 0xa12c: - case 0xa130: case 0xa134: case 0xa138: case 0xa13c: - case 0xa140: case 0xa144: case 0xa148: case 0xa14c: - case 0xa150: case 0xa154: case 0xa158: case 0xa15c: - case 0xa160: case 0xa164: case 0xa168: case 0xa16c: - case 0xa170: case 0xa174: case 0xa178: case 0xa17c: - case 0xa180: case 0xa184: case 0xa188: case 0xa18c: - case 0xa190: case 0xa194: case 0xa198: case 0xa19c: - case 0xa1a0: case 0xa1a4: case 0xa1a8: case 0xa1ac: - case 0xa1b0: case 0xa1b4: case 0xa1b8: case 0xa1bc: - case 0xa1c0: case 0xa1c4: case 0xa1c8: case 0xa1cc: - case 0xa1d0: case 0xa1d4: case 0xa1d8: case 0xa1dc: - case 0xa1e0: case 0xa1e4: case 0xa1e8: case 0xa1ec: - case 0xa1f0: case 0xa1f4: case 0xa1f8: case 0xa1fc: - { - int x = (fifo->addr_type & FIFO_ADDR) & 4; - int y = ((fifo->addr_type & FIFO_ADDR) >> 3) & 7; - virge->s3d.pattern_8[y*8 + x] = val & 0xff; - virge->s3d.pattern_8[y*8 + x + 1] = val >> 8; - virge->s3d.pattern_8[y*8 + x + 2] = val >> 16; - virge->s3d.pattern_8[y*8 + x + 3] = val >> 24; - - x = ((fifo->addr_type & FIFO_ADDR) >> 1) & 6; - y = ((fifo->addr_type & FIFO_ADDR) >> 4) & 7; - virge->s3d.pattern_16[y*8 + x] = val & 0xffff; - virge->s3d.pattern_16[y*8 + x + 1] = val >> 16; - - x = ((fifo->addr_type & FIFO_ADDR) >> 2) & 7; - y = ((fifo->addr_type & FIFO_ADDR) >> 5) & 7; - virge->s3d.pattern_32[y*8 + x] = val & 0xffffff; - } - break; - case 0xa4d4: case 0xa8d4: - virge->s3d.src_base = val & 0x3ffff8; - break; - case 0xa4d8: case 0xa8d8: - virge->s3d.dest_base = val & 0x3ffff8; - break; - case 0xa4dc: case 0xa8dc: - virge->s3d.clip_l = (val >> 16) & 0x7ff; - virge->s3d.clip_r = val & 0x7ff; - break; - case 0xa4e0: case 0xa8e0: - virge->s3d.clip_t = (val >> 16) & 0x7ff; - virge->s3d.clip_b = val & 0x7ff; - break; - case 0xa4e4: case 0xa8e4: - virge->s3d.dest_str = (val >> 16) & 0xff8; - virge->s3d.src_str = val & 0xff8; - break; - case 0xa4e8: case 0xace8: - virge->s3d.mono_pat_0 = val; - break; - case 0xa4ec: case 0xacec: - virge->s3d.mono_pat_1 = val; - break; - case 0xa4f0: case 0xacf0: - virge->s3d.pat_bg_clr = val; - break; - case 0xa4f4: case 0xa8f4: case 0xacf4: - virge->s3d.pat_fg_clr = val; - break; - case 0xa4f8: - virge->s3d.src_bg_clr = val; - break; - case 0xa4fc: - virge->s3d.src_fg_clr = val; - break; - case 0xa500: case 0xa900: - virge->s3d.cmd_set = val; - if (!(val & CMD_SET_AE)) - s3_virge_bitblt(virge, -1, 0); - break; - case 0xa504: - virge->s3d.r_width = (val >> 16) & 0x7ff; - virge->s3d.r_height = val & 0x7ff; - break; - case 0xa508: - virge->s3d.rsrc_x = (val >> 16) & 0x7ff; - virge->s3d.rsrc_y = val & 0x7ff; - break; - case 0xa50c: - virge->s3d.rdest_x = (val >> 16) & 0x7ff; - virge->s3d.rdest_y = val & 0x7ff; - if (virge->s3d.cmd_set & CMD_SET_AE) - s3_virge_bitblt(virge, -1, 0); - break; - case 0xa96c: - virge->s3d.lxend0 = (val >> 16) & 0x7ff; - virge->s3d.lxend1 = val & 0x7ff; - break; - case 0xa970: - virge->s3d.ldx = (int32_t)val; - break; - case 0xa974: - virge->s3d.lxstart = val; - break; - case 0xa978: - virge->s3d.lystart = val & 0x7ff; - break; - case 0xa97c: - virge->s3d.lycnt = val & 0x7ff; - virge->s3d.line_dir = val >> 31; - if (virge->s3d.cmd_set & CMD_SET_AE) - s3_virge_bitblt(virge, -1, 0); - break; - - case 0xad00: - virge->s3d.cmd_set = val; - if (!(val & CMD_SET_AE)) - s3_virge_bitblt(virge, -1, 0); - break; - case 0xad68: - virge->s3d.prdx = val; - break; - case 0xad6c: - virge->s3d.prxstart = val; - break; - case 0xad70: - virge->s3d.pldx = val; - break; - case 0xad74: - virge->s3d.plxstart = val; - break; - case 0xad78: - virge->s3d.pystart = val & 0x7ff; - break; - case 0xad7c: - virge->s3d.pycnt = val & 0x300007ff; - if (virge->s3d.cmd_set & CMD_SET_AE) - s3_virge_bitblt(virge, -1, 0); - break; - - case 0xb4d4: - virge->s3d_tri.z_base = val & 0x3ffff8; - break; - case 0xb4d8: - virge->s3d_tri.dest_base = val & 0x3ffff8; - break; - case 0xb4dc: - virge->s3d_tri.clip_l = (val >> 16) & 0x7ff; - virge->s3d_tri.clip_r = val & 0x7ff; - break; - case 0xb4e0: - virge->s3d_tri.clip_t = (val >> 16) & 0x7ff; - virge->s3d_tri.clip_b = val & 0x7ff; - break; - case 0xb4e4: - virge->s3d_tri.dest_str = (val >> 16) & 0xff8; - virge->s3d.src_str = val & 0xff8; - break; - case 0xb4e8: - virge->s3d_tri.z_str = val & 0xff8; - break; - case 0xb4ec: - virge->s3d_tri.tex_base = val & 0x3ffff8; - break; - case 0xb4f0: - virge->s3d_tri.tex_bdr_clr = val & 0xffffff; - break; - case 0xb500: - virge->s3d_tri.cmd_set = val; - if (!(val & CMD_SET_AE)) - queue_triangle(virge); - break; - case 0xb504: - virge->s3d_tri.tbv = val & 0xfffff; - break; - case 0xb508: - virge->s3d_tri.tbu = val & 0xfffff; - break; - case 0xb50c: - virge->s3d_tri.TdWdX = val; - break; - case 0xb510: - virge->s3d_tri.TdWdY = val; - break; - case 0xb514: - virge->s3d_tri.tws = val; - break; - case 0xb518: - virge->s3d_tri.TdDdX = val; - break; - case 0xb51c: - virge->s3d_tri.TdVdX = val; - break; - case 0xb520: - virge->s3d_tri.TdUdX = val; - break; - case 0xb524: - virge->s3d_tri.TdDdY = val; - break; - case 0xb528: - virge->s3d_tri.TdVdY = val; - break; - case 0xb52c: - virge->s3d_tri.TdUdY = val; - break; - case 0xb530: - virge->s3d_tri.tds = val; - break; - case 0xb534: - virge->s3d_tri.tvs = val; - break; - case 0xb538: - virge->s3d_tri.tus = val; - break; - case 0xb53c: - virge->s3d_tri.TdGdX = val >> 16; - virge->s3d_tri.TdBdX = val & 0xffff; - break; - case 0xb540: - virge->s3d_tri.TdAdX = val >> 16; - virge->s3d_tri.TdRdX = val & 0xffff; - break; - case 0xb544: - virge->s3d_tri.TdGdY = val >> 16; - virge->s3d_tri.TdBdY = val & 0xffff; - break; - case 0xb548: - virge->s3d_tri.TdAdY = val >> 16; - virge->s3d_tri.TdRdY = val & 0xffff; - break; - case 0xb54c: - virge->s3d_tri.tgs = (val >> 16) & 0xffff; - virge->s3d_tri.tbs = val & 0xffff; - break; - case 0xb550: - virge->s3d_tri.tas = (val >> 16) & 0xffff; - virge->s3d_tri.trs = val & 0xffff; - break; - - case 0xb554: - virge->s3d_tri.TdZdX = val; - break; - case 0xb558: - virge->s3d_tri.TdZdY = val; - break; - case 0xb55c: - virge->s3d_tri.tzs = val; - break; - case 0xb560: - virge->s3d_tri.TdXdY12 = val; - break; - case 0xb564: - virge->s3d_tri.txend12 = val; - break; - case 0xb568: - virge->s3d_tri.TdXdY01 = val; - break; - case 0xb56c: - virge->s3d_tri.txend01 = val; - break; - case 0xb570: - virge->s3d_tri.TdXdY02 = val; - break; - case 0xb574: - virge->s3d_tri.txs = val; - break; - case 0xb578: - virge->s3d_tri.tys = val; - break; - case 0xb57c: - virge->s3d_tri.ty01 = (val >> 16) & 0x7ff; - virge->s3d_tri.ty12 = val & 0x7ff; - virge->s3d_tri.tlr = val >> 31; - if (virge->s3d_tri.cmd_set & CMD_SET_AE) - queue_triangle(virge); - break; - } - } + case 0xa4d4: case 0xa8d4: + virge->s3d.src_base = val & 0x3ffff8; + break; + case 0xa4d8: case 0xa8d8: + virge->s3d.dest_base = val & 0x3ffff8; + break; + case 0xa4dc: case 0xa8dc: + virge->s3d.clip_l = (val >> 16) & 0x7ff; + virge->s3d.clip_r = val & 0x7ff; + break; + case 0xa4e0: case 0xa8e0: + virge->s3d.clip_t = (val >> 16) & 0x7ff; + virge->s3d.clip_b = val & 0x7ff; + break; + case 0xa4e4: case 0xa8e4: + virge->s3d.dest_str = (val >> 16) & 0xff8; + virge->s3d.src_str = val & 0xff8; + break; + case 0xa4e8: case 0xace8: + virge->s3d.mono_pat_0 = val; + break; + case 0xa4ec: case 0xacec: + virge->s3d.mono_pat_1 = val; + break; + case 0xa4f0: case 0xacf0: + virge->s3d.pat_bg_clr = val; + break; + case 0xa4f4: case 0xa8f4: case 0xacf4: + virge->s3d.pat_fg_clr = val; + break; + case 0xa4f8: + virge->s3d.src_bg_clr = val; + break; + case 0xa4fc: + virge->s3d.src_fg_clr = val; + break; + case 0xa500: case 0xa900: + virge->s3d.cmd_set = val; + if (!(val & CMD_SET_AE)) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xa504: + virge->s3d.r_width = (val >> 16) & 0x7ff; + virge->s3d.r_height = val & 0x7ff; + break; + case 0xa508: + virge->s3d.rsrc_x = (val >> 16) & 0x7ff; + virge->s3d.rsrc_y = val & 0x7ff; + break; + case 0xa50c: + virge->s3d.rdest_x = (val >> 16) & 0x7ff; + virge->s3d.rdest_y = val & 0x7ff; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xa96c: + virge->s3d.lxend0 = (val >> 16) & 0x7ff; + virge->s3d.lxend1 = val & 0x7ff; + break; + case 0xa970: + virge->s3d.ldx = (int32_t)val; + break; + case 0xa974: + virge->s3d.lxstart = val; + break; + case 0xa978: + virge->s3d.lystart = val & 0x7ff; + break; + case 0xa97c: + virge->s3d.lycnt = val & 0x7ff; + virge->s3d.line_dir = val >> 31; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); break; - } - - virge->fifo_read_idx++; - fifo->addr_type = FIFO_INVALID; - - if (FIFO_ENTRIES > 0xe000) - thread_set_event(virge->fifo_not_full_event); - end_time = timer_read(); - virge_time += end_time - start_time; - } - virge->virge_busy = 0; - virge->subsys_stat |= INT_FIFO_EMP | INT_3DF_EMP; - s3_virge_update_irqs(virge); - } -} + case 0xad00: + virge->s3d.cmd_set = val; + if (!(val & CMD_SET_AE)) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xad68: + virge->s3d.prdx = val; + break; + case 0xad6c: + virge->s3d.prxstart = val; + break; + case 0xad70: + virge->s3d.pldx = val; + break; + case 0xad74: + virge->s3d.plxstart = val; + break; + case 0xad78: + virge->s3d.pystart = val & 0x7ff; + break; + case 0xad7c: + virge->s3d.pycnt = val & 0x300007ff; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; -static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) -{ - fifo_entry_t *fifo = &virge->fifo[virge->fifo_write_idx & FIFO_MASK]; + case 0xb4d4: + virge->s3d_tri.z_base = val & 0x3ffff8; + break; + case 0xb4d8: + virge->s3d_tri.dest_base = val & 0x3ffff8; + break; + case 0xb4dc: + virge->s3d_tri.clip_l = (val >> 16) & 0x7ff; + virge->s3d_tri.clip_r = val & 0x7ff; + break; + case 0xb4e0: + virge->s3d_tri.clip_t = (val >> 16) & 0x7ff; + virge->s3d_tri.clip_b = val & 0x7ff; + break; + case 0xb4e4: + virge->s3d_tri.dest_str = (val >> 16) & 0xff8; + virge->s3d.src_str = val & 0xff8; + break; + case 0xb4e8: + virge->s3d_tri.z_str = val & 0xff8; + break; + case 0xb4ec: + virge->s3d_tri.tex_base = val & 0x3ffff8; + break; + case 0xb4f0: + virge->s3d_tri.tex_bdr_clr = val & 0xffffff; + break; + case 0xb500: + virge->s3d_tri.cmd_set = val; + if (!(val & CMD_SET_AE)) + queue_triangle(virge); + break; + case 0xb504: + virge->s3d_tri.tbv = val & 0xfffff; + break; + case 0xb508: + virge->s3d_tri.tbu = val & 0xfffff; + break; + case 0xb50c: + virge->s3d_tri.TdWdX = val; + break; + case 0xb510: + virge->s3d_tri.TdWdY = val; + break; + case 0xb514: + virge->s3d_tri.tws = val; + break; + case 0xb518: + virge->s3d_tri.TdDdX = val; + break; + case 0xb51c: + virge->s3d_tri.TdVdX = val; + break; + case 0xb520: + virge->s3d_tri.TdUdX = val; + break; + case 0xb524: + virge->s3d_tri.TdDdY = val; + break; + case 0xb528: + virge->s3d_tri.TdVdY = val; + break; + case 0xb52c: + virge->s3d_tri.TdUdY = val; + break; + case 0xb530: + virge->s3d_tri.tds = val; + break; + case 0xb534: + virge->s3d_tri.tvs = val; + break; + case 0xb538: + virge->s3d_tri.tus = val; + break; + case 0xb53c: + virge->s3d_tri.TdGdX = val >> 16; + virge->s3d_tri.TdBdX = val & 0xffff; + break; + case 0xb540: + virge->s3d_tri.TdAdX = val >> 16; + virge->s3d_tri.TdRdX = val & 0xffff; + break; + case 0xb544: + virge->s3d_tri.TdGdY = val >> 16; + virge->s3d_tri.TdBdY = val & 0xffff; + break; + case 0xb548: + virge->s3d_tri.TdAdY = val >> 16; + virge->s3d_tri.TdRdY = val & 0xffff; + break; + case 0xb54c: + virge->s3d_tri.tgs = (val >> 16) & 0xffff; + virge->s3d_tri.tbs = val & 0xffff; + break; + case 0xb550: + virge->s3d_tri.tas = (val >> 16) & 0xffff; + virge->s3d_tri.trs = val & 0xffff; + break; - if (FIFO_FULL) - { - thread_reset_event(virge->fifo_not_full_event); - if (FIFO_FULL) - { - thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + case 0xb554: + virge->s3d_tri.TdZdX = val; + break; + case 0xb558: + virge->s3d_tri.TdZdY = val; + break; + case 0xb55c: + virge->s3d_tri.tzs = val; + break; + case 0xb560: + virge->s3d_tri.TdXdY12 = val; + break; + case 0xb564: + virge->s3d_tri.txend12 = val; + break; + case 0xb568: + virge->s3d_tri.TdXdY01 = val; + break; + case 0xb56c: + virge->s3d_tri.txend01 = val; + break; + case 0xb570: + virge->s3d_tri.TdXdY02 = val; + break; + case 0xb574: + virge->s3d_tri.txs = val; + break; + case 0xb578: + virge->s3d_tri.tys = val; + break; + case 0xb57c: + virge->s3d_tri.ty01 = (val >> 16) & 0x7ff; + virge->s3d_tri.ty12 = val & 0x7ff; + virge->s3d_tri.tlr = val >> 31; + if (virge->s3d_tri.cmd_set & CMD_SET_AE) + queue_triangle(virge); + break; + } } + break; } - fifo->val = val; - fifo->addr_type = (addr & FIFO_ADDR) | type; + end_time = timer_read(); + virge_time += end_time - start_time; - virge->fifo_write_idx++; - - if (FIFO_ENTRIES > 0xe000) - wake_fifo_thread(virge); - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) - wake_fifo_thread(virge); + virge->subsys_stat |= INT_FIFO_EMP | INT_3DF_EMP; + s3_virge_update_irqs(virge); } static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p) { virge_t *virge = (virge_t *)p; - + // pclog("New MMIO writeb %08X %02X %04x(%08x):%08x\n", addr, val, CS, cs, pc); - reg_writes++; + reg_writes++; if ((addr & 0xfffc) < 0x8000) { s3_virge_queue(virge, addr, val, FIFO_WRITE_BYTE); @@ -1357,7 +1238,7 @@ static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p) break; } - + } static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p) { @@ -1367,7 +1248,7 @@ static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p) if ((addr & 0xfffc) < 0x8000) { s3_virge_queue(virge, addr, val, FIFO_WRITE_WORD); - } + } else switch (addr & 0xfffe) { case 0x83d4: @@ -1486,38 +1367,38 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) case 0x81f0: virge->streams.pri_start = val; virge->streams.pri_x = (val >> 16) & 0x7ff; - virge->streams.pri_y = val & 0x7ff; + virge->streams.pri_y = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81f4: virge->streams.pri_size = val; virge->streams.pri_w = (val >> 16) & 0x7ff; - virge->streams.pri_h = val & 0x7ff; + virge->streams.pri_h = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81f8: virge->streams.sec_start = val; virge->streams.sec_x = (val >> 16) & 0x7ff; - virge->streams.sec_y = val & 0x7ff; + virge->streams.sec_y = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81fc: virge->streams.sec_size = val; virge->streams.sec_w = (val >> 16) & 0x7ff; - virge->streams.sec_h = val & 0x7ff; + virge->streams.sec_h = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; - + case 0x8504: virge->subsys_stat &= ~(val & 0xff); virge->subsys_cntl = (val >> 8); s3_virge_update_irqs(virge); break; - + case 0xa000: case 0xa004: case 0xa008: case 0xa00c: case 0xa010: case 0xa014: case 0xa018: case 0xa01c: case 0xa020: case 0xa024: case 0xa028: case 0xa02c: @@ -1557,7 +1438,7 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) virge->s3d.pattern_8[y*8 + x + 1] = val >> 8; virge->s3d.pattern_8[y*8 + x + 2] = val >> 16; virge->s3d.pattern_8[y*8 + x + 3] = val >> 24; - + x = (addr >> 1) & 6; y = (addr >> 4) & 7; virge->s3d.pattern_16[y*8 + x] = val & 0xffff; @@ -1669,7 +1550,7 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) if (virge->s3d.cmd_set & CMD_SET_AE) s3_virge_bitblt(virge, -1, 0); break; - + case 0xb4d4: virge->s3d_tri.z_base = val & 0x3ffff8; break; @@ -1701,11 +1582,6 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) virge->s3d_tri.cmd_set = val; if (!(val & CMD_SET_AE)) queue_triangle(virge); -/* { - thread_set_event(virge->wake_render_thread); - thread_wait_event(virge->wake_main_thread, -1); - } */ -// s3_virge_triangle(virge); break; case 0xb504: virge->s3d_tri.tbv = val & 0xfffff; @@ -1773,7 +1649,7 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) virge->s3d_tri.tas = (val >> 16) & 0xffff; virge->s3d_tri.trs = val & 0xffff; break; - + case 0xb554: virge->s3d_tri.TdZdX = val; break; @@ -1810,12 +1686,6 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) virge->s3d_tri.tlr = val >> 31; if (virge->s3d_tri.cmd_set & CMD_SET_AE) queue_triangle(virge); -/* { - thread_set_event(virge->wake_render_thread); - thread_wait_event(virge->wake_main_thread, -1); - }*/ - -// s3_virge_triangle(virge); break; } } @@ -1879,7 +1749,7 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) case 7: update = 1; Zzb = Zs; break; \ } \ } while (0) - + #define MIX() \ do \ { \ @@ -1927,7 +1797,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) int cpu_dat_shift; uint32_t *pattern_data; uint32_t src_fg_clr, src_bg_clr; - + switch (virge->s3d.cmd_set & CMD_SET_FORMAT_MASK) { case CMD_SET_FORMAT_8: @@ -1958,7 +1828,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) } if (virge->s3d.cmd_set & CMD_SET_MP) pattern_data = mono_pattern; - + switch (virge->s3d.cmd_set & CMD_SET_ITA_MASK) { case CMD_SET_ITA_BYTE: @@ -1994,7 +1864,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) { case CMD_SET_COMMAND_NOP: break; - + case CMD_SET_COMMAND_BITBLT: if (count == -1) { @@ -2006,7 +1876,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.h = virge->s3d.r_height; virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; virge->s3d.data_left_count = 0; - + /* pclog("BitBlt start %i,%i %i,%i %i,%i %02X %x %x\n", virge->s3d.src_x, virge->s3d.src_y, @@ -2017,7 +1887,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.rop, virge->s3d.src_base, virge->s3d.dest_base);*/ - + if (virge->s3d.cmd_set & CMD_SET_IDS) return; } @@ -2089,7 +1959,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) WRITE(dest_addr, out); } - + virge->s3d.src_x += x_inc; virge->s3d.src_x &= 0x7ff; virge->s3d.dest_x += x_inc; @@ -2103,7 +1973,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.src_y += y_inc; virge->s3d.dest_y += y_inc; virge->s3d.h--; - + switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) { case CMD_SET_IDS: @@ -2123,10 +1993,10 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) } } else - virge->s3d.w--; + virge->s3d.w--; } break; - + case CMD_SET_COMMAND_RECTFILL: /*No source, pattern = pat_fg_clr*/ if (count == -1) @@ -2138,7 +2008,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.w = virge->s3d.r_width; virge->s3d.h = virge->s3d.r_height; virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; - + /* pclog("RctFll start %i,%i %i,%i %02X %08x\n", virge->s3d.dest_x, virge->s3d.dest_y, virge->s3d.w, @@ -2183,11 +2053,11 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) } } else - virge->s3d.w--; + virge->s3d.w--; count--; } break; - + case CMD_SET_COMMAND_LINE: if (count == -1) { @@ -2201,7 +2071,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) int x; int new_x; int first_pixel = 1; - + x = virge->s3d.dest_x >> 20; if (virge->s3d.h == virge->s3d.lycnt && @@ -2214,11 +2084,11 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) else new_x = (virge->s3d.dest_x + virge->s3d.ldx) >> 20; - + if ((virge->s3d.line_dir && x > new_x) || (!virge->s3d.line_dir && x < new_x)) goto skip_line; - + do { uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); @@ -2247,7 +2117,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) WRITE(dest_addr, out); } - + if (x < new_x) x++; else if (x > new_x) @@ -2295,7 +2165,7 @@ skip_line: WRITE(dest_addr, out); } - + x = (x + xdir) & 0x7ff; } while (x != (xend + xdir)); @@ -2344,21 +2214,21 @@ typedef struct s3d_state_t int32_t r, g, b, a, u, v, d, w; int32_t base_r, base_g, base_b, base_a, base_u, base_v, base_d, base_w; - + uint32_t base_z; uint32_t tbu, tbv; uint32_t cmd_set; int max_d; - + uint16_t *texture[10]; - + uint32_t tex_bdr_clr; - + int32_t x1, x2; int y; - + rgba_t dest_rgba; } s3d_state_t; @@ -2366,7 +2236,7 @@ typedef struct s3d_texture_state_t { int level; int texture_shift; - + int32_t u, v; } s3d_texture_state_t; @@ -2462,7 +2332,7 @@ static void tex_ARGB8888_nowrap(s3d_state_t *state, s3d_texture_state_t *texture static void tex_sample_normal(s3d_state_t *state) { s3d_texture_state_t texture_state; - + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); texture_state.u = state->u + state->tbu; @@ -2500,12 +2370,12 @@ static void tex_sample_normal_filter(s3d_state_t *state) texture_state.u = state->u + state->tbu + tex_offset; texture_state.v = state->v + state->tbv + tex_offset; tex_read(state, &texture_state, &tex_samples[3]); - + d[0] = (256 - du) * (256 - dv); d[1] = du * (256 - dv); d[2] = (256 - du) * dv; d[3] = du * dv; - + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; @@ -2539,7 +2409,7 @@ static void tex_sample_mipmap_filter(s3d_state_t *state) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); tex_offset = 1 << texture_state.texture_shift; - + texture_state.u = state->u + state->tbu; texture_state.v = state->v + state->tbv; tex_read(state, &texture_state, &tex_samples[0]); @@ -2562,7 +2432,7 @@ static void tex_sample_mipmap_filter(s3d_state_t *state) d[1] = du * (256 - dv); d[2] = (256 - du) * dv; d[3] = du * dv; - + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; @@ -2576,9 +2446,9 @@ static void tex_sample_persp_normal(s3d_state_t *state) if (state->w) w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - + texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.texture_shift = 18 + (9 - texture_state.level); texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; @@ -2603,7 +2473,7 @@ static void tex_sample_persp_normal_filter(s3d_state_t *state) texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); tex_offset = 1 << texture_state.texture_shift; - + texture_state.u = u; texture_state.v = v; tex_read(state, &texture_state, &tex_samples[0]); @@ -2626,7 +2496,7 @@ static void tex_sample_persp_normal_filter(s3d_state_t *state) d[1] = du * (256 - dv); d[2] = (256 - du) * dv; d[3] = du * dv; - + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; @@ -2640,9 +2510,9 @@ static void tex_sample_persp_normal_375(s3d_state_t *state) if (state->w) w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - + texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.texture_shift = 18 + (9 - texture_state.level); texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; @@ -2663,7 +2533,7 @@ static void tex_sample_persp_normal_filter_375(s3d_state_t *state) u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; - + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); tex_offset = 1 << texture_state.texture_shift; @@ -2690,7 +2560,7 @@ static void tex_sample_persp_normal_filter_375(s3d_state_t *state) d[1] = du * (256 - dv); d[2] = (256 - du) * dv; d[3] = du * dv; - + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; @@ -2705,7 +2575,7 @@ static void tex_sample_persp_mipmap(s3d_state_t *state) if (state->w) w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; @@ -2730,7 +2600,7 @@ static void tex_sample_persp_mipmap_filter(s3d_state_t *state) u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; - + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; @@ -2759,7 +2629,7 @@ static void tex_sample_persp_mipmap_filter(s3d_state_t *state) d[1] = du * (256 - dv); d[2] = (256 - du) * dv; d[3] = du * dv; - + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; @@ -2773,7 +2643,7 @@ static void tex_sample_persp_mipmap_375(s3d_state_t *state) if (state->w) w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; @@ -2798,13 +2668,13 @@ static void tex_sample_persp_mipmap_filter_375(s3d_state_t *state) u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; - + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); tex_offset = 1 << texture_state.texture_shift; - + texture_state.u = u; texture_state.v = v; tex_read(state, &texture_state, &tex_samples[0]); @@ -2827,7 +2697,7 @@ static void tex_sample_persp_mipmap_filter_375(s3d_state_t *state) d[1] = du * (256 - dv); d[2] = (256 - du) * dv; d[3] = du * dv; - + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; @@ -2851,7 +2721,7 @@ static void tex_sample_persp_mipmap_filter_375(s3d_state_t *state) b = ((b) < 0) ? 0 : 0xff; \ if ((a) & ~0xff) \ a = ((a) < 0) ? 0 : 0xff; - + #define CLAMP_RGB(r, g, b) do \ { \ if ((r) < 0) \ @@ -2916,11 +2786,11 @@ static void dest_pixel_lit_texture_reflection(s3d_state_t *state) static void dest_pixel_lit_texture_modulate(s3d_state_t *state) { int r = state->r >> 7, g = state->g >> 7, b = state->b >> 7, a = state->a >> 7; - + tex_sample(state); - + CLAMP_RGBA(r, g, b, a); - + state->dest_rgba.r = ((state->dest_rgba.r) * r) >> 8; state->dest_rgba.g = ((state->dest_rgba.g) * g) >> 8; state->dest_rgba.b = ((state->dest_rgba.b) * b) >> 8; @@ -2935,13 +2805,13 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 uint8_t *vram = virge->svga.vram; int x_dir = s3d_tri->tlr ? 1 : -1; - + int use_z = !(s3d_tri->cmd_set & CMD_SET_ZB_MODE); int y_count = yc; - + int bpp = (s3d_tri->cmd_set >> 2) & 7; - + uint32_t dest_offset, z_offset; dest_offset = s3d_tri->dest_base + (state->y * s3d_tri->dest_str); @@ -2954,10 +2824,10 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 if (state->y > s3d_tri->clip_b) { int diff_y = state->y - s3d_tri->clip_b; - + if (diff_y > y_count) diff_y = y_count; - + state->base_u += (s3d_tri->TdUdY * diff_y); state->base_v += (s3d_tri->TdVdY * diff_y); state->base_z += (s3d_tri->TdZdY * diff_y); @@ -2977,7 +2847,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 if ((state->y - y_count) < s3d_tri->clip_t) y_count = state->y - s3d_tri->clip_t; } - + for (; y_count > 0; y_count--) { int x = (state->x1 + ((1 << 20) - 1)) >> 20; @@ -3022,7 +2892,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 if (x < s3d_tri->clip_l) { int diff_x = s3d_tri->clip_l - x; - + z += (s3d_tri->TdZdX * diff_x); state->u += (s3d_tri->TdUdX * diff_x); state->v += (s3d_tri->TdVdX * diff_x); @@ -3032,7 +2902,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 state->a += (s3d_tri->TdAdX * diff_x); state->d += (s3d_tri->TdDdX * diff_x); state->w += (s3d_tri->TdWdX * diff_x); - + x = s3d_tri->clip_l; } } @@ -3047,7 +2917,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 if (x > s3d_tri->clip_r) { int diff_x = x - s3d_tri->clip_r; - + z += (s3d_tri->TdZdX * diff_x); state->u += (s3d_tri->TdUdX * diff_x); state->v += (s3d_tri->TdVdX * diff_x); @@ -3057,7 +2927,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 state->a += (s3d_tri->TdAdX * diff_x); state->d += (s3d_tri->TdDdX * diff_x); state->w += (s3d_tri->TdWdX * diff_x); - + x = s3d_tri->clip_r; } } @@ -3090,7 +2960,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 { uint32_t src_col; int src_r = 0, src_g = 0, src_b = 0; - + switch (bpp) { case 0: /*8 bpp*/ @@ -3113,7 +2983,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 switch (bpp) { - case 0: /*8 bpp*/ + case 0: /*8 bpp*/ /*Not implemented yet*/ break; case 1: /*16 bpp*/ @@ -3188,11 +3058,11 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) state.tbu = s3d_tri->tbu << 11; state.tbv = s3d_tri->tbv << 11; - + state.max_d = (s3d_tri->cmd_set >> 8) & 15; - + state.tex_bdr_clr = s3d_tri->tex_bdr_clr; - + state.cmd_set = s3d_tri->cmd_set; state.base_u = s3d_tri->tus; @@ -3204,7 +3074,7 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) state.base_a = (int32_t)s3d_tri->tas; state.base_d = s3d_tri->tds; state.base_w = s3d_tri->tws; - + tex_base = s3d_tri->tex_base; for (c = 9; c >= 0; c--) { @@ -3248,8 +3118,8 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) default: pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); return; - } - + } + switch (((s3d_tri->cmd_set >> 12) & 7) | ((s3d_tri->cmd_set & (1 << 29)) ? 8 : 0)) { case 0: case 1: @@ -3297,7 +3167,7 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) // pclog("use tex_sample_persp_normal_filter\n"); break; } - + switch ((s3d_tri->cmd_set >> 5) & 7) { case 0: @@ -3316,7 +3186,7 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; break; } - + // 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); state.y = s3d_tri->tys; @@ -3329,47 +3199,15 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) virge->tri_count++; end_time = timer_read(); - - virge_time += end_time - start_time; -} -static void render_thread(void *param) -{ - virge_t *virge = (virge_t *)param; - - while (1) - { - thread_wait_event(virge->wake_render_thread, -1); - thread_reset_event(virge->wake_render_thread); - virge->s3d_busy = 1; - while (!RB_EMPTY) - { - s3_virge_triangle(virge, &virge->s3d_buffer[virge->s3d_read_idx & RB_MASK]); - virge->s3d_read_idx++; - - if (RB_ENTRIES == RB_SIZE - 1) - thread_set_event(virge->not_full_event); - } - virge->s3d_busy = 0; - virge->subsys_stat |= INT_S3D_DONE; - s3_virge_update_irqs(virge); - } + virge_time += end_time - start_time; } static void queue_triangle(virge_t *virge) { -// 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); - if (RB_FULL) - { - thread_reset_event(virge->not_full_event); - if (RB_FULL) - thread_wait_event(virge->not_full_event, -1); /*Wait for room in ringbuffer*/ - } -// pclog(" add at read=%i write=%i %i\n", virge->s3d_read_idx, virge->s3d_write_idx, virge->s3d_write_idx & RB_MASK); - virge->s3d_buffer[virge->s3d_write_idx & RB_MASK] = virge->s3d_tri; - virge->s3d_write_idx++; - if (!virge->s3d_busy) - thread_set_event(virge->wake_render_thread); /*Wake up render thread if moving from idle*/ + s3_virge_triangle(virge, &virge->s3d_tri); + virge->subsys_stat |= INT_S3D_DONE; + s3_virge_update_irqs(virge); } static void s3_virge_hwcursor_draw(svga_t *svga, int displine) @@ -3380,20 +3218,20 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int displine) int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; uint32_t fg, bg; - + // pclog("HWcursor %i %i %08x %08x\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y, virge->hwcursor_col[0],virge->hwcursor_col[1]); switch (svga->bpp) - { + { case 15: fg = video_15to32[virge->hwc_fg_col & 0xffff]; bg = video_15to32[virge->hwc_bg_col & 0xffff]; break; - + case 16: fg = video_16to32[virge->hwc_fg_col & 0xffff]; bg = video_16to32[virge->hwc_bg_col & 0xffff]; break; - + case 24: case 32: fg = virge->hwc_fg_col; bg = virge->hwc_bg_col; @@ -3419,7 +3257,7 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int displine) if (dat[0] & 0x8000) ((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[1] & 0x8000) ? fg : bg; } - + offset++; dat[0] <<= 1; dat[1] <<= 1; @@ -3438,7 +3276,7 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int displine) ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff; // pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga->hwcursor_on, dat[0], dat[1]); } - + offset++; dat[0] <<= 1; dat[1] <<= 1; @@ -3685,16 +3523,16 @@ static void s3_virge_overlay_draw(svga_t *svga, int displine) int x; uint32_t *p; uint8_t *src = &svga->vram[svga->overlay_latch.addr]; - + p = &((uint32_t *)buffer32->line[displine])[offset + 32]; - + if ((offset + virge->streams.sec_w) > virge->streams.pri_w) x_size = (virge->streams.pri_w - virge->streams.sec_x) + 1; else x_size = virge->streams.sec_w + 1; OVERLAY_SAMPLE(); - + for (x = 0; x < x_size; x++) { *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); @@ -3728,22 +3566,22 @@ static uint8_t s3_virge_pci_read(int func, int addr, void *p) { case 0x00: ret = 0x33; break; /*'S3'*/ case 0x01: ret = 0x53; break; - + case 0x02: ret = virge->virge_id_low; break; case 0x03: ret = virge->virge_id_high; break; case 0x04: ret = virge->pci_regs[0x04] & 0x27; break; - + case 0x07: ret = virge->pci_regs[0x07] & 0x36; break; - + case 0x08: ret = 0; break; /*Revision ID*/ case 0x09: ret = 0; break; /*Programming interface*/ - + case 0x0a: ret = 0x00; break; /*Supports VGA interface*/ case 0x0b: ret = 0x03; /*output = 3; */break; case 0x0d: ret = virge->pci_regs[0x0d] & 0xf8; break; - + case 0x10: ret = 0x00; break;/*Linear frame buffer address*/ case 0x11: ret = 0x00; break; case 0x12: ret = 0x00; break; @@ -3755,12 +3593,12 @@ static uint8_t s3_virge_pci_read(int func, int addr, void *p) case 0x33: ret = virge->pci_regs[0x33]; break; case 0x3c: ret = virge->pci_regs[0x3c]; break; - + case 0x3d: ret = 0x01; break; /*INTA*/ - + case 0x3e: ret = 0x04; break; case 0x3f: ret = 0xff; break; - + } // pclog("%02X\n", ret); return ret; @@ -3777,7 +3615,7 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x3d: case 0x3e: case 0x3f: return; - + case PCI_REG_COMMAND: if (val & PCI_COMMAND_IO) { @@ -3787,18 +3625,18 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) else io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); virge->pci_regs[PCI_REG_COMMAND] = val & 0x27; - s3_virge_updatemapping(virge); + s3_virge_updatemapping(virge); return; case 0x07: virge->pci_regs[0x07] = val & 0x3e; return; - case 0x0d: + case 0x0d: virge->pci_regs[0x0d] = val & 0xf8; return; - - case 0x13: - svga->crtc[0x59] = val & 0xfc; - s3_virge_updatemapping(virge); + + case 0x13: + svga->crtc[0x59] = val & 0xfc; + s3_virge_updatemapping(virge); return; case 0x30: case 0x32: case 0x33: @@ -3816,7 +3654,7 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) mem_mapping_disable(&virge->bios_rom.mapping); } return; - case 0x3c: + case 0x3c: virge->pci_regs[0x3c] = val; return; } @@ -3830,7 +3668,7 @@ static void *s3_virge_init() virge->bilinear_enabled = device_get_config_int("bilinear"); virge->dithering_enabled = device_get_config_int("dithering"); virge->memory_size = device_get_config_int("memory"); - + svga_init(&virge->svga, virge, virge->memory_size << 20, s3_virge_recalctimings, s3_virge_in, s3_virge_out, @@ -3872,14 +3710,14 @@ static void *s3_virge_init() io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); virge->pci_regs[4] = 3; - virge->pci_regs[5] = 0; + virge->pci_regs[5] = 0; virge->pci_regs[6] = 0; virge->pci_regs[7] = 2; virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; + virge->pci_regs[0x3d] = 1; virge->pci_regs[0x3e] = 4; virge->pci_regs[0x3f] = 0xff; - + virge->virge_id_high = 0x56; virge->virge_id_low = 0x31; virge->virge_rev = 0; @@ -3895,24 +3733,15 @@ static void *s3_virge_init() virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); break; } - + virge->svga.crtc[0x37] = 1;// | (7 << 5); virge->svga.crtc[0x53] = 1 << 3; virge->svga.crtc[0x59] = 0x70; virge->is_375 = 0; - + pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); - - virge->wake_render_thread = thread_create_event(); - virge->wake_main_thread = thread_create_event(); - virge->not_full_event = thread_create_event(); - virge->render_thread = thread_create(render_thread, virge); - - virge->wake_fifo_thread = thread_create_event(); - virge->fifo_not_full_event = thread_create_event(); - virge->fifo_thread = thread_create(fifo_thread, virge); - + return virge; } @@ -3920,7 +3749,7 @@ static void *s3_virge_375_init() { virge_t *virge = malloc(sizeof(virge_t)); memset(virge, 0, sizeof(virge_t)); - + virge->bilinear_enabled = device_get_config_int("bilinear"); virge->dithering_enabled = device_get_config_int("dithering"); virge->memory_size = device_get_config_int("memory"); @@ -3967,14 +3796,14 @@ static void *s3_virge_375_init() io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); virge->pci_regs[4] = 3; - virge->pci_regs[5] = 0; + virge->pci_regs[5] = 0; virge->pci_regs[6] = 0; virge->pci_regs[7] = 2; virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; + virge->pci_regs[0x3d] = 1; virge->pci_regs[0x3e] = 4; virge->pci_regs[0x3f] = 0xff; - + virge->virge_id_high = 0x8a; virge->virge_id_low = 0x01; virge->virge_rev = 0; @@ -3994,22 +3823,13 @@ static void *s3_virge_375_init() virge->svga.crtc[0x37] = 1;// | (7 << 5); virge->svga.crtc[0x53] = 1 << 3; virge->svga.crtc[0x59] = 0x70; - + virge->svga.crtc[0x6c] = 0x01; - + virge->is_375 = 1; - + virge->card = pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); - - virge->wake_render_thread = thread_create_event(); - virge->wake_main_thread = thread_create_event(); - virge->not_full_event = thread_create_event(); - virge->render_thread = thread_create(render_thread, virge); - - virge->wake_fifo_thread = thread_create_event(); - virge->fifo_not_full_event = thread_create_event(); - virge->fifo_thread = thread_create(fifo_thread, virge); - + return virge; } @@ -4022,17 +3842,8 @@ static void s3_virge_close(void *p) fclose(f); #endif - thread_kill(virge->render_thread); - thread_destroy_event(virge->not_full_event); - thread_destroy_event(virge->wake_main_thread); - thread_destroy_event(virge->wake_render_thread); - - thread_kill(virge->fifo_thread); - thread_destroy_event(virge->wake_fifo_thread); - thread_destroy_event(virge->fifo_not_full_event); - svga_close(&virge->svga); - + free(virge); } @@ -4049,7 +3860,7 @@ static int s3_virge_375_available() static void s3_virge_speed_changed(void *p) { virge_t *virge = (virge_t *)p; - + svga_recalctimings(&virge->svga); } diff --git a/src/video.c b/src/video.c index 34a3789..e36f1cc 100644 --- a/src/video.c +++ b/src/video.c @@ -883,19 +883,19 @@ void loadfont(char *s, int format) fclose(f); } -static struct -{ - int x, y, y1, y2, w, h; - int busy; - int buffer_in_use; - - thread_t *blit_thread; - event_t *wake_blit_thread; - event_t *blit_complete; - event_t *buffer_not_in_use; -} blit_data; - -static void blit_thread(void *param); +// static struct +// { +// int x, y, y1, y2, w, h; +// int busy; +// int buffer_in_use; +// + // thread_t *blit_thread; + // event_t *wake_blit_thread; + // event_t *blit_complete; + // event_t *buffer_not_in_use; +// } blit_data; + +// static void blit_thread(void *param); uint32_t cgapal[16]; @@ -937,18 +937,18 @@ void initvideo() cgapal_rebuild(DISPLAY_RGB, 0); - blit_data.wake_blit_thread = thread_create_event(); - blit_data.blit_complete = thread_create_event(); - blit_data.buffer_not_in_use = thread_create_event(); - blit_data.blit_thread = thread_create(blit_thread, NULL); + // blit_data.wake_blit_thread = thread_create_event(); + // blit_data.blit_complete = thread_create_event(); + // blit_data.buffer_not_in_use = thread_create_event(); + // blit_data.blit_thread = thread_create(blit_thread, NULL); } void closevideo() { - thread_kill(blit_data.blit_thread); - thread_destroy_event(blit_data.buffer_not_in_use); - thread_destroy_event(blit_data.blit_complete); - thread_destroy_event(blit_data.wake_blit_thread); + // thread_kill(blit_data.blit_thread); + // thread_destroy_event(blit_data.buffer_not_in_use); + // thread_destroy_event(blit_data.blit_complete); + // thread_destroy_event(blit_data.wake_blit_thread); free(video_15to32); free(video_16to32); @@ -956,37 +956,37 @@ void closevideo() } -static void blit_thread(void *param) -{ - while (1) - { - thread_wait_event(blit_data.wake_blit_thread, -1); - thread_reset_event(blit_data.wake_blit_thread); - - video_blit_memtoscreen_func(blit_data.x, blit_data.y, blit_data.y1, blit_data.y2, blit_data.w, blit_data.h); - - blit_data.busy = 0; - thread_set_event(blit_data.blit_complete); - } -} +// static void blit_thread(void *param) +// { +// while (1) +// { +// thread_wait_event(blit_data.wake_blit_thread, -1); +// thread_reset_event(blit_data.wake_blit_thread); +// +// video_blit_memtoscreen_func(blit_data.x, blit_data.y, blit_data.y1, blit_data.y2, blit_data.w, blit_data.h); +// +// blit_data.busy = 0; +// thread_set_event(blit_data.blit_complete); +// } +// } void video_blit_complete() { - blit_data.buffer_in_use = 0; - thread_set_event(blit_data.buffer_not_in_use); + // blit_data.buffer_in_use = 0; + // thread_set_event(blit_data.buffer_not_in_use); } void video_wait_for_blit() { - while (blit_data.busy) - thread_wait_event(blit_data.blit_complete, 1); - thread_reset_event(blit_data.blit_complete); + // while (blit_data.busy) + // thread_wait_event(blit_data.blit_complete, 1); + // thread_reset_event(blit_data.blit_complete); } void video_wait_for_buffer() { - while (blit_data.buffer_in_use) - thread_wait_event(blit_data.buffer_not_in_use, 1); - thread_reset_event(blit_data.buffer_not_in_use); + // while (blit_data.buffer_in_use) + // thread_wait_event(blit_data.buffer_not_in_use, 1); + // thread_reset_event(blit_data.buffer_not_in_use); } void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) @@ -994,16 +994,16 @@ void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) video_frames++; if (h <= 0) return; - video_wait_for_blit(); - blit_data.busy = 1; - blit_data.buffer_in_use = 1; - blit_data.x = x; - blit_data.y = y; - blit_data.y1 = y1; - blit_data.y2 = y2; - blit_data.w = w; - blit_data.h = h; - thread_set_event(blit_data.wake_blit_thread); + // video_wait_for_blit(); + // blit_data.busy = 1; + // blit_data.buffer_in_use = 1; + // blit_data.x = x; + // blit_data.y = y; + // blit_data.y1 = y1; + // blit_data.y2 = y2; + // blit_data.w = w; + // blit_data.h = h; + video_blit_memtoscreen_func(x, y, y1, y2, w, h); } void cgapal_rebuild(int display_type, int contrast) diff --git a/src/wx-sdl2-display-win.c b/src/wx-sdl2-display-win.c index cb0fcb8..cbc4dae 100644 --- a/src/wx-sdl2-display-win.c +++ b/src/wx-sdl2-display-win.c @@ -306,7 +306,7 @@ LRESULT CALLBACK subWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPAR int display_init() { - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) + if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("SDL could not initialize! Error: %s\n", SDL_GetError()); return 0; diff --git a/src/wx-sdl2-display.c b/src/wx-sdl2-display.c index 239c8e1..7c83c5f 100644 --- a/src/wx-sdl2-display.c +++ b/src/wx-sdl2-display.c @@ -1,5 +1,6 @@ #include <SDL2/SDL.h> #include "video.h" +#include "wx-sdl2.h" #include "wx-sdl2-video.h" #include "wx-utils.h" #include "ibm.h" @@ -85,7 +86,7 @@ void releasemouse() int display_init() { - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) + if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("SDL could not initialize! Error: %s\n", SDL_GetError()); return 0; @@ -690,7 +691,21 @@ int renderer_thread(void* params) if (!render()) internal_rendering = 0; - SDL_Delay(1); + SDL_LockMutex(syncMutex); + syncRender = 0; + SDL_CondSignal(syncCond); + SDL_UnlockMutex(syncMutex); + + if (!rendering || !internal_rendering) + break; + + SDL_LockMutex(syncMutex); + while (!syncRender) { + SDL_CondWait(syncCond, syncMutex); + } + SDL_UnlockMutex(syncMutex); + + // SDL_Delay(1); } window_close(); } @@ -760,7 +775,12 @@ void renderer_stop(int timeout) if (rendering) { SDL_LockMutex(rendererMutex); + SDL_LockMutex(syncMutex); rendering = 0; + syncRender = 1; + SDL_CondSignal(syncCond); + SDL_UnlockMutex(syncMutex); + if (timeout) SDL_CondWaitTimeout(rendererCond, rendererMutex, timeout); else diff --git a/src/wx-sdl2-video-renderer.c b/src/wx-sdl2-video-renderer.c index 7a53092..e109761 100644 --- a/src/wx-sdl2-video-renderer.c +++ b/src/wx-sdl2-video-renderer.c @@ -156,7 +156,7 @@ sdl_renderer_t* sdl2_renderer_create() renderer->close = sdl_video_renderer_close; renderer->update = sdl_video_renderer_update; renderer->present = sdl_video_renderer_present; - renderer->always_update = 0; + renderer->always_update = 1; return renderer; } diff --git a/src/wx-sdl2.c b/src/wx-sdl2.c index f926af0..ac9eba5 100644 --- a/src/wx-sdl2.c +++ b/src/wx-sdl2.c @@ -70,6 +70,11 @@ SDL_cond* mainCond; SDL_Thread* mainthreadh = NULL; +SDL_mutex* syncMutex; +SDL_cond* syncCond; +int syncRender = 1; + + SDL_TimerID onesectimer; int running = 0; @@ -188,6 +193,12 @@ int mainthread(void* param) running = 1; while (running) { + SDL_LockMutex(syncMutex); + while (syncRender) { + SDL_CondWait(syncCond, syncMutex); + } + SDL_UnlockMutex(syncMutex); + new_time = SDL_GetTicks(); drawits += new_time - old_time; old_time = new_time; @@ -197,8 +208,6 @@ int mainthread(void* param) uint64_t start_time = timer_read(); uint64_t end_time; drawits -= 10; - if (drawits > 50) - drawits = 0; runpc(); frames++; if (frames >= 200 && nvr_dosave) @@ -212,6 +221,11 @@ int mainthread(void* param) } else SDL_Delay(1); + + SDL_LockMutex(syncMutex); + syncRender = 1; + SDL_CondSignal(syncCond); + SDL_UnlockMutex(syncMutex); } SDL_LockMutex(mainMutex); @@ -624,6 +638,9 @@ int start_emulation(void* params) mainMutex = SDL_CreateMutex(); mainCond = SDL_CreateCond(); + syncMutex = SDL_CreateMutex(); + syncCond = SDL_CreateCond(); + if (!loadbios()) { if (romset != -1) @@ -665,7 +682,7 @@ int start_emulation(void* params) display_start(params); mainthreadh = SDL_CreateThread(mainthread, "Main Thread", NULL); - onesectimer = SDL_AddTimer(1000, timer_onesec, NULL); + // onesectimer = SDL_AddTimer(1000, timer_onesec, NULL); updatewindowsize(640, 480); @@ -697,14 +714,22 @@ int stop_emulation() SDL_DestroyCond(mainCond); SDL_DestroyMutex(mainMutex); + SDL_LockMutex(syncMutex); + syncRender = 0; + SDL_CondSignal(syncCond); + SDL_UnlockMutex(syncMutex); + startblit(); display_stop(); + SDL_DestroyCond(syncCond); + SDL_DestroyMutex(syncMutex); + #if SDL_VERSION_ATLEAST(2, 0, 2) SDL_DetachThread(mainthreadh); #endif mainthreadh = NULL; - SDL_RemoveTimer(onesectimer); + // SDL_RemoveTimer(onesectimer); savenvr(); saveconfig(NULL); diff --git a/src/wx-sdl2.h b/src/wx-sdl2.h index 416ed96..8c16faf 100644 --- a/src/wx-sdl2.h +++ b/src/wx-sdl2.h @@ -1,3 +1,5 @@ +#include <SDL2/SDL.h> + #ifdef __cplusplus extern "C" { #endif @@ -16,3 +18,7 @@ extern char openfilestring[260]; extern int pause; extern int take_screenshot; + +extern SDL_mutex* syncMutex; +extern SDL_cond* syncCond; +extern int syncRender;
Optional Paste Settings
Category:
None
Cryptocurrency
Cybersecurity
Fixit
Food
Gaming
Haiku
Help
History
Housing
Jokes
Legal
Money
Movies
Music
Pets
Photo
Science
Software
Source Code
Spirit
Sports
Travel
TV
Writing
Tags:
Syntax Highlighting:
None
Bash
C
C#
C++
CSS
HTML
JSON
Java
JavaScript
Lua
Markdown (PRO members only)
Objective C
PHP
Perl
Python
Ruby
Swift
4CS
6502 ACME Cross Assembler
6502 Kick Assembler
6502 TASM/64TASS
ABAP
AIMMS
ALGOL 68
APT Sources
ARM
ASM (NASM)
ASP
ActionScript
ActionScript 3
Ada
Apache Log
AppleScript
Arduino
Asymptote
AutoIt
Autohotkey
Avisynth
Awk
BASCOM AVR
BNF
BOO
Bash
Basic4GL
Batch
BibTeX
Blitz Basic
Blitz3D
BlitzMax
BrainFuck
C
C (WinAPI)
C Intermediate Language
C for Macs
C#
C++
C++ (WinAPI)
C++ (with Qt extensions)
C: Loadrunner
CAD DCL
CAD Lisp
CFDG
CMake
COBOL
CSS
Ceylon
ChaiScript
Chapel
Clojure
Clone C
Clone C++
CoffeeScript
ColdFusion
Cuesheet
D
DCL
DCPU-16
DCS
DIV
DOT
Dart
Delphi
Delphi Prism (Oxygene)
Diff
E
ECMAScript
EPC
Easytrieve
Eiffel
Email
Erlang
Euphoria
F#
FO Language
Falcon
Filemaker
Formula One
Fortran
FreeBasic
FreeSWITCH
GAMBAS
GDB
GDScript
Game Maker
Genero
Genie
GetText
Go
Godot GLSL
Groovy
GwBasic
HQ9 Plus
HTML
HTML 5
Haskell
Haxe
HicEst
IDL
INI file
INTERCAL
IO
ISPF Panel Definition
Icon
Inno Script
J
JCL
JSON
Java
Java 5
JavaScript
Julia
KSP (Kontakt Script)
KiXtart
Kotlin
LDIF
LLVM
LOL Code
LScript
Latex
Liberty BASIC
Linden Scripting
Lisp
Loco Basic
Logtalk
Lotus Formulas
Lotus Script
Lua
M68000 Assembler
MIX Assembler
MK-61/52
MPASM
MXML
MagikSF
Make
MapBasic
Markdown (PRO members only)
MatLab
Mercury
MetaPost
Modula 2
Modula 3
Motorola 68000 HiSoft Dev
MySQL
Nagios
NetRexx
Nginx
Nim
NullSoft Installer
OCaml
OCaml Brief
Oberon 2
Objeck Programming Langua
Objective C
Octave
Open Object Rexx
OpenBSD PACKET FILTER
OpenGL Shading
Openoffice BASIC
Oracle 11
Oracle 8
Oz
PARI/GP
PCRE
PHP
PHP Brief
PL/I
PL/SQL
POV-Ray
ParaSail
Pascal
Pawn
Per
Perl
Perl 6
Phix
Pic 16
Pike
Pixel Bender
PostScript
PostgreSQL
PowerBuilder
PowerShell
ProFTPd
Progress
Prolog
Properties
ProvideX
Puppet
PureBasic
PyCon
Python
Python for S60
QBasic
QML
R
RBScript
REBOL
REG
RPM Spec
Racket
Rails
Rexx
Robots
Roff Manpage
Ruby
Ruby Gnuplot
Rust
SAS
SCL
SPARK
SPARQL
SQF
SQL
SSH Config
Scala
Scheme
Scilab
SdlBasic
Smalltalk
Smarty
StandardML
StoneScript
SuperCollider
Swift
SystemVerilog
T-SQL
TCL
TeXgraph
Tera Term
TypeScript
TypoScript
UPC
Unicon
UnrealScript
Urbi
VB.NET
VBScript
VHDL
VIM
Vala
Vedit
VeriLog
Visual Pro Log
VisualBasic
VisualFoxPro
WHOIS
WhiteSpace
Winbatch
XBasic
XML
XPP
Xojo
Xorg Config
YAML
YARA
Z80 Assembler
ZXBasic
autoconf
jQuery
mIRC
newLISP
q/kdb+
thinBasic
Paste Expiration:
Never
Burn after read
10 Minutes
1 Hour
1 Day
1 Week
2 Weeks
1 Month
6 Months
1 Year
Paste Exposure:
Public
Unlisted
Private
Folder:
(members only)
Password
NEW
Enabled
Disabled
Burn after read
NEW
Paste Name / Title:
Create New Paste
Hello
Guest
Sign Up
or
Login
Sign in with Facebook
Sign in with Twitter
Sign in with Google
You are currently not logged in, this means you can not edit or delete anything you paste.
Sign Up
or
Login
Public Pastes
I made $15,000 * 2 hours
CSS | 11 min ago | 0.99 KB
✅ API Glitch (Docs Leak)
CSS | 11 min ago | 0.99 KB
Custom Placeholder: Event Image using alt tag...
12 hours ago | 0.50 KB
Untitled
Bash | 22 hours ago | 1.17 KB
Using Prepared statement with bind vars to pr...
Go | 1 day ago | 3.67 KB
rc
2 days ago | 2.49 KB
Stripe Session Vars
2 days ago | 0.67 KB
[TLF 16] Hylandra's File / Introduction
2 days ago | 3.37 KB
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the
Cookies Policy
.
OK, I Understand
Not a member of Pastebin yet?
Sign Up
, it unlocks many cool features!