Guest User

Untitled

a guest
Mar 1st, 2014
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 80.67 KB | None | 0 0
  1. /*S3 emulation*/
  2. #include <stdlib.h>
  3. #include "ibm.h"
  4. #include "device.h"
  5. #include "io.h"
  6. #include "mem.h"
  7. #include "pci.h"
  8. #include "video.h"
  9. #include "vid_s3.h"
  10. #include "vid_svga.h"
  11. #include "vid_svga_render.h"
  12. #include "vid_sdac_ramdac.h"
  13.  
  14. typedef struct s3_t
  15. {
  16. mem_mapping_t linear_mapping;
  17. mem_mapping_t mmio_mapping;
  18.  
  19. svga_t svga;
  20. sdac_ramdac_t ramdac;
  21.  
  22. uint8_t bank;
  23. uint8_t ma_ext;
  24. int width;
  25. int bpp;
  26.  
  27. uint8_t id, id_ext;
  28.  
  29. uint32_t linear_base, linear_size;
  30.  
  31. float (*getclock)(int clock, void *p);
  32. void *getclock_p;
  33.  
  34. struct
  35. {
  36. uint8_t subsys_cntl;
  37. uint8_t setup_md;
  38. uint8_t advfunc_cntl;
  39. uint16_t cur_y;
  40. uint16_t cur_x;
  41. int16_t desty_axstp;
  42. int16_t destx_distp;
  43. int16_t err_term;
  44. int16_t maj_axis_pcnt;
  45. uint16_t cmd;
  46. uint16_t short_stroke;
  47. uint32_t bkgd_color;
  48. uint32_t frgd_color;
  49. uint32_t wrt_mask;
  50. uint32_t rd_mask;
  51. uint32_t color_cmp;
  52. uint8_t bkgd_mix;
  53. uint8_t frgd_mix;
  54. uint16_t multifunc_cntl;
  55. uint16_t multifunc[16];
  56. uint8_t pix_trans[4];
  57.  
  58. int cx, cy;
  59. int sx, sy;
  60. int dx, dy;
  61. uint32_t src, dest, pattern;
  62. int pix_trans_count;
  63.  
  64. uint32_t dat_buf;
  65. int dat_count;
  66. } accel;
  67. } s3_t;
  68.  
  69. void s3_updatemapping();
  70.  
  71. void s3_accel_write(uint32_t addr, uint8_t val, void *p);
  72. void s3_accel_write_w(uint32_t addr, uint16_t val, void *p);
  73. void s3_accel_write_l(uint32_t addr, uint32_t val, void *p);
  74. uint8_t s3_accel_read(uint32_t addr, void *p);
  75.  
  76.  
  77. void s3_out(uint16_t addr, uint8_t val, void *p)
  78. {
  79. s3_t *s3 = (s3_t *)p;
  80. svga_t *svga = &s3->svga;
  81. uint8_t old;
  82.  
  83. if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
  84. addr ^= 0x60;
  85.  
  86. pclog("S3 out %04X %02X\n", addr, val);
  87.  
  88. switch (addr)
  89. {
  90. case 0x3c5:
  91. if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20)
  92. {
  93. svga->seqregs[svga->seqaddr] = val;
  94. switch (svga->seqaddr)
  95. {
  96. case 0x12: case 0x13:
  97. svga_recalctimings(svga);
  98. return;
  99. }
  100. }
  101. if (svga->seqaddr == 4) /*Chain-4 - update banking*/
  102. {
  103. if (val & 8) svga->write_bank = svga->read_bank = s3->bank << 16;
  104. else svga->write_bank = svga->read_bank = s3->bank << 14;
  105. }
  106. break;
  107.  
  108. case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
  109. // pclog("Write RAMDAC %04X %02X %04X:%04X\n", addr, val, CS, pc);
  110. sdac_ramdac_out(addr, val, &s3->ramdac, svga);
  111. return;
  112.  
  113. case 0x3D4:
  114. svga->crtcreg = val & 0x7f;
  115. return;
  116. case 0x3D5:
  117. // if (crtcreg == 0x67) pclog("Write CRTC R%02X %02X\n", crtcreg, val);
  118. if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return;
  119. if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) return;
  120. old = svga->crtc[svga->crtcreg];
  121. svga->crtc[svga->crtcreg] = val;
  122. switch (svga->crtcreg)
  123. {
  124. case 0x31:
  125. s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4);
  126. svga->vrammask = /*(val & 8) ? */0x3fffff/* : 0x3ffff*/;
  127. break;
  128.  
  129. case 0x50:
  130. switch (svga->crtc[0x50] & 0xc1)
  131. {
  132. case 0x00: s3->width = (svga->crtc[0x31] & 2) ? 2048 : 1024; break;
  133. case 0x01: s3->width = 1152; break;
  134. case 0x40: s3->width = 640; break;
  135. case 0x80: s3->width = 800; break;
  136. case 0x81: s3->width = 1600; break;
  137. case 0xc0: s3->width = 1280; break;
  138. }
  139. s3->bpp = (svga->crtc[0x50] >> 4) & 3;
  140. break;
  141. case 0x69:
  142. s3->ma_ext = val & 0x1f;
  143. break;
  144.  
  145. case 0x35:
  146. s3->bank = (s3->bank & 0x70) | (val & 0xf);
  147. // pclog("CRTC write R35 %02X\n", val);
  148. if (svga->chain4) svga->write_bank = svga->read_bank = s3->bank << 16;
  149. else svga->write_bank = svga->read_bank = s3->bank << 14;
  150. break;
  151. case 0x51:
  152. s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2);
  153. // pclog("CRTC write R51 %02X\n", val);
  154. if (svga->chain4) svga->write_bank = svga->read_bank = s3->bank << 16;
  155. else svga->write_bank = svga->read_bank = s3->bank << 14;
  156. s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2);
  157. break;
  158. case 0x6a:
  159. s3->bank = val;
  160. // pclog("CRTC write R6a %02X\n", val);
  161. if (svga->chain4) svga->write_bank = svga->read_bank = s3->bank << 16;
  162. else svga->write_bank = svga->read_bank = s3->bank << 14;
  163. break;
  164.  
  165. case 0x3a:
  166. if (val & 0x10)
  167. svga->gdcreg[5] |= 0x40; /*Horrible cheat*/
  168. break;
  169.  
  170. case 0x45:
  171. svga->hwcursor.ena = val & 1;
  172. break;
  173. case 0x48:
  174. svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff;
  175. if (svga->bpp == 32) svga->hwcursor.x >>= 1;
  176. svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff;
  177. svga->hwcursor.xoff = svga->crtc[0x4e] & 63;
  178. svga->hwcursor.yoff = svga->crtc[0x4f] & 63;
  179. svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16);
  180. if (gfxcard == GFX_N9_9FX && svga->bpp == 32) /*Trio64*/
  181. svga->hwcursor.x <<= 1;
  182. break;
  183.  
  184. case 0x53:
  185. case 0x58: case 0x59: case 0x5a:
  186. s3_updatemapping(s3);
  187. break;
  188.  
  189. case 0x67:
  190. if (gfxcard == GFX_N9_9FX) /*Trio64*/
  191. {
  192. switch (val >> 4)
  193. {
  194. case 3: svga->bpp = 15; break;
  195. case 5: svga->bpp = 16; break;
  196. case 7: svga->bpp = 24; break;
  197. case 13: svga->bpp = 32; break;
  198. default: svga->bpp = 8; break;
  199. }
  200. }
  201. break;
  202. //case 0x55: case 0x43:
  203. // pclog("Write CRTC R%02X %02X\n", crtcreg, val);
  204. }
  205. if (old != val)
  206. {
  207. if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
  208. {
  209. svga->fullchange = changeframecount;
  210. svga_recalctimings(svga);
  211. }
  212. }
  213. break;
  214. }
  215. svga_out(addr, val, svga);
  216. }
  217.  
  218. uint8_t s3_in(uint16_t addr, void *p)
  219. {
  220. s3_t *s3 = (s3_t *)p;
  221. svga_t *svga = &s3->svga;
  222.  
  223. if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
  224. addr ^= 0x60;
  225.  
  226. if (addr != 0x3da) pclog("S3 in %04X\n", addr);
  227. switch (addr)
  228. {
  229. case 0x3c5:
  230. if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20)
  231. return svga->seqregs[svga->seqaddr];
  232. break;
  233.  
  234. case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9:
  235. // pclog("Read RAMDAC %04X %04X:%04X\n", addr, CS, pc);
  236. return sdac_ramdac_in(addr, &s3->ramdac, svga);
  237.  
  238. case 0x3d4:
  239. return svga->crtcreg;
  240. case 0x3d5:
  241. // pclog("Read CRTC R%02X %04X:%04X\n", crtcreg, CS, pc);
  242. switch (svga->crtcreg)
  243. {
  244. case 0x2d: return 0x88; /*Extended chip ID*/
  245. case 0x2e: return s3->id_ext; /*New chip ID*/
  246. case 0x30: return s3->id; /*Chip ID*/
  247. case 0x31: return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4);
  248. case 0x35: return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf);
  249. case 0x51: return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3);
  250. case 0x69: return s3->ma_ext;
  251. case 0x6a: return s3->bank;
  252. }
  253. return svga->crtc[svga->crtcreg];
  254. }
  255. return svga_in(addr, svga);
  256. }
  257.  
  258. void s3_recalctimings(svga_t *svga)
  259. {
  260. s3_t *s3 = (s3_t *)svga->p;
  261. svga->hdisp = svga->hdisp_old;
  262.  
  263. // pclog("%i %i\n", svga->hdisp, svga->hdisp_time);
  264. // pclog("recalctimings\n");
  265. svga->ma_latch |= (s3->ma_ext << 16);
  266. // pclog("SVGA_MA %08X\n", svga_ma);
  267. if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100;
  268. if (svga->crtc[0x5d] & 0x02)
  269. {
  270. svga->hdisp_time += 0x100;
  271. svga->hdisp += 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8);
  272. }
  273. if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400;
  274. if (svga->crtc[0x5e] & 0x02) svga->dispend += 0x400;
  275. if (svga->crtc[0x5e] & 0x10) svga->vsyncstart += 0x400;
  276. if (svga->crtc[0x5e] & 0x40) svga->split += 0x400;
  277. if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4;
  278. else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100;
  279. if (!svga->rowoffset) svga->rowoffset = 256;
  280. svga->interlace = svga->crtc[0x42] & 0x20;
  281. svga->clock = cpuclock / s3->getclock((svga->miscout >> 2) & 3, s3->getclock_p);
  282.  
  283. switch (svga->crtc[0x67] >> 4)
  284. {
  285. case 3: case 5: case 7:
  286. svga->clock /= 2;
  287. break;
  288. }
  289.  
  290. svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10));
  291. if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10))
  292. {
  293. switch (svga->bpp)
  294. {
  295. case 8:
  296. svga->render = svga_render_8bpp_highres;
  297. break;
  298. case 15:
  299. svga->render = svga_render_15bpp_highres;
  300. svga->hdisp /= 2;
  301. break;
  302. case 16:
  303. svga->render = svga_render_16bpp_highres;
  304. svga->hdisp /= 2;
  305. break;
  306. case 24:
  307. svga->render = svga_render_24bpp_highres;
  308. svga->hdisp /= 3;
  309. break;
  310. case 32:
  311. svga->render = svga_render_32bpp_highres;
  312. if (gfxcard != GFX_N9_9FX) /*Trio64*/
  313. svga->hdisp /= 4;
  314. break;
  315. }
  316. }
  317. }
  318.  
  319. void s3_updatemapping(s3_t *s3)
  320. {
  321. svga_t *svga = &s3->svga;
  322.  
  323. // video_write_a000_w = video_write_a000_l = NULL;
  324.  
  325.  
  326. // pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc);
  327. switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/
  328. {
  329. case 0x0: /*128k at A0000*/
  330. mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
  331. svga->banked_mask = 0xffff;
  332. break;
  333. case 0x4: /*64k at A0000*/
  334. mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
  335. svga->banked_mask = 0xffff;
  336. break;
  337. case 0x8: /*32k at B0000*/
  338. mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
  339. svga->banked_mask = 0x7fff;
  340. break;
  341. case 0xC: /*32k at B8000*/
  342. mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
  343. svga->banked_mask = 0x7fff;
  344. break;
  345. }
  346.  
  347. // pclog("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10);
  348. if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/
  349. {
  350. mem_mapping_disable(&svga->mapping);
  351.  
  352. s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24);
  353. switch (svga->crtc[0x58] & 3)
  354. {
  355. case 0: /*64k*/
  356. s3->linear_size = 0x10000;
  357. break;
  358. case 1: /*1mb*/
  359. s3->linear_size = 0x100000;
  360. break;
  361. case 2: /*2mb*/
  362. s3->linear_size = 0x200000;
  363. break;
  364. case 3: /*8mb*/
  365. s3->linear_size = 0x800000;
  366. break;
  367. }
  368. s3->linear_base &= ~(s3->linear_size - 1);
  369. // pclog("%08X %08X %02X %02X %02X\n", linear_base, linear_size, crtc[0x58], crtc[0x59], crtc[0x5a]);
  370. // pclog("Linear framebuffer at %08X size %08X\n", s3->linear_base, s3->linear_size);
  371. if (s3->linear_base == 0xa0000)
  372. {
  373. mem_mapping_disable(&s3->linear_mapping);
  374. mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
  375. svga->banked_mask = 0xffff;
  376. // mem_mapping_set_addr(&s3->linear_mapping, 0xa0000, 0x10000);
  377. }
  378. else
  379. mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size);
  380. }
  381. else
  382. mem_mapping_disable(&s3->linear_mapping);
  383.  
  384. // pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x10);
  385. if (svga->crtc[0x53] & 0x10) /*Memory mapped IO*/
  386. mem_mapping_enable(&s3->mmio_mapping);
  387. else
  388. mem_mapping_disable(&s3->mmio_mapping);
  389. }
  390.  
  391. static float s3_trio64_getclock(int clock, void *p)
  392. {
  393. s3_t *s3 = (s3_t *)p;
  394. svga_t *svga = &s3->svga;
  395. float t;
  396. int m, n1, n2;
  397. // pclog("Trio64_getclock %i %02X %02X\n", clock, svga->seqregs[0x13], svga->seqregs[0x12]);
  398. if (clock == 0) return 25175000.0;
  399. if (clock == 1) return 28322000.0;
  400. m = svga->seqregs[0x13] + 2;
  401. n1 = (svga->seqregs[0x12] & 0x1f) + 2;
  402. n2 = ((svga->seqregs[0x12] >> 5) & 0x07);
  403. t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2);
  404. // pclog("TRIO64 clock %i %i %i %f %f %i\n", m, n1, n2, t, 14318184.0 * ((float)m / (float)n1), 1 << n2);
  405. return t;
  406. }
  407.  
  408.  
  409. void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3);
  410.  
  411. void s3_accel_out(uint16_t port, uint8_t val, void *p)
  412. {
  413. s3_t *s3 = (s3_t *)p;
  414. pclog("Accel out %04X %02X\n", port, val);
  415. switch (port)
  416. {
  417. case 0x42e8:
  418. break;
  419. case 0x42e9:
  420. s3->accel.subsys_cntl = val;
  421. break;
  422. case 0x46e8:
  423. s3->accel.setup_md = val;
  424. break;
  425. case 0x4ae8:
  426. s3->accel.advfunc_cntl = val;
  427. break;
  428.  
  429. case 0x8100:
  430. case 0x82e8:
  431. s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val;
  432. break;
  433. case 0x8101:
  434. case 0x82e9:
  435. s3->accel.cur_y = (s3->accel.cur_y & 0xff) | ((val & 0x1f) << 8);
  436. break;
  437.  
  438. case 0x8102:
  439. case 0x86e8:
  440. s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val;
  441. break;
  442. case 0x8103:
  443. case 0x86e9:
  444. s3->accel.cur_x = (s3->accel.cur_x & 0xff) | ((val & 0x1f) << 8);
  445. break;
  446.  
  447. case 0x8108:
  448. case 0x8ae8:
  449. s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val;
  450. break;
  451. case 0x8109:
  452. case 0x8ae9:
  453. s3->accel.desty_axstp = (s3->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8);
  454. if (val & 0x20)
  455. s3->accel.desty_axstp |= ~0x3fff;
  456. break;
  457.  
  458. case 0x810a:
  459. case 0x8ee8:
  460. s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val;
  461. break;
  462.  
  463. case 0x810b:
  464. case 0x8ee9:
  465. s3->accel.destx_distp = (s3->accel.destx_distp & 0xff) | ((val & 0x3f) << 8);
  466. if (val & 0x20)
  467. s3->accel.destx_distp |= ~0x3fff;
  468. break;
  469.  
  470. case 0x92e8:
  471. s3->accel.err_term = (s3->accel.err_term & 0x3f00) | val;
  472. break;
  473. case 0x92e9:
  474. s3->accel.err_term = (s3->accel.err_term & 0xff) | ((val & 0x3f) << 8);
  475. if (val & 0x20)
  476. s3->accel.err_term |= ~0x3fff;
  477. break;
  478.  
  479. case 0x814a:
  480. case 0x96e8:
  481. s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0x3f00) | val;
  482. break;
  483. case 0x814b:
  484. case 0x96e9:
  485. s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xff) | ((val & 0x0f) << 8);
  486. if (val & 0x08)
  487. s3->accel.maj_axis_pcnt |= ~0x0fff;
  488. break;
  489.  
  490. case 0x8118:
  491. case 0x9ae8:
  492. s3->accel.cmd = (s3->accel.cmd & 0xff00) | val;
  493. break;
  494. case 0x8119:
  495. case 0x9ae9:
  496. s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8);
  497. s3_accel_start(-1, 0, 0xffffffff, 0, s3);
  498. s3->accel.pix_trans_count = 0;
  499. break;
  500.  
  501. case 0x9ee8:
  502. s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val;
  503. break;
  504. case 0x9ee9:
  505. s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8);
  506. break;
  507.  
  508. case 0x8120:
  509. case 0xa2e8:
  510. if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10)
  511. s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16);
  512. else
  513. s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val;
  514. break;
  515. case 0x8121:
  516. case 0xa2e9:
  517. if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10)
  518. s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24);
  519. else
  520. s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8);
  521. s3->accel.multifunc[0xe] ^= 0x10;
  522. break;
  523.  
  524. case 0x8124:
  525. case 0xa6e8:
  526. if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10)
  527. s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16);
  528. else
  529. s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val;
  530. // pclog("Foreground colour now %08X %i\n", s3->accel.frgd_color, s3->bpp);
  531. break;
  532. case 0x8125:
  533. case 0xa6e9:
  534. if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10)
  535. s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24);
  536. else
  537. s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8);
  538. s3->accel.multifunc[0xe] ^= 0x10;
  539. // pclog("Foreground colour now %08X\n", s3->accel.frgd_color);
  540. break;
  541.  
  542. case 0x8128:
  543. case 0xaae8:
  544. if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10)
  545. s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16);
  546. else
  547. s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val;
  548. break;
  549. case 0x8129:
  550. case 0xaae9:
  551. if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10)
  552. s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24);
  553. else
  554. s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8);
  555. s3->accel.multifunc[0xe] ^= 0x10;
  556. break;
  557.  
  558. case 0x812c:
  559. case 0xaee8:
  560. if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10)
  561. s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16);
  562. else
  563. s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val;
  564. break;
  565. case 0x812d:
  566. case 0xaee9:
  567. if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10)
  568. s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24);
  569. else
  570. s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8);
  571. s3->accel.multifunc[0xe] ^= 0x10;
  572. break;
  573.  
  574. case 0xb2e8:
  575. if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10)
  576. s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16);
  577. else
  578. s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val;
  579. break;
  580. case 0xb2e9:
  581. if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10)
  582. s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24);
  583. else
  584. s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8);
  585. s3->accel.multifunc[0xe] ^= 0x10;
  586. break;
  587.  
  588. case 0x8134:
  589. case 0xb6e8:
  590. s3->accel.bkgd_mix = val;
  591. break;
  592.  
  593. case 0x8136:
  594. case 0xbae8:
  595. s3->accel.frgd_mix = val;
  596. break;
  597.  
  598. case 0x8138:
  599. s3->accel.multifunc[1] = (s3->accel.multifunc[1] & 0xff00) | (val << 0);
  600. break;
  601. case 0x8139:
  602. s3->accel.multifunc[1] = (s3->accel.multifunc[1] & 0x00ff) | (val << 8);
  603. break;
  604.  
  605. case 0x813a:
  606. s3->accel.multifunc[2] = (s3->accel.multifunc[2] & 0xff00) | (val << 0);
  607. break;
  608. case 0x813b:
  609. s3->accel.multifunc[2] = (s3->accel.multifunc[2] & 0x00ff) | (val << 8);
  610. break;
  611.  
  612. case 0x813c:
  613. s3->accel.multifunc[3] = (s3->accel.multifunc[3] & 0xff00) | (val << 0);
  614. break;
  615. case 0x813d:
  616. s3->accel.multifunc[3] = (s3->accel.multifunc[3] & 0x00ff) | (val << 8);
  617. break;
  618.  
  619. case 0x813e:
  620. s3->accel.multifunc[4] = (s3->accel.multifunc[4] & 0xff00) | (val << 0);
  621. break;
  622. case 0x813f:
  623. s3->accel.multifunc[4] = (s3->accel.multifunc[4] & 0x00ff) | (val << 8);
  624. break;
  625.  
  626. case 0x8148:
  627. s3->accel.multifunc[0] = (s3->accel.multifunc[0] & 0xff00) | (val << 0);
  628. break;
  629. case 0x8149:
  630. s3->accel.multifunc[0] = (s3->accel.multifunc[0] & 0x00ff) | (val << 8);
  631. break;
  632.  
  633. case 0xbee8:
  634. s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff00) | val;
  635. break;
  636. case 0xbee9:
  637. s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff) | (val << 8);
  638. s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff;
  639. break;
  640.  
  641. case 0xe2e8:
  642. s3->accel.pix_trans[0] = val;
  643. if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100))
  644. s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
  645. else if (!(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100))
  646. s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
  647. break;
  648. case 0xe2e9:
  649. s3->accel.pix_trans[1] = val;
  650. if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100))
  651. {
  652. if (s3->accel.cmd & 0x1000) s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3);
  653. else s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
  654. }
  655. else if ((s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100))
  656. {
  657. if (s3->accel.cmd & 0x1000) s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3);
  658. else s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
  659. }
  660. break;
  661. case 0xe2ea:
  662. s3->accel.pix_trans[2] = val;
  663. break;
  664. case 0xe2eb:
  665. s3->accel.pix_trans[3] = val;
  666. if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100))
  667. s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
  668. else if ((s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100))
  669. s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
  670. break;
  671. }
  672. }
  673.  
  674. void s3_accel_out_w(uint16_t port, uint16_t val, void *p)
  675. {
  676. s3_t *s3 = (s3_t *)p;
  677. // pclog("Accel out w %04X %04X\n", port, val);
  678. if (s3->accel.cmd & 0x100)
  679. {
  680. if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
  681. {
  682. if (s3->accel.cmd & 0x1000)
  683. val = (val >> 8) | (val << 8);
  684. s3_accel_start(16, 1, val | (val << 16), 0, s3);
  685. }
  686. else
  687. s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3);
  688. }
  689. }
  690.  
  691. void s3_accel_out_l(uint16_t port, uint32_t val, void *p)
  692. {
  693. s3_t *s3 = (s3_t *)p;
  694. pclog("Accel out l %04X %08X\n", port, val);
  695. if (s3->accel.cmd & 0x100)
  696. {
  697. if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
  698. {
  699. if (s3->accel.cmd & 0x1000)
  700. val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
  701. if ((s3->accel.cmd & 0x600) == 0x400)
  702. s3_accel_start(32, 1, val, 0, s3);
  703. else if ((s3->accel.cmd & 0x600) == 0x200)
  704. {
  705. s3_accel_start(16, 1, val >> 16, 0, s3);
  706. s3_accel_start(16, 1, val, 0, s3);
  707. }
  708. else if (!(s3->accel.cmd & 0x600))
  709. {
  710. s3_accel_start(8, 1, val >> 24, 0, s3);
  711. s3_accel_start(8, 1, val >> 16, 0, s3);
  712. s3_accel_start(8, 1, val >> 8, 0, s3);
  713. s3_accel_start(8, 1, val, 0, s3);
  714. }
  715. }
  716. else
  717. {
  718. if ((s3->accel.cmd & 0x600) == 0x400)
  719. s3_accel_start(4, 1, 0xffffffff, val, s3);
  720. else if ((s3->accel.cmd & 0x600) == 0x200)
  721. {
  722. s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
  723. s3_accel_start(2, 1, 0xffffffff, val, s3);
  724. }
  725. else if (!(s3->accel.cmd & 0x600))
  726. {
  727. s3_accel_start(1, 1, 0xffffffff, val >> 24, s3);
  728. s3_accel_start(1, 1, 0xffffffff, val >> 16, s3);
  729. s3_accel_start(1, 1, 0xffffffff, val >> 8, s3);
  730. s3_accel_start(1, 1, 0xffffffff, val, s3);
  731. }
  732. }
  733. }
  734. }
  735.  
  736. uint8_t s3_accel_in(uint16_t port, void *p)
  737. {
  738. s3_t *s3 = (s3_t *)p;
  739. int temp;
  740. pclog("Accel in %04X\n", port);
  741. switch (port)
  742. {
  743. case 0x42e8:
  744. return 0;
  745. case 0x42e9:
  746. return 0;
  747.  
  748. case 0x82e8:
  749. return s3->accel.cur_y & 0xff;
  750. case 0x82e9:
  751. return s3->accel.cur_y >> 8;
  752.  
  753. case 0x86e8:
  754. return s3->accel.cur_x & 0xff;
  755. case 0x86e9:
  756. return s3->accel.cur_x >> 8;
  757.  
  758. case 0x8ae8:
  759. return s3->accel.desty_axstp & 0xff;
  760. case 0x8ae9:
  761. return s3->accel.desty_axstp >> 8;
  762.  
  763. case 0x8ee8:
  764. return s3->accel.destx_distp & 0xff;
  765. case 0x8ee9:
  766. return s3->accel.destx_distp >> 8;
  767.  
  768. case 0x92e8:
  769. return s3->accel.err_term & 0xff;
  770. case 0x92e9:
  771. return s3->accel.err_term >> 8;
  772.  
  773. case 0x96e8:
  774. return s3->accel.maj_axis_pcnt & 0xff;
  775. case 0x96e9:
  776. return s3->accel.maj_axis_pcnt >> 8;
  777.  
  778. case 0x9ae8:
  779. return 0;
  780. case 0x9ae9:
  781. return 0;
  782.  
  783. case 0xa2e8:
  784. return s3->accel.bkgd_color & 0xff;
  785. case 0xa2e9:
  786. return s3->accel.bkgd_color >> 8;
  787.  
  788. case 0xa6e8:
  789. return s3->accel.frgd_color & 0xff;
  790. case 0xa6e9:
  791. return s3->accel.frgd_color >> 8;
  792.  
  793. case 0xaae8:
  794. return s3->accel.wrt_mask & 0xff;
  795. case 0xaae9:
  796. return s3->accel.wrt_mask >> 8;
  797.  
  798. case 0xaee8:
  799. return s3->accel.rd_mask & 0xff;
  800. case 0xaee9:
  801. return s3->accel.rd_mask >> 8;
  802.  
  803. case 0xb2e8:
  804. return s3->accel.color_cmp & 0xff;
  805. case 0xb2e9:
  806. return s3->accel.color_cmp >> 8;
  807.  
  808. case 0xb6e8:
  809. return s3->accel.bkgd_mix;
  810.  
  811. case 0xbae8:
  812. return s3->accel.frgd_mix;
  813.  
  814. case 0xbee8:
  815. temp = s3->accel.multifunc[0xf] & 0xf;
  816. switch (temp)
  817. {
  818. case 0x0: return s3->accel.multifunc[0x0] & 0xff;
  819. case 0x1: return s3->accel.multifunc[0x1] & 0xff;
  820. case 0x2: return s3->accel.multifunc[0x2] & 0xff;
  821. case 0x3: return s3->accel.multifunc[0x3] & 0xff;
  822. case 0x4: return s3->accel.multifunc[0x4] & 0xff;
  823. case 0x5: return s3->accel.multifunc[0xa] & 0xff;
  824. case 0x6: return s3->accel.multifunc[0xe] & 0xff;
  825. case 0x7: return s3->accel.cmd & 0xff;
  826. case 0x8: return s3->accel.subsys_cntl & 0xff;
  827. case 0x9: return s3->accel.setup_md & 0xff;
  828. case 0xa: return s3->accel.multifunc[0xd] & 0xff;
  829. }
  830. return 0xff;
  831. case 0xbee9:
  832. temp = s3->accel.multifunc[0xf] & 0xf;
  833. s3->accel.multifunc[0xf]++;
  834. switch (temp)
  835. {
  836. case 0x0: return s3->accel.multifunc[0x0] >> 8;
  837. case 0x1: return s3->accel.multifunc[0x1] >> 8;
  838. case 0x2: return s3->accel.multifunc[0x2] >> 8;
  839. case 0x3: return s3->accel.multifunc[0x3] >> 8;
  840. case 0x4: return s3->accel.multifunc[0x4] >> 8;
  841. case 0x5: return s3->accel.multifunc[0xa] >> 8;
  842. case 0x6: return s3->accel.multifunc[0xe] >> 8;
  843. case 0x7: return s3->accel.cmd >> 8;
  844. case 0x8: return (s3->accel.subsys_cntl >> 8) & ~0xe000;
  845. case 0x9: return (s3->accel.setup_md >> 8) & ~0xf000;
  846. case 0xa: return s3->accel.multifunc[0xd] >> 8;
  847. }
  848. return 0xff;
  849.  
  850. case 0xe2e8: case 0xe2e9: case 0xe2ea: case 0xe2eb: /*PIX_TRANS*/
  851. break;
  852. }
  853. return 0;
  854. }
  855.  
  856. void s3_accel_write(uint32_t addr, uint8_t val, void *p)
  857. {
  858. s3_t *s3 = (s3_t *)p;
  859. pclog("Write S3 accel %08X %02X\n", addr, val);
  860. if (addr & 0x8000)
  861. s3_accel_out(addr & 0xffff, val, p);
  862. else
  863. {
  864. if (s3->accel.cmd & 0x100)
  865. {
  866. if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
  867. s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3);
  868. else
  869. s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3);
  870. }
  871. }
  872. }
  873.  
  874. void s3_accel_write_w(uint32_t addr, uint16_t val, void *p)
  875. {
  876. s3_t *s3 = (s3_t *)p;
  877. pclog("Write S3 accel w %08X %04X\n", addr, val);
  878. if (addr & 0x8000)
  879. {
  880. s3_accel_out( addr & 0xffff, val, p);
  881. s3_accel_out((addr & 0xffff) + 1, val >> 8, p);
  882. }
  883. else
  884. {
  885. if (s3->accel.cmd & 0x100)
  886. {
  887. if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
  888. {
  889. if (s3->accel.cmd & 0x1000)
  890. val = (val >> 8) | (val << 8);
  891. s3_accel_start(16, 1, val | (val << 16), 0, s3);
  892. }
  893. else
  894. s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3);
  895. }
  896. }
  897. }
  898.  
  899. void s3_accel_write_l(uint32_t addr, uint32_t val, void *p)
  900. {
  901. s3_t *s3 = (s3_t *)p;
  902. pclog("Write S3 accel l %08X %08X\n", addr, val);
  903. if (addr & 0x8000)
  904. {
  905. s3_accel_out( addr & 0xffff, val, p);
  906. s3_accel_out((addr & 0xffff) + 1, val >> 8, p);
  907. s3_accel_out((addr & 0xffff) + 2, val >> 16, p);
  908. s3_accel_out((addr & 0xffff) + 3, val >> 24, p);
  909. }
  910. else
  911. {
  912. if (s3->accel.cmd & 0x100)
  913. {
  914. if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
  915. {
  916. if (s3->accel.cmd & 0x1000)
  917. val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
  918. if ((s3->accel.cmd & 0x600) == 0x400)
  919. s3_accel_start(32, 1, val, 0, s3);
  920. else if ((s3->accel.cmd & 0x600) == 0x200)
  921. {
  922. s3_accel_start(16, 1, val >> 16, 0, s3);
  923. s3_accel_start(16, 1, val, 0, s3);
  924. }
  925. else if (!(s3->accel.cmd & 0x600))
  926. {
  927. s3_accel_start(8, 1, val >> 24, 0, s3);
  928. s3_accel_start(8, 1, val >> 16, 0, s3);
  929. s3_accel_start(8, 1, val >> 8, 0, s3);
  930. s3_accel_start(8, 1, val, 0, s3);
  931. }
  932. }
  933. else
  934. {
  935. if ((s3->accel.cmd & 0x600) == 0x400)
  936. s3_accel_start(4, 1, 0xffffffff, val, s3);
  937. else if ((s3->accel.cmd & 0x600) == 0x200)
  938. {
  939. s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
  940. s3_accel_start(2, 1, 0xffffffff, val, s3);
  941. }
  942. else if (!(s3->accel.cmd & 0x600))
  943. {
  944. s3_accel_start(1, 1, 0xffffffff, val >> 24, s3);
  945. s3_accel_start(1, 1, 0xffffffff, val >> 16, s3);
  946. s3_accel_start(1, 1, 0xffffffff, val >> 8, s3);
  947. s3_accel_start(1, 1, 0xffffffff, val, s3);
  948. }
  949. }
  950. }
  951. }
  952. }
  953.  
  954. uint8_t s3_accel_read(uint32_t addr, void *p)
  955. {
  956. if (addr & 0x8000)
  957. return s3_accel_in(addr & 0xffff, p);
  958. return 0;
  959. }
  960.  
  961. #define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & 0x3fffff]; \
  962. else if (s3->bpp == 1) dat = vram_w[(addr) & 0x1fffff]; \
  963. else dat = vram_l[(addr) & 0x0fffff];
  964.  
  965. #define MIX switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \
  966. { \
  967. case 0x0: dest_dat = ~dest_dat; break; \
  968. case 0x1: dest_dat = 0; break; \
  969. case 0x2: dest_dat = 1; break; \
  970. case 0x3: dest_dat = dest_dat; break; \
  971. case 0x4: dest_dat = ~src_dat; break; \
  972. case 0x5: dest_dat = src_dat ^ dest_dat; break; \
  973. case 0x6: dest_dat = ~(src_dat ^ dest_dat); break; \
  974. case 0x7: dest_dat = src_dat; break; \
  975. case 0x8: dest_dat = ~(src_dat & dest_dat); break; \
  976. case 0x9: dest_dat = ~src_dat | dest_dat; break; \
  977. case 0xa: dest_dat = src_dat | ~dest_dat; break; \
  978. case 0xb: dest_dat = src_dat | dest_dat; break; \
  979. case 0xc: dest_dat = src_dat & dest_dat; break; \
  980. case 0xd: dest_dat = src_dat & ~dest_dat; break; \
  981. case 0xe: dest_dat = ~src_dat & dest_dat; break; \
  982. case 0xf: dest_dat = ~(src_dat | dest_dat); break; \
  983. }
  984.  
  985.  
  986. #define WRITE(addr) if (s3->bpp == 0) \
  987. { \
  988. svga->vram[(addr) & 0x3fffff] = dest_dat; \
  989. svga->changedvram[((addr) & 0x3fffff) >> 10] = changeframecount; \
  990. } \
  991. else if (s3->bpp == 1) \
  992. { \
  993. vram_w[(addr) & 0x1fffff] = dest_dat; \
  994. svga->changedvram[((addr) & 0x1fffff) >> 9] = changeframecount; \
  995. } \
  996. else \
  997. { \
  998. vram_l[(addr) & 0xfffff] = dest_dat; \
  999. svga->changedvram[((addr) & 0xfffff) >> 8] = changeframecount; \
  1000. }
  1001.  
  1002. void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3)
  1003. {
  1004. svga_t *svga = &s3->svga;
  1005. uint32_t src_dat, dest_dat;
  1006. int frgd_mix, bkgd_mix;
  1007. int clip_t = s3->accel.multifunc[1] & 0xfff;
  1008. int clip_l = s3->accel.multifunc[2] & 0xfff;
  1009. int clip_b = s3->accel.multifunc[3] & 0xfff;
  1010. int clip_r = s3->accel.multifunc[4] & 0xfff;
  1011. int vram_mask = (s3->accel.multifunc[0xa] & 0xc0) == 0xc0;
  1012. uint32_t mix_mask;
  1013. uint16_t *vram_w = (uint16_t *)svga->vram;
  1014. uint32_t *vram_l = (uint32_t *)svga->vram;
  1015. uint32_t compare = s3->accel.color_cmp;
  1016. int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3;
  1017. //return;
  1018. // if (!cpu_input) pclog("Start S3 command %i %i, %i %i, %i (clip %i, %i to %i, %i %i)\n", s3->accel.cmd >> 13, s3->accel.cur_x, s3->accel.cur_y, s3->accel.maj_axis_pcnt & 0xfff, s3->accel.multifunc[0] & 0xfff, clip_l, clip_t, clip_r, clip_b, s3->accel.multifunc[0xe] & 0x20);
  1019. // else pclog(" S3 command %i, %i, %08x %08x\n", s3->accel.cmd >> 13, count, mix_dat, cpu_dat);
  1020.  
  1021. if (!cpu_input) s3->accel.dat_count = 0;
  1022. if (cpu_input && (s3->accel.multifunc[0xa] & 0xc0) != 0x80)
  1023. {
  1024. if (s3->bpp == 3 && count == 2)
  1025. {
  1026. if (s3->accel.dat_count)
  1027. {
  1028. cpu_dat = (cpu_dat & 0xffff) | (s3->accel.dat_buf << 16);
  1029. count = 4;
  1030. s3->accel.dat_count = 0;
  1031. }
  1032. else
  1033. {
  1034. s3->accel.dat_buf = cpu_dat & 0xffff;
  1035. s3->accel.dat_count = 1;
  1036. }
  1037. }
  1038. if (s3->bpp == 1) count >>= 1;
  1039. if (s3->bpp == 3) count >>= 2;
  1040. }
  1041.  
  1042. switch (s3->accel.cmd & 0x600)
  1043. {
  1044. case 0x000: mix_mask = 0x80; break;
  1045. case 0x200: mix_mask = 0x8000; break;
  1046. case 0x400: mix_mask = 0x80000000; break;
  1047. case 0x600: mix_mask = 0x80000000; break;
  1048. }
  1049.  
  1050. if (s3->bpp == 0) compare &= 0xff;
  1051. if (s3->bpp == 1) compare &= 0xffff;
  1052. switch (s3->accel.cmd >> 13)
  1053. {
  1054. case 1: /*Draw line*/
  1055. if (!cpu_input) /*!cpu_input is trigger to start operation*/
  1056. {
  1057. s3->accel.cx = s3->accel.cur_x;
  1058. if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff;
  1059. s3->accel.cy = s3->accel.cur_y;
  1060. if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
  1061.  
  1062. s3->accel.sy = s3->accel.maj_axis_pcnt;
  1063. }
  1064. if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
  1065.  
  1066. frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
  1067. bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
  1068.  
  1069. if (s3->accel.cmd & 8) /*Radial*/
  1070. {
  1071. while (count-- && s3->accel.sy >= 0)
  1072. {
  1073. if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
  1074. s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
  1075. {
  1076. switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
  1077. {
  1078. case 0: src_dat = s3->accel.bkgd_color; break;
  1079. case 1: src_dat = s3->accel.frgd_color; break;
  1080. case 2: src_dat = cpu_dat; break;
  1081. case 3: src_dat = 0; break;
  1082. }
  1083.  
  1084. if ((compare_mode == 2 && src_dat != compare) ||
  1085. (compare_mode == 3 && src_dat == compare) ||
  1086. compare_mode < 2)
  1087. {
  1088. READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
  1089.  
  1090. MIX
  1091.  
  1092. WRITE((s3->accel.cy * s3->width) + s3->accel.cx);
  1093. }
  1094. }
  1095.  
  1096. mix_dat <<= 1;
  1097. mix_dat |= 1;
  1098. if (s3->bpp == 0) cpu_dat >>= 8;
  1099. else cpu_dat >>= 16;
  1100.  
  1101. switch (s3->accel.cmd & 0xe0)
  1102. {
  1103. case 0x00: s3->accel.cx++; break;
  1104. case 0x20: s3->accel.cx++; s3->accel.cy--; break;
  1105. case 0x40: s3->accel.cy--; break;
  1106. case 0x60: s3->accel.cx--; s3->accel.cy--; break;
  1107. case 0x80: s3->accel.cx--; break;
  1108. case 0xa0: s3->accel.cx--; s3->accel.cy++; break;
  1109. case 0xc0: s3->accel.cy++; break;
  1110. case 0xe0: s3->accel.cx++; s3->accel.cy++; break;
  1111. }
  1112. s3->accel.sy--;
  1113. }
  1114. }
  1115. else /*Bresenham*/
  1116. {
  1117. while (count-- && s3->accel.sy >= 0)
  1118. {
  1119. if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
  1120. s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
  1121. {
  1122. switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
  1123. {
  1124. case 0: src_dat = s3->accel.bkgd_color; break;
  1125. case 1: src_dat = s3->accel.frgd_color; break;
  1126. case 2: src_dat = cpu_dat; break;
  1127. case 3: src_dat = 0; break;
  1128. }
  1129.  
  1130. if ((compare_mode == 2 && src_dat != compare) ||
  1131. (compare_mode == 3 && src_dat == compare) ||
  1132. compare_mode < 2)
  1133. {
  1134. READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
  1135.  
  1136. // pclog("Line : %04i, %04i (%06X) - %02X (%02X %04X %05X) %02X (%02X %02X) ", s3->accel.cx, s3->accel.cy, s3->accel.dest + s3->accel.cx, src_dat, vram[s3->accel.src + s3->accel.cx], mix_dat & mix_mask, s3->accel.src + s3->accel.cx, dest_dat, s3->accel.frgd_color, s3->accel.bkgd_color);
  1137.  
  1138. MIX
  1139.  
  1140. // pclog("%02X\n", dest_dat);
  1141.  
  1142. WRITE((s3->accel.cy * s3->width) + s3->accel.cx);
  1143. }
  1144. }
  1145.  
  1146. mix_dat <<= 1;
  1147. mix_dat |= 1;
  1148. if (s3->bpp == 0) cpu_dat >>= 8;
  1149. else cpu_dat >>= 16;
  1150.  
  1151. // pclog("%i, %i - %i %i %i %i\n", s3->accel.cx, s3->accel.cy, s3->accel.err_term, s3->accel.maj_axis_pcnt, s3->accel.desty_axstp, s3->accel.destx_distp);
  1152.  
  1153. if (s3->accel.err_term >= s3->accel.maj_axis_pcnt)
  1154. {
  1155. s3->accel.err_term += s3->accel.destx_distp;
  1156. /*Step minor axis*/
  1157. switch (s3->accel.cmd & 0xe0)
  1158. {
  1159. case 0x00: s3->accel.cy--; break;
  1160. case 0x20: s3->accel.cy--; break;
  1161. case 0x40: s3->accel.cx--; break;
  1162. case 0x60: s3->accel.cx++; break;
  1163. case 0x80: s3->accel.cy++; break;
  1164. case 0xa0: s3->accel.cy++; break;
  1165. case 0xc0: s3->accel.cx--; break;
  1166. case 0xe0: s3->accel.cx++; break;
  1167. }
  1168. }
  1169. else
  1170. s3->accel.err_term += s3->accel.desty_axstp;
  1171.  
  1172. /*Step major axis*/
  1173. switch (s3->accel.cmd & 0xe0)
  1174. {
  1175. case 0x00: s3->accel.cx--; break;
  1176. case 0x20: s3->accel.cx++; break;
  1177. case 0x40: s3->accel.cy--; break;
  1178. case 0x60: s3->accel.cy--; break;
  1179. case 0x80: s3->accel.cx--; break;
  1180. case 0xa0: s3->accel.cx++; break;
  1181. case 0xc0: s3->accel.cy++; break;
  1182. case 0xe0: s3->accel.cy++; break;
  1183. }
  1184. s3->accel.sy--;
  1185. }
  1186. }
  1187. break;
  1188.  
  1189. case 2: /*Rectangle fill*/
  1190. if (!cpu_input) /*!cpu_input is trigger to start operation*/
  1191. {
  1192. s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
  1193. s3->accel.sy = s3->accel.multifunc[0] & 0xfff;
  1194. s3->accel.cx = s3->accel.cur_x;
  1195. if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff;
  1196. s3->accel.cy = s3->accel.cur_y;
  1197. if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
  1198.  
  1199. s3->accel.dest = s3->accel.cy * s3->width;
  1200.  
  1201. // pclog("Dest %08X (%i, %i) %04X %04X\n", s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.cur_x, s3->accel.cur_x & 0x1000);
  1202. }
  1203. if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
  1204. // if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !cpu_input) /*Mix data from CPU*/
  1205. // return;
  1206.  
  1207. frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
  1208. bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
  1209.  
  1210. while (count-- && s3->accel.sy >= 0)
  1211. {
  1212. if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
  1213. s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
  1214. {
  1215. switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
  1216. {
  1217. case 0: src_dat = s3->accel.bkgd_color; break;
  1218. case 1: src_dat = s3->accel.frgd_color; break;
  1219. case 2: src_dat = cpu_dat; break;
  1220. case 3: src_dat = 0; break;
  1221. }
  1222.  
  1223. if ((compare_mode == 2 && src_dat != compare) ||
  1224. (compare_mode == 3 && src_dat == compare) ||
  1225. compare_mode < 2)
  1226. {
  1227. READ(s3->accel.dest + s3->accel.cx, dest_dat);
  1228.  
  1229. // if (CS != 0xc000) pclog("Write %05X %02X %02X %04X (%02X %02X) ", s3->accel.dest + s3->accel.cx, src_dat, dest_dat, mix_dat, s3->accel.frgd_mix, s3->accel.bkgd_mix);
  1230.  
  1231. MIX
  1232.  
  1233. // if (CS != 0xc000) pclog("%02X\n", dest_dat);
  1234.  
  1235. WRITE(s3->accel.dest + s3->accel.cx);
  1236. }
  1237. }
  1238.  
  1239. mix_dat <<= 1;
  1240. mix_dat |= 1;
  1241. if (s3->bpp == 0) cpu_dat >>= 8;
  1242. else cpu_dat >>= 16;
  1243.  
  1244. if (s3->accel.cmd & 0x20) s3->accel.cx++;
  1245. else s3->accel.cx--;
  1246. s3->accel.sx--;
  1247. if (s3->accel.sx < 0)
  1248. {
  1249. if (s3->accel.cmd & 0x20) s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
  1250. else s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1;
  1251. // s3->accel.dest -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
  1252. s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
  1253.  
  1254. // s3->accel.dest += s3_width;
  1255. if (s3->accel.cmd & 0x80) s3->accel.cy++;
  1256. else s3->accel.cy--;
  1257.  
  1258. s3->accel.dest = s3->accel.cy * s3->width;
  1259. s3->accel.sy--;
  1260.  
  1261. if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return;
  1262. if (s3->accel.sy < 0)
  1263. {
  1264. return;
  1265. }
  1266. }
  1267. }
  1268. break;
  1269.  
  1270. case 6: /*BitBlt*/
  1271. if (!cpu_input) /*!cpu_input is trigger to start operation*/
  1272. {
  1273. s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
  1274. s3->accel.sy = s3->accel.multifunc[0] & 0xfff;
  1275.  
  1276. s3->accel.dx = s3->accel.destx_distp & 0xfff;
  1277. if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff;
  1278. s3->accel.dy = s3->accel.desty_axstp & 0xfff;
  1279. if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff;
  1280.  
  1281. s3->accel.cx = s3->accel.cur_x & 0xfff;
  1282. if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff;
  1283. s3->accel.cy = s3->accel.cur_y & 0xfff;
  1284. if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
  1285.  
  1286. s3->accel.src = s3->accel.cy * s3->width;
  1287. s3->accel.dest = s3->accel.dy * s3->width;
  1288.  
  1289. // pclog("Source %08X Dest %08X (%i, %i) - (%i, %i)\n", s3->accel.src, s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy);
  1290. }
  1291. if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
  1292. // if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !cpu_input) /*Mix data from CPU*/
  1293. // return;
  1294.  
  1295. if (s3->accel.sy < 0)
  1296. return;
  1297.  
  1298. frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
  1299. bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
  1300.  
  1301. if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode &&
  1302. (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7)
  1303. {
  1304. while (1)
  1305. {
  1306. if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
  1307. s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
  1308. {
  1309. READ(s3->accel.src + s3->accel.cx, src_dat);
  1310.  
  1311. dest_dat = src_dat;
  1312.  
  1313. WRITE(s3->accel.dest + s3->accel.dx);
  1314. }
  1315.  
  1316. s3->accel.cx++;
  1317. s3->accel.dx++;
  1318. s3->accel.sx--;
  1319. if (s3->accel.sx < 0)
  1320. {
  1321. s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
  1322. s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
  1323. s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
  1324.  
  1325. s3->accel.cy++;
  1326. s3->accel.dy++;
  1327.  
  1328. s3->accel.src = s3->accel.cy * s3->width;
  1329. s3->accel.dest = s3->accel.dy * s3->width;
  1330.  
  1331. s3->accel.sy--;
  1332.  
  1333. if (s3->accel.sy < 0)
  1334. return;
  1335. }
  1336. }
  1337. }
  1338. else
  1339. {
  1340. while (count-- && s3->accel.sy >= 0)
  1341. {
  1342. if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
  1343. s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
  1344. {
  1345. if (vram_mask)
  1346. {
  1347. READ(s3->accel.src + s3->accel.cx, mix_dat)
  1348. mix_dat = mix_dat ? mix_mask : 0;
  1349. }
  1350. switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
  1351. {
  1352. case 0: src_dat = s3->accel.bkgd_color; break;
  1353. case 1: src_dat = s3->accel.frgd_color; break;
  1354. case 2: src_dat = cpu_dat; break;
  1355. case 3: READ(s3->accel.src + s3->accel.cx, src_dat); break;
  1356. }
  1357.  
  1358. if ((compare_mode == 2 && src_dat != compare) ||
  1359. (compare_mode == 3 && src_dat == compare) ||
  1360. compare_mode < 2)
  1361. {
  1362. READ(s3->accel.dest + s3->accel.dx, dest_dat);
  1363.  
  1364. // pclog("BitBlt : %04i, %04i (%06X) - %02X (%02X %04X %05X) %02X ", s3->accel.dx, s3->accel.dy, s3->accel.dest + s3->accel.dx, src_dat, vram[s3->accel.src + s3->accel.cx], mix_dat, s3->accel.src + s3->accel.cx, dest_dat);
  1365.  
  1366. MIX
  1367.  
  1368. // pclog("%02X\n", dest_dat);
  1369.  
  1370. WRITE(s3->accel.dest + s3->accel.dx);
  1371. }
  1372. }
  1373.  
  1374. mix_dat <<= 1;
  1375. mix_dat |= 1;
  1376. if (s3->bpp == 0) cpu_dat >>= 8;
  1377. else cpu_dat >>= 16;
  1378.  
  1379. if (s3->accel.cmd & 0x20)
  1380. {
  1381. s3->accel.cx++;
  1382. s3->accel.dx++;
  1383. }
  1384. else
  1385. {
  1386. s3->accel.cx--;
  1387. s3->accel.dx--;
  1388. }
  1389. s3->accel.sx--;
  1390. if (s3->accel.sx < 0)
  1391. {
  1392. if (s3->accel.cmd & 0x20)
  1393. {
  1394. s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
  1395. s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
  1396. }
  1397. else
  1398. {
  1399. s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1;
  1400. s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1;
  1401. }
  1402. s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
  1403.  
  1404. if (s3->accel.cmd & 0x80)
  1405. {
  1406. s3->accel.cy++;
  1407. s3->accel.dy++;
  1408. }
  1409. else
  1410. {
  1411. s3->accel.cy--;
  1412. s3->accel.dy--;
  1413. }
  1414.  
  1415. s3->accel.src = s3->accel.cy * s3->width;
  1416. s3->accel.dest = s3->accel.dy * s3->width;
  1417.  
  1418. s3->accel.sy--;
  1419.  
  1420. if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return;
  1421. if (s3->accel.sy < 0)
  1422. {
  1423. return;
  1424. }
  1425. }
  1426. }
  1427. }
  1428. break;
  1429.  
  1430. case 7: /*Pattern fill - BitBlt but with source limited to 8x8*/
  1431. if (!cpu_input) /*!cpu_input is trigger to start operation*/
  1432. {
  1433. s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
  1434. s3->accel.sy = s3->accel.multifunc[0] & 0xfff;
  1435.  
  1436. s3->accel.dx = s3->accel.destx_distp & 0xfff;
  1437. if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff;
  1438. s3->accel.dy = s3->accel.desty_axstp & 0xfff;
  1439. if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff;
  1440.  
  1441. s3->accel.cx = s3->accel.cur_x & 0xfff;
  1442. if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff;
  1443. s3->accel.cy = s3->accel.cur_y & 0xfff;
  1444. if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
  1445.  
  1446. /*Align source with destination*/
  1447. // s3->accel.cx = (s3->accel.cx & ~7) | (s3->accel.dx & 7);
  1448. // s3->accel.cy = (s3->accel.cy & ~7) | (s3->accel.dy & 7);
  1449.  
  1450. s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx;
  1451. s3->accel.dest = s3->accel.dy * s3->width;
  1452.  
  1453. s3->accel.cx = s3->accel.dx & 7;
  1454. s3->accel.cy = s3->accel.dy & 7;
  1455.  
  1456. s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width);
  1457.  
  1458. // pclog("Source %08X Dest %08X (%i, %i) - (%i, %i)\n", s3->accel.src, s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy);
  1459. // dumpregs();
  1460. // exit(-1);
  1461. }
  1462. if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
  1463. // if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !cpu_input) /*Mix data from CPU*/
  1464. // return;
  1465.  
  1466. frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
  1467. bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
  1468.  
  1469. while (count-- && s3->accel.sy >= 0)
  1470. {
  1471. if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
  1472. s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
  1473. {
  1474. if (vram_mask)
  1475. {
  1476. READ(s3->accel.src + s3->accel.cx, mix_dat)
  1477. mix_dat = mix_dat ? mix_mask : 0;
  1478. }
  1479. switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
  1480. {
  1481. case 0: src_dat = s3->accel.bkgd_color; break;
  1482. case 1: src_dat = s3->accel.frgd_color; break;
  1483. case 2: src_dat = cpu_dat; break;
  1484. case 3: READ(s3->accel.src + s3->accel.cx, src_dat); break;
  1485. }
  1486.  
  1487. if ((compare_mode == 2 && src_dat != compare) ||
  1488. (compare_mode == 3 && src_dat == compare) ||
  1489. compare_mode < 2)
  1490. {
  1491. READ(s3->accel.dest + s3->accel.dx, dest_dat);
  1492.  
  1493. // pclog("Pattern fill : %04i, %04i (%06X) - %02X (%02X %04X %05X) %02X ", s3->accel.dx, s3->accel.dy, s3->accel.dest + s3->accel.dx, src_dat, vram[s3->accel.src + s3->accel.cx], mix_dat, s3->accel.src + s3->accel.cx, dest_dat);
  1494.  
  1495. MIX
  1496.  
  1497. // pclog("%02X\n", dest_dat);
  1498.  
  1499. WRITE(s3->accel.dest + s3->accel.dx);
  1500. }
  1501. }
  1502.  
  1503. mix_dat <<= 1;
  1504. mix_dat |= 1;
  1505. if (s3->bpp == 0) cpu_dat >>= 8;
  1506. else cpu_dat >>= 16;
  1507.  
  1508. if (s3->accel.cmd & 0x20)
  1509. {
  1510. s3->accel.cx = ((s3->accel.cx + 1) & 7) | (s3->accel.cx & ~7);
  1511. s3->accel.dx++;
  1512. }
  1513. else
  1514. {
  1515. s3->accel.cx = ((s3->accel.cx - 1) & 7) | (s3->accel.cx & ~7);
  1516. s3->accel.dx--;
  1517. }
  1518. s3->accel.sx--;
  1519. if (s3->accel.sx < 0)
  1520. {
  1521. if (s3->accel.cmd & 0x20)
  1522. {
  1523. s3->accel.cx = ((s3->accel.cx - ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7);
  1524. s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
  1525. }
  1526. else
  1527. {
  1528. s3->accel.cx = ((s3->accel.cx + ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7);
  1529. s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1;
  1530. }
  1531. s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
  1532.  
  1533. if (s3->accel.cmd & 0x80)
  1534. {
  1535. s3->accel.cy = ((s3->accel.cy + 1) & 7) | (s3->accel.cy & ~7);
  1536. s3->accel.dy++;
  1537. }
  1538. else
  1539. {
  1540. s3->accel.cy = ((s3->accel.cy - 1) & 7) | (s3->accel.cy & ~7);
  1541. s3->accel.dy--;
  1542. }
  1543.  
  1544. s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width);
  1545. s3->accel.dest = s3->accel.dy * s3->width;
  1546.  
  1547. s3->accel.sy--;
  1548.  
  1549. if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return;
  1550. if (s3->accel.sy < 0)
  1551. {
  1552. return;
  1553. }
  1554. }
  1555. }
  1556. break;
  1557. }
  1558. }
  1559.  
  1560. void s3_hwcursor_draw(svga_t *svga, int displine)
  1561. {
  1562. int x;
  1563. uint16_t dat[2];
  1564. int xx;
  1565. int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
  1566.  
  1567. // pclog("HWcursor %i %i\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y);
  1568. for (x = 0; x < 64; x += 16)
  1569. {
  1570. dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 8) | svga->vram[svga->hwcursor_latch.addr + 1];
  1571. dat[1] = (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3];
  1572. for (xx = 0; xx < 16; xx++)
  1573. {
  1574. if (offset >= svga->hwcursor_latch.x)
  1575. {
  1576. if (!(dat[0] & 0x8000))
  1577. ((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[1] & 0x8000) ? 0xffffff : 0;
  1578. else if (dat[1] & 0x8000)
  1579. ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
  1580. // pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga_hwcursor_on, dat[0], dat[1]);
  1581. }
  1582.  
  1583. offset++;
  1584. dat[0] <<= 1;
  1585. dat[1] <<= 1;
  1586. }
  1587. svga->hwcursor_latch.addr += 4;
  1588. }
  1589. }
  1590.  
  1591.  
  1592. uint8_t s3_pci_read(int func, int addr, void *p)
  1593. {
  1594. s3_t *s3 = (s3_t *)p;
  1595. svga_t *svga = &s3->svga;
  1596. // pclog("S3 PCI read %08X\n", addr);
  1597. switch (addr)
  1598. {
  1599. case 0x00: return 0x33; /*'S3'*/
  1600. case 0x01: return 0x53;
  1601.  
  1602. case 0x02: return s3->id_ext;
  1603. case 0x03: return 0x88;
  1604.  
  1605. case 0x04: return 0x03; /*Respond to IO and memory accesses*/
  1606.  
  1607. case 0x07: return 1 << 1; /*Medium DEVSEL timing*/
  1608.  
  1609. case 0x08: return 0; /*Revision ID*/
  1610. case 0x09: return 0; /*Programming interface*/
  1611.  
  1612. case 0x0a: return 0x01; /*Supports VGA interface*/
  1613. case 0x0b: return 0x03;
  1614.  
  1615. case 0x10: return 0x00; /*Linear frame buffer address*/
  1616. case 0x11: return 0x00;
  1617. case 0x12: return svga->crtc[0x5a] & 0x80;
  1618. case 0x13: return svga->crtc[0x59];
  1619.  
  1620. case 0x30: return 0x01; /*BIOS ROM address*/
  1621. case 0x31: return 0x00;
  1622. case 0x32: return 0x0C;
  1623. case 0x33: return 0x00;
  1624. }
  1625. return 0;
  1626. }
  1627.  
  1628. void s3_pci_write(int func, int addr, uint8_t val, void *p)
  1629. {
  1630. s3_t *s3 = (s3_t *)p;
  1631. svga_t *svga = &s3->svga;
  1632. switch (addr)
  1633. {
  1634. case 0x12:
  1635. svga->crtc[0x5a] = val & 0x80;
  1636. s3_updatemapping(s3);
  1637. break;
  1638. case 0x13:
  1639. svga->crtc[0x59] = val;
  1640. s3_updatemapping(s3);
  1641. break;
  1642. }
  1643. }
  1644.  
  1645. static void *s3_init()
  1646. {
  1647. s3_t *s3 = malloc(sizeof(s3_t));
  1648. svga_t *svga = &s3->svga;
  1649. memset(s3, 0, sizeof(s3_t));
  1650.  
  1651. mem_mapping_add(&s3->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, &s3->svga);
  1652. mem_mapping_add(&s3->mmio_mapping, 0xa0000, 0x10000, s3_accel_read, NULL, NULL, s3_accel_write, s3_accel_write_w, s3_accel_write_l, s3);
  1653. mem_mapping_disable(&s3->mmio_mapping);
  1654.  
  1655. svga_init(&s3->svga, s3, 1 << 22, /*4mb - 864 supports 8mb but buggy VESA driver reports 0mb*/
  1656. s3_recalctimings,
  1657. s3_in, s3_out,
  1658. s3_hwcursor_draw);
  1659.  
  1660. io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3);
  1661.  
  1662. svga->crtc[0x36] = 1 | (2 << 2) | (1 << 4) | (4 << 5);
  1663. svga->crtc[0x37] = 1 | (7 << 5);
  1664.  
  1665. io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1666. io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1667. io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1668. io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1669. io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1670. io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1671. io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1672. io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1673. io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1674. io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1675. io_sethandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1676. io_sethandler(0xa2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1677. io_sethandler(0xa6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1678. io_sethandler(0xaae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1679. io_sethandler(0xaee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1680. io_sethandler(0xb2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1681. io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1682. io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1683. io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
  1684. io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3);
  1685.  
  1686. pci_add(s3_pci_read, s3_pci_write, s3);
  1687.  
  1688. return s3;
  1689. }
  1690.  
  1691. void *s3_bahamas64_init()
  1692. {
  1693. s3_t *s3 = s3_init();
  1694.  
  1695. s3->id = 0xc1; /*Vision864P*/
  1696. s3->id_ext = 0xc1; /*Trio64*/
  1697.  
  1698. s3->getclock = sdac_getclock;
  1699. s3->getclock_p = &s3->ramdac;
  1700.  
  1701. return s3;
  1702. }
  1703.  
  1704. void *s3_9fx_init()
  1705. {
  1706. s3_t *s3 = s3_init();
  1707.  
  1708. s3->id = 0xe1;
  1709. s3->id_ext = 0x11; /*Trio64*/
  1710.  
  1711. s3->getclock = s3_trio64_getclock;
  1712. s3->getclock_p = s3;
  1713.  
  1714. return s3;
  1715. }
  1716.  
  1717. void s3_close(void *p)
  1718. {
  1719. s3_t *s3 = (s3_t *)p;
  1720.  
  1721. svga_close(&s3->svga);
  1722.  
  1723. free(s3);
  1724. }
  1725.  
  1726. void s3_speed_changed(void *p)
  1727. {
  1728. s3_t *s3 = (s3_t *)p;
  1729.  
  1730. svga_recalctimings(&s3->svga);
  1731. }
  1732.  
  1733. void s3_force_redraw(void *p)
  1734. {
  1735. s3_t *s3 = (s3_t *)p;
  1736.  
  1737. s3->svga.fullchange = changeframecount;
  1738. }
  1739.  
  1740. int s3_add_status_info(char *s, int max_len, void *p)
  1741. {
  1742. s3_t *s3 = (s3_t *)p;
  1743.  
  1744. return svga_add_status_info(s, max_len, &s3->svga);
  1745. }
  1746.  
  1747. device_t s3_bahamas64_device =
  1748. {
  1749. "Paradise Bahamas 64 (S3 Vision864)",
  1750. 0,
  1751. s3_bahamas64_init,
  1752. s3_close,
  1753. NULL,
  1754. s3_speed_changed,
  1755. s3_force_redraw,
  1756. s3_add_status_info
  1757. };
  1758.  
  1759. device_t s3_9fx_device =
  1760. {
  1761. "Number 9 9FX (S3 Trio64)",
  1762. 0,
  1763. s3_9fx_init,
  1764. s3_close,
  1765. NULL,
  1766. s3_speed_changed,
  1767. s3_force_redraw,
  1768. s3_add_status_info
  1769. };
Advertisement
Add Comment
Please, Sign In to add comment