PageRenderTime 67ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/src/fake86/render.c

https://bitbucket.org/infact/fake86gc
C | 582 lines | 516 code | 34 blank | 32 comment | 141 complexity | 16ae44ac865f42bf16dcc354ec3e4439 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. Fake86: A portable, open-source 8086 PC emulator.
  3. Copyright (C)2010-2012 Mike Chambers
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  15. */
  16. /* render.c: functions for SDL initialization, as well as video scaling/rendering.
  17. it is a bit messy. i plan to rework much of this in the future. i am also
  18. going to add hardware accelerated scaling soon. */
  19. #include <SDL/SDL.h>
  20. #include <stdint.h>
  21. #include <stdio.h>
  22. #include "mutex.h"
  23. #ifdef _WIN32
  24. CRITICAL_SECTION screenmutex;
  25. #else
  26. #ifdef GEKKO
  27. lwp_t vidthread;
  28. mutex_t screenmutex;
  29. #else
  30. pthread_t vidthread;
  31. pthread_mutex_t screenmutex = PTHREAD_MUTEX_INITIALIZER;
  32. #endif
  33. #endif
  34. SDL_Surface *screen = NULL;
  35. uint32_t *scalemap = NULL;
  36. uint8_t regenscalemap = 1;
  37. extern uint8_t RAM[0x100000], portram[0x10000];
  38. extern uint8_t VRAM[262144], vidmode, cgabg, blankattr, vidgfxmode, vidcolor, running;
  39. extern uint16_t cursx, cursy, cols, rows, vgapage, cursorposition, cursorvisible;
  40. extern uint8_t updatedscreen, clocksafe, port3da, port6, portout16;
  41. extern uint16_t VGA_SC[0x100], VGA_CRTC[0x100], VGA_ATTR[0x100], VGA_GC[0x100];
  42. extern uint32_t videobase, textbase, x, y;
  43. extern uint8_t fontcga[32768];
  44. extern uint32_t palettecga[16], palettevga[256];
  45. extern uint32_t usefullscreen, usegrabmode;
  46. uint64_t totalframes = 0;
  47. uint32_t framedelay = 20;
  48. uint8_t scrmodechange = 0, noscale = 0, nosmooth = 1, renderbenchmark = 0, doaudio = 1;
  49. char windowtitle[128];
  50. void initcga();
  51. #ifdef _WIN32
  52. void VideoThread (void *dummy);
  53. #else
  54. void *VideoThread (void *dummy);
  55. #endif
  56. void setwindowtitle (uint8_t *extra) {
  57. char temptext[128];
  58. sprintf (temptext, "%s%s", windowtitle, extra);
  59. SDL_WM_SetCaption ( (const char *) temptext, NULL);
  60. }
  61. int initcubescreen() {
  62. if (doaudio) {
  63. if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) ) return (0);
  64. }
  65. else {
  66. if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER) ) return (0);
  67. }
  68. screen = SDL_SetVideoMode (640, 480, 32, SDL_HWSURFACE);
  69. if (screen == NULL) return (0);
  70. }
  71. uint8_t initscreen (uint8_t *ver) {
  72. #ifndef GEKKO
  73. if (doaudio) {
  74. if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) ) return (0);
  75. }
  76. else {
  77. if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER) ) return (0);
  78. }
  79. screen = SDL_SetVideoMode (640, 400, 32, SDL_HWSURFACE);
  80. if (screen == NULL) return (0);
  81. sprintf (windowtitle, "%s", ver);
  82. setwindowtitle ("");
  83. #endif
  84. initcga();
  85. #ifdef _WIN32
  86. InitializeCriticalSection (&screenmutex);
  87. _beginthread (VideoThread, 0, NULL);
  88. #else
  89. #ifdef GEKKO
  90. LWP_MutexInit(&screenmutex, false);
  91. LWP_CreateThread(&vidthread, (void *) VideoThread, NULL, NULL, 0, 64);
  92. #else
  93. pthread_create (&vidthread, NULL, (void *) VideoThread, NULL);
  94. #endif
  95. #endif
  96. return (1);
  97. }
  98. uint32_t prestretch[1024][1024];
  99. uint32_t nw, nh; //native width and height, pre-stretching (i.e. 320x200 for mode 13h)
  100. void createscalemap() {
  101. uint32_t srcx, srcy, dstx, dsty, scalemapptr;
  102. double xscale, yscale;
  103. xscale = (double) nw / (double) screen->w;
  104. yscale = (double) nh / (double) screen->h;
  105. if (scalemap != NULL) free(scalemap);
  106. scalemap = (void *)malloc( ((uint32_t)screen->w + 1) * (uint32_t)screen->h * 4);
  107. if (scalemap == NULL) {
  108. printf("\nFATAL: Unable to allocate memory for scalemap!\n");
  109. exit(1);
  110. }
  111. scalemapptr = 0;
  112. for (dsty=0; dsty<(uint32_t)screen->h; dsty++) {
  113. srcy = (uint32_t) ( (double) dsty * yscale);
  114. scalemap[scalemapptr++] = srcy;
  115. for (dstx=0; dstx<(uint32_t)screen->w; dstx++) {
  116. srcx = (uint32_t) ( (double) dstx * xscale);
  117. scalemap[scalemapptr++] = srcx;
  118. }
  119. }
  120. regenscalemap = 0;
  121. }
  122. extern uint16_t oldw, oldh, constantw, constanth;
  123. void draw();
  124. extern void handleinput();
  125. #ifdef _WIN32
  126. void VideoThread (void *dummy) {
  127. #else
  128. void *VideoThread (void *dummy) {
  129. #endif
  130. uint32_t cursorprevtick, cursorcurtick, delaycalc;
  131. cursorprevtick = SDL_GetTicks();
  132. cursorvisible = 0;
  133. while (running) {
  134. cursorcurtick = SDL_GetTicks();
  135. if ( (cursorcurtick - cursorprevtick) >= 250) {
  136. updatedscreen = 1;
  137. cursorvisible = ~cursorvisible & 1;
  138. cursorprevtick = cursorcurtick;
  139. }
  140. if (updatedscreen || renderbenchmark) {
  141. updatedscreen = 0;
  142. if (screen != NULL) {
  143. MutexLock (screenmutex);
  144. if (regenscalemap) createscalemap();
  145. draw();
  146. MutexUnlock (screenmutex);
  147. }
  148. totalframes++;
  149. }
  150. if (!renderbenchmark) {
  151. delaycalc = framedelay - (SDL_GetTicks() - cursorcurtick);
  152. if (delaycalc > framedelay) delaycalc = framedelay;
  153. SDL_Delay (delaycalc);
  154. }
  155. }
  156. }
  157. void doscrmodechange() {
  158. MutexLock (screenmutex);
  159. if (scrmodechange) {
  160. if (screen != NULL) SDL_FreeSurface (screen);
  161. if (constantw && constanth) screen = SDL_SetVideoMode (constantw, constanth, 32, SDL_HWSURFACE | usefullscreen);
  162. else if (noscale) screen = SDL_SetVideoMode (nw, nh, 32, SDL_HWSURFACE | usefullscreen);
  163. else {
  164. if ( (nw >= 640) || (nh >= 400) ) screen = SDL_SetVideoMode (nw, nh, 32, SDL_HWSURFACE | usefullscreen);
  165. else screen = SDL_SetVideoMode (640, 400, 32, SDL_HWSURFACE | usefullscreen);
  166. }
  167. if (usefullscreen) SDL_WM_GrabInput (SDL_GRAB_ON); //always have mouse grab turned on for full screen mode
  168. else SDL_WM_GrabInput (usegrabmode);
  169. SDL_ShowCursor (SDL_DISABLE);
  170. if (!usefullscreen) {
  171. if (usegrabmode == SDL_GRAB_ON) setwindowtitle (" (press Ctrl + Alt to release mouse)");
  172. else setwindowtitle ("");
  173. }
  174. regenscalemap = 1;
  175. createscalemap();
  176. }
  177. MutexUnlock (screenmutex);
  178. scrmodechange = 0;
  179. }
  180. void stretchblit (SDL_Surface *target) {
  181. uint32_t srcx, srcy, dstx, dsty, lastx, lasty, r, g, b;
  182. uint32_t consecutivex, consecutivey = 0, limitx, limity, scalemapptr;
  183. uint32_t ofs;
  184. uint8_t *pixelrgb;
  185. limitx = (uint32_t)((double) nw / (double) target->w);
  186. limity = (uint32_t)((double) nh / (double) target->h);
  187. if (SDL_MUSTLOCK (target) )
  188. if (SDL_LockSurface (target) < 0)
  189. return;
  190. lasty = 0;
  191. scalemapptr = 0;
  192. for (dsty=0; dsty<(uint32_t)target->h; dsty++) {
  193. srcy = scalemap[scalemapptr++];
  194. ofs = dsty*target->w;
  195. consecutivex = 0;
  196. lastx = 0;
  197. if (srcy == lasty) consecutivey++;
  198. else consecutivey = 0;
  199. for (dstx=0; dstx<(uint32_t)target->w; dstx++) {
  200. srcx = scalemap[scalemapptr++];
  201. pixelrgb = (uint8_t *) &prestretch[srcy][srcx];
  202. r = pixelrgb[0];
  203. g = pixelrgb[1];
  204. b = pixelrgb[2];
  205. if (srcx == lastx) consecutivex++;
  206. else consecutivex = 0;
  207. if ( (consecutivex > limitx) && (consecutivey > limity) ) {
  208. pixelrgb = (uint8_t *) &prestretch[srcy][srcx+1];
  209. r += pixelrgb[0];
  210. g += pixelrgb[1];
  211. b += pixelrgb[2];
  212. pixelrgb = (uint8_t *) &prestretch[srcy+1][srcx];
  213. r += pixelrgb[0];
  214. g += pixelrgb[1];
  215. b += pixelrgb[2];
  216. pixelrgb = (uint8_t *) &prestretch[srcy+1][srcx+1];
  217. r += pixelrgb[0];
  218. g += pixelrgb[1];
  219. b += pixelrgb[2];
  220. r = r >> 2;
  221. g = g >> 2;
  222. b = b >> 2;
  223. //r = 255; g = 0; b = 0;
  224. }
  225. else if (consecutivex > limitx) {
  226. pixelrgb = (uint8_t *) &prestretch[srcy][srcx+1];
  227. r += pixelrgb[0];
  228. r = r >> 1;
  229. g += pixelrgb[1];
  230. g = g >> 1;
  231. b += pixelrgb[2];
  232. b = b >> 1;
  233. //r = 0; g = 255; b = 0;
  234. }
  235. else if (consecutivey > limity) {
  236. pixelrgb = (uint8_t *) &prestretch[srcy+1][srcx];
  237. r += pixelrgb[0];
  238. r = r >> 1;
  239. g += pixelrgb[1];
  240. g = g >> 1;
  241. b += pixelrgb[2];
  242. b = b >> 1;
  243. //r = 0; g = 0; b = 255;
  244. }
  245. ( (uint32_t *) target->pixels) [ofs++] = SDL_MapRGB (target->format, (uint8_t) r, (uint8_t) g, (uint8_t) b);
  246. lastx = srcx;
  247. }
  248. lasty = srcy;
  249. }
  250. if (SDL_MUSTLOCK (target) )
  251. SDL_UnlockSurface (target);
  252. SDL_UpdateRect (target, 0, 0, target->w, target->h);
  253. }
  254. void roughblit (SDL_Surface *target) {
  255. uint32_t srcx, srcy, dstx, dsty, scalemapptr;
  256. int32_t ofs;
  257. uint8_t *pixelrgb;
  258. if (SDL_MUSTLOCK (target) )
  259. if (SDL_LockSurface (target) < 0)
  260. return;
  261. scalemapptr = 0;
  262. for (dsty=0; dsty<(uint32_t)target->h; dsty++) {
  263. srcy = scalemap[scalemapptr++];
  264. ofs = dsty*target->w;
  265. for (dstx=0; dstx<(uint32_t)target->w; dstx++) {
  266. srcx = scalemap[scalemapptr++];
  267. pixelrgb = (uint8_t *) &prestretch[srcy][srcx];
  268. ( (uint32_t *) target->pixels) [ofs++] = SDL_MapRGB (target->format, pixelrgb[0], pixelrgb[1], pixelrgb[2]);
  269. }
  270. }
  271. if (SDL_MUSTLOCK (target) )
  272. SDL_UnlockSurface (target);
  273. SDL_UpdateRect (target, 0, 0, target->w, target->h);
  274. }
  275. /* NOTE: doubleblit is only used when smoothing is not enabled, and the SDL window size
  276. is exactly double of native resolution for the current video mode. we can take
  277. advantage of the fact that every pixel is simply doubled both horizontally and
  278. vertically. this way, we do not need to waste mountains of CPU time doing
  279. floating point multiplication for each and every on-screen pixel. it makes the
  280. difference between games being smooth and playable, and being jerky on my old
  281. 400 MHz PowerPC G3 iMac.
  282. */
  283. void doubleblit (SDL_Surface *target) {
  284. uint32_t srcx, srcy, dstx, dsty, curcolor;
  285. int32_t ofs, startofs;
  286. uint8_t *pixelrgb;
  287. if (SDL_MUSTLOCK (target) )
  288. if (SDL_LockSurface (target) < 0)
  289. return;
  290. for (dsty=0; dsty<(uint32_t)target->h; dsty += 2) {
  291. srcy = (uint32_t) (dsty >> 1);
  292. startofs = ofs = dsty*target->w;
  293. for (dstx=0; dstx<(uint32_t)target->w; dstx += 2) {
  294. srcx = (uint32_t) (dstx >> 1);
  295. pixelrgb = (uint8_t *) &prestretch[srcy][srcx];
  296. curcolor = SDL_MapRGB (target->format, pixelrgb[0], pixelrgb[1], pixelrgb[2]);
  297. ( (uint32_t *) target->pixels) [ofs+target->w] = curcolor;
  298. ( (uint32_t *) target->pixels) [ofs++] = curcolor;
  299. ( (uint32_t *) target->pixels) [ofs+target->w] = curcolor;
  300. ( (uint32_t *) target->pixels) [ofs++] = curcolor;
  301. }
  302. }
  303. if (SDL_MUSTLOCK (target) )
  304. SDL_UnlockSurface (target);
  305. SDL_UpdateRect (target, 0, 0, target->w, target->h);
  306. }
  307. extern uint16_t vtotal;
  308. void draw () {
  309. uint32_t planemode, vgapage, color, chary, charx, vidptr, divx, divy, curchar, curpixel, usepal, intensity, blockw, curheight, x1, y1;
  310. switch (vidmode) {
  311. case 0:
  312. case 1:
  313. case 2: //text modes
  314. case 3:
  315. case 7:
  316. case 0x82:
  317. nw = 640;
  318. nh = 400;
  319. vgapage = ( (uint32_t) VGA_CRTC[0xC]<<8) + (uint32_t) VGA_CRTC[0xD];
  320. for (y=0; y<400; y++)
  321. for (x=0; x<640; x++) {
  322. if (cols==80) {
  323. charx = x/8;
  324. divx = 1;
  325. }
  326. else {
  327. charx = x/16;
  328. divx = 2;
  329. }
  330. if ( (portram[0x3D8]==9) && (portram[0x3D4]==9) ) {
  331. chary = y/4;
  332. vidptr = vgapage + videobase + chary*cols*2 + charx*2;
  333. curchar = RAM[vidptr];
  334. color = fontcga[curchar*128 + (y%4) *8 + ( (x/divx) %8) ];
  335. }
  336. else {
  337. chary = y/16;
  338. vidptr = videobase + chary*cols*2 + charx*2;
  339. curchar = RAM[vidptr];
  340. color = fontcga[curchar*128 + (y%16) *8 + ( (x/divx) %8) ];
  341. }
  342. if (vidcolor) {
  343. if (!color) if (portram[0x3D8]&128) color = palettecga[ (RAM[vidptr+1]/16) &7];
  344. else color = palettecga[RAM[vidptr+1]/16]; //high intensity background
  345. else color = palettecga[RAM[vidptr+1]&15];
  346. }
  347. else {
  348. if ( (RAM[vidptr+1] & 0x70) ) {
  349. if (!color) color = palettecga[7];
  350. else color = palettecga[0];
  351. }
  352. else {
  353. if (!color) color = palettecga[0];
  354. else color = palettecga[7];
  355. }
  356. }
  357. prestretch[y][x] = color;
  358. }
  359. break;
  360. case 4:
  361. case 5:
  362. nw = 320;
  363. nh = 200;
  364. usepal = (portram[0x3D9]>>5) & 1;
  365. intensity = ( (portram[0x3D9]>>4) & 1) << 3;
  366. for (y=0; y<200; y++) {
  367. for (x=0; x<320; x++) {
  368. charx = x;
  369. chary = y;
  370. vidptr = videobase + ( (chary>>1) * 80) + ( (chary & 1) * 8192) + (charx >> 2);
  371. curpixel = RAM[vidptr];
  372. switch (charx & 3) {
  373. case 3:
  374. curpixel = curpixel & 3;
  375. break;
  376. case 2:
  377. curpixel = (curpixel>>2) & 3;
  378. break;
  379. case 1:
  380. curpixel = (curpixel>>4) & 3;
  381. break;
  382. case 0:
  383. curpixel = (curpixel>>6) & 3;
  384. break;
  385. }
  386. if (vidmode==4) {
  387. curpixel = curpixel * 2 + usepal + intensity;
  388. if (curpixel == (usepal + intensity) ) curpixel = cgabg;
  389. color = palettecga[curpixel];
  390. prestretch[y][x] = color;
  391. }
  392. else {
  393. curpixel = curpixel * 63;
  394. color = palettecga[curpixel];
  395. prestretch[y][x] = color;
  396. }
  397. }
  398. }
  399. break;
  400. case 6:
  401. nw = 640;
  402. nh = 200;
  403. for (y=0; y<200; y++) {
  404. for (x=0; x<640; x++) {
  405. charx = x;
  406. chary = y;
  407. vidptr = videobase + ( (chary>>1) * 80) + ( (chary&1) * 8192) + (charx>>3);
  408. curpixel = (RAM[vidptr]>> (7- (charx&7) ) ) &1;
  409. color = palettecga[curpixel*15];
  410. prestretch[y][x] = color;
  411. }
  412. }
  413. break;
  414. case 127:
  415. nw = 720;
  416. nh = 348;
  417. for (y=0; y<348; y++) {
  418. for (x=0; x<720; x++) {
  419. charx = x;
  420. chary = y>>1;
  421. vidptr = videobase + ( (y & 3) << 13) + (y >> 2) *90 + (x >> 3);
  422. curpixel = (RAM[vidptr]>> (7- (charx&7) ) ) &1;
  423. #ifdef __BIG_ENDIAN__
  424. if (curpixel) color = 0xFFFFFF00;
  425. #else
  426. if (curpixel) color = 0x00FFFFFF;
  427. #endif
  428. else color = 0x00000000;
  429. prestretch[y][x] = color;
  430. }
  431. }
  432. break;
  433. case 0x8: //160x200 16-color (PCjr)
  434. nw = 640; //fix this
  435. nh = 400; //part later
  436. for (y=0; y<400; y++)
  437. for (x=0; x<640; x++) {
  438. vidptr = 0xB8000 + (y>>2) *80 + (x>>3) + ( (y>>1) &1) *8192;
  439. if ( ( (x>>1) &1) ==0) color = palettecga[RAM[vidptr] >> 4];
  440. else color = palettecga[RAM[vidptr] & 15];
  441. prestretch[y][x] = color;
  442. }
  443. break;
  444. case 0x9: //320x200 16-color (Tandy/PCjr)
  445. nw = 640; //fix this
  446. nh = 400; //part later
  447. for (y=0; y<400; y++)
  448. for (x=0; x<640; x++) {
  449. vidptr = 0xB8000 + (y>>3) *160 + (x>>2) + ( (y>>1) &3) *8192;
  450. if ( ( (x>>1) &1) ==0) color = palettecga[RAM[vidptr] >> 4];
  451. else color = palettecga[RAM[vidptr] & 15];
  452. prestretch[y][x] = color;
  453. }
  454. break;
  455. case 0xD:
  456. case 0xE:
  457. nw = 640; //fix this
  458. nh = 400; //part later
  459. for (y=0; y<400; y++)
  460. for (x=0; x<640; x++) {
  461. divx = x>>1;
  462. divy = y>>1;
  463. vidptr = divy*40 + (divx>>3);
  464. x1 = 7 - (divx & 7);
  465. color = (VRAM[vidptr] >> x1) & 1;
  466. color += ( ( (VRAM[0x10000 + vidptr] >> x1) & 1) << 1);
  467. color += ( ( (VRAM[0x20000 + vidptr] >> x1) & 1) << 2);
  468. color += ( ( (VRAM[0x30000 + vidptr] >> x1) & 1) << 3);
  469. color = palettevga[color];
  470. prestretch[y][x] = color;
  471. }
  472. break;
  473. case 0x10:
  474. nw = 640;
  475. nh = 350;
  476. for (y=0; y<350; y++)
  477. for (x=0; x<640; x++) {
  478. vidptr = y*80 + (x>>3);
  479. x1 = 7 - (x & 7);
  480. color = (VRAM[vidptr] >> x1) & 1;
  481. color += ( ( (VRAM[0x10000 + vidptr] >> x1) & 1) << 1);
  482. color += ( ( (VRAM[0x20000 + vidptr] >> x1) & 1) << 2);
  483. color += ( ( (VRAM[0x30000 + vidptr] >> x1) & 1) << 3);
  484. color = palettevga[color];
  485. prestretch[y][x] = color;
  486. }
  487. break;
  488. case 0x12:
  489. nw = 640;
  490. nh = 480;
  491. vgapage = ( (uint32_t) VGA_CRTC[0xC]<<8) + (uint32_t) VGA_CRTC[0xD];
  492. for (y=0; y<nh; y++)
  493. for (x=0; x<nw; x++) {
  494. vidptr = y*80 + (x/8);
  495. color = (VRAM[vidptr] >> (~x & 7) ) & 1;
  496. color |= ( (VRAM[vidptr+0x10000] >> (~x & 7) ) & 1) << 1;
  497. color |= ( (VRAM[vidptr+0x20000] >> (~x & 7) ) & 1) << 2;
  498. color |= ( (VRAM[vidptr+0x30000] >> (~x & 7) ) & 1) << 3;
  499. prestretch[y][x] = palettevga[color];
  500. }
  501. break;
  502. case 0x13:
  503. if (vtotal == 11) { //ugly hack to show Flashback at the proper resolution
  504. nw = 256;
  505. nh = 224;
  506. }
  507. else {
  508. nw = 320;
  509. nh = 200;
  510. }
  511. if (VGA_SC[4] & 6) planemode = 1;
  512. else planemode = 0;
  513. vgapage = ( (uint32_t) VGA_CRTC[0xC]<<8) + (uint32_t) VGA_CRTC[0xD];
  514. for (y=0; y<nh; y++)
  515. for (x=0; x<nw; x++) {
  516. if (!planemode) color = palettevga[RAM[videobase + y*nw + x]];
  517. else {
  518. vidptr = y*nw + x;
  519. vidptr = vidptr/4 + (x & 3) *0x10000;
  520. vidptr = vidptr + vgapage - (VGA_ATTR[0x13] & 15);
  521. color = palettevga[VRAM[vidptr]];
  522. }
  523. prestretch[y][x] = color;
  524. }
  525. }
  526. if (vidgfxmode==0) {
  527. if (cursorvisible) {
  528. curheight = 2;
  529. if (cols==80) blockw = 8;
  530. else blockw = 16;
  531. x1 = cursx * blockw;
  532. y1 = cursy * 8 + 8 - curheight;
  533. for (y=y1*2; y<=y1*2+curheight-1; y++)
  534. for (x=x1; x<=x1+blockw-1; x++) {
  535. color = palettecga[RAM[videobase+cursy*cols*2+cursx*2+1]&15];
  536. prestretch[y&1023][x&1023] = color;
  537. }
  538. }
  539. }
  540. if (nosmooth) {
  541. if ( ((nw << 1) == screen->w) && ((nh << 1) == screen->h) ) doubleblit (screen);
  542. else roughblit (screen);
  543. }
  544. else stretchblit (screen);
  545. }