PageRenderTime 89ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/od-win32/picasso96_win.cpp

https://github.com/tonioni/WinUAE
C++ | 6750 lines | 5706 code | 551 blank | 493 comment | 1153 complexity | a6c89be97c3e5a3b9a711fb653319ab0 MD5 | raw file
  1. /*
  2. * UAE - The U*nix Amiga Emulator
  3. *
  4. * Picasso96 Support Module
  5. *
  6. * Copyright 1997-2001 Brian King <Brian_King@CodePoet.com>
  7. * Copyright 2000-2001 Bernd Roesch <>
  8. *
  9. * Theory of operation:
  10. * On the Amiga side, a Picasso card consists mainly of a memory area that
  11. * contains the frame buffer. On the UAE side, we allocate a block of memory
  12. * that will hold the frame buffer. This block is in normal memory, it is
  13. * never directly on the graphics card. All graphics operations, which are
  14. * mainly reads and writes into this block and a few basic operations like
  15. * filling a rectangle, operate on this block of memory.
  16. * Since the memory is not on the graphics card, some work must be done to
  17. * synchronize the display with the data in the Picasso frame buffer. There
  18. * are various ways to do this. One possibility is to allocate a second
  19. * buffer of the same size, and perform all write operations twice. Since
  20. * we never read from the second buffer, it can actually be placed in video
  21. * memory. The X11 driver could be made to use the Picasso frame buffer as
  22. * the data buffer of an XImage, which could then be XPutImage()d from time
  23. * to time. Another possibility is to translate all Picasso accesses into
  24. * Xlib (or GDI, or whatever your graphics system is) calls. This possibility
  25. * is a bit tricky, since there is a risk of generating very many single pixel
  26. * accesses which may be rather slow.
  27. *
  28. * TODO:
  29. * - we want to add a manual switch to override SetSwitch for hardware banging
  30. * programs started from a Picasso workbench.
  31. */
  32. #include "sysconfig.h"
  33. #include "sysdeps.h"
  34. #include <stdlib.h>
  35. #if defined(PICASSO96)
  36. #define MULTIDISPLAY 0
  37. #define WINCURSOR 1
  38. #define NEWTRAP 1
  39. #define OVERLAY 1
  40. #define USE_HARDWARESPRITE 1
  41. #define P96TRACING_ENABLED 0
  42. #define P96TRACING_LEVEL 0
  43. #define P96TRACING_SETUP_ENABLED 0
  44. #define P96SPRTRACING_ENABLED 0
  45. #include "options.h"
  46. #include "threaddep/thread.h"
  47. #include "memory.h"
  48. #include "custom.h"
  49. #include "events.h"
  50. #include "newcpu.h"
  51. #include "xwin.h"
  52. #include "savestate.h"
  53. #include "autoconf.h"
  54. #include "traps.h"
  55. #include "native2amiga.h"
  56. #include "drawing.h"
  57. #include "inputdevice.h"
  58. #include "debug.h"
  59. #include "registry.h"
  60. #include "dxwrap.h"
  61. #ifdef RETROPLATFORM
  62. #include "rp.h"
  63. #endif
  64. #include "picasso96_win.h"
  65. #include "win32gfx.h"
  66. #include "direct3d.h"
  67. #include "clipboard.h"
  68. #include "gfxboard.h"
  69. #include "gfxfilter.h"
  70. #include "dxwrap.h"
  71. #include "devices.h"
  72. int debug_rtg_blitter = 3;
  73. #define NOBLITTER (0 || !(debug_rtg_blitter & 1))
  74. #define NOBLITTER_BLIT (0 || !(debug_rtg_blitter & 2))
  75. #define NOBLITTER_ALL 0
  76. static int hwsprite = 0;
  77. static int picasso96_BT = BT_uaegfx;
  78. static int picasso96_GCT = GCT_Unknown;
  79. static int picasso96_PCT = PCT_Unknown;
  80. int mman_GetWriteWatch (PVOID lpBaseAddress, SIZE_T dwRegionSize, PVOID *lpAddresses, PULONG_PTR lpdwCount, PULONG lpdwGranularity);
  81. void mman_ResetWatch (PVOID lpBaseAddress, SIZE_T dwRegionSize);
  82. void picasso_flushpixels(int index, uae_u8 *src, int offset, bool render);
  83. int p96refresh_active;
  84. bool have_done_picasso = 1; /* For the JIT compiler */
  85. int p96syncrate;
  86. static int p96hsync_counter;
  87. static smp_comm_pipe *render_pipe;
  88. static volatile int render_thread_state;
  89. static CRITICAL_SECTION render_cs;
  90. #define PICASSO_STATE_SETDISPLAY 1
  91. #define PICASSO_STATE_SETPANNING 2
  92. #define PICASSO_STATE_SETGC 4
  93. #define PICASSO_STATE_SETDAC 8
  94. #define PICASSO_STATE_SETSWITCH 16
  95. #if defined(X86_MSVC_ASSEMBLY)
  96. #define SWAPSPEEDUP
  97. #endif
  98. #ifdef PICASSO96
  99. #ifdef DEBUG // Change this to _DEBUG for debugging
  100. #define P96TRACING_ENABLED 1
  101. #define P96TRACING_LEVEL 1
  102. #endif
  103. #if P96TRACING_ENABLED
  104. #define P96TRACE(x) do { write_log x; } while(0)
  105. #else
  106. #define P96TRACE(x)
  107. #endif
  108. #if P96TRACING_SETUP_ENABLED
  109. #define P96TRACE_SETUP(x) do { write_log x; } while(0)
  110. #else
  111. #define P96TRACE_SETUP(x)
  112. #endif
  113. #if P96SPRTRACING_ENABLED
  114. #define P96TRACE_SPR(x) do { write_log x; } while(0)
  115. #else
  116. #define P96TRACE_SPR(x)
  117. #endif
  118. #define P96TRACE2(x) do { write_log x; } while(0)
  119. #define TAG_DONE (0L) /* terminates array of TagItems. ti_Data unused */
  120. #define TAG_IGNORE (1L) /* ignore this item, not end of array */
  121. #define TAG_MORE (2L) /* ti_Data is pointer to another array of TagItems */
  122. #define TAG_SKIP (3L) /* skip this and the next ti_Data items */
  123. static uae_u8 all_ones_bitmap, all_zeros_bitmap; /* yuk */
  124. struct picasso96_state_struct picasso96_state[MAX_AMIGAMONITORS];
  125. //static struct picasso96_state_struct picasso96_state_uaegfx;
  126. struct picasso_vidbuf_description picasso_vidinfo[MAX_AMIGAMONITORS];
  127. static struct PicassoResolution *newmodes;
  128. /* These are the maximum resolutions... They are filled in by GetSupportedResolutions() */
  129. /* have to fill this in, otherwise problems occur on the Amiga side P96 s/w which expects
  130. /* data here. */
  131. static struct ScreenResolution planar = { 320, 240 };
  132. static struct ScreenResolution chunky = { 640, 480 };
  133. static struct ScreenResolution hicolour = { 640, 480 };
  134. static struct ScreenResolution truecolour = { 640, 480 };
  135. static struct ScreenResolution alphacolour = { 640, 480 };
  136. uae_u32 p96_rgbx16[65536];
  137. uae_u32 p96rc[256], p96gc[256], p96bc[256];
  138. static int newcursor_x, newcursor_y;
  139. static int cursorwidth, cursorheight, cursorok;
  140. static uae_u8 *cursordata;
  141. static uae_u32 cursorrgb[4], cursorrgbn[4];
  142. static int cursordeactivate, setupcursor_needed;
  143. static bool cursorvisible;
  144. static HCURSOR wincursor;
  145. static int wincursor_shown;
  146. static uaecptr boardinfo, ABI_interrupt;
  147. static int interrupt_enabled;
  148. float p96vblank;
  149. #define OVERLAY_DEBUG 1
  150. static int overlay_src_width_in, overlay_src_height_in;
  151. static int overlay_src_height, overlay_src_width;
  152. static uae_u32 overlay_format, overlay_color, overlay_color_unswapped;
  153. static uae_u32 overlay_modeformat, overlay_modeinfo;
  154. static uae_u32 overlay_brightness;
  155. static int overlay_x, overlay_y;
  156. static int overlay_w, overlay_h;
  157. static int overlay_clipleft, overlay_cliptop;
  158. static int overlay_clipwidth, overlay_clipheight;
  159. static int overlay_pix;
  160. static uaecptr overlay_bitmap, overlay_vram;
  161. static int overlay_vram_offset;
  162. static int overlay_active;
  163. static int overlay_convert;
  164. static int overlay_occlusion;
  165. static struct MyCLUTEntry overlay_clutc[256 * 2];
  166. static uae_u32 overlay_clut[256 * 2];
  167. static uae_u32 *p96_rgbx16_ovl;
  168. static bool delayed_set_switch;
  169. static int uaegfx_old, uaegfx_active;
  170. static uae_u32 reserved_gfxmem;
  171. static uaecptr uaegfx_resname,
  172. uaegfx_resid,
  173. uaegfx_init,
  174. uaegfx_base,
  175. uaegfx_rom;
  176. typedef enum {
  177. BLIT_FALSE,
  178. BLIT_NOR,
  179. BLIT_ONLYDST,
  180. BLIT_NOTSRC,
  181. BLIT_ONLYSRC,
  182. BLIT_NOTDST,
  183. BLIT_EOR,
  184. BLIT_NAND,
  185. BLIT_AND,
  186. BLIT_NEOR,
  187. BLIT_DST,
  188. BLIT_NOTONLYSRC,
  189. BLIT_SRC,
  190. BLIT_NOTONLYDST,
  191. BLIT_OR,
  192. BLIT_TRUE,
  193. BLIT_SWAP = 30
  194. } BLIT_OPCODE;
  195. #include "win32gui.h"
  196. #include "resource.h"
  197. static void init_picasso_screen(int);
  198. static uae_u32 p2ctab[256][2];
  199. static int set_gc_called = 0, init_picasso_screen_called = 0;
  200. //fastscreen
  201. static uaecptr oldscr = 0;
  202. extern addrbank gfxmem_bank;
  203. extern addrbank *gfxmem_banks[MAX_RTG_BOARDS];
  204. extern int rtg_index;
  205. void lockrtg(void)
  206. {
  207. if (currprefs.rtg_multithread && render_pipe)
  208. EnterCriticalSection(&render_cs);
  209. }
  210. void unlockrtg(void)
  211. {
  212. if (currprefs.rtg_multithread && render_pipe)
  213. LeaveCriticalSection(&render_cs);
  214. }
  215. STATIC_INLINE void endianswap (uae_u32 *vp, int bpp)
  216. {
  217. switch (bpp)
  218. {
  219. case 2:
  220. *vp = _byteswap_ushort(*vp);
  221. break;
  222. case 4:
  223. *vp = _byteswap_ulong(*vp);
  224. break;
  225. }
  226. }
  227. #if P96TRACING_ENABLED
  228. /*
  229. * Debugging dumps
  230. */
  231. static void DumpModeInfoStructure(TrapContext *ctx, uaecptr amigamodeinfoptr)
  232. {
  233. write_log (_T("ModeInfo Structure Dump:\n"));
  234. write_log (_T(" Node.ln_Succ = 0x%x\n"), trap_get_long(ctx, amigamodeinfoptr));
  235. write_log (_T(" Node.ln_Pred = 0x%x\n"), trap_get_long(ctx, amigamodeinfoptr + 4));
  236. write_log (_T(" Node.ln_Type = 0x%x\n"), trap_get_byte(ctx, amigamodeinfoptr + 8));
  237. write_log (_T(" Node.ln_Pri = %d\n"), trap_get_byte(ctx, amigamodeinfoptr + 9));
  238. /*write_log (_T(" Node.ln_Name = %s\n"), uaememptr->Node.ln_Name); */
  239. write_log (_T(" OpenCount = %d\n"), trap_get_word(ctx, amigamodeinfoptr + PSSO_ModeInfo_OpenCount));
  240. write_log (_T(" Active = %d\n"), trap_get_byte(ctx, amigamodeinfoptr + PSSO_ModeInfo_Active));
  241. write_log (_T(" Width = %d\n"), trap_get_word(ctx, amigamodeinfoptr + PSSO_ModeInfo_Width));
  242. write_log (_T(" Height = %d\n"), trap_get_word(ctx, amigamodeinfoptr + PSSO_ModeInfo_Height));
  243. write_log (_T(" Depth = %d\n"), trap_get_byte(ctx, amigamodeinfoptr + PSSO_ModeInfo_Depth));
  244. write_log (_T(" Flags = %d\n"), trap_get_byte(ctx, amigamodeinfoptr + PSSO_ModeInfo_Flags));
  245. write_log (_T(" HorTotal = %d\n"), trap_get_word(ctx, amigamodeinfoptr + PSSO_ModeInfo_HorTotal));
  246. write_log (_T(" HorBlankSize = %d\n"), trap_get_word(ctx, amigamodeinfoptr + PSSO_ModeInfo_HorBlankSize));
  247. write_log (_T(" HorSyncStart = %d\n"), trap_get_word(ctx, amigamodeinfoptr + PSSO_ModeInfo_HorSyncStart));
  248. write_log (_T(" HorSyncSize = %d\n"), trap_get_word(ctx, amigamodeinfoptr + PSSO_ModeInfo_HorSyncSize));
  249. write_log (_T(" HorSyncSkew = %d\n"), trap_get_byte(ctx, amigamodeinfoptr + PSSO_ModeInfo_HorSyncSkew));
  250. write_log (_T(" HorEnableSkew = %d\n"), trap_get_byte(ctx, amigamodeinfoptr + PSSO_ModeInfo_HorEnableSkew));
  251. write_log (_T(" VerTotal = %d\n"), trap_get_word(ctx, amigamodeinfoptr + PSSO_ModeInfo_VerTotal));
  252. write_log (_T(" VerBlankSize = %d\n"), trap_get_word(ctx, amigamodeinfoptr + PSSO_ModeInfo_VerBlankSize));
  253. write_log (_T(" VerSyncStart = %d\n"), trap_get_word(ctx, amigamodeinfoptr + PSSO_ModeInfo_VerSyncStart));
  254. write_log (_T(" VerSyncSize = %d\n"), trap_get_word(ctx, amigamodeinfoptr + PSSO_ModeInfo_VerSyncSize));
  255. write_log (_T(" Clock = %d\n"), trap_get_byte(ctx, amigamodeinfoptr + PSSO_ModeInfo_first_union));
  256. write_log (_T(" ClockDivide = %d\n"), trap_get_byte(ctx, amigamodeinfoptr + PSSO_ModeInfo_second_union));
  257. write_log (_T(" PixelClock = %d\n"), trap_get_long(ctx, amigamodeinfoptr + PSSO_ModeInfo_PixelClock));
  258. }
  259. static void DumpLibResolutionStructure(TrapContext *ctx, uaecptr amigalibresptr)
  260. {
  261. int i;
  262. uaecptr amigamodeinfoptr;
  263. struct LibResolution *uaememptr = (struct LibResolution *)get_mem_bank(amigalibresptr).xlateaddr(amigalibresptr);
  264. write_log (_T("LibResolution Structure Dump:\n"));
  265. if (trap_get_long(ctx, amigalibresptr + PSSO_LibResolution_DisplayID) == 0xFFFFFFFF) {
  266. write_log (_T(" Finished With LibResolutions...\n"));
  267. } else {
  268. write_log (_T(" Name = %s\n"), uaememptr->P96ID);
  269. write_log (_T(" DisplayID = 0x%x\n"), trap_get_long(ctx, amigalibresptr + PSSO_LibResolution_DisplayID));
  270. write_log (_T(" Width = %d\n"), trap_get_word(ctx, amigalibresptr + PSSO_LibResolution_Width));
  271. write_log (_T(" Height = %d\n"), trap_get_word(ctx, amigalibresptr + PSSO_LibResolution_Height));
  272. write_log (_T(" Flags = %d\n"), trap_get_word(ctx, amigalibresptr + PSSO_LibResolution_Flags));
  273. for (i = 0; i < MAXMODES; i++) {
  274. amigamodeinfoptr = trap_get_long(ctx, amigalibresptr + PSSO_LibResolution_Modes + i*4);
  275. write_log (_T(" ModeInfo[%d] = 0x%x\n"), i, amigamodeinfoptr);
  276. if (amigamodeinfoptr)
  277. DumpModeInfoStructure(ctx, amigamodeinfoptr);
  278. }
  279. write_log (_T(" BoardInfo = 0x%x\n"), trap_get_long(ctx, amigalibresptr + PSSO_LibResolution_BoardInfo));
  280. }
  281. }
  282. static TCHAR binary_byte[9] = { 0,0,0,0,0,0,0,0,0 };
  283. static TCHAR *BuildBinaryString (uae_u8 value)
  284. {
  285. int i;
  286. for (i = 0; i < 8; i++) {
  287. binary_byte[i] = (value & (1 << (7 - i))) ? '#' : '.';
  288. }
  289. return binary_byte;
  290. }
  291. static void DumpPattern (struct Pattern *patt)
  292. {
  293. uae_u8 *mem;
  294. int row, col;
  295. if (!patt->Memory)
  296. return;
  297. for (row = 0; row < (1 << patt->Size); row++) {
  298. mem = patt->Memory + row * 2;
  299. for (col = 0; col < 2; col++) {
  300. write_log (_T("%s "), BuildBinaryString (*mem++));
  301. }
  302. write_log (_T("\n"));
  303. }
  304. }
  305. static void DumpTemplate (struct Template *tmp, unsigned long w, unsigned long h)
  306. {
  307. uae_u8 *mem = tmp->Memory;
  308. unsigned int row, col, width;
  309. if (!mem)
  310. return;
  311. width = (w + 7) >> 3;
  312. write_log (_T("xoffset = %d, bpr = %d\n"), tmp->XOffset, tmp->BytesPerRow);
  313. for (row = 0; row < h; row++) {
  314. mem = tmp->Memory + row * tmp->BytesPerRow;
  315. for (col = 0; col < width; col++) {
  316. write_log (_T("%s "), BuildBinaryString (*mem++));
  317. }
  318. write_log (_T("\n"));
  319. }
  320. }
  321. static void DumpLine(struct Line *line)
  322. {
  323. if (line) {
  324. write_log (_T("Line->X = %d\n"), line->X);
  325. write_log (_T("Line->Y = %d\n"), line->Y);
  326. write_log (_T("Line->Length = %d\n"), line->Length);
  327. write_log (_T("Line->dX = %d\n"), line->dX);
  328. write_log (_T("Line->dY = %d\n"), line->dY);
  329. write_log (_T("Line->sDelta = %d\n"), line->sDelta);
  330. write_log (_T("Line->lDelta = %d\n"), line->lDelta);
  331. write_log (_T("Line->twoSDminusLD = %d\n"), line->twoSDminusLD);
  332. write_log (_T("Line->LinePtrn = %d\n"), line->LinePtrn);
  333. write_log (_T("Line->PatternShift = %d\n"), line->PatternShift);
  334. write_log (_T("Line->FgPen = 0x%x\n"), line->FgPen);
  335. write_log (_T("Line->BgPen = 0x%x\n"), line->BgPen);
  336. write_log (_T("Line->Horizontal = %d\n"), line->Horizontal);
  337. write_log (_T("Line->DrawMode = %d\n"), line->DrawMode);
  338. write_log (_T("Line->Xorigin = %d\n"), line->Xorigin);
  339. write_log (_T("Line->Yorigin = %d\n"), line->Yorigin);
  340. }
  341. }
  342. static void ShowSupportedResolutions (void)
  343. {
  344. int i = 0;
  345. write_log (_T("-----------------\n"));
  346. while (newmodes[i].depth >= 0) {
  347. write_log (_T("%s\n"), newmodes[i].name);
  348. i++;
  349. }
  350. write_log (_T("-----------------\n"));
  351. }
  352. #endif
  353. static void **gwwbuf[MAX_RTG_BOARDS];
  354. static int gwwbufsize[MAX_RTG_BOARDS], gwwpagesize[MAX_RTG_BOARDS], gwwpagemask[MAX_RTG_BOARDS];
  355. extern uae_u8 *natmem_offset;
  356. static uae_u8 GetBytesPerPixel (uae_u32 RGBfmt)
  357. {
  358. switch (RGBfmt)
  359. {
  360. case RGBFB_CLUT:
  361. case RGBFB_Y4U1V1:
  362. return 1;
  363. case RGBFB_A8R8G8B8:
  364. case RGBFB_A8B8G8R8:
  365. case RGBFB_R8G8B8A8:
  366. case RGBFB_B8G8R8A8:
  367. return 4;
  368. case RGBFB_B8G8R8:
  369. case RGBFB_R8G8B8:
  370. return 3;
  371. case RGBFB_R5G5B5:
  372. case RGBFB_R5G6B5:
  373. case RGBFB_R5G6B5PC:
  374. case RGBFB_R5G5B5PC:
  375. case RGBFB_B5G6R5PC:
  376. case RGBFB_B5G5R5PC:
  377. case RGBFB_Y4U2V2:
  378. return 2;
  379. }
  380. return 0;
  381. }
  382. STATIC_INLINE bool validatecoords2(TrapContext *ctx, struct RenderInfo *ri, uae_u32 *Xp, uae_u32 *Yp, uae_u32 *Widthp, uae_u32 *Heightp)
  383. {
  384. uae_u32 Width = *Widthp;
  385. uae_u32 Height = *Heightp;
  386. uae_u32 X = *Xp;
  387. uae_u32 Y = *Yp;
  388. if (!Width || !Height) {
  389. return true;
  390. }
  391. if (Width > 32767 || Height > 32767 || X > 32767 || Y > 32767) {
  392. return false;
  393. }
  394. if (ri) {
  395. int bpp = GetBytesPerPixel (ri->RGBFormat);
  396. if (X * bpp >= ri->BytesPerRow) {
  397. return false;
  398. }
  399. uae_u32 X2 = X + Width;
  400. if (X2 * bpp > ri->BytesPerRow) {
  401. X2 = ri->BytesPerRow / bpp;
  402. Width = X2 - X;
  403. *Widthp = Width;
  404. }
  405. uaecptr start = gfxmem_banks[0]->start;
  406. uae_u32 size = gfxmem_banks[0]->allocated_size;
  407. uaecptr mem = ri->AMemory;
  408. if (mem < start || mem >= start + size) {
  409. return false;
  410. }
  411. mem += (Y + Height - 1) * ri->BytesPerRow + (X + Width - 1) * bpp;
  412. if (mem < start || mem >= start + size) {
  413. return false;
  414. }
  415. }
  416. return true;
  417. }
  418. static bool validatecoords(TrapContext *ctx, struct RenderInfo *ri, uae_u32 *X, uae_u32 *Y, uae_u32 *Width, uae_u32 *Height)
  419. {
  420. if (validatecoords2(ctx, ri, X, Y, Width, Height))
  421. return true;
  422. write_log (_T("RTG invalid region: %08X:%d:%d (%dx%d)-(%dx%d)\n"), ri->AMemory, ri->BytesPerRow, ri->RGBFormat, *X, *Y, *Width, *Height);
  423. return false;
  424. }
  425. /*
  426. * Amiga <-> native structure conversion functions
  427. */
  428. static int CopyRenderInfoStructureA2U(TrapContext *ctx, uaecptr amigamemptr, struct RenderInfo *ri)
  429. {
  430. if (trap_valid_address(ctx, amigamemptr, PSSO_RenderInfo_sizeof)) {
  431. struct trapmd md[] =
  432. {
  433. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_RenderInfo_Memory } },
  434. { TRAPCMD_GET_WORD, { amigamemptr + PSSO_RenderInfo_BytesPerRow } },
  435. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_RenderInfo_RGBFormat } }
  436. };
  437. trap_multi(ctx, md, sizeof md / sizeof(struct trapmd));
  438. uaecptr memp = md[0].params[0];
  439. ri->AMemory = memp;
  440. ri->BytesPerRow = md[1].params[0];
  441. ri->RGBFormat = (RGBFTYPE)md[2].params[0];
  442. // Can't really validate this better at this point, no height.
  443. if (trap_valid_address(ctx, memp, ri->BytesPerRow)) {
  444. ri->Memory = get_real_address(memp);
  445. return 1;
  446. }
  447. }
  448. write_log (_T("ERROR - Invalid RenderInfo memory area...\n"));
  449. return 0;
  450. }
  451. static int CopyPatternStructureA2U(TrapContext *ctx, uaecptr amigamemptr, struct Pattern *pattern)
  452. {
  453. if (trap_valid_address(ctx, amigamemptr, PSSO_Pattern_sizeof)) {
  454. struct trapmd md[] =
  455. {
  456. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_Pattern_Memory } },
  457. { TRAPCMD_GET_WORD, { amigamemptr + PSSO_Pattern_XOffset } },
  458. { TRAPCMD_GET_WORD, { amigamemptr + PSSO_Pattern_YOffset } },
  459. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_Pattern_FgPen } },
  460. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_Pattern_BgPen } },
  461. { TRAPCMD_GET_BYTE, { amigamemptr + PSSO_Pattern_Size } },
  462. { TRAPCMD_GET_BYTE, { amigamemptr + PSSO_Pattern_DrawMode } }
  463. };
  464. trap_multi(ctx, md, sizeof md / sizeof(struct trapmd));
  465. uaecptr memp = md[0].params[0];
  466. pattern->AMemory = memp;
  467. pattern->XOffset = md[1].params[0];
  468. pattern->YOffset = md[2].params[0];
  469. pattern->FgPen = md[3].params[0];
  470. pattern->BgPen = md[4].params[0];
  471. pattern->Size = md[5].params[0];
  472. pattern->DrawMode = md[6].params[0];
  473. if (trap_valid_address(ctx, memp, 2)) {
  474. if (trap_is_indirect())
  475. pattern->Memory = NULL;
  476. else
  477. pattern->Memory = get_real_address(memp);
  478. return 1;
  479. }
  480. }
  481. write_log (_T("ERROR - Invalid Pattern memory area...\n"));
  482. return 0;
  483. }
  484. static int CopyBitMapStructureA2U(TrapContext *ctx, uaecptr amigamemptr, struct BitMap *bm)
  485. {
  486. int i;
  487. struct trapmd md[] =
  488. {
  489. { TRAPCMD_GET_WORD, { amigamemptr + PSSO_BitMap_BytesPerRow } },
  490. { TRAPCMD_GET_WORD, { amigamemptr + PSSO_BitMap_Rows } },
  491. { TRAPCMD_GET_BYTE, { amigamemptr + PSSO_BitMap_Flags } },
  492. { TRAPCMD_GET_BYTE, { amigamemptr + PSSO_BitMap_Depth } },
  493. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_BitMap_Planes + 0 } },
  494. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_BitMap_Planes + 4 } },
  495. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_BitMap_Planes + 8 } },
  496. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_BitMap_Planes + 12 } },
  497. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_BitMap_Planes + 16 } },
  498. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_BitMap_Planes + 20 } },
  499. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_BitMap_Planes + 24 } },
  500. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_BitMap_Planes + 28} }
  501. };
  502. trap_multi(ctx, md, sizeof md / sizeof(struct trapmd));
  503. bm->BytesPerRow = md[0].params[0];
  504. bm->Rows = md[1].params[0];
  505. bm->Flags = md[2].params[0];
  506. bm->Depth = md[3].params[0];
  507. /* ARGH - why is THIS happening? */
  508. if(bm->Depth > 8)
  509. bm->Depth = 8;
  510. for (i = 0; i < bm->Depth; i++) {
  511. uaecptr plane = md[4 + i].params[0];
  512. bm->APlanes[i] = plane;
  513. switch (plane) {
  514. case 0:
  515. bm->Planes[i] = &all_zeros_bitmap;
  516. break;
  517. case 0xFFFFFFFF:
  518. bm->Planes[i] = &all_ones_bitmap;
  519. break;
  520. default:
  521. if (!trap_is_indirect() && trap_valid_address(ctx, plane, bm->BytesPerRow * bm->Rows))
  522. bm->Planes[i] = get_real_address(plane);
  523. else
  524. bm->Planes[i] = &all_zeros_bitmap;
  525. break;
  526. }
  527. }
  528. return 1;
  529. }
  530. static int CopyTemplateStructureA2U(TrapContext *ctx, uaecptr amigamemptr, struct Template *tmpl)
  531. {
  532. if (trap_valid_address(ctx, amigamemptr, PSSO_Template_sizeof)) {
  533. struct trapmd md[] =
  534. {
  535. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_Template_Memory } },
  536. { TRAPCMD_GET_WORD, { amigamemptr + PSSO_Template_BytesPerRow } },
  537. { TRAPCMD_GET_BYTE, { amigamemptr + PSSO_Template_XOffset } },
  538. { TRAPCMD_GET_BYTE, { amigamemptr + PSSO_Template_DrawMode } },
  539. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_Template_FgPen } },
  540. { TRAPCMD_GET_LONG, { amigamemptr + PSSO_Template_BgPen } }
  541. };
  542. trap_multi(ctx, md, sizeof md / sizeof(struct trapmd));
  543. uaecptr memp = md[0].params[0];
  544. if (trap_is_indirect()) {
  545. tmpl->Memory = NULL;
  546. } else {
  547. if (!trap_valid_address(ctx, memp, 1)) {
  548. write_log(_T("ERROR - Invalid Template memory region %08x...\n"), memp);
  549. return 0;
  550. }
  551. tmpl->Memory = get_real_address(memp);
  552. }
  553. tmpl->AMemory = memp;
  554. tmpl->BytesPerRow = md[1].params[0];
  555. tmpl->XOffset = md[2].params[0];
  556. tmpl->DrawMode = md[3].params[0];
  557. tmpl->FgPen = md[4].params[0];
  558. tmpl->BgPen = md[5].params[0];
  559. return 1;
  560. }
  561. write_log (_T("ERROR - Invalid Template memory area...\n"));
  562. return 0;
  563. }
  564. static int CopyLineStructureA2U(TrapContext *ctx, uaecptr amigamemptr, struct Line *line)
  565. {
  566. if (trap_valid_address(ctx, amigamemptr, sizeof(struct Line))) {
  567. line->X = trap_get_word(ctx, amigamemptr + PSSO_Line_X);
  568. line->Y = trap_get_word(ctx, amigamemptr + PSSO_Line_Y);
  569. line->Length = trap_get_word(ctx, amigamemptr + PSSO_Line_Length);
  570. line->dX = trap_get_word(ctx, amigamemptr + PSSO_Line_dX);
  571. line->dY = trap_get_word(ctx, amigamemptr + PSSO_Line_dY);
  572. line->lDelta = trap_get_word(ctx, amigamemptr + PSSO_Line_lDelta);
  573. line->sDelta = trap_get_word(ctx, amigamemptr + PSSO_Line_sDelta);
  574. line->twoSDminusLD = trap_get_word(ctx, amigamemptr + PSSO_Line_twoSDminusLD);
  575. line->LinePtrn = trap_get_word(ctx, amigamemptr + PSSO_Line_LinePtrn);
  576. line->PatternShift = trap_get_word(ctx, amigamemptr + PSSO_Line_PatternShift);
  577. line->FgPen = trap_get_long(ctx, amigamemptr + PSSO_Line_FgPen);
  578. line->BgPen = trap_get_long(ctx, amigamemptr + PSSO_Line_BgPen);
  579. line->Horizontal = trap_get_word(ctx, amigamemptr + PSSO_Line_Horizontal);
  580. line->DrawMode = trap_get_byte(ctx, amigamemptr + PSSO_Line_DrawMode);
  581. line->Xorigin = trap_get_word(ctx, amigamemptr + PSSO_Line_Xorigin);
  582. line->Yorigin = trap_get_word(ctx, amigamemptr + PSSO_Line_Yorigin);
  583. return 1;
  584. }
  585. write_log (_T("ERROR - Invalid Line structure...\n"));
  586. return 0;
  587. }
  588. /* list is Amiga address of list, in correct endian format for UAE
  589. * node is Amiga address of node, in correct endian format for UAE */
  590. static void AmigaListAddTail(TrapContext *ctx, uaecptr l, uaecptr n)
  591. {
  592. trap_put_long(ctx, n + 0, l + 4); // n->ln_Succ = (struct Node *)&l->lh_Tail;
  593. trap_put_long(ctx, n + 4, trap_get_long(ctx, l + 8)); // n->ln_Pred = l->lh_TailPred;
  594. trap_put_long(ctx, trap_get_long(ctx, l + 8) + 0, n); // l->lh_TailPred->ln_Succ = n;
  595. trap_put_long(ctx, l + 8, n); // l->lh_TailPred = n;
  596. }
  597. /*
  598. * Fill a rectangle in the screen.
  599. */
  600. static void do_fillrect_frame_buffer(struct RenderInfo *ri, int X, int Y, int Width, int Height, uae_u32 Pen, int Bpp)
  601. {
  602. int cols;
  603. uae_u8 *dst;
  604. int bpr = ri->BytesPerRow;
  605. dst = ri->Memory + X * Bpp + Y * bpr;
  606. endianswap (&Pen, Bpp);
  607. switch (Bpp)
  608. {
  609. case 1:
  610. for (int lines = 0; lines < Height; lines++, dst += bpr) {
  611. memset (dst, Pen, Width);
  612. }
  613. break;
  614. case 2:
  615. {
  616. Pen |= Pen << 16;
  617. for (int lines = 0; lines < Height; lines++, dst += bpr) {
  618. uae_u32 *p = (uae_u32*)dst;
  619. for (cols = 0; cols < (Width & ~15); cols += 16) {
  620. *p++ = Pen;
  621. *p++ = Pen;
  622. *p++ = Pen;
  623. *p++ = Pen;
  624. *p++ = Pen;
  625. *p++ = Pen;
  626. *p++ = Pen;
  627. *p++ = Pen;
  628. }
  629. while (cols < (Width & ~1)) {
  630. *p++ = Pen;
  631. cols += 2;
  632. }
  633. if (Width & 1) {
  634. ((uae_u16*)p)[0] = Pen;
  635. }
  636. }
  637. }
  638. break;
  639. case 3:
  640. {
  641. uae_u16 Pen1 = Pen & 0xffff;
  642. uae_u16 Pen2 = (Pen << 8) | ((Pen >> 16) & 0xff);
  643. uae_u16 Pen3 = Pen >> 8;
  644. bool same = (Pen & 0xff) == ((Pen >> 8) & 0xff) && (Pen & 0xff) == ((Pen >> 16) & 0xff);
  645. for (int lines = 0; lines < Height; lines++, dst += bpr) {
  646. uae_u16 *p = (uae_u16*)dst;
  647. if (same) {
  648. memset(p, Pen & 0xff, Width * 3);
  649. } else {
  650. for (cols = 0; cols < (Width & ~7); cols += 8) {
  651. *p++ = Pen1;
  652. *p++ = Pen2;
  653. *p++ = Pen3;
  654. *p++ = Pen1;
  655. *p++ = Pen2;
  656. *p++ = Pen3;
  657. *p++ = Pen1;
  658. *p++ = Pen2;
  659. *p++ = Pen3;
  660. *p++ = Pen1;
  661. *p++ = Pen2;
  662. *p++ = Pen3;
  663. }
  664. uae_u8 *p8 = (uae_u8*)p;
  665. while (cols < Width) {
  666. *p8++ = Pen >> 0;
  667. *p8++ = Pen >> 8;
  668. *p8++ = Pen >> 16;
  669. cols++;
  670. }
  671. }
  672. }
  673. }
  674. break;
  675. case 4:
  676. {
  677. for (int lines = 0; lines < Height; lines++, dst += bpr) {
  678. uae_u32 *p = (uae_u32*)dst;
  679. for (cols = 0; cols < (Width & ~7); cols += 8) {
  680. *p++ = Pen;
  681. *p++ = Pen;
  682. *p++ = Pen;
  683. *p++ = Pen;
  684. *p++ = Pen;
  685. *p++ = Pen;
  686. *p++ = Pen;
  687. *p++ = Pen;
  688. }
  689. while (cols < Width) {
  690. *p++ = Pen;
  691. cols++;
  692. }
  693. }
  694. }
  695. break;
  696. }
  697. }
  698. static void setupcursor(void)
  699. {
  700. uae_u8 *dptr;
  701. int bpp = 4;
  702. int pitch;
  703. struct rtgboardconfig *rbc = &currprefs.rtgboards[0];
  704. if (rbc->rtgmem_type >= GFXBOARD_HARDWARE || !currprefs.gfx_api)
  705. return;
  706. gfx_lock ();
  707. setupcursor_needed = 1;
  708. dptr = D3D_setcursorsurface(rbc->monitor_id, &pitch);
  709. if (dptr) {
  710. for (int y = 0; y < CURSORMAXHEIGHT; y++) {
  711. uae_u8 *p2 = dptr + pitch * y;
  712. memset (p2, 0, CURSORMAXWIDTH * bpp);
  713. }
  714. if (cursordata && cursorwidth && cursorheight) {
  715. for (int y = 0; y < cursorheight; y++) {
  716. uae_u8 *p1 = cursordata + cursorwidth * bpp * y;
  717. uae_u8 *p2 = dptr + pitch * y;
  718. memcpy (p2, p1, cursorwidth * bpp);
  719. }
  720. }
  721. D3D_setcursorsurface(rbc->monitor_id, NULL);
  722. setupcursor_needed = 0;
  723. P96TRACE_SPR((_T("cursorsurface3d updated\n")));
  724. } else {
  725. P96TRACE_SPR((_T("cursorsurfaced3d LockRect() failed %08x\n"), hr));
  726. }
  727. gfx_unlock ();
  728. }
  729. static void disablemouse (void)
  730. {
  731. cursorok = FALSE;
  732. cursordeactivate = 0;
  733. if (!hwsprite)
  734. return;
  735. if (!currprefs.gfx_api)
  736. return;
  737. D3D_setcursor(0, 0, 0, 0, 0, false, true);
  738. }
  739. static void mouseupdate(struct AmigaMonitor *mon)
  740. {
  741. struct picasso96_state_struct *state = &picasso96_state[mon->monitor_id];
  742. int x = newcursor_x;
  743. int y = newcursor_y;
  744. int forced = 0;
  745. if (!hwsprite)
  746. return;
  747. if (cursordeactivate > 0) {
  748. cursordeactivate--;
  749. if (cursordeactivate == 0) {
  750. disablemouse ();
  751. cursorvisible = false;
  752. }
  753. }
  754. if (!currprefs.gfx_api)
  755. return;
  756. if (currprefs.gf[1].gfx_filter_autoscale == RTG_MODE_CENTER) {
  757. D3D_setcursor(mon->monitor_id, x, y, WIN32GFX_GetWidth(mon), WIN32GFX_GetHeight(mon), cursorvisible, mon->scalepicasso == 2);
  758. } else {
  759. D3D_setcursor(mon->monitor_id, x, y, state->Width, state->Height, cursorvisible, false);
  760. }
  761. }
  762. static int p96_framecnt;
  763. int p96skipmode = -1;
  764. static int doskip (void)
  765. {
  766. if (p96_framecnt >= currprefs.gfx_framerate)
  767. p96_framecnt = 0;
  768. return p96_framecnt > 0;
  769. }
  770. void picasso_trigger_vblank(void)
  771. {
  772. TrapContext *ctx = NULL;
  773. if (!ABI_interrupt || !uaegfx_base || !interrupt_enabled || !currprefs.rtg_hardwareinterrupt)
  774. return;
  775. trap_put_long(ctx, uaegfx_base + CARD_IRQPTR, ABI_interrupt + PSSO_BoardInfo_SoftInterrupt);
  776. trap_put_byte(ctx, uaegfx_base + CARD_IRQFLAG, 1);
  777. if (currprefs.win32_rtgvblankrate != 0)
  778. INTREQ (0x8000 | 0x0008);
  779. }
  780. static bool is_uaegfx_active(void)
  781. {
  782. if (currprefs.rtgboards[0].rtgmem_type >= GFXBOARD_HARDWARE || !currprefs.rtgboards[0].rtgmem_size)
  783. return false;
  784. return true;
  785. }
  786. static void rtg_render(void)
  787. {
  788. int monid = currprefs.rtgboards[0].monitor_id;
  789. bool uaegfx_active = is_uaegfx_active();
  790. int uaegfx_index = 0;
  791. struct AmigaMonitor *mon = &AMonitors[monid];
  792. struct picasso96_state_struct *state = &picasso96_state[monid];
  793. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  794. struct amigadisplay *ad = &adisplays[monid];
  795. if (D3D_restore)
  796. D3D_restore(monid, true);
  797. if (doskip () && p96skipmode == 0) {
  798. ;
  799. } else {
  800. bool full = vidinfo->full_refresh > 0;
  801. if (uaegfx_active) {
  802. if (!currprefs.rtg_multithread) {
  803. picasso_flushpixels(0, gfxmem_banks[uaegfx_index]->start + natmem_offset, state->XYOffset - gfxmem_banks[uaegfx_index]->start, true);
  804. }
  805. } else {
  806. if (vidinfo->full_refresh < 0)
  807. vidinfo->full_refresh = 0;
  808. if (vidinfo->full_refresh > 0)
  809. vidinfo->full_refresh--;
  810. }
  811. gfxboard_vsync_handler(full, true);
  812. if (currprefs.rtg_multithread && uaegfx_active) {
  813. if (ad->pending_render) {
  814. ad->pending_render = false;
  815. gfx_unlock_picasso(mon->monitor_id, true);
  816. }
  817. write_comm_pipe_int(render_pipe, uaegfx_index, 0);
  818. }
  819. }
  820. }
  821. static void rtg_clear(int monid)
  822. {
  823. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  824. vidinfo->rtg_clear_flag = 2;
  825. }
  826. enum {
  827. /* DEST = RGBFB_B8G8R8A8,32 */
  828. RGBFB_A8R8G8B8_32 = 1,
  829. RGBFB_A8B8G8R8_32,
  830. RGBFB_R8G8B8A8_32,
  831. RGBFB_B8G8R8A8_32,
  832. RGBFB_R8G8B8_32,
  833. RGBFB_B8G8R8_32,
  834. RGBFB_R5G6B5PC_32,
  835. RGBFB_R5G5B5PC_32,
  836. RGBFB_R5G6B5_32,
  837. RGBFB_R5G5B5_32,
  838. RGBFB_B5G6R5PC_32,
  839. RGBFB_B5G5R5PC_32,
  840. RGBFB_CLUT_RGBFB_32,
  841. RGBFB_Y4U2V2_32,
  842. RGBFB_Y4U1V1_32,
  843. /* DEST = RGBFB_R5G6B5PC,16 */
  844. RGBFB_A8R8G8B8_16,
  845. RGBFB_A8B8G8R8_16,
  846. RGBFB_R8G8B8A8_16,
  847. RGBFB_B8G8R8A8_16,
  848. RGBFB_R8G8B8_16,
  849. RGBFB_B8G8R8_16,
  850. RGBFB_R5G6B5PC_16,
  851. RGBFB_R5G5B5PC_16,
  852. RGBFB_R5G6B5_16,
  853. RGBFB_R5G5B5_16,
  854. RGBFB_B5G6R5PC_16,
  855. RGBFB_B5G5R5PC_16,
  856. RGBFB_CLUT_RGBFB_16,
  857. RGBFB_Y4U2V2_16,
  858. RGBFB_Y4U1V1_16,
  859. /* DEST = RGBFB_CLUT,8 */
  860. RGBFB_CLUT_8
  861. };
  862. int getconvert(int rgbformat, int pixbytes)
  863. {
  864. int v = 0;
  865. int d = pixbytes;
  866. switch (rgbformat)
  867. {
  868. case RGBFB_CLUT:
  869. if (d == 1)
  870. v = RGBFB_CLUT_8;
  871. else if (d == 2)
  872. v = RGBFB_CLUT_RGBFB_16;
  873. else if (d == 4)
  874. v = RGBFB_CLUT_RGBFB_32;
  875. break;
  876. case RGBFB_B5G6R5PC:
  877. if (d == 2)
  878. v = RGBFB_B5G6R5PC_16;
  879. else if (d == 4)
  880. v = RGBFB_B5G6R5PC_32;
  881. break;
  882. case RGBFB_R5G6B5PC:
  883. if (d == 2)
  884. v = RGBFB_R5G6B5PC_16;
  885. else if (d == 4)
  886. v = RGBFB_R5G6B5PC_32;
  887. break;
  888. case RGBFB_R5G5B5PC:
  889. if (d == 4)
  890. v = RGBFB_R5G5B5PC_32;
  891. else if (d == 2)
  892. v = RGBFB_R5G5B5PC_16;
  893. break;
  894. case RGBFB_R5G6B5:
  895. if (d == 4)
  896. v = RGBFB_R5G6B5_32;
  897. else
  898. v = RGBFB_R5G6B5_16;
  899. break;
  900. case RGBFB_R5G5B5:
  901. if (d == 4)
  902. v = RGBFB_R5G5B5_32;
  903. else
  904. v = RGBFB_R5G5B5_16;
  905. break;
  906. case RGBFB_B5G5R5PC:
  907. if (d == 4)
  908. v = RGBFB_B5G5R5PC_32;
  909. else
  910. v = RGBFB_B5G5R5PC_16;
  911. break;
  912. case RGBFB_A8R8G8B8:
  913. if (d == 2)
  914. v = RGBFB_A8R8G8B8_16;
  915. else if (d == 4)
  916. v = RGBFB_A8R8G8B8_32;
  917. break;
  918. case RGBFB_R8G8B8:
  919. if (d == 2)
  920. v = RGBFB_R8G8B8_16;
  921. else if (d == 4)
  922. v = RGBFB_R8G8B8_32;
  923. break;
  924. case RGBFB_B8G8R8:
  925. if (d == 2)
  926. v = RGBFB_B8G8R8_16;
  927. else if (d == 4)
  928. v = RGBFB_B8G8R8_32;
  929. break;
  930. case RGBFB_A8B8G8R8:
  931. if (d == 2)
  932. v = RGBFB_A8B8G8R8_16;
  933. else if (d == 4)
  934. v = RGBFB_A8B8G8R8_32;
  935. break;
  936. case RGBFB_B8G8R8A8:
  937. if (d == 2)
  938. v = RGBFB_B8G8R8A8_16;
  939. else if (d == 4)
  940. v = RGBFB_B8G8R8A8_32;
  941. break;
  942. case RGBFB_R8G8B8A8:
  943. if (d == 2)
  944. v = RGBFB_R8G8B8A8_16;
  945. else if (d == 4)
  946. v = RGBFB_R8G8B8A8_32;
  947. break;
  948. case RGBFB_Y4U2V2:
  949. if (d == 4)
  950. v = RGBFB_Y4U2V2_32;
  951. else
  952. v = RGBFB_Y4U2V2_16;
  953. break;
  954. case RGBFB_Y4U1V1:
  955. if (d == 4)
  956. v = RGBFB_Y4U1V1_32;
  957. else
  958. v = RGBFB_Y4U1V1_16;
  959. break;
  960. }
  961. return v;
  962. }
  963. static void setconvert(int monid)
  964. {
  965. lockrtg();
  966. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  967. struct picasso96_state_struct *state = &picasso96_state[monid];
  968. vidinfo->picasso_convert = getconvert(state->RGBFormat, picasso_vidinfo[monid].pixbytes);
  969. if (currprefs.gfx_api) {
  970. vidinfo->host_mode = picasso_vidinfo[monid].pixbytes == 4 ? RGBFB_B8G8R8A8 : RGBFB_B5G6R5PC;
  971. } else {
  972. vidinfo->host_mode = DirectDraw_GetSurfacePixelFormat(NULL);
  973. }
  974. if (picasso_vidinfo[monid].pixbytes == 4)
  975. alloc_colors_rgb(8, 8, 8, 16, 8, 0, 0, 0, 0, 0, p96rc, p96gc, p96bc);
  976. else
  977. alloc_colors_rgb(5, 6, 5, 11, 5, 0, 0, 0, 0, 0, p96rc, p96gc, p96bc);
  978. gfx_set_picasso_colors(monid, state->RGBFormat);
  979. picasso_palette(state->CLUT, vidinfo->clut);
  980. if (vidinfo->host_mode != vidinfo->ohost_mode || state->RGBFormat != vidinfo->orgbformat) {
  981. write_log (_T("RTG conversion: Depth=%d HostRGBF=%d P96RGBF=%d Mode=%d\n"),
  982. picasso_vidinfo[monid].pixbytes, vidinfo->host_mode, state->RGBFormat, vidinfo->picasso_convert);
  983. vidinfo->ohost_mode = vidinfo->host_mode;
  984. vidinfo->orgbformat = state->RGBFormat;
  985. }
  986. vidinfo->full_refresh = 1;
  987. unlockrtg();
  988. }
  989. bool picasso_is_active(int monid)
  990. {
  991. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  992. return vidinfo->picasso_active;
  993. }
  994. /* Clear our screen, since we've got a new Picasso screen-mode, and refresh with the proper contents
  995. * This is called on several occasions:
  996. * 1. Amiga-->Picasso transition, via SetSwitch()
  997. * 2. Picasso-->Picasso transition, via SetPanning().
  998. * 3. whenever the graphics code notifies us that the screen contents have been lost.
  999. */
  1000. void picasso_refresh(int monid)
  1001. {
  1002. struct RenderInfo ri;
  1003. struct AmigaMonitor *mon = &AMonitors[monid];
  1004. struct amigadisplay *ad = &adisplays[monid];
  1005. struct picasso96_state_struct *state = &picasso96_state[monid];
  1006. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  1007. if (!ad->picasso_on)
  1008. return;
  1009. lockrtg();
  1010. vidinfo->full_refresh = 1;
  1011. setconvert(monid);
  1012. setupcursor();
  1013. rtg_clear(monid);
  1014. if (currprefs.rtgboards[0].rtgmem_type >= GFXBOARD_HARDWARE) {
  1015. gfxboard_refresh(monid);
  1016. unlockrtg();
  1017. return;
  1018. }
  1019. /* Make sure that the first time we show a Picasso video mode, we don't blit any crap.
  1020. * We can do this by checking if we have an Address yet.
  1021. */
  1022. if (state->Address) {
  1023. unsigned int width, height;
  1024. /* blit the stuff from our static frame-buffer to the gfx-card */
  1025. ri.Memory = gfxmem_bank.baseaddr + (state->Address - gfxmem_bank.start);
  1026. ri.BytesPerRow = state->BytesPerRow;
  1027. ri.RGBFormat = state->RGBFormat;
  1028. if (vidinfo->set_panning_called) {
  1029. width = (state->VirtualWidth < state->Width) ?
  1030. state->VirtualWidth : state->Width;
  1031. height = (state->VirtualHeight < state->Height) ?
  1032. state->VirtualHeight : state->Height;
  1033. // Let's put a black-border around the case where we've got a sub-screen...
  1034. if (!state->BigAssBitmap) {
  1035. if (state->XOffset || state->YOffset)
  1036. DX_Fill(mon, 0, 0, state->Width, state->Height, 0);
  1037. }
  1038. } else {
  1039. width = state->Width;
  1040. height = state->Height;
  1041. }
  1042. } else {
  1043. write_log (_T("ERROR - picasso_refresh() can't refresh!\n"));
  1044. }
  1045. unlockrtg();
  1046. }
  1047. static void picasso_handle_vsync2(struct AmigaMonitor *mon)
  1048. {
  1049. struct amigadisplay *ad = &adisplays[mon->monitor_id];
  1050. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[mon->monitor_id];
  1051. static int vsynccnt;
  1052. int thisisvsync = 1;
  1053. int vsync = isvsync_rtg();
  1054. int mult;
  1055. bool rendered = false;
  1056. bool uaegfx = currprefs.rtgboards[0].rtgmem_type < GFXBOARD_HARDWARE;
  1057. bool uaegfx_active = is_uaegfx_active();
  1058. int state = vidinfo->picasso_state_change;
  1059. if (state)
  1060. lockrtg();
  1061. if (state & PICASSO_STATE_SETDAC) {
  1062. atomic_and(&vidinfo->picasso_state_change, ~PICASSO_STATE_SETDAC);
  1063. rtg_clear(mon->monitor_id);
  1064. }
  1065. if (state & PICASSO_STATE_SETGC) {
  1066. atomic_and(&vidinfo->picasso_state_change, ~PICASSO_STATE_SETGC);
  1067. set_gc_called = 1;
  1068. vidinfo->picasso_changed = true;
  1069. init_picasso_screen(mon->monitor_id);
  1070. init_hz_p96(mon->monitor_id);
  1071. if (delayed_set_switch) {
  1072. delayed_set_switch = false;
  1073. atomic_or(&vidinfo->picasso_state_change, PICASSO_STATE_SETSWITCH);
  1074. ad->picasso_requested_on = 1;
  1075. set_config_changed();
  1076. }
  1077. }
  1078. if (state & PICASSO_STATE_SETSWITCH) {
  1079. atomic_and(&vidinfo->picasso_state_change, ~PICASSO_STATE_SETSWITCH);
  1080. /* Do not switch immediately. Tell the custom chip emulation about the
  1081. * desired state, and wait for custom.c to call picasso_enablescreen
  1082. * whenever it is ready to change the screen state. */
  1083. if (ad->picasso_on == ad->picasso_requested_on && ad->picasso_requested_on && vidinfo->picasso_changed) {
  1084. ad->picasso_requested_forced_on = true;
  1085. }
  1086. vidinfo->picasso_changed = false;
  1087. vidinfo->picasso_active = ad->picasso_requested_on;
  1088. }
  1089. if (state & PICASSO_STATE_SETPANNING) {
  1090. atomic_and(&vidinfo->picasso_state_change, ~PICASSO_STATE_SETPANNING);
  1091. vidinfo->full_refresh = 1;
  1092. vidinfo->set_panning_called = 1;
  1093. init_picasso_screen(mon->monitor_id);
  1094. vidinfo->set_panning_called = 0;
  1095. }
  1096. if (state & PICASSO_STATE_SETDISPLAY) {
  1097. atomic_and(&vidinfo->picasso_state_change, ~PICASSO_STATE_SETDISPLAY);
  1098. // do nothing
  1099. }
  1100. if (state)
  1101. unlockrtg();
  1102. if (ad->picasso_on) {
  1103. #if 0
  1104. if (vsync < 0) {
  1105. vsync_busywait_end(NULL);
  1106. vsync_busywait_do(NULL, false, false);
  1107. }
  1108. #endif
  1109. }
  1110. getvsyncrate(mon->monitor_id, currprefs.chipset_refreshrate, &mult);
  1111. if (vsync && mult < 0) {
  1112. vsynccnt++;
  1113. if (vsynccnt < 2)
  1114. thisisvsync = 0;
  1115. else
  1116. vsynccnt = 0;
  1117. }
  1118. p96_framecnt++;
  1119. if (!uaegfx && !ad->picasso_on) {
  1120. rtg_render();
  1121. return;
  1122. }
  1123. if (!ad->picasso_on)
  1124. return;
  1125. if (uaegfx && uaegfx_active)
  1126. if (setupcursor_needed)
  1127. setupcursor();
  1128. mouseupdate(mon);
  1129. if (thisisvsync) {
  1130. rtg_render();
  1131. frame_drawn(mon->monitor_id);
  1132. }
  1133. if (uaegfx) {
  1134. if (thisisvsync)
  1135. picasso_trigger_vblank();
  1136. }
  1137. #if 0
  1138. if (vsync < 0) {
  1139. vsync_busywait_start();
  1140. }
  1141. #endif
  1142. }
  1143. static int p96hsync;
  1144. void picasso_handle_vsync(void)
  1145. {
  1146. struct AmigaMonitor *mon = &AMonitors[currprefs.rtgboards[0].monitor_id];
  1147. struct amigadisplay *ad = &adisplays[currprefs.rtgboards[0].monitor_id];
  1148. bool uaegfx = currprefs.rtgboards[0].rtgmem_type < GFXBOARD_HARDWARE;
  1149. bool uaegfx_active = is_uaegfx_active();
  1150. if (currprefs.rtgboards[0].rtgmem_size == 0)
  1151. return;
  1152. if (!ad->picasso_on && uaegfx) {
  1153. if (uaegfx_active) {
  1154. createwindowscursor(mon->monitor_id, 0, 0, 0, 0, 0, 1);
  1155. }
  1156. picasso_trigger_vblank();
  1157. if (!delayed_set_switch)
  1158. return;
  1159. }
  1160. int vsync = isvsync_rtg();
  1161. if (vsync < 0) {
  1162. p96hsync = 0;
  1163. picasso_handle_vsync2(mon);
  1164. } else if (currprefs.win32_rtgvblankrate == 0) {
  1165. picasso_handle_vsync2(mon);
  1166. }
  1167. }
  1168. static void picasso_handle_hsync(void)
  1169. {
  1170. struct AmigaMonitor *mon = &AMonitors[currprefs.rtgboards[0].monitor_id];
  1171. struct amigadisplay *ad = &adisplays[currprefs.rtgboards[0].monitor_id];
  1172. bool uaegfx = currprefs.rtgboards[0].rtgmem_type < GFXBOARD_HARDWARE;
  1173. bool uaegfx_active = is_uaegfx_active();
  1174. if (currprefs.rtgboards[0].rtgmem_size == 0)
  1175. return;
  1176. if (ad->pending_render) {
  1177. ad->pending_render = false;
  1178. gfx_unlock_picasso(mon->monitor_id, true);
  1179. }
  1180. int vsync = isvsync_rtg();
  1181. if (vsync < 0) {
  1182. p96hsync++;
  1183. if (p96hsync >= p96syncrate * 3) {
  1184. p96hsync = 0;
  1185. // kickstart vblank vsync_busywait stuff
  1186. picasso_handle_vsync();
  1187. }
  1188. return;
  1189. }
  1190. if (currprefs.win32_rtgvblankrate == 0)
  1191. return;
  1192. p96hsync++;
  1193. if (p96hsync >= p96syncrate) {
  1194. if (!ad->picasso_on) {
  1195. if (uaegfx) {
  1196. if (uaegfx_active) {
  1197. createwindowscursor(mon->monitor_id, 0, 0, 0, 0, 0, 1);
  1198. }
  1199. picasso_trigger_vblank();
  1200. }
  1201. gfxboard_vsync_handler(false, false);
  1202. } else {
  1203. picasso_handle_vsync2(mon);
  1204. }
  1205. p96hsync = 0;
  1206. }
  1207. }
  1208. #define BLT_SIZE 4
  1209. #define BLT_MULT 1
  1210. #define BLT_NAME BLIT_FALSE_32
  1211. #define BLT_FUNC(s,d) *d = 0
  1212. #include "../p96_blit.cpp"
  1213. #define BLT_NAME BLIT_NOR_32
  1214. #define BLT_FUNC(s,d) *d = ~((*s) | (*d))
  1215. #include "../p96_blit.cpp"
  1216. #define BLT_NAME BLIT_ONLYDST_32
  1217. #define BLT_FUNC(s,d) *d = (*d) & ~(*s)
  1218. #include "../p96_blit.cpp"
  1219. #define BLT_NAME BLIT_NOTSRC_32
  1220. #define BLT_FUNC(s,d) *d = ~(*s)
  1221. #include "../p96_blit.cpp"
  1222. #define BLT_NAME BLIT_ONLYSRC_32
  1223. #define BLT_FUNC(s,d) *d = (*s) & ~(*d)
  1224. #include "../p96_blit.cpp"
  1225. #define BLT_NAME BLIT_NOTDST_32
  1226. #define BLT_FUNC(s,d) *d = ~(*d)
  1227. #include "../p96_blit.cpp"
  1228. #define BLT_NAME BLIT_EOR_32
  1229. #define BLT_FUNC(s,d) *d = (*s) ^ (*d)
  1230. #include "../p96_blit.cpp"
  1231. #define BLT_NAME BLIT_NAND_32
  1232. #define BLT_FUNC(s,d) *d = ~((*s) & (*d))
  1233. #include "../p96_blit.cpp"
  1234. #define BLT_NAME BLIT_AND_32
  1235. #define BLT_FUNC(s,d) *d = (*s) & (*d)
  1236. #include "../p96_blit.cpp"
  1237. #define BLT_NAME BLIT_NEOR_32
  1238. #define BLT_FUNC(s,d) *d = ~((*s) ^ (*d))
  1239. #include "../p96_blit.cpp"
  1240. #define BLT_NAME BLIT_NOTONLYSRC_32
  1241. #define BLT_FUNC(s,d) *d = ~(*s) | (*d)
  1242. #include "../p96_blit.cpp"
  1243. #define BLT_NAME BLIT_NOTONLYDST_32
  1244. #define BLT_FUNC(s,d) *d = ~(*d) | (*s)
  1245. #include "../p96_blit.cpp"
  1246. #define BLT_NAME BLIT_OR_32
  1247. #define BLT_FUNC(s,d) *d = (*s) | (*d)
  1248. #include "../p96_blit.cpp"
  1249. #define BLT_NAME BLIT_TRUE_32
  1250. #define BLT_FUNC(s,d) *d = 0xffffffff
  1251. #include "../p96_blit.cpp"
  1252. #define BLT_NAME BLIT_SWAP_32
  1253. #define BLT_FUNC(s,d) tmp = *d ; *d = *s; *s = tmp;
  1254. #define BLT_TEMP
  1255. #include "../p96_blit.cpp"
  1256. #undef BLT_SIZE
  1257. #undef BLT_MULT
  1258. #define BLT_SIZE 3
  1259. #define BLT_MULT 1
  1260. #define BLT_NAME BLIT_FALSE_24
  1261. #define BLT_FUNC(s,d) *d = 0
  1262. #include "../p96_blit.cpp"
  1263. #define BLT_NAME BLIT_NOR_24
  1264. #define BLT_FUNC(s,d) *d = ~((*s) | (*d))
  1265. #include "../p96_blit.cpp"
  1266. #define BLT_NAME BLIT_ONLYDST_24
  1267. #define BLT_FUNC(s,d) *d = (*d) & ~(*s)
  1268. #include "../p96_blit.cpp"
  1269. #define BLT_NAME BLIT_NOTSRC_24
  1270. #define BLT_FUNC(s,d) *d = ~(*s)
  1271. #include "../p96_blit.cpp"
  1272. #define BLT_NAME BLIT_ONLYSRC_24
  1273. #define BLT_FUNC(s,d) *d = (*s) & ~(*d)
  1274. #include "../p96_blit.cpp"
  1275. #define BLT_NAME BLIT_NOTDST_24
  1276. #define BLT_FUNC(s,d) *d = ~(*d)
  1277. #include "../p96_blit.cpp"
  1278. #define BLT_NAME BLIT_EOR_24
  1279. #define BLT_FUNC(s,d) *d = (*s) ^ (*d)
  1280. #include "../p96_blit.cpp"
  1281. #define BLT_NAME BLIT_NAND_24
  1282. #define BLT_FUNC(s,d) *d = ~((*s) & (*d))
  1283. #include "../p96_blit.cpp"
  1284. #define BLT_NAME BLIT_AND_24
  1285. #define BLT_FUNC(s,d) *d = (*s) & (*d)
  1286. #include "../p96_blit.cpp"
  1287. #define BLT_NAME BLIT_NEOR_24
  1288. #define BLT_FUNC(s,d) *d = ~((*s) ^ (*d))
  1289. #include "../p96_blit.cpp"
  1290. #define BLT_NAME BLIT_NOTONLYSRC_24
  1291. #define BLT_FUNC(s,d) *d = ~(*s) | (*d)
  1292. #include "../p96_blit.cpp"
  1293. #define BLT_NAME BLIT_NOTONLYDST_24
  1294. #define BLT_FUNC(s,d) *d = ~(*d) | (*s)
  1295. #include "../p96_blit.cpp"
  1296. #define BLT_NAME BLIT_OR_24
  1297. #define BLT_FUNC(s,d) *d = (*s) | (*d)
  1298. #include "../p96_blit.cpp"
  1299. #define BLT_NAME BLIT_TRUE_24
  1300. #define BLT_FUNC(s,d) *d = 0xffffffff
  1301. #include "../p96_blit.cpp"
  1302. #define BLT_NAME BLIT_SWAP_24
  1303. #define BLT_FUNC(s,d) tmp = *d ; *d = *s; *s = tmp;
  1304. #define BLT_TEMP
  1305. #include "../p96_blit.cpp"
  1306. #undef BLT_SIZE
  1307. #undef BLT_MULT
  1308. #define BLT_SIZE 2
  1309. #define BLT_MULT 2
  1310. #define BLT_NAME BLIT_FALSE_16
  1311. #define BLT_FUNC(s,d) *d = 0
  1312. #include "../p96_blit.cpp"
  1313. #define BLT_NAME BLIT_NOR_16
  1314. #define BLT_FUNC(s,d) *d = ~((*s) | (*d))
  1315. #include "../p96_blit.cpp"
  1316. #define BLT_NAME BLIT_ONLYDST_16
  1317. #define BLT_FUNC(s,d) *d = (*d) & ~(*s)
  1318. #include "../p96_blit.cpp"
  1319. #define BLT_NAME BLIT_NOTSRC_16
  1320. #define BLT_FUNC(s,d) *d = ~(*s)
  1321. #include "../p96_blit.cpp"
  1322. #define BLT_NAME BLIT_ONLYSRC_16
  1323. #define BLT_FUNC(s,d) *d = (*s) & ~(*d)
  1324. #include "../p96_blit.cpp"
  1325. #define BLT_NAME BLIT_NOTDST_16
  1326. #define BLT_FUNC(s,d) *d = ~(*d)
  1327. #include "../p96_blit.cpp"
  1328. #define BLT_NAME BLIT_EOR_16
  1329. #define BLT_FUNC(s,d) *d = (*s) ^ (*d)
  1330. #include "../p96_blit.cpp"
  1331. #define BLT_NAME BLIT_NAND_16
  1332. #define BLT_FUNC(s,d) *d = ~((*s) & (*d))
  1333. #include "../p96_blit.cpp"
  1334. #define BLT_NAME BLIT_AND_16
  1335. #define BLT_FUNC(s,d) *d = (*s) & (*d)
  1336. #include "../p96_blit.cpp"
  1337. #define BLT_NAME BLIT_NEOR_16
  1338. #define BLT_FUNC(s,d) *d = ~((*s) ^ (*d))
  1339. #include "../p96_blit.cpp"
  1340. #define BLT_NAME BLIT_NOTONLYSRC_16
  1341. #define BLT_FUNC(s,d) *d = ~(*s) | (*d)
  1342. #include "../p96_blit.cpp"
  1343. #define BLT_NAME BLIT_NOTONLYDST_16
  1344. #define BLT_FUNC(s,d) *d = ~(*d) | (*s)
  1345. #include "../p96_blit.cpp"
  1346. #define BLT_NAME BLIT_OR_16
  1347. #define BLT_FUNC(s,d) *d = (*s) | (*d)
  1348. #include "../p96_blit.cpp"
  1349. #define BLT_NAME BLIT_TRUE_16
  1350. #define BLT_FUNC(s,d) *d = 0xffffffff
  1351. #include "../p96_blit.cpp"
  1352. #define BLT_NAME BLIT_SWAP_16
  1353. #define BLT_FUNC(s,d) tmp = *d ; *d = *s; *s = tmp;
  1354. #define BLT_TEMP
  1355. #include "../p96_blit.cpp"
  1356. #undef BLT_SIZE
  1357. #undef BLT_MULT
  1358. #define BLT_SIZE 1
  1359. #define BLT_MULT 4
  1360. #define BLT_NAME BLIT_FALSE_8
  1361. #define BLT_FUNC(s,d) *d = 0
  1362. #include "../p96_blit.cpp"
  1363. #define BLT_NAME BLIT_NOR_8
  1364. #define BLT_FUNC(s,d) *d = ~((*s) | (*d))
  1365. #include "../p96_blit.cpp"
  1366. #define BLT_NAME BLIT_ONLYDST_8
  1367. #define BLT_FUNC(s,d) *d = (*d) & ~(*s)
  1368. #include "../p96_blit.cpp"
  1369. #define BLT_NAME BLIT_NOTSRC_8
  1370. #define BLT_FUNC(s,d) *d = ~(*s)
  1371. #include "../p96_blit.cpp"
  1372. #define BLT_NAME BLIT_ONLYSRC_8
  1373. #define BLT_FUNC(s,d) *d = (*s) & ~(*d)
  1374. #include "../p96_blit.cpp"
  1375. #define BLT_NAME BLIT_NOTDST_8
  1376. #define BLT_FUNC(s,d) *d = ~(*d)
  1377. #include "../p96_blit.cpp"
  1378. #define BLT_NAME BLIT_EOR_8
  1379. #define BLT_FUNC(s,d) *d = (*s) ^ (*d)
  1380. #include "../p96_blit.cpp"
  1381. #define BLT_NAME BLIT_NAND_8
  1382. #define BLT_FUNC(s,d) *d = ~((*s) & (*d))
  1383. #include "../p96_blit.cpp"
  1384. #define BLT_NAME BLIT_AND_8
  1385. #define BLT_FUNC(s,d) *d = (*s) & (*d)
  1386. #include "../p96_blit.cpp"
  1387. #define BLT_NAME BLIT_NEOR_8
  1388. #define BLT_FUNC(s,d) *d = ~((*s) ^ (*d))
  1389. #include "../p96_blit.cpp"
  1390. #define BLT_NAME BLIT_NOTONLYSRC_8
  1391. #define BLT_FUNC(s,d) *d = ~(*s) | (*d)
  1392. #include "../p96_blit.cpp"
  1393. #define BLT_NAME BLIT_NOTONLYDST_8
  1394. #define BLT_FUNC(s,d) *d = ~(*d) | (*s)
  1395. #include "../p96_blit.cpp"
  1396. #define BLT_NAME BLIT_OR_8
  1397. #define BLT_FUNC(s,d) *d = (*s) | (*d)
  1398. #include "../p96_blit.cpp"
  1399. #define BLT_NAME BLIT_TRUE_8
  1400. #define BLT_FUNC(s,d) *d = 0xffffffff
  1401. #include "../p96_blit.cpp"
  1402. #define BLT_NAME BLIT_SWAP_8
  1403. #define BLT_FUNC(s,d) tmp = *d ; *d = *s; *s = tmp;
  1404. #define BLT_TEMP
  1405. #include "../p96_blit.cpp"
  1406. #undef BLT_SIZE
  1407. #undef BLT_MULT
  1408. #define PARMS width, height, src, dst, ri->BytesPerRow, dstri->BytesPerRow
  1409. /*
  1410. * Functions to perform an action on the frame-buffer
  1411. */
  1412. static int do_blitrect_frame_buffer (struct RenderInfo *ri, struct
  1413. RenderInfo *dstri, unsigned long srcx, unsigned long srcy,
  1414. unsigned long dstx, unsigned long dsty, unsigned long width, unsigned
  1415. long height, uae_u8 mask, BLIT_OPCODE opcode)
  1416. {
  1417. uae_u8 *src, *dst;
  1418. uae_u8 Bpp = GetBytesPerPixel (ri->RGBFormat);
  1419. unsigned long total_width = width * Bpp;
  1420. src = ri->Memory + srcx * Bpp + srcy * ri->BytesPerRow;
  1421. dst = dstri->Memory + dstx * Bpp + dsty * dstri->BytesPerRow;
  1422. if (mask != 0xFF && Bpp > 1) {
  1423. write_log (_T("WARNING - BlitRect() has mask 0x%x with Bpp %d.\n"), mask, Bpp);
  1424. }
  1425. P96TRACE ((_T("(%dx%d)=(%dx%d)=(%dx%d)=%d\n"), srcx, srcy, dstx, dsty, width, height, opcode));
  1426. if (mask == 0xFF || Bpp > 1) {
  1427. if(opcode == BLIT_SRC) {
  1428. /* handle normal case efficiently */
  1429. if (ri->Memory == dstri->Memory && dsty == srcy) {
  1430. unsigned long i;
  1431. for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
  1432. memmove (dst, src, total_width);
  1433. } else if (dsty < srcy) {
  1434. unsigned long i;
  1435. for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
  1436. memcpy (dst, src, total_width);
  1437. } else {
  1438. unsigned long i;
  1439. src += (height - 1) * ri->BytesPerRow;
  1440. dst += (height - 1) * dstri->BytesPerRow;
  1441. for (i = 0; i < height; i++, src -= ri->BytesPerRow, dst -= dstri->BytesPerRow)
  1442. memcpy (dst, src, total_width);
  1443. }
  1444. return 1;
  1445. } else {
  1446. if (Bpp == 4) {
  1447. /* 32-bit optimized */
  1448. switch (opcode)
  1449. {
  1450. case BLIT_FALSE: BLIT_FALSE_32 (PARMS); break;
  1451. case BLIT_NOR: BLIT_NOR_32 (PARMS); break;
  1452. case BLIT_ONLYDST: BLIT_ONLYDST_32 (PARMS); break;
  1453. case BLIT_NOTSRC: BLIT_NOTSRC_32 (PARMS); break;
  1454. case BLIT_ONLYSRC: BLIT_ONLYSRC_32 (PARMS); break;
  1455. case BLIT_NOTDST: BLIT_NOTDST_32 (PARMS); break;
  1456. case BLIT_EOR: BLIT_EOR_32 (PARMS); break;
  1457. case BLIT_NAND: BLIT_NAND_32 (PARMS); break;
  1458. case BLIT_AND: BLIT_AND_32 (PARMS); break;
  1459. case BLIT_NEOR: BLIT_NEOR_32 (PARMS); break;
  1460. case BLIT_NOTONLYSRC: BLIT_NOTONLYSRC_32 (PARMS); break;
  1461. case BLIT_NOTONLYDST: BLIT_NOTONLYDST_32 (PARMS); break;
  1462. case BLIT_OR: BLIT_OR_32 (PARMS); break;
  1463. case BLIT_TRUE: BLIT_TRUE_32 (PARMS); break;
  1464. case BLIT_SWAP: BLIT_SWAP_32 (PARMS); break;
  1465. }
  1466. } else if (Bpp == 3) {
  1467. /* 24-bit (not very) optimized */
  1468. switch (opcode)
  1469. {
  1470. case BLIT_FALSE: BLIT_FALSE_24 (PARMS); break;
  1471. case BLIT_NOR: BLIT_NOR_24 (PARMS); break;
  1472. case BLIT_ONLYDST: BLIT_ONLYDST_24 (PARMS); break;
  1473. case BLIT_NOTSRC: BLIT_NOTSRC_24 (PARMS); break;
  1474. case BLIT_ONLYSRC: BLIT_ONLYSRC_24 (PARMS); break;
  1475. case BLIT_NOTDST: BLIT_NOTDST_24 (PARMS); break;
  1476. case BLIT_EOR: BLIT_EOR_24 (PARMS); break;
  1477. case BLIT_NAND: BLIT_NAND_24 (PARMS); break;
  1478. case BLIT_AND: BLIT_AND_24 (PARMS); break;
  1479. case BLIT_NEOR: BLIT_NEOR_24 (PARMS); break;
  1480. case BLIT_NOTONLYSRC: BLIT_NOTONLYSRC_24 (PARMS); break;
  1481. case BLIT_NOTONLYDST: BLIT_NOTONLYDST_24 (PARMS); break;
  1482. case BLIT_OR: BLIT_OR_24 (PARMS); break;
  1483. case BLIT_TRUE: BLIT_TRUE_24 (PARMS); break;
  1484. case BLIT_SWAP: BLIT_SWAP_24 (PARMS); break;
  1485. }
  1486. } else if (Bpp == 2) {
  1487. /* 16-bit optimized */
  1488. switch (opcode)
  1489. {
  1490. case BLIT_FALSE: BLIT_FALSE_16 (PARMS); break;
  1491. case BLIT_NOR: BLIT_NOR_16 (PARMS); break;
  1492. case BLIT_ONLYDST: BLIT_ONLYDST_16 (PARMS); break;
  1493. case BLIT_NOTSRC: BLIT_NOTSRC_16 (PARMS); break;
  1494. case BLIT_ONLYSRC: BLIT_ONLYSRC_16 (PARMS); break;
  1495. case BLIT_NOTDST: BLIT_NOTDST_16 (PARMS); break;
  1496. case BLIT_EOR: BLIT_EOR_16 (PARMS); break;
  1497. case BLIT_NAND: BLIT_NAND_16 (PARMS); break;
  1498. case BLIT_AND: BLIT_AND_16 (PARMS); break;
  1499. case BLIT_NEOR: BLIT_NEOR_16 (PARMS); break;
  1500. case BLIT_NOTONLYSRC: BLIT_NOTONLYSRC_16 (PARMS); break;
  1501. case BLIT_NOTONLYDST: BLIT_NOTONLYDST_16 (PARMS); break;
  1502. case BLIT_OR: BLIT_OR_16 (PARMS); break;
  1503. case BLIT_TRUE: BLIT_TRUE_16 (PARMS); break;
  1504. case BLIT_SWAP: BLIT_SWAP_16 (PARMS); break;
  1505. }
  1506. } else if (Bpp == 1) {
  1507. /* 8-bit optimized */
  1508. switch (opcode)
  1509. {
  1510. case BLIT_FALSE: BLIT_FALSE_8 (PARMS); break;
  1511. case BLIT_NOR: BLIT_NOR_8 (PARMS); break;
  1512. case BLIT_ONLYDST: BLIT_ONLYDST_8 (PARMS); break;
  1513. case BLIT_NOTSRC: BLIT_NOTSRC_8 (PARMS); break;
  1514. case BLIT_ONLYSRC: BLIT_ONLYSRC_8 (PARMS); break;
  1515. case BLIT_NOTDST: BLIT_NOTDST_8 (PARMS); break;
  1516. case BLIT_EOR: BLIT_EOR_8 (PARMS); break;
  1517. case BLIT_NAND: BLIT_NAND_8 (PARMS); break;
  1518. case BLIT_AND: BLIT_AND_8 (PARMS); break;
  1519. case BLIT_NEOR: BLIT_NEOR_8 (PARMS); break;
  1520. case BLIT_NOTONLYSRC: BLIT_NOTONLYSRC_8 (PARMS); break;
  1521. case BLIT_NOTONLYDST: BLIT_NOTONLYDST_8 (PARMS); break;
  1522. case BLIT_OR: BLIT_OR_8 (PARMS); break;
  1523. case BLIT_TRUE: BLIT_TRUE_8 (PARMS); break;
  1524. case BLIT_SWAP: BLIT_SWAP_8 (PARMS); break;
  1525. }
  1526. }
  1527. }
  1528. return 1;
  1529. }
  1530. return 0;
  1531. }
  1532. /*
  1533. SetSpritePosition:
  1534. Synopsis: SetSpritePosition(bi, RGBFormat);
  1535. Inputs: a0: struct BoardInfo *bi
  1536. d7: RGBFTYPE RGBFormat
  1537. */
  1538. static uae_u32 REGPARAM2 picasso_SetSpritePosition (TrapContext *ctx)
  1539. {
  1540. int monid = currprefs.rtgboards[0].monitor_id;
  1541. struct picasso96_state_struct *state = &picasso96_state[monid];
  1542. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  1543. uaecptr bi = trap_get_areg(ctx, 0);
  1544. boardinfo = bi;
  1545. #if 1
  1546. int x = (uae_s16)trap_get_word(ctx, bi + PSSO_BoardInfo_MouseX) - state->XOffset;
  1547. int y = (uae_s16)trap_get_word(ctx, bi + PSSO_BoardInfo_MouseY) - state->YOffset;
  1548. #else
  1549. int x = (uae_s16)trap_get_dreg(ctx, 0) - state->XOffset;
  1550. int y = (uae_s16)trap_get_dreg(ctx, 1) - state->YOffset;
  1551. #endif
  1552. if (vidinfo->splitypos >= 0) {
  1553. y += vidinfo->splitypos;
  1554. }
  1555. newcursor_x = x;
  1556. newcursor_y = y;
  1557. if (!hwsprite)
  1558. return 0;
  1559. return 1;
  1560. }
  1561. /*
  1562. SetSpriteColor:
  1563. Synopsis: SetSpriteColor(bi, index, red, green, blue, RGBFormat);
  1564. Inputs: a0: struct BoardInfo *bi
  1565. d0.b: index
  1566. d1.b: red
  1567. d2.b: green
  1568. d3.b: blue
  1569. d7: RGBFTYPE RGBFormat
  1570. This function changes one of the possible three colors of the hardware sprite.
  1571. */
  1572. static uae_u32 REGPARAM2 picasso_SetSpriteColor (TrapContext *ctx)
  1573. {
  1574. uaecptr bi = trap_get_areg(ctx, 0);
  1575. uae_u8 idx = trap_get_dreg(ctx, 0);
  1576. uae_u8 red = trap_get_dreg(ctx, 1);
  1577. uae_u8 green = trap_get_dreg(ctx, 2);
  1578. uae_u8 blue = trap_get_dreg(ctx, 3);
  1579. boardinfo = bi;
  1580. idx++;
  1581. if (!hwsprite)
  1582. return 0;
  1583. if (idx >= 4)
  1584. return 0;
  1585. cursorrgb[idx] = (red << 16) | (green << 8) | (blue << 0);
  1586. P96TRACE_SPR ((_T("SetSpriteColor(%08x,%d:%02X%02X%02X). %x\n"), bi, idx, red, green, blue, bi + PSSO_BoardInfo_MousePens));
  1587. return 1;
  1588. }
  1589. STATIC_INLINE uae_u16 rgb32torgb16pc (uae_u32 rgb)
  1590. {
  1591. return (((rgb >> (16 + 3)) & 0x1f) << 11) | (((rgb >> (8 + 2)) & 0x3f) << 5) | (((rgb >> (0 + 3)) & 0x1f) << 0);
  1592. }
  1593. static void updatesprcolors (int bpp)
  1594. {
  1595. int i;
  1596. for (i = 0; i < 4; i++) {
  1597. uae_u32 v = cursorrgb[i];
  1598. switch (bpp)
  1599. {
  1600. case 2:
  1601. cursorrgbn[i] = rgb32torgb16pc (v);
  1602. break;
  1603. case 4:
  1604. if (i > 0)
  1605. v |= 0xff000000;
  1606. else
  1607. v &= 0x00ffffff;
  1608. cursorrgbn[i] = v;
  1609. break;
  1610. }
  1611. }
  1612. }
  1613. STATIC_INLINE void putmousepixel (uae_u8 *d, int bpp, int idx)
  1614. {
  1615. uae_u32 val;
  1616. val = cursorrgbn[idx];
  1617. switch (bpp)
  1618. {
  1619. case 2:
  1620. ((uae_u16*)d)[0] = (uae_u16)val;
  1621. break;
  1622. case 4:
  1623. ((uae_u32*)d)[0] = (uae_u32)val;
  1624. break;
  1625. }
  1626. }
  1627. static void putwinmousepixel (HDC andDC, HDC xorDC, int x, int y, int c, uae_u32 *ct)
  1628. {
  1629. if (c == 0) {
  1630. SetPixel (andDC, x, y, RGB (255, 255, 255));
  1631. SetPixel (xorDC, x, y, RGB (0, 0, 0));
  1632. } else {
  1633. uae_u32 val = ct[c];
  1634. SetPixel (andDC, x, y, RGB (0, 0, 0));
  1635. SetPixel (xorDC, x, y, RGB ((val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff));
  1636. }
  1637. }
  1638. static int wincursorcnt;
  1639. static int tmp_sprite_w, tmp_sprite_h, tmp_sprite_hires, tmp_sprite_doubled;
  1640. static uae_u8 *tmp_sprite_data;
  1641. static uae_u32 tmp_sprite_colors[4];
  1642. extern uaecptr sprite_0;
  1643. extern int sprite_0_width, sprite_0_height, sprite_0_doubled;
  1644. extern uae_u32 sprite_0_colors[4];
  1645. int createwindowscursor(int monid, uaecptr src, int w, int h, int hiressprite, int doubledsprite, int chipset)
  1646. {
  1647. HBITMAP andBM, xorBM;
  1648. HBITMAP andoBM, xoroBM;
  1649. HDC andDC, xorDC, DC, mainDC;
  1650. ICONINFO ic;
  1651. int x, y, yy, w2, h2;
  1652. int ret, isdata, datasize;
  1653. HCURSOR oldwincursor = wincursor;
  1654. uae_u8 *realsrc;
  1655. uae_u32 *ct;
  1656. TrapContext *ctx = NULL;
  1657. ret = 0;
  1658. wincursor_shown = 0;
  1659. if (isfullscreen () > 0 || currprefs.input_tablet == 0 || !(currprefs.input_mouse_untrap & MOUSEUNTRAP_MAGIC))
  1660. goto exit;
  1661. if (currprefs.input_magic_mouse_cursor != MAGICMOUSE_HOST_ONLY)
  1662. goto exit;
  1663. if (chipset) {
  1664. if (!sprite_0 || !mousehack_alive ()) {
  1665. if (wincursor)
  1666. SetCursor (normalcursor);
  1667. goto exit;
  1668. }
  1669. w2 = w = sprite_0_width;
  1670. h2 = h = sprite_0_height;
  1671. hiressprite = sprite_0_width / 16;
  1672. doubledsprite = sprite_0_doubled;
  1673. if (doubledsprite) {
  1674. h2 *= 2;
  1675. w2 *= 2;
  1676. }
  1677. src = sprite_0;
  1678. ct = sprite_0_colors;
  1679. } else {
  1680. h2 = h;
  1681. w2 = w;
  1682. ct = cursorrgbn;
  1683. }
  1684. datasize = h * ((w + 15) / 16) * 4;
  1685. if (!valid_address(src, datasize)) {
  1686. goto exit;
  1687. }
  1688. realsrc = get_real_address (src);
  1689. if (w > 64 || h > 64)
  1690. goto exit;
  1691. if (wincursor && tmp_sprite_data) {
  1692. if (w == tmp_sprite_w && h == tmp_sprite_h &&
  1693. !memcmp (tmp_sprite_data, realsrc, datasize) && !memcmp (tmp_sprite_colors, ct, sizeof (uae_u32)*4)
  1694. && hiressprite == tmp_sprite_hires && doubledsprite == tmp_sprite_doubled
  1695. ) {
  1696. if (GetCursor () == wincursor) {
  1697. wincursor_shown = 1;
  1698. return 1;
  1699. }
  1700. }
  1701. }
  1702. write_log (_T("wincursor: %dx%d hires=%d doubled=%d\n"), w2, h2, hiressprite, doubledsprite);
  1703. xfree (tmp_sprite_data);
  1704. tmp_sprite_data = NULL;
  1705. tmp_sprite_w = tmp_sprite_h = 0;
  1706. DC = mainDC = andDC = xorDC = NULL;
  1707. andBM = xorBM = NULL;
  1708. DC = GetDC (NULL);
  1709. if (!DC)
  1710. goto end;
  1711. mainDC = CreateCompatibleDC (DC);
  1712. andDC = CreateCompatibleDC (DC);
  1713. xorDC = CreateCompatibleDC (DC);
  1714. if (!mainDC || !andDC || !xorDC)
  1715. goto end;
  1716. andBM = CreateCompatibleBitmap (DC, w2, h2);
  1717. xorBM = CreateCompatibleBitmap (DC, w2, h2);
  1718. if (!andBM || !xorBM)
  1719. goto end;
  1720. andoBM = (HBITMAP)SelectObject (andDC, andBM);
  1721. xoroBM = (HBITMAP)SelectObject (xorDC, xorBM);
  1722. isdata = 0;
  1723. for (y = 0, yy = 0; y < h2; yy++) {
  1724. int dbl;
  1725. uaecptr img = src + yy * 4 * hiressprite;
  1726. for (dbl = 0; dbl < (doubledsprite ? 2 : 1); dbl++) {
  1727. x = 0;
  1728. while (x < w2) {
  1729. uae_u32 d1 = trap_get_long(ctx, img);
  1730. uae_u32 d2 = trap_get_long(ctx, img + 2 * hiressprite);
  1731. int bits;
  1732. int maxbits = w2 - x;
  1733. if (maxbits > 16 * hiressprite)
  1734. maxbits = 16 * hiressprite;
  1735. for (bits = 0; bits < maxbits && x < w2; bits++) {
  1736. uae_u8 c = ((d2 & 0x80000000) ? 2 : 0) + ((d1 & 0x80000000) ? 1 : 0);
  1737. d1 <<= 1;
  1738. d2 <<= 1;
  1739. putwinmousepixel (andDC, xorDC, x, y, c, ct);
  1740. if (c > 0)
  1741. isdata = 1;
  1742. x++;
  1743. if (doubledsprite && x < w2) {
  1744. putwinmousepixel (andDC, xorDC, x, y, c, ct);
  1745. x++;
  1746. }
  1747. }
  1748. }
  1749. if (y <= h2)
  1750. y++;
  1751. }
  1752. }
  1753. ret = 1;
  1754. SelectObject (andDC, andoBM);
  1755. SelectObject (xorDC, xoroBM);
  1756. end:
  1757. DeleteDC (xorDC);
  1758. DeleteDC (andDC);
  1759. DeleteDC (mainDC);
  1760. ReleaseDC (NULL, DC);
  1761. if (!isdata) {
  1762. wincursor = LoadCursor (NULL, IDC_ARROW);
  1763. } else if (ret) {
  1764. memset (&ic, 0, sizeof ic);
  1765. ic.hbmColor = xorBM;
  1766. ic.hbmMask = andBM;
  1767. wincursor = CreateIconIndirect (&ic);
  1768. tmp_sprite_w = w;
  1769. tmp_sprite_h = h;
  1770. tmp_sprite_data = xmalloc (uae_u8, datasize);
  1771. tmp_sprite_hires = hiressprite;
  1772. tmp_sprite_doubled = doubledsprite;
  1773. memcpy (tmp_sprite_data, realsrc, datasize);
  1774. memcpy (tmp_sprite_colors, ct, sizeof (uae_u32) * 4);
  1775. }
  1776. DeleteObject (andBM);
  1777. DeleteObject (xorBM);
  1778. if (wincursor) {
  1779. SetCursor (wincursor);
  1780. wincursor_shown = 1;
  1781. }
  1782. if (!ret)
  1783. write_log (_T("RTG Windows color cursor creation failed\n"));
  1784. exit:
  1785. if (currprefs.input_tablet && (currprefs.input_mouse_untrap & MOUSEUNTRAP_MAGIC) && currprefs.input_magic_mouse_cursor == MAGICMOUSE_NATIVE_ONLY) {
  1786. if (GetCursor () != NULL)
  1787. SetCursor (NULL);
  1788. } else {
  1789. if (wincursor == oldwincursor && normalcursor != NULL)
  1790. SetCursor (normalcursor);
  1791. }
  1792. if (oldwincursor)
  1793. DestroyIcon (oldwincursor);
  1794. oldwincursor = NULL;
  1795. return ret;
  1796. }
  1797. int picasso_setwincursor(int monid)
  1798. {
  1799. struct amigadisplay *ad = &adisplays[monid];
  1800. if (wincursor) {
  1801. SetCursor(wincursor);
  1802. return 1;
  1803. } else if (!ad->picasso_on) {
  1804. if (createwindowscursor(monid, 0, 0, 0, 0, 0, 1))
  1805. return 1;
  1806. }
  1807. return 0;
  1808. }
  1809. static uae_u32 setspriteimage(TrapContext *ctx, uaecptr bi)
  1810. {
  1811. uae_u32 flags;
  1812. int x, y, yy, bits, bpp;
  1813. int hiressprite, doubledsprite;
  1814. int ret = 0;
  1815. int w, h;
  1816. cursordeactivate = 0;
  1817. if (!hwsprite)
  1818. return 0;
  1819. xfree (cursordata);
  1820. cursordata = NULL;
  1821. bpp = 4;
  1822. w = trap_get_byte(ctx, bi + PSSO_BoardInfo_MouseWidth);
  1823. h = trap_get_byte(ctx, bi + PSSO_BoardInfo_MouseHeight);
  1824. flags = trap_get_long(ctx, bi + PSSO_BoardInfo_Flags);
  1825. hiressprite = 1;
  1826. doubledsprite = 0;
  1827. if (flags & BIF_HIRESSPRITE)
  1828. hiressprite = 2;
  1829. if (flags & BIF_BIGSPRITE)
  1830. doubledsprite = 1;
  1831. updatesprcolors (bpp);
  1832. P96TRACE_SPR ((_T("SetSpriteImage(%08x,%08x,w=%d,h=%d,%d/%d,%08x)\n"),
  1833. bi, trap_get_long(ctx, bi + PSSO_BoardInfo_MouseImage), w, h,
  1834. hiressprite - 1, doubledsprite, bi + PSSO_BoardInfo_MouseImage));
  1835. if (!w || !h || trap_get_long(ctx, bi + PSSO_BoardInfo_MouseImage) == 0) {
  1836. cursordeactivate = 1;
  1837. ret = 1;
  1838. goto end;
  1839. }
  1840. createwindowscursor (0, trap_get_long(ctx, bi + PSSO_BoardInfo_MouseImage) + 4 * hiressprite,
  1841. w, h, hiressprite, doubledsprite, 0);
  1842. cursordata = xmalloc (uae_u8, w * h * bpp);
  1843. for (y = 0, yy = 0; y < h; y++, yy++) {
  1844. uae_u8 *p = cursordata + w * bpp * y;
  1845. uae_u8 *pprev = p;
  1846. uaecptr img = trap_get_long(ctx, bi + PSSO_BoardInfo_MouseImage) + 4 * hiressprite + yy * 4 * hiressprite;
  1847. x = 0;
  1848. while (x < w) {
  1849. uae_u32 d1 = trap_get_long(ctx, img);
  1850. uae_u32 d2 = trap_get_long(ctx, img + 2 * hiressprite);
  1851. int maxbits = w - x;
  1852. if (maxbits > 16 * hiressprite)
  1853. maxbits = 16 * hiressprite;
  1854. for (bits = 0; bits < maxbits && x < w; bits++) {
  1855. uae_u8 c = ((d2 & 0x80000000) ? 2 : 0) + ((d1 & 0x80000000) ? 1 : 0);
  1856. d1 <<= 1;
  1857. d2 <<= 1;
  1858. putmousepixel (p, bpp, c);
  1859. p += bpp;
  1860. x++;
  1861. if (doubledsprite && x < w) {
  1862. putmousepixel (p, bpp, c);
  1863. p += bpp;
  1864. x++;
  1865. }
  1866. }
  1867. }
  1868. if (doubledsprite && y < h) {
  1869. y++;
  1870. memcpy (p, pprev, w * bpp);
  1871. }
  1872. }
  1873. cursorwidth = w;
  1874. if (cursorwidth > CURSORMAXWIDTH)
  1875. cursorwidth = CURSORMAXWIDTH;
  1876. cursorheight = h;
  1877. if (cursorheight > CURSORMAXHEIGHT)
  1878. cursorheight = CURSORMAXHEIGHT;
  1879. setupcursor ();
  1880. ret = 1;
  1881. cursorok = TRUE;
  1882. P96TRACE_SPR ((_T("hardware sprite created\n")));
  1883. end:
  1884. return ret;
  1885. }
  1886. /*
  1887. SetSpriteImage:
  1888. Synopsis: SetSpriteImage(bi, RGBFormat);
  1889. Inputs: a0: struct BoardInfo *bi
  1890. d7: RGBFTYPE RGBFormat
  1891. This function gets new sprite image data from the MouseImage field of the BoardInfo structure and writes
  1892. it to the board.
  1893. There are three possible cases:
  1894. BIB_HIRESSPRITE is set:
  1895. skip the first two long words and the following sprite data is arranged as an array of two longwords. Those form the
  1896. two bit planes for one image line respectively.
  1897. BIB_HIRESSPRITE and BIB_BIGSPRITE are not set:
  1898. skip the first two words and the following sprite data is arranged as an array of two words. Those form the two
  1899. bit planes for one image line respectively.
  1900. BIB_HIRESSPRITE is not set and BIB_BIGSPRITE is set:
  1901. skip the first two words and the following sprite data is arranged as an array of two words. Those form the two bit
  1902. planes for one image line respectively. You have to double each pixel horizontally and vertically. All coordinates
  1903. used in this case already assume a zoomed sprite, only the sprite data is not zoomed yet. You will have to
  1904. compensate for this when accounting for hotspot offsets and sprite dimensions.
  1905. */
  1906. static uae_u32 REGPARAM2 picasso_SetSpriteImage(TrapContext *ctx)
  1907. {
  1908. uaecptr bi = trap_get_areg(ctx, 0);
  1909. boardinfo = bi;
  1910. return setspriteimage(ctx, bi);
  1911. }
  1912. /*
  1913. SetSprite:
  1914. Synopsis: SetSprite(bi, activate, RGBFormat);
  1915. Inputs: a0: struct BoardInfo *bi
  1916. d0: BOOL activate
  1917. d7: RGBFTYPE RGBFormat
  1918. This function activates or deactivates the hardware sprite.
  1919. */
  1920. static uae_u32 REGPARAM2 picasso_SetSprite (TrapContext *ctx)
  1921. {
  1922. uae_u32 result = 0;
  1923. uae_u32 activate = trap_get_dreg(ctx, 0);
  1924. if (!hwsprite)
  1925. return 0;
  1926. if (activate) {
  1927. picasso_SetSpriteImage (ctx);
  1928. cursorvisible = true;
  1929. } else {
  1930. cursordeactivate = 2;
  1931. }
  1932. result = 1;
  1933. P96TRACE_SPR ((_T("SetSprite: %d\n"), activate));
  1934. return result;
  1935. }
  1936. /*
  1937. * BOOL FindCard(struct BoardInfo *bi); and
  1938. *
  1939. * FindCard is called in the first stage of the board initialisation and
  1940. * configuration and is used to look if there is a free and unconfigured
  1941. * board of the type the driver is capable of managing. If it finds one,
  1942. * it immediately reserves it for use by Picasso96, usually by clearing
  1943. * the CDB_CONFIGME bit in the flags field of the ConfigDev struct of
  1944. * this expansion card. But this is only a common example, a driver can
  1945. * do whatever it wants to mark this card as used by the driver. This
  1946. * mechanism is intended to ensure that a board is only configured and
  1947. * used by one driver. FindBoard also usually fills some fields of the
  1948. * BoardInfo struct supplied by the caller, the rtg.library, for example
  1949. * the MemoryBase, MemorySize and RegisterBase fields.
  1950. */
  1951. static void picasso96_alloc2 (TrapContext *ctx);
  1952. static uae_u32 REGPARAM2 picasso_FindCard (TrapContext *ctx)
  1953. {
  1954. uaecptr AmigaBoardInfo = trap_get_areg(ctx, 0);
  1955. struct picasso96_state_struct *state = &picasso96_state[currprefs.rtgboards[0].monitor_id];
  1956. /* NOTES: See BoardInfo struct definition in Picasso96 dev info */
  1957. if (!uaegfx_active || !(gfxmem_bank.flags & ABFLAG_MAPPED))
  1958. return 0;
  1959. if (uaegfx_base) {
  1960. trap_put_long(ctx, uaegfx_base + CARD_BOARDINFO, AmigaBoardInfo);
  1961. } else if (uaegfx_old) {
  1962. picasso96_alloc2 (ctx);
  1963. }
  1964. boardinfo = AmigaBoardInfo;
  1965. if (gfxmem_bank.allocated_size && !state->CardFound) {
  1966. /* Fill in MemoryBase, MemorySize */
  1967. trap_put_long(ctx, AmigaBoardInfo + PSSO_BoardInfo_MemoryBase, gfxmem_bank.start);
  1968. trap_put_long(ctx, AmigaBoardInfo + PSSO_BoardInfo_MemorySize, gfxmem_bank.allocated_size - reserved_gfxmem);
  1969. state->CardFound = 1; /* mark our "card" as being found */
  1970. return -1;
  1971. } else
  1972. return 0;
  1973. }
  1974. static void FillBoardInfo(TrapContext *ctx, uaecptr amigamemptr, struct LibResolution *res, int width, int height, int depth)
  1975. {
  1976. switch (depth)
  1977. {
  1978. case 8:
  1979. res->Modes[CHUNKY] = amigamemptr;
  1980. break;
  1981. case 15:
  1982. case 16:
  1983. res->Modes[HICOLOR] = amigamemptr;
  1984. break;
  1985. case 24:
  1986. res->Modes[TRUECOLOR] = amigamemptr;
  1987. break;
  1988. default:
  1989. res->Modes[TRUEALPHA] = amigamemptr;
  1990. break;
  1991. }
  1992. trap_set_bytes(ctx, amigamemptr, 0, PSSO_ModeInfo_sizeof);
  1993. trap_put_word(ctx, amigamemptr + PSSO_ModeInfo_Width, width);
  1994. trap_put_word(ctx, amigamemptr + PSSO_ModeInfo_Height, height);
  1995. trap_put_byte(ctx, amigamemptr + PSSO_ModeInfo_Depth, depth);
  1996. trap_put_byte(ctx, amigamemptr + PSSO_ModeInfo_Flags, 0);
  1997. trap_put_word(ctx, amigamemptr + PSSO_ModeInfo_HorTotal, width);
  1998. trap_put_word(ctx, amigamemptr + PSSO_ModeInfo_HorBlankSize, 1);
  1999. trap_put_word(ctx, amigamemptr + PSSO_ModeInfo_HorSyncStart, 0);
  2000. trap_put_word(ctx, amigamemptr + PSSO_ModeInfo_HorSyncSize, 1);
  2001. trap_put_byte(ctx, amigamemptr + PSSO_ModeInfo_HorSyncSkew, 0);
  2002. trap_put_byte(ctx, amigamemptr + PSSO_ModeInfo_HorEnableSkew, 0);
  2003. trap_put_word(ctx, amigamemptr + PSSO_ModeInfo_VerTotal, height);
  2004. trap_put_word(ctx, amigamemptr + PSSO_ModeInfo_VerBlankSize, 1);
  2005. trap_put_word(ctx, amigamemptr + PSSO_ModeInfo_VerSyncStart, 0);
  2006. trap_put_word(ctx, amigamemptr + PSSO_ModeInfo_VerSyncSize, 1);
  2007. trap_put_byte(ctx, amigamemptr + PSSO_ModeInfo_first_union, 98);
  2008. trap_put_byte(ctx, amigamemptr + PSSO_ModeInfo_second_union, 14);
  2009. trap_put_long(ctx, amigamemptr + PSSO_ModeInfo_PixelClock,
  2010. width * height * (currprefs.gfx_apmode[1].gfx_refreshrate ? abs (currprefs.gfx_apmode[1].gfx_refreshrate) : default_freq));
  2011. }
  2012. struct modeids {
  2013. int width, height;
  2014. int id;
  2015. };
  2016. static struct modeids mi[] =
  2017. {
  2018. /* "original" modes */
  2019. 320, 200, 0,
  2020. 320, 240, 1,
  2021. 640, 400, 2,
  2022. 640, 480, 3,
  2023. 800, 600, 4,
  2024. 1024, 768, 5,
  2025. 1152, 864, 6,
  2026. 1280,1024, 7,
  2027. 1600,1280, 8,
  2028. 320, 256, 9,
  2029. 640, 512,10,
  2030. /* new modes */
  2031. 704, 480, 129,
  2032. 704, 576, 130,
  2033. 720, 480, 131,
  2034. 720, 576, 132,
  2035. 768, 483, 133,
  2036. 768, 576, 134,
  2037. 800, 480, 135,
  2038. 848, 480, 136,
  2039. 854, 480, 137,
  2040. 948, 576, 138,
  2041. 1024, 576, 139,
  2042. 1152, 768, 140,
  2043. 1152, 864, 141,
  2044. 1280, 720, 142,
  2045. 1280, 768, 143,
  2046. 1280, 800, 144,
  2047. 1280, 854, 145,
  2048. 1280, 960, 146,
  2049. 1366, 768, 147,
  2050. 1440, 900, 148,
  2051. 1440, 960, 149,
  2052. 1600,1200, 150,
  2053. 1680,1050, 151,
  2054. 1920,1080, 152,
  2055. 1920,1200, 153,
  2056. 2048,1152, 154,
  2057. 2048,1536, 155,
  2058. 2560,1600, 156,
  2059. 2560,2048, 157,
  2060. 400, 300, 158,
  2061. 512, 384, 159,
  2062. 640, 432, 160,
  2063. 1360, 768, 161,
  2064. 1360,1024, 162,
  2065. 1400,1050, 163,
  2066. 1792,1344, 164,
  2067. 1800,1440, 165,
  2068. 1856,1392, 166,
  2069. 1920,1440, 167,
  2070. 480, 360, 168,
  2071. 640, 350, 169,
  2072. 1600, 900, 170,
  2073. 960, 600, 171,
  2074. 1088, 612, 172,
  2075. 1152, 648, 173,
  2076. 1776,1000, 174,
  2077. 2560,1440, 175,
  2078. -1,-1,0
  2079. };
  2080. static int AssignModeID (int w, int h, int *unkcnt)
  2081. {
  2082. int i;
  2083. #ifdef NEWMODES2
  2084. return 0x40000000 | (w << 14) | h;
  2085. #endif
  2086. for (i = 0; mi[i].width > 0; i++) {
  2087. if (w == mi[i].width && h == mi[i].height)
  2088. return 0x50001000 | (mi[i].id * 0x10000);
  2089. }
  2090. (*unkcnt)++;
  2091. write_log (_T("P96: Non-unique mode %dx%d"), w, h);
  2092. if (i > 0 && 256 - (*unkcnt) == mi[i - 1].id + 1) {
  2093. (*unkcnt) = 256 - 127;
  2094. write_log(_T(" (Skipped reserved)"));
  2095. } else if (256 - (*unkcnt) == 11) {
  2096. (*unkcnt) = 511;
  2097. write_log(_T(" (Using extra)"));
  2098. }
  2099. write_log(_T("\n"));
  2100. return 0x51001000 - (*unkcnt) * 0x10000;
  2101. }
  2102. static uaecptr picasso96_amem, picasso96_amemend;
  2103. static void CopyLibResolutionStructureU2A(TrapContext *ctx, struct LibResolution *libres, uaecptr amigamemptr)
  2104. {
  2105. int i;
  2106. trap_set_bytes(ctx, amigamemptr, 0, PSSO_LibResolution_sizeof);
  2107. for (i = 0; i < strlen (libres->P96ID); i++)
  2108. trap_put_byte(ctx, amigamemptr + PSSO_LibResolution_P96ID + i, libres->P96ID[i]);
  2109. trap_put_long(ctx, amigamemptr + PSSO_LibResolution_DisplayID, libres->DisplayID);
  2110. trap_put_word(ctx, amigamemptr + PSSO_LibResolution_Width, libres->Width);
  2111. trap_put_word(ctx, amigamemptr + PSSO_LibResolution_Height, libres->Height);
  2112. trap_put_word(ctx, amigamemptr + PSSO_LibResolution_Flags, libres->Flags);
  2113. for (i = 0; i < MAXMODES; i++)
  2114. trap_put_long(ctx, amigamemptr + PSSO_LibResolution_Modes + i * 4, libres->Modes[i]);
  2115. trap_put_long(ctx, amigamemptr + 10, amigamemptr + PSSO_LibResolution_P96ID);
  2116. trap_put_long(ctx, amigamemptr + PSSO_LibResolution_BoardInfo, libres->BoardInfo);
  2117. }
  2118. void picasso_allocatewritewatch (int index, int gfxmemsize)
  2119. {
  2120. SYSTEM_INFO si;
  2121. xfree (gwwbuf[index]);
  2122. GetSystemInfo (&si);
  2123. gwwpagesize[index] = si.dwPageSize;
  2124. gwwbufsize[index] = gfxmemsize / gwwpagesize[index] + 1;
  2125. gwwpagemask[index] = gwwpagesize[index] - 1;
  2126. gwwbuf[index] = xmalloc (void*, gwwbufsize[index]);
  2127. }
  2128. static ULONG_PTR writewatchcount[MAX_RTG_BOARDS];
  2129. static int watch_offset[MAX_RTG_BOARDS];
  2130. int picasso_getwritewatch (int index, int offset, uae_u8 ***gwwbufp, uae_u8 **startp)
  2131. {
  2132. ULONG ps;
  2133. writewatchcount[index] = gwwbufsize[index];
  2134. watch_offset[index] = offset;
  2135. uae_u8 *start = gfxmem_banks[index]->start + natmem_offset + offset;
  2136. if (GetWriteWatch (WRITE_WATCH_FLAG_RESET, gfxmem_banks[index]->start + natmem_offset + offset, (gwwbufsize[index] - 1) * gwwpagesize[index], gwwbuf[index], &writewatchcount[index], &ps)) {
  2137. write_log (_T("picasso_getwritewatch %d\n"), GetLastError ());
  2138. writewatchcount[index] = 0;
  2139. return -1;
  2140. }
  2141. if (gwwbufp)
  2142. *gwwbufp = (uae_u8**)gwwbuf[index];
  2143. if (startp)
  2144. *startp = start;
  2145. return writewatchcount[index];
  2146. }
  2147. bool picasso_is_vram_dirty (int index, uaecptr addr, int size)
  2148. {
  2149. static ULONG_PTR last;
  2150. uae_u8 *a = addr + natmem_offset + watch_offset[index];
  2151. int s = size;
  2152. int ms = gwwpagesize[index];
  2153. for (;;) {
  2154. for (ULONG_PTR i = last; i < writewatchcount[index]; i++) {
  2155. uae_u8 *ma = (uae_u8*)gwwbuf[index][i];
  2156. if (
  2157. (a < ma && a + s >= ma) ||
  2158. (a < ma + ms && a + s >= ma + ms) ||
  2159. (a >= ma && a < ma + ms)) {
  2160. last = i;
  2161. return true;
  2162. }
  2163. }
  2164. if (last == 0)
  2165. break;
  2166. last = 0;
  2167. }
  2168. return false;
  2169. }
  2170. static void init_alloc (TrapContext *ctx, int size)
  2171. {
  2172. picasso96_amem = picasso96_amemend = 0;
  2173. if (uaegfx_base) {
  2174. int size = trap_get_long(ctx, uaegfx_base + CARD_RESLISTSIZE);
  2175. picasso96_amem = trap_get_long(ctx, uaegfx_base + CARD_RESLIST);
  2176. } else if (uaegfx_active) {
  2177. reserved_gfxmem = size;
  2178. picasso96_amem = gfxmem_bank.start + gfxmem_bank.allocated_size - size;
  2179. }
  2180. picasso96_amemend = picasso96_amem + size;
  2181. write_log (_T("P96 RESINFO: %08X-%08X (%d,%d)\n"), picasso96_amem, picasso96_amemend, size / PSSO_ModeInfo_sizeof, size);
  2182. picasso_allocatewritewatch (0, gfxmem_bank.allocated_size);
  2183. }
  2184. static int p96depth (int depth)
  2185. {
  2186. uae_u32 f = currprefs.picasso96_modeflags;
  2187. int ok = 0;
  2188. if (depth == 8 && (f & RGBFF_CLUT))
  2189. ok = 1;
  2190. if (depth == 15 && (f & (RGBFF_R5G5B5PC | RGBFF_R5G5B5 | RGBFF_B5G5R5PC)))
  2191. ok = 2;
  2192. if (depth == 16 && (f & (RGBFF_R5G6B5PC | RGBFF_R5G6B5 | RGBFF_B5G6R5PC)))
  2193. ok = 2;
  2194. if (depth == 24 && (f & (RGBFF_R8G8B8 | RGBFF_B8G8R8)))
  2195. ok = 3;
  2196. if (depth == 32 && (f & (RGBFF_A8R8G8B8 | RGBFF_A8B8G8R8 | RGBFF_R8G8B8A8 | RGBFF_B8G8R8A8)))
  2197. ok = 4;
  2198. return ok;
  2199. }
  2200. static int _cdecl resolution_compare (const void *a, const void *b)
  2201. {
  2202. struct PicassoResolution *ma = (struct PicassoResolution *)a;
  2203. struct PicassoResolution *mb = (struct PicassoResolution *)b;
  2204. if (ma->res.width < mb->res.width)
  2205. return -1;
  2206. if (ma->res.width > mb->res.width)
  2207. return 1;
  2208. if (ma->res.height < mb->res.height)
  2209. return -1;
  2210. if (ma->res.height > mb->res.height)
  2211. return 1;
  2212. return ma->depth - mb->depth;
  2213. }
  2214. static int missmodes[] = { 320, 200, 320, 240, 320, 256, 640, 400, 640, 480, 640, 512, 800, 600, 1024, 768, 1280, 1024, -1 };
  2215. static uaecptr uaegfx_card_install (TrapContext *ctx, uae_u32 size);
  2216. static void picasso96_alloc2 (TrapContext *ctx)
  2217. {
  2218. int i, j, size, cnt;
  2219. int misscnt, depths;
  2220. xfree (newmodes);
  2221. newmodes = NULL;
  2222. picasso96_amem = picasso96_amemend = 0;
  2223. if (gfxmem_bank.allocated_size == 0)
  2224. return;
  2225. misscnt = 0;
  2226. newmodes = xmalloc (struct PicassoResolution, MAX_PICASSO_MODES);
  2227. size = 0;
  2228. depths = 0;
  2229. if (p96depth (8))
  2230. depths++;
  2231. if (p96depth (15))
  2232. depths++;
  2233. if (p96depth (16))
  2234. depths++;
  2235. if (p96depth (24))
  2236. depths++;
  2237. if (p96depth (32))
  2238. depths++;
  2239. for (int mon = 0; Displays[mon].monitorname; mon++) {
  2240. struct PicassoResolution *DisplayModes = Displays[mon].DisplayModes;
  2241. i = 0;
  2242. while (DisplayModes[i].depth >= 0) {
  2243. for (j = 0; missmodes[j * 2] >= 0; j++) {
  2244. if (DisplayModes[i].res.width == missmodes[j * 2 + 0] && DisplayModes[i].res.height == missmodes[j * 2 + 1]) {
  2245. missmodes[j * 2 + 0] = 0;
  2246. missmodes[j * 2 + 1] = 0;
  2247. }
  2248. }
  2249. i++;
  2250. }
  2251. }
  2252. cnt = 0;
  2253. for (int mon = 0; Displays[mon].monitorname; mon++) {
  2254. struct PicassoResolution *DisplayModes = Displays[mon].DisplayModes;
  2255. i = 0;
  2256. while (DisplayModes[i].depth >= 0) {
  2257. if (DisplayModes[i].rawmode) {
  2258. i++;
  2259. continue;
  2260. }
  2261. // Not even 256 color mode fits in VRAM? Ignore it completely.
  2262. if (DisplayModes[i].res.width * DisplayModes[i].res.height > gfxmem_bank.allocated_size - 256) {
  2263. i++;
  2264. continue;
  2265. }
  2266. j = i;
  2267. size += PSSO_LibResolution_sizeof;
  2268. while (missmodes[misscnt * 2] == 0)
  2269. misscnt++;
  2270. if (missmodes[misscnt * 2] >= 0) {
  2271. int w = DisplayModes[i].res.width;
  2272. int h = DisplayModes[i].res.height;
  2273. if (w > missmodes[misscnt * 2 + 0] || (w == missmodes[misscnt * 2 + 0] && h > missmodes[misscnt * 2 + 1])) {
  2274. struct PicassoResolution *pr = &newmodes[cnt];
  2275. memcpy (pr, &DisplayModes[i], sizeof (struct PicassoResolution));
  2276. pr->res.width = missmodes[misscnt * 2 + 0];
  2277. pr->res.height = missmodes[misscnt * 2 + 1];
  2278. _stprintf (pr->name, _T("%dx%d FAKE"), pr->res.width, pr->res.height);
  2279. size += PSSO_ModeInfo_sizeof * depths;
  2280. cnt++;
  2281. misscnt++;
  2282. continue;
  2283. }
  2284. }
  2285. int k;
  2286. for (k = 0; k < cnt; k++) {
  2287. if (newmodes[k].res.width == DisplayModes[i].res.width &&
  2288. newmodes[k].res.height == DisplayModes[i].res.height &&
  2289. newmodes[k].depth == DisplayModes[i].depth)
  2290. break;
  2291. }
  2292. if (k >= cnt) {
  2293. memcpy (&newmodes[cnt], &DisplayModes[i], sizeof (struct PicassoResolution));
  2294. size += PSSO_ModeInfo_sizeof * depths;
  2295. cnt++;
  2296. }
  2297. i++;
  2298. }
  2299. }
  2300. qsort (newmodes, cnt, sizeof (struct PicassoResolution), resolution_compare);
  2301. #if MULTIDISPLAY
  2302. for (i = 0; Displays[i].name; i++) {
  2303. size += PSSO_LibResolution_sizeof;
  2304. size += PSSO_ModeInfo_sizeof * depths;
  2305. }
  2306. #endif
  2307. newmodes[cnt].depth = -1;
  2308. for (i = 0; i < cnt; i++) {
  2309. int depth;
  2310. for (depth = 1; depth <= 4; depth++) {
  2311. switch (depth) {
  2312. case 1:
  2313. if (newmodes[i].res.width > chunky.width)
  2314. chunky.width = newmodes[i].res.width;
  2315. if (newmodes[i].res.height > chunky.height)
  2316. chunky.height = newmodes[i].res.height;
  2317. break;
  2318. case 2:
  2319. if (newmodes[i].res.width > hicolour.width)
  2320. hicolour.width = newmodes[i].res.width;
  2321. if (newmodes[i].res.height > hicolour.height)
  2322. hicolour.height = newmodes[i].res.height;
  2323. break;
  2324. case 3:
  2325. if (newmodes[i].res.width > truecolour.width)
  2326. truecolour.width = newmodes[i].res.width;
  2327. if (newmodes[i].res.height > truecolour.height)
  2328. truecolour.height = newmodes[i].res.height;
  2329. break;
  2330. case 4:
  2331. if (newmodes[i].res.width > alphacolour.width)
  2332. alphacolour.width = newmodes[i].res.width;
  2333. if (newmodes[i].res.height > alphacolour.height)
  2334. alphacolour.height = newmodes[i].res.height;
  2335. break;
  2336. }
  2337. }
  2338. }
  2339. #if 0
  2340. ShowSupportedResolutions ();
  2341. #endif
  2342. uaegfx_card_install (ctx, size);
  2343. init_alloc (ctx, size);
  2344. }
  2345. void picasso96_alloc (TrapContext *ctx)
  2346. {
  2347. if (currprefs.rtgboards[0].rtgmem_type >= GFXBOARD_HARDWARE)
  2348. return;
  2349. uaegfx_resname = ds (_T("uaegfx.card"));
  2350. if (uaegfx_old)
  2351. return;
  2352. picasso96_alloc2 (ctx);
  2353. }
  2354. static void inituaegfxfuncs (TrapContext *ctx, uaecptr start, uaecptr ABI);
  2355. static void inituaegfx(TrapContext *ctx, uaecptr ABI)
  2356. {
  2357. uae_u32 flags;
  2358. cursorvisible = false;
  2359. cursorok = 0;
  2360. cursordeactivate = 0;
  2361. write_log (_T("RTG mode mask: %x BI=%08x\n"), currprefs.picasso96_modeflags, ABI);
  2362. trap_put_word(ctx, ABI + PSSO_BoardInfo_BitsPerCannon, 8);
  2363. trap_put_word(ctx, ABI + PSSO_BoardInfo_RGBFormats, currprefs.picasso96_modeflags);
  2364. trap_put_long(ctx, ABI + PSSO_BoardInfo_BoardType, picasso96_BT);
  2365. trap_put_long(ctx, ABI + PSSO_BoardInfo_GraphicsControllerType, picasso96_GCT);
  2366. trap_put_long(ctx, ABI + PSSO_BoardInfo_PaletteChipType, picasso96_PCT);
  2367. trap_put_long(ctx, ABI + PSSO_BoardInfo_BoardName, uaegfx_resname);
  2368. trap_put_long(ctx, ABI + PSSO_BoardInfo_BoardType, 1);
  2369. trap_put_long(ctx, ABI + PSSO_BoardInfo_MemoryClock, 100000000);
  2370. /* only 1 clock */
  2371. trap_put_long(ctx, ABI + PSSO_BoardInfo_PixelClockCount + PLANAR * 4, 1);
  2372. trap_put_long(ctx, ABI + PSSO_BoardInfo_PixelClockCount + CHUNKY * 4, 1);
  2373. trap_put_long(ctx, ABI + PSSO_BoardInfo_PixelClockCount + HICOLOR * 4, 1);
  2374. trap_put_long(ctx, ABI + PSSO_BoardInfo_PixelClockCount + TRUECOLOR * 4, 1);
  2375. trap_put_long(ctx, ABI + PSSO_BoardInfo_PixelClockCount + TRUEALPHA * 4, 1);
  2376. /* we have 16 bits for horizontal and vertical timings - hack */
  2377. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxHorValue + PLANAR * 2, 0x4000);
  2378. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxHorValue + CHUNKY * 2, 0x4000);
  2379. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxHorValue + HICOLOR * 2, 0x4000);
  2380. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxHorValue + TRUECOLOR * 2, 0x4000);
  2381. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxHorValue + TRUEALPHA * 2, 0x4000);
  2382. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxVerValue + PLANAR * 2, 0x4000);
  2383. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxVerValue + CHUNKY * 2, 0x4000);
  2384. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxVerValue + HICOLOR * 2, 0x4000);
  2385. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxVerValue + TRUECOLOR * 2, 0x4000);
  2386. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxVerValue + TRUEALPHA * 2, 0x4000);
  2387. flags = trap_get_long(ctx, ABI + PSSO_BoardInfo_Flags);
  2388. flags &= 0xffff0000;
  2389. if (flags & BIF_NOBLITTER)
  2390. write_log (_T("P96: Blitter disabled in devs:monitors/uaegfx!\n"));
  2391. if (NOBLITTER_ALL) {
  2392. flags |= BIF_NOBLITTER;
  2393. flags &= ~BIF_BLITTER;
  2394. } else {
  2395. flags |= BIF_BLITTER;
  2396. }
  2397. flags |= BIF_NOMEMORYMODEMIX;
  2398. flags |= BIF_GRANTDIRECTACCESS;
  2399. flags &= ~BIF_HARDWARESPRITE;
  2400. if (currprefs.gfx_api && D3D_goodenough () > 0 && D3D_setcursor(0, -1, -1, -1, -1, false, false) && USE_HARDWARESPRITE && currprefs.rtg_hardwaresprite) {
  2401. hwsprite = 1;
  2402. flags |= BIF_HARDWARESPRITE;
  2403. write_log (_T("P96: Hardware sprite support enabled\n"));
  2404. } else {
  2405. hwsprite = 0;
  2406. write_log (_T("P96: Hardware sprite support disabled\n"));
  2407. }
  2408. if (currprefs.rtg_hardwareinterrupt && !uaegfx_old)
  2409. flags |= BIF_VBLANKINTERRUPT;
  2410. // force INDISPLAYCHAIN if no multiple monitors emulated
  2411. if (!(flags & BIF_INDISPLAYCHAIN)) {
  2412. if (currprefs.rtgboards[0].monitor_id == 0) {
  2413. write_log(_T("P96: BIF_INDISPLAYCHAIN force-enabled!\n"));
  2414. flags |= BIF_INDISPLAYCHAIN;
  2415. }
  2416. }
  2417. #if OVERLAY
  2418. flags |= BIF_VIDEOWINDOW;
  2419. #endif
  2420. flags |= BIF_VGASCREENSPLIT;
  2421. flags |= BIF_PALETTESWITCH;
  2422. trap_put_long(ctx, ABI + PSSO_BoardInfo_Flags, flags);
  2423. if (debug_rtg_blitter != 3)
  2424. write_log (_T("P96: Blitter mode = %x!\n"), debug_rtg_blitter);
  2425. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxHorResolution + 0, planar.width);
  2426. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxHorResolution + 2, chunky.width);
  2427. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxHorResolution + 4, hicolour.width);
  2428. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxHorResolution + 6, truecolour.width);
  2429. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxHorResolution + 8, alphacolour.width);
  2430. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxVerResolution + 0, planar.height);
  2431. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxVerResolution + 2, chunky.height);
  2432. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxVerResolution + 4, hicolour.height);
  2433. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxVerResolution + 6, truecolour.height);
  2434. trap_put_word(ctx, ABI + PSSO_BoardInfo_MaxVerResolution + 8, alphacolour.height);
  2435. inituaegfxfuncs(ctx, uaegfx_rom, ABI);
  2436. }
  2437. static bool addmode(TrapContext *ctx, uaecptr AmigaBoardInfo, uaecptr *amem, struct LibResolution *res, int w, int h, const TCHAR *name, int display, int *unkcnt)
  2438. {
  2439. int depth;
  2440. bool added = false;
  2441. if (display > 0) {
  2442. res->DisplayID = 0x51000000 + display * 0x100000;
  2443. } else {
  2444. res->DisplayID = AssignModeID (w, h, unkcnt);
  2445. }
  2446. res->BoardInfo = AmigaBoardInfo;
  2447. res->Width = w;
  2448. res->Height = h;
  2449. res->Flags = P96F_PUBLIC;
  2450. memcpy (res->P96ID, "P96-0:", 6);
  2451. if (name) {
  2452. char *n2 = ua (name);
  2453. strcpy (res->Name, n2);
  2454. xfree (n2);
  2455. } else {
  2456. sprintf (res->Name, "UAE:%4dx%4d", w, h);
  2457. }
  2458. for (depth = 8; depth <= 32; depth++) {
  2459. if (!p96depth (depth))
  2460. continue;
  2461. if(gfxmem_bank.allocated_size >= w * h * ((depth + 7) / 8)) {
  2462. FillBoardInfo(ctx, *amem, res, w, h, depth);
  2463. *amem += PSSO_ModeInfo_sizeof;
  2464. added = true;
  2465. }
  2466. }
  2467. return added;
  2468. }
  2469. /****************************************
  2470. * InitCard()
  2471. *
  2472. * a2: BoardInfo structure ptr - Amiga-based address in Intel endian-format
  2473. *
  2474. */
  2475. static uae_u32 REGPARAM2 picasso_InitCard (TrapContext *ctx)
  2476. {
  2477. int LibResolutionStructureCount = 0;
  2478. int i, unkcnt, cnt;
  2479. uaecptr amem;
  2480. uaecptr AmigaBoardInfo = trap_get_areg(ctx, 0);
  2481. if (!picasso96_amem) {
  2482. write_log (_T("P96: InitCard() but no resolution memory!\n"));
  2483. return 0;
  2484. }
  2485. amem = picasso96_amem;
  2486. inituaegfx(ctx, AmigaBoardInfo);
  2487. i = 0;
  2488. unkcnt = cnt = 0;
  2489. while (newmodes[i].depth >= 0) {
  2490. struct LibResolution res = { 0 };
  2491. int j = i;
  2492. if (addmode(ctx, AmigaBoardInfo, &amem, &res, newmodes[i].res.width, newmodes[i].res.height, NULL, 0, &unkcnt)) {
  2493. TCHAR *s;
  2494. s = au (res.Name);
  2495. write_log (_T("%2d: %08X %4dx%4d %s\n"), ++cnt, res.DisplayID, res.Width, res.Height, s);
  2496. xfree (s);
  2497. while (newmodes[i].depth >= 0
  2498. && newmodes[i].res.width == newmodes[j].res.width
  2499. && newmodes[i].res.height == newmodes[j].res.height)
  2500. i++;
  2501. LibResolutionStructureCount++;
  2502. CopyLibResolutionStructureU2A(ctx, &res, amem);
  2503. #if P96TRACING_ENABLED && P96TRACING_LEVEL > 1
  2504. DumpLibResolutionStructure(ctx, amem);
  2505. #endif
  2506. AmigaListAddTail(ctx, AmigaBoardInfo + PSSO_BoardInfo_ResolutionsList, amem);
  2507. amem += PSSO_LibResolution_sizeof;
  2508. } else {
  2509. write_log (_T("--: %08X %4dx%4d Not enough VRAM\n"), res.DisplayID, res.Width, res.Height);
  2510. i++;
  2511. }
  2512. }
  2513. #if MULTIDISPLAY
  2514. for (i = 0; Displays[i].name; i++) {
  2515. struct LibResolution res = { 0 };
  2516. struct MultiDisplay *md = &Displays[i];
  2517. int w = md->rect.right - md->rect.left;
  2518. int h = md->rect.bottom - md->rect.top;
  2519. TCHAR tmp[100];
  2520. if (md->primary)
  2521. strcpy (tmp, "UAE:Primary");
  2522. else
  2523. _stprintf (tmp, "UAE:Display#%d", i);
  2524. addmode (AmigaBoardInfo, &amem, &res, w, h, tmp, i + 1, &unkcnt);
  2525. write_log (_T("%08X %4dx%4d %s\n"), res.DisplayID, res.Width + 16, res.Height, res.Name);
  2526. LibResolutionStructureCount++;
  2527. CopyLibResolutionStructureU2A (&res, amem);
  2528. #if P96TRACING_ENABLED && P96TRACING_LEVEL > 1
  2529. DumpLibResolutionStructure(ctx, amem);
  2530. #endif
  2531. AmigaListAddTail (AmigaBoardInfo + PSSO_BoardInfo_ResolutionsList, amem);
  2532. amem += PSSO_LibResolution_sizeof;
  2533. }
  2534. #endif
  2535. if (amem > picasso96_amemend)
  2536. write_log (_T("P96: display resolution list corruption %08x<>%08x (%d)\n"), amem, picasso96_amemend, i);
  2537. return -1;
  2538. }
  2539. /*
  2540. * SetSwitch:
  2541. * a0: struct BoardInfo
  2542. * d0.w: BOOL state
  2543. * this function should set a board switch to let the Amiga signal pass
  2544. * through when supplied with a 0 in d0 and to show the board signal if
  2545. * a 1 is passed in d0. You should remember the current state of the
  2546. * switch to avoid unneeded switching. If your board has no switch, then
  2547. * simply supply a function that does nothing except a RTS.
  2548. *
  2549. * NOTE: Return the opposite of the switch-state. BDK
  2550. */
  2551. static uae_u32 REGPARAM2 picasso_SetSwitch (TrapContext *ctx)
  2552. {
  2553. lockrtg();
  2554. int monid = currprefs.rtgboards[0].monitor_id;
  2555. struct picasso96_state_struct *state = &picasso96_state[monid];
  2556. struct amigadisplay *ad = &adisplays[monid];
  2557. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  2558. uae_u16 flag = trap_get_dreg(ctx, 0) & 0xFFFF;
  2559. TCHAR p96text[100];
  2560. p96text[0] = 0;
  2561. if (flag && (state->BytesPerPixel == 0 || state->Width == 0 || state->Height == 0) && monid > 0) {
  2562. state->Width = 640;
  2563. state->VirtualWidth = state->Width;
  2564. state->Height = 480;
  2565. state->VirtualHeight = state->Height;
  2566. state->GC_Depth = 8;
  2567. state->GC_Flags = 0;
  2568. state->BytesPerPixel = 1;
  2569. state->HostAddress = NULL;
  2570. delayed_set_switch = true;
  2571. atomic_or(&vidinfo->picasso_state_change, PICASSO_STATE_SETGC);
  2572. } else {
  2573. delayed_set_switch = false;
  2574. atomic_or(&vidinfo->picasso_state_change, PICASSO_STATE_SETSWITCH);
  2575. ad->picasso_requested_on = flag != 0;
  2576. set_config_changed();
  2577. }
  2578. if (flag)
  2579. _stprintf(p96text, _T("Picasso96 %dx%dx%d (%dx%dx%d)"),
  2580. state->Width, state->Height, state->BytesPerPixel * 8,
  2581. vidinfo->width, vidinfo->height, vidinfo->pixbytes * 8);
  2582. write_log(_T("SetSwitch() - %s - %s. Monitor=%d\n"), flag ? p96text : _T("amiga"), delayed_set_switch ? _T("delayed") : _T("immediate"), monid);
  2583. /* Put old switch-state in D0 */
  2584. unlockrtg();
  2585. return !flag;
  2586. }
  2587. void picasso_enablescreen(int monid, int on)
  2588. {
  2589. bool uaegfx = currprefs.rtgboards[0].rtgmem_type < GFXBOARD_HARDWARE && currprefs.rtgboards[0].rtgmem_size;
  2590. bool uaegfx_active = is_uaegfx_active();
  2591. if (uaegfx_active && uaegfx) {
  2592. if (!init_picasso_screen_called)
  2593. init_picasso_screen(monid);
  2594. }
  2595. setconvert(monid);
  2596. picasso_refresh(0);
  2597. }
  2598. static void resetpalette(struct picasso96_state_struct *state)
  2599. {
  2600. for (int i = 0; i < 256 * 2; i++) {
  2601. state->CLUT[i].Pad = 0xff;
  2602. }
  2603. }
  2604. /*
  2605. * SetColorArray:
  2606. * a0: struct BoardInfo
  2607. * d0.w: startindex
  2608. * d1.w: count
  2609. * when this function is called, your driver has to fetch "count" color
  2610. * values starting at "startindex" from the CLUT field of the BoardInfo
  2611. * structure and write them to the hardware. The color values are always
  2612. * between 0 and 255 for each component regardless of the number of bits
  2613. * per cannon your board has. So you might have to shift the colors
  2614. * before writing them to the hardware.
  2615. */
  2616. static int updateclut(TrapContext *ctx, uaecptr clut, int start, int count, int offset)
  2617. {
  2618. bool uaegfx = currprefs.rtgboards[0].rtgmem_type < GFXBOARD_HARDWARE && currprefs.rtgboards[0].rtgmem_size;
  2619. int monid = currprefs.rtgboards[0].monitor_id;
  2620. struct picasso96_state_struct *state = &picasso96_state[monid];
  2621. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  2622. uae_u8 clutbuf[256 * 3];
  2623. int i, changed = 0;
  2624. clut += start * 3;
  2625. trap_get_bytes(ctx, clutbuf + start * 3, clut, count * 3);
  2626. for (i = start; i < start + count; i++) {
  2627. int coffset = i + offset;
  2628. int r = clutbuf[i * 3 + 0];
  2629. int g = clutbuf[i * 3 + 1];
  2630. int b = clutbuf[i * 3 + 2];
  2631. //write_log(_T("%d: %02x%02x%02x\n"), i, r, g, b);
  2632. changed |= state->CLUT[coffset].Red != r
  2633. || state->CLUT[coffset].Green != g
  2634. || state->CLUT[coffset].Blue != b;
  2635. if (state->CLUT[coffset].Pad) {
  2636. changed = 1;
  2637. state->CLUT[coffset].Pad = 0;
  2638. }
  2639. state->CLUT[coffset].Red = r;
  2640. state->CLUT[coffset].Green = g;
  2641. state->CLUT[coffset].Blue = b;
  2642. }
  2643. if (offset) {
  2644. state->dualclut = true;
  2645. }
  2646. changed |= picasso_palette(state->CLUT, vidinfo->clut);
  2647. return changed;
  2648. }
  2649. static uae_u32 REGPARAM2 picasso_SetColorArray (TrapContext *ctx)
  2650. {
  2651. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[currprefs.rtgboards[0].monitor_id];
  2652. /* Fill in some static UAE related structure about this new CLUT setting
  2653. * We need this for CLUT-based displays, and for mapping CLUT to hi/true colour */
  2654. uae_u16 start = trap_get_dreg (ctx, 0);
  2655. uae_u16 count = trap_get_dreg (ctx, 1);
  2656. uaecptr boardinfo = trap_get_areg (ctx, 0);
  2657. uaecptr clut = boardinfo + PSSO_BoardInfo_CLUT;
  2658. int offset = 0;
  2659. if (start > 512 || count > 512 || start + count > 512)
  2660. return 0;
  2661. if (start >= 256) {
  2662. clut = boardinfo + PSSO_BoardInfo_SecondaryCLUT;
  2663. start -= 256;
  2664. offset = 256;
  2665. }
  2666. lockrtg();
  2667. if (updateclut(ctx, clut, start, count, offset))
  2668. vidinfo->full_refresh = 1;
  2669. unlockrtg();
  2670. P96TRACE_SETUP((_T("SetColorArray(%d,%d)\n"), start, count));
  2671. return 1;
  2672. }
  2673. /*
  2674. * SetDAC:
  2675. * a0: struct BoardInfo
  2676. * d7: RGBFTYPE RGBFormat
  2677. * This function is called whenever the RGB format of the display changes,
  2678. * e.g. from chunky to TrueColor. Usually, all you have to do is to set
  2679. * the RAMDAC of your board accordingly.
  2680. */
  2681. static uae_u32 REGPARAM2 picasso_SetDAC (TrapContext *ctx)
  2682. {
  2683. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[currprefs.rtgboards[0].monitor_id];
  2684. /* Fill in some static UAE related structure about this new DAC setting
  2685. * Lets us keep track of what pixel format the Amiga is thinking about in our frame-buffer */
  2686. atomic_or(&vidinfo->picasso_state_change, PICASSO_STATE_SETDAC);
  2687. P96TRACE_SETUP((_T("SetDAC()\n")));
  2688. return 1;
  2689. }
  2690. static void init_picasso_screen(int monid)
  2691. {
  2692. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  2693. struct picasso96_state_struct *state = &picasso96_state[monid];
  2694. if(vidinfo->set_panning_called) {
  2695. state->Extent = state->Address + state->BytesPerRow * state->VirtualHeight;
  2696. }
  2697. if (set_gc_called) {
  2698. gfx_set_picasso_modeinfo(monid, state->RGBFormat);
  2699. set_gc_called = 0;
  2700. }
  2701. if((vidinfo->width == state->Width) &&
  2702. (vidinfo->height == state->Height) &&
  2703. (vidinfo->depth == (state->GC_Depth >> 3)) &&
  2704. (vidinfo->selected_rgbformat == state->RGBFormat))
  2705. {
  2706. picasso_refresh(monid);
  2707. }
  2708. init_picasso_screen_called = 1;
  2709. mman_ResetWatch (gfxmem_bank.start + natmem_offset, gfxmem_bank.allocated_size);
  2710. }
  2711. /*
  2712. * SetGC:
  2713. * a0: struct BoardInfo
  2714. * a1: struct ModeInfo
  2715. * d0: BOOL Border
  2716. * This function is called whenever another ModeInfo has to be set. This
  2717. * function simply sets up the CRTC and TS registers to generate the
  2718. * timing used for that screen mode. You should not set the DAC, clocks
  2719. * or linear start address. They will be set when appropriate by their
  2720. * own functions.
  2721. */
  2722. static uae_u32 REGPARAM2 picasso_SetGC (TrapContext *ctx)
  2723. {
  2724. lockrtg();
  2725. int monid = currprefs.rtgboards[0].monitor_id;
  2726. struct picasso96_state_struct *state = &picasso96_state[monid];
  2727. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  2728. /* Fill in some static UAE related structure about this new ModeInfo setting */
  2729. uaecptr AmigaBoardInfo = trap_get_areg(ctx, 0);
  2730. uae_u32 border = trap_get_dreg(ctx, 0);
  2731. uaecptr modeinfo = trap_get_areg(ctx, 1);
  2732. trap_put_long(ctx, AmigaBoardInfo + PSSO_BoardInfo_ModeInfo, modeinfo);
  2733. trap_put_word(ctx, AmigaBoardInfo + PSSO_BoardInfo_Border, border);
  2734. state->Width = trap_get_word(ctx, modeinfo + PSSO_ModeInfo_Width);
  2735. state->VirtualWidth = state->Width; /* in case SetPanning doesn't get called */
  2736. state->Height = trap_get_word(ctx, modeinfo + PSSO_ModeInfo_Height);
  2737. state->VirtualHeight = state->Height; /* in case SetPanning doesn't get called */
  2738. state->GC_Depth = trap_get_byte(ctx, modeinfo + PSSO_ModeInfo_Depth);
  2739. state->GC_Flags = trap_get_byte(ctx, modeinfo + PSSO_ModeInfo_Flags);
  2740. P96TRACE_SETUP((_T("SetGC(%d,%d,%d,%d)\n"), state->Width, state->Height, state->GC_Depth, border));
  2741. state->HostAddress = NULL;
  2742. atomic_or(&vidinfo->picasso_state_change, PICASSO_STATE_SETGC);
  2743. unlockrtg();
  2744. return 1;
  2745. }
  2746. /*
  2747. * SetPanning:
  2748. * a0: struct BoardInfo
  2749. * a1: UBYTE *Memory
  2750. * d0: uae_u16 Width
  2751. * d1: WORD XOffset
  2752. * d2: WORD YOffset
  2753. * d7: RGBFTYPE RGBFormat
  2754. * This function sets the view origin of a display which might also be
  2755. * overscanned. In register a1 you get the start address of the screen
  2756. * bitmap on the Amiga side. You will have to subtract the starting
  2757. * address of the board memory from that value to get the memory start
  2758. * offset within the board. Then you get the offset in pixels of the
  2759. * left upper edge of the visible part of an overscanned display. From
  2760. * these values you will have to calculate the LinearStartingAddress
  2761. * fields of the CRTC registers.
  2762. * NOTE: SetPanning() can be used to know when a Picasso96 screen is
  2763. * being opened. Better to do the appropriate clearing of the
  2764. * background here than in SetSwitch() derived functions,
  2765. * because SetSwitch() is not called for subsequent Picasso screens.
  2766. */
  2767. static void picasso_SetPanningInit (struct picasso96_state_struct *state)
  2768. {
  2769. state->XYOffset = state->Address + (state->XOffset * state->BytesPerPixel)
  2770. + (state->YOffset * state->BytesPerRow);
  2771. if(state->VirtualWidth > state->Width || state->VirtualHeight > state->Height)
  2772. state->BigAssBitmap = 1;
  2773. else
  2774. state->BigAssBitmap = 0;
  2775. }
  2776. static uae_u32 REGPARAM2 picasso_SetPanning (TrapContext *ctx)
  2777. {
  2778. lockrtg();
  2779. int monid = currprefs.rtgboards[0].monitor_id;
  2780. struct picasso96_state_struct *state = &picasso96_state[monid];
  2781. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  2782. uae_u16 Width = trap_get_dreg(ctx, 0);
  2783. uaecptr start_of_screen = trap_get_areg(ctx, 1);
  2784. uaecptr bi = trap_get_areg(ctx, 0);
  2785. uaecptr bmeptr = trap_get_long(ctx, bi + PSSO_BoardInfo_BitMapExtra); /* Get our BoardInfo ptr's BitMapExtra ptr */
  2786. uae_u16 bme_width, bme_height;
  2787. int changed = 0;
  2788. RGBFTYPE rgbf;
  2789. if (oldscr == 0) {
  2790. oldscr = start_of_screen;
  2791. changed = 1;
  2792. }
  2793. if (oldscr != start_of_screen) {
  2794. oldscr = start_of_screen;
  2795. changed = 1;
  2796. }
  2797. bme_width = trap_get_word(ctx, bmeptr + PSSO_BitMapExtra_Width);
  2798. bme_height = trap_get_word(ctx, bmeptr + PSSO_BitMapExtra_Height);
  2799. rgbf = state->RGBFormat;
  2800. state->Address = start_of_screen; /* Amiga-side address */
  2801. state->XOffset = (uae_s16)(trap_get_dreg(ctx, 1) & 0xFFFF);
  2802. state->YOffset = (uae_s16)(trap_get_dreg(ctx, 2) & 0xFFFF);
  2803. trap_put_word(ctx, bi + PSSO_BoardInfo_XOffset, state->XOffset);
  2804. trap_put_word(ctx, bi + PSSO_BoardInfo_YOffset, state->YOffset);
  2805. state->VirtualWidth = bme_width;
  2806. state->VirtualHeight = bme_height;
  2807. state->RGBFormat = (RGBFTYPE)trap_get_dreg(ctx, 7);
  2808. state->BytesPerPixel = GetBytesPerPixel (state->RGBFormat);
  2809. state->BytesPerRow = state->VirtualWidth * state->BytesPerPixel;
  2810. picasso_SetPanningInit(state);
  2811. if (rgbf != state->RGBFormat) {
  2812. setconvert(monid);
  2813. }
  2814. P96TRACE_SETUP((_T("SetPanning(%d, %d, %d) (%dx%d) Start 0x%x, BPR %d Bpp %d RGBF %d\n"),
  2815. Width, state->XOffset, state->YOffset,
  2816. bme_width, bme_height,
  2817. start_of_screen, state->BytesPerRow, state->BytesPerPixel, state->RGBFormat));
  2818. atomic_or(&vidinfo->picasso_state_change, PICASSO_STATE_SETPANNING);
  2819. unlockrtg();
  2820. return 1;
  2821. }
  2822. static uae_u32 picasso_SetSplitPosition(TrapContext *ctx)
  2823. {
  2824. lockrtg();
  2825. int monid = currprefs.rtgboards[0].monitor_id;
  2826. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  2827. uaecptr bi = trap_get_areg(ctx, 0);
  2828. uae_s16 pos = trap_get_dreg(ctx, 0);
  2829. trap_put_word(ctx, bi + PSSO_BoardInfo_YSplit, pos);
  2830. pos--;
  2831. if (pos != vidinfo->splitypos) {
  2832. vidinfo->splitypos = pos;
  2833. vidinfo->full_refresh = 1;
  2834. }
  2835. unlockrtg();
  2836. return 1;
  2837. }
  2838. #ifdef CPU_64_BIT
  2839. static void do_xor8 (uae_u8 *p, int w, uae_u32 v)
  2840. {
  2841. while (ALIGN_POINTER_TO32 (p) != 7 && w) {
  2842. *p ^= v;
  2843. p++;
  2844. w--;
  2845. }
  2846. uae_u64 vv = v | ((uae_u64)v << 32);
  2847. while (w >= 2 * 8) {
  2848. *((uae_u64*)p) ^= vv;
  2849. p += 8;
  2850. *((uae_u64*)p) ^= vv;
  2851. p += 8;
  2852. w -= 2 * 8;
  2853. }
  2854. while (w) {
  2855. *p ^= v;
  2856. p++;
  2857. w--;
  2858. }
  2859. }
  2860. #else
  2861. static void do_xor8 (uae_u8 *p, int w, uae_u32 v)
  2862. {
  2863. while (ALIGN_POINTER_TO32 (p) != 3 && w) {
  2864. *p ^= v;
  2865. p++;
  2866. w--;
  2867. }
  2868. while (w >= 2 * 4) {
  2869. *((uae_u32*)p) ^= v;
  2870. p += 4;
  2871. *((uae_u32*)p) ^= v;
  2872. p += 4;
  2873. w -= 2 * 4;
  2874. }
  2875. while (w) {
  2876. *p ^= v;
  2877. p++;
  2878. w--;
  2879. }
  2880. }
  2881. #endif
  2882. /*
  2883. * InvertRect:
  2884. *
  2885. * Inputs:
  2886. * a0:struct BoardInfo *bi
  2887. * a1:struct RenderInfo *ri
  2888. * d0.w:X
  2889. * d1.w:Y
  2890. * d2.w:Width
  2891. * d3.w:Height
  2892. * d4.l:Mask
  2893. * d7.l:RGBFormat
  2894. *
  2895. * This function is used to invert a rectangular area on the board. It is called by BltBitMap,
  2896. * BltPattern and BltTemplate.
  2897. */
  2898. static uae_u32 REGPARAM2 picasso_InvertRect (TrapContext *ctx)
  2899. {
  2900. uaecptr renderinfo = trap_get_areg(ctx, 1);
  2901. uae_u32 X = (uae_u16)trap_get_dreg(ctx, 0);
  2902. uae_u32 Y = (uae_u16)trap_get_dreg(ctx, 1);
  2903. uae_u32 Width = (uae_u16)trap_get_dreg(ctx, 2);
  2904. uae_u32 Height = (uae_u16)trap_get_dreg(ctx, 3);
  2905. uae_u8 mask = (uae_u8)trap_get_dreg(ctx, 4);
  2906. int Bpp = GetBytesPerPixel (trap_get_dreg(ctx, 7));
  2907. uae_u32 xorval;
  2908. unsigned int lines;
  2909. struct RenderInfo ri;
  2910. uae_u8 *uae_mem, *rectstart;
  2911. unsigned long width_in_bytes;
  2912. uae_u32 result = 0;
  2913. if (NOBLITTER)
  2914. return 0;
  2915. if (CopyRenderInfoStructureA2U(ctx, renderinfo, &ri)) {
  2916. P96TRACE((_T("InvertRect %dbpp 0x%lx\n"), Bpp, (long)mask));
  2917. if (!validatecoords(ctx, &ri, &X, &Y, &Width, &Height))
  2918. return 1;
  2919. if (mask != 0xFF && Bpp > 1)
  2920. mask = 0xFF;
  2921. xorval = 0x01010101 * (mask & 0xFF);
  2922. width_in_bytes = Bpp * Width;
  2923. rectstart = uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
  2924. for (lines = 0; lines < Height; lines++, uae_mem += ri.BytesPerRow)
  2925. do_xor8 (uae_mem, width_in_bytes, xorval);
  2926. result = 1;
  2927. }
  2928. return result; /* 1 if supported, 0 otherwise */
  2929. }
  2930. /***********************************************************
  2931. FillRect:
  2932. ***********************************************************
  2933. * a0: struct BoardInfo *
  2934. * a1: struct RenderInfo *
  2935. * d0: WORD X
  2936. * d1: WORD Y
  2937. * d2: WORD Width
  2938. * d3: WORD Height
  2939. * d4: uae_u32 Pen
  2940. * d5: UBYTE Mask
  2941. * d7: uae_u32 RGBFormat
  2942. ***********************************************************/
  2943. static uae_u32 REGPARAM2 picasso_FillRect(TrapContext *ctx)
  2944. {
  2945. uaecptr renderinfo = trap_get_areg(ctx, 1);
  2946. uae_u32 X = (uae_u16)trap_get_dreg(ctx, 0);
  2947. uae_u32 Y = (uae_u16)trap_get_dreg(ctx, 1);
  2948. uae_u32 Width = (uae_u16)trap_get_dreg(ctx, 2);
  2949. uae_u32 Height = (uae_u16)trap_get_dreg(ctx, 3);
  2950. uae_u32 Pen = trap_get_dreg(ctx, 4);
  2951. uae_u8 Mask = (uae_u8)trap_get_dreg(ctx, 5);
  2952. RGBFTYPE RGBFormat = (RGBFTYPE)trap_get_dreg(ctx, 7);
  2953. uae_u8 *oldstart;
  2954. int Bpp;
  2955. struct RenderInfo ri;
  2956. uae_u32 result = 0;
  2957. if (NOBLITTER)
  2958. return 0;
  2959. if (CopyRenderInfoStructureA2U(ctx, renderinfo, &ri)) {
  2960. if (!validatecoords(ctx, &ri, &X, &Y, &Width, &Height))
  2961. return 1;
  2962. Bpp = GetBytesPerPixel(RGBFormat);
  2963. P96TRACE((_T("FillRect(%d, %d, %d, %d) Pen 0x%x BPP %d BPR %d Mask 0x%x\n"),
  2964. X, Y, Width, Height, Pen, Bpp, ri.BytesPerRow, Mask));
  2965. if(Bpp > 1)
  2966. Mask = 0xFF;
  2967. if (Mask == 0xFF) {
  2968. /* Do the fill-rect in the frame-buffer */
  2969. do_fillrect_frame_buffer(&ri, X, Y, Width, Height, Pen, Bpp);
  2970. result = 1;
  2971. } else {
  2972. /* We get here only if Mask != 0xFF */
  2973. if (Bpp != 1) {
  2974. write_log (_T("WARNING - FillRect() has unhandled mask 0x%x with Bpp %d. Using fall-back routine.\n"), Mask, Bpp);
  2975. } else {
  2976. Pen &= Mask;
  2977. Mask = ~Mask;
  2978. oldstart = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
  2979. {
  2980. uae_u8 *start = oldstart;
  2981. uae_u8 *end = start + Height * ri.BytesPerRow;
  2982. for (; start != end; start += ri.BytesPerRow) {
  2983. uae_u8 *p = start;
  2984. unsigned long cols;
  2985. for (cols = 0; cols < Width; cols++) {
  2986. uae_u32 tmpval = do_get_mem_byte (p + cols) & Mask;
  2987. do_put_mem_byte (p + cols, (uae_u8)(Pen | tmpval));
  2988. }
  2989. }
  2990. }
  2991. result = 1;
  2992. }
  2993. }
  2994. }
  2995. return result;
  2996. }
  2997. /*
  2998. * BlitRect() is a generic (any chunky pixel format) rectangle copier
  2999. * NOTE: If dstri is NULL, then we're only dealing with one RenderInfo area, and called from picasso_BlitRect()
  3000. *
  3001. * OpCodes:
  3002. * 0 = FALSE: dst = 0
  3003. * 1 = NOR: dst = ~(src | dst)
  3004. * 2 = ONLYDST: dst = dst & ~src
  3005. * 3 = NOTSRC: dst = ~src
  3006. * 4 = ONLYSRC: dst = src & ~dst
  3007. * 5 = NOTDST: dst = ~dst
  3008. * 6 = EOR: dst = src^dst
  3009. * 7 = NAND: dst = ~(src & dst)
  3010. * 8 = AND: dst = (src & dst)
  3011. * 9 = NEOR: dst = ~(src ^ dst)
  3012. *10 = DST: dst = dst
  3013. *11 = NOTONLYSRC: dst = ~src | dst
  3014. *12 = SRC: dst = src
  3015. *13 = NOTONLYDST: dst = ~dst | src
  3016. *14 = OR: dst = src | dst
  3017. *15 = TRUE: dst = 0xFF
  3018. */
  3019. struct blitdata
  3020. {
  3021. struct RenderInfo ri_struct;
  3022. struct RenderInfo dstri_struct;
  3023. struct RenderInfo *ri; /* Self-referencing pointers */
  3024. struct RenderInfo *dstri;
  3025. unsigned long srcx;
  3026. unsigned long srcy;
  3027. unsigned long dstx;
  3028. unsigned long dsty;
  3029. unsigned long width;
  3030. unsigned long height;
  3031. uae_u8 mask;
  3032. BLIT_OPCODE opcode;
  3033. } blitrectdata;
  3034. STATIC_INLINE int BlitRectHelper(TrapContext *ctx)
  3035. {
  3036. struct RenderInfo *ri = blitrectdata.ri;
  3037. struct RenderInfo *dstri = blitrectdata.dstri;
  3038. uae_u32 srcx = blitrectdata.srcx;
  3039. uae_u32 srcy = blitrectdata.srcy;
  3040. uae_u32 dstx = blitrectdata.dstx;
  3041. uae_u32 dsty = blitrectdata.dsty;
  3042. uae_u32 width = blitrectdata.width;
  3043. uae_u32 height = blitrectdata.height;
  3044. uae_u8 mask = blitrectdata.mask;
  3045. BLIT_OPCODE opcode = blitrectdata.opcode;
  3046. if (!validatecoords(ctx, ri, &srcx, &srcy, &width, &height))
  3047. return 1;
  3048. if (!validatecoords(ctx, dstri, &dstx, &dsty, &width, &height))
  3049. return 1;
  3050. uae_u8 Bpp = GetBytesPerPixel (ri->RGBFormat);
  3051. if (opcode == BLIT_DST) {
  3052. write_log ( _T("WARNING: BlitRect() being called with opcode of BLIT_DST\n") );
  3053. return 1;
  3054. }
  3055. /*
  3056. * If we have no destination RenderInfo, then we're dealing with a single-buffer action, called
  3057. * from picasso_BlitRect(). The code in do_blitrect_frame_buffer() deals with the frame-buffer,
  3058. * while the do_blit() code deals with the visible screen.
  3059. *
  3060. * If we have a destination RenderInfo, then we've been called from picasso_BlitRectNoMaskComplete()
  3061. * and we need to put the results on the screen from the frame-buffer.
  3062. */
  3063. if (dstri == NULL || dstri->Memory == ri->Memory) {
  3064. if (mask != 0xFF && Bpp > 1)
  3065. mask = 0xFF;
  3066. dstri = ri;
  3067. }
  3068. /* Do our virtual frame-buffer memory first */
  3069. return do_blitrect_frame_buffer(ri, dstri, srcx, srcy, dstx, dsty, width, height, mask, opcode);
  3070. }
  3071. static int BlitRect(TrapContext *ctx, uaecptr ri, uaecptr dstri,
  3072. unsigned long srcx, unsigned long srcy, unsigned long dstx, unsigned long dsty,
  3073. unsigned long width, unsigned long height, uae_u8 mask, BLIT_OPCODE opcode)
  3074. {
  3075. /* Set up the params */
  3076. CopyRenderInfoStructureA2U(ctx, ri, &blitrectdata.ri_struct);
  3077. blitrectdata.ri = &blitrectdata.ri_struct;
  3078. if(dstri) {
  3079. CopyRenderInfoStructureA2U(ctx, dstri, &blitrectdata.dstri_struct);
  3080. blitrectdata.dstri = &blitrectdata.dstri_struct;
  3081. } else {
  3082. blitrectdata.dstri = NULL;
  3083. }
  3084. blitrectdata.srcx = srcx;
  3085. blitrectdata.srcy = srcy;
  3086. blitrectdata.dstx = dstx;
  3087. blitrectdata.dsty = dsty;
  3088. blitrectdata.width = width;
  3089. blitrectdata.height = height;
  3090. blitrectdata.mask = mask;
  3091. blitrectdata.opcode = opcode;
  3092. return BlitRectHelper(ctx);
  3093. }
  3094. /***********************************************************
  3095. BlitRect:
  3096. ***********************************************************
  3097. * a0: struct BoardInfo
  3098. * a1: struct RenderInfo
  3099. * d0: WORD SrcX
  3100. * d1: WORD SrcY
  3101. * d2: WORD DstX
  3102. * d3: WORD DstY
  3103. * d4: WORD Width
  3104. * d5: WORD Height
  3105. * d6: UBYTE Mask
  3106. * d7: uae_u32 RGBFormat
  3107. ***********************************************************/
  3108. static uae_u32 REGPARAM2 picasso_BlitRect (TrapContext *ctx)
  3109. {
  3110. uaecptr renderinfo = trap_get_areg(ctx, 1);
  3111. unsigned long srcx = (uae_u16)trap_get_dreg(ctx, 0);
  3112. unsigned long srcy = (uae_u16)trap_get_dreg(ctx, 1);
  3113. unsigned long dstx = (uae_u16)trap_get_dreg(ctx, 2);
  3114. unsigned long dsty = (uae_u16)trap_get_dreg(ctx, 3);
  3115. unsigned long width = (uae_u16)trap_get_dreg(ctx, 4);
  3116. unsigned long height = (uae_u16)trap_get_dreg(ctx, 5);
  3117. uae_u8 Mask = (uae_u8)trap_get_dreg(ctx, 6);
  3118. uae_u32 result = 0;
  3119. if (NOBLITTER_BLIT)
  3120. return 0;
  3121. P96TRACE((_T("BlitRect(%d, %d, %d, %d, %d, %d, 0x%x)\n"), srcx, srcy, dstx, dsty, width, height, Mask));
  3122. result = BlitRect(ctx, renderinfo, (uaecptr)NULL, srcx, srcy, dstx, dsty, width, height, Mask, BLIT_SRC);
  3123. return result;
  3124. }
  3125. /***********************************************************
  3126. BlitRectNoMaskComplete:
  3127. ***********************************************************
  3128. * a0: struct BoardInfo
  3129. * a1: struct RenderInfo (src)
  3130. * a2: struct RenderInfo (dst)
  3131. * d0: WORD SrcX
  3132. * d1: WORD SrcY
  3133. * d2: WORD DstX
  3134. * d3: WORD DstY
  3135. * d4: WORD Width
  3136. * d5: WORD Height
  3137. * d6: UBYTE OpCode
  3138. * d7: uae_u32 RGBFormat
  3139. * NOTE: MUST return 0 in D0 if we're not handling this operation
  3140. * because the RGBFormat or opcode aren't supported.
  3141. * OTHERWISE return 1
  3142. ***********************************************************/
  3143. static uae_u32 REGPARAM2 picasso_BlitRectNoMaskComplete (TrapContext *ctx)
  3144. {
  3145. uaecptr srcri = trap_get_areg(ctx, 1);
  3146. uaecptr dstri = trap_get_areg(ctx, 2);
  3147. unsigned long srcx = (uae_u16)trap_get_dreg(ctx, 0);
  3148. unsigned long srcy = (uae_u16)trap_get_dreg(ctx, 1);
  3149. unsigned long dstx = (uae_u16)trap_get_dreg(ctx, 2);
  3150. unsigned long dsty = (uae_u16)trap_get_dreg(ctx, 3);
  3151. unsigned long width = (uae_u16)trap_get_dreg(ctx, 4);
  3152. unsigned long height = (uae_u16)trap_get_dreg(ctx, 5);
  3153. BLIT_OPCODE OpCode = (BLIT_OPCODE)(trap_get_dreg(ctx, 6) & 0xff);
  3154. uae_u32 RGBFmt = trap_get_dreg(ctx, 7);
  3155. uae_u32 result = 0;
  3156. if (NOBLITTER_BLIT)
  3157. return 0;
  3158. P96TRACE((_T("BlitRectNoMaskComplete() op 0x%02x, %08x:(%4d,%4d) --> %08x:(%4d,%4d), wh(%4d,%4d)\n"),
  3159. OpCode, trap_get_long(ctx, srcri + PSSO_RenderInfo_Memory), srcx, srcy, trap_get_long(ctx, dstri + PSSO_RenderInfo_Memory), dstx, dsty, width, height));
  3160. result = BlitRect(ctx, srcri, dstri, srcx, srcy, dstx, dsty, width, height, 0xFF, OpCode);
  3161. return result;
  3162. }
  3163. /* NOTE: fgpen MUST be in host byte order */
  3164. STATIC_INLINE void PixelWrite(uae_u8 *mem, int bits, uae_u32 fgpen, int Bpp, uae_u32 mask)
  3165. {
  3166. switch (Bpp)
  3167. {
  3168. case 1:
  3169. if (mask != 0xFF)
  3170. fgpen = (fgpen & mask) | (mem[bits] & ~mask);
  3171. mem[bits] = (uae_u8)fgpen;
  3172. break;
  3173. case 2:
  3174. ((uae_u16 *)mem)[bits] = (uae_u16)fgpen;
  3175. break;
  3176. case 3:
  3177. mem[bits * 3 + 0] = fgpen >> 0;
  3178. mem[bits * 3 + 1] = fgpen >> 8;
  3179. mem[bits * 3 + 2] = fgpen >> 16;
  3180. break;
  3181. case 4:
  3182. ((uae_u32 *)mem)[bits] = fgpen;
  3183. break;
  3184. }
  3185. }
  3186. /*
  3187. * BlitPattern:
  3188. *
  3189. * Synopsis:BlitPattern(bi, ri, pattern, X, Y, Width, Height, Mask, RGBFormat);
  3190. * Inputs:
  3191. * a0:struct BoardInfo *bi
  3192. * a1:struct RenderInfo *ri
  3193. * a2:struct Pattern *pattern
  3194. * d0.w:X
  3195. * d1.w:Y
  3196. * d2.w:Width
  3197. * d3.w:Height
  3198. * d4.w:Mask
  3199. * d7.l:RGBFormat
  3200. *
  3201. * This function is used to paint a pattern on the board memory using the blitter. It is called by
  3202. * BltPattern, if a AreaPtrn is used with positive AreaPtSz. The pattern consists of a b/w image
  3203. * using a single plane of image data which will be expanded repeatedly to the destination RGBFormat
  3204. * using ForeGround and BackGround pens as well as draw modes. The width of the pattern data is
  3205. * always 16 pixels (one word) and the height is calculated as 2^Size. The data must be shifted up
  3206. * and to the left by XOffset and YOffset pixels at the beginning.
  3207. */
  3208. static uae_u32 REGPARAM2 picasso_BlitPattern (TrapContext *ctx)
  3209. {
  3210. uaecptr rinf = trap_get_areg(ctx, 1);
  3211. uaecptr pinf = trap_get_areg(ctx, 2);
  3212. uae_u32 X = (uae_u16)trap_get_dreg(ctx, 0);
  3213. uae_u32 Y = (uae_u16)trap_get_dreg(ctx, 1);
  3214. uae_u32 W = (uae_u16)trap_get_dreg(ctx, 2);
  3215. uae_u32 H = (uae_u16)trap_get_dreg(ctx, 3);
  3216. uae_u8 Mask = (uae_u8)trap_get_dreg(ctx, 4);
  3217. uae_u32 RGBFmt = trap_get_dreg(ctx, 7);
  3218. uae_u8 Bpp = GetBytesPerPixel (RGBFmt);
  3219. int inversion = 0;
  3220. struct RenderInfo ri;
  3221. struct Pattern pattern;
  3222. unsigned long rows;
  3223. uae_u8 *uae_mem;
  3224. int xshift;
  3225. unsigned long ysize_mask;
  3226. uae_u32 result = 0;
  3227. if (NOBLITTER)
  3228. return 0;
  3229. if(CopyRenderInfoStructureA2U(ctx, rinf, &ri) && CopyPatternStructureA2U(ctx, pinf, &pattern)) {
  3230. if (!validatecoords(ctx, &ri, &X, &Y, &W, &H))
  3231. return 0;
  3232. Bpp = GetBytesPerPixel(ri.RGBFormat);
  3233. uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp; /* offset with address */
  3234. if (pattern.DrawMode & INVERS)
  3235. inversion = 1;
  3236. pattern.DrawMode &= 0x03;
  3237. if (Mask != 0xFF) {
  3238. if(Bpp > 1)
  3239. Mask = 0xFF;
  3240. result = 1;
  3241. } else {
  3242. result = 1;
  3243. }
  3244. if (pattern.Size >= 16)
  3245. result = 0;
  3246. if(result) {
  3247. bool indirect = trap_is_indirect();
  3248. uae_u32 fgpen, bgpen;
  3249. P96TRACE((_T("BlitPattern() xy(%d,%d), wh(%d,%d) draw 0x%x, off(%d,%d), ph %d\n"),
  3250. X, Y, W, H, pattern.DrawMode, pattern.XOffset, pattern.YOffset, 1 << pattern.Size));
  3251. #if P96TRACING_ENABLED
  3252. DumpPattern(&pattern);
  3253. #endif
  3254. ysize_mask = (1 << pattern.Size) - 1;
  3255. xshift = pattern.XOffset & 15;
  3256. fgpen = pattern.FgPen;
  3257. endianswap (&fgpen, Bpp);
  3258. bgpen = pattern.BgPen;
  3259. endianswap (&bgpen, Bpp);
  3260. uae_u16 *tmplbuf = NULL;
  3261. if (indirect) {
  3262. tmplbuf = xcalloc(uae_u16, 1 << pattern.Size);
  3263. trap_get_words(ctx, tmplbuf, pattern.AMemory, 1 << pattern.Size);
  3264. }
  3265. for (rows = 0; rows < H; rows++, uae_mem += ri.BytesPerRow) {
  3266. unsigned long prow = (rows + pattern.YOffset) & ysize_mask;
  3267. unsigned int d;
  3268. uae_u8 *uae_mem2 = uae_mem;
  3269. unsigned long cols;
  3270. if (indirect) {
  3271. d = do_get_mem_word(tmplbuf + prow);
  3272. } else {
  3273. d = do_get_mem_word(((uae_u16 *)pattern.Memory) + prow);
  3274. }
  3275. if (xshift != 0)
  3276. d = (d << xshift) | (d >> (16 - xshift));
  3277. for (cols = 0; cols < W; cols += 16, uae_mem2 += Bpp * 16) {
  3278. long bits;
  3279. long max = W - cols;
  3280. unsigned int data = d;
  3281. if (max > 16)
  3282. max = 16;
  3283. switch (pattern.DrawMode)
  3284. {
  3285. case JAM1:
  3286. {
  3287. for (bits = 0; bits < max; bits++) {
  3288. int bit_set = data & 0x8000;
  3289. data <<= 1;
  3290. if (inversion)
  3291. bit_set = !bit_set;
  3292. if (bit_set)
  3293. PixelWrite (uae_mem2, bits, fgpen, Bpp, Mask);
  3294. }
  3295. break;
  3296. }
  3297. case JAM2:
  3298. {
  3299. for (bits = 0; bits < max; bits++) {
  3300. int bit_set = data & 0x8000;
  3301. data <<= 1;
  3302. if (inversion)
  3303. bit_set = !bit_set;
  3304. PixelWrite (uae_mem2, bits, bit_set ? fgpen : bgpen, Bpp, Mask);
  3305. }
  3306. break;
  3307. }
  3308. case COMP:
  3309. {
  3310. for (bits = 0; bits < max; bits++) {
  3311. int bit_set = data & 0x8000;
  3312. data <<= 1;
  3313. if (bit_set) {
  3314. switch (Bpp)
  3315. {
  3316. case 1:
  3317. {
  3318. uae_mem2[bits] ^= 0xff & Mask;
  3319. }
  3320. break;
  3321. case 2:
  3322. {
  3323. uae_u16 *addr = (uae_u16 *)uae_mem2;
  3324. addr[bits] ^= 0xffff;
  3325. }
  3326. break;
  3327. case 3:
  3328. {
  3329. uae_u32 *addr = (uae_u32 *)(uae_mem2 + bits * 3);
  3330. do_put_mem_long (addr, do_get_mem_long (addr) ^ 0x00ffffff);
  3331. }
  3332. break;
  3333. case 4:
  3334. {
  3335. uae_u32 *addr = (uae_u32 *)uae_mem2;
  3336. addr[bits] ^= 0xffffffff;
  3337. }
  3338. break;
  3339. }
  3340. }
  3341. }
  3342. break;
  3343. }
  3344. }
  3345. }
  3346. }
  3347. result = 1;
  3348. xfree(tmplbuf);
  3349. }
  3350. }
  3351. return result;
  3352. }
  3353. /*************************************************
  3354. BlitTemplate:
  3355. **************************************************
  3356. * Synopsis: BlitTemplate(bi, ri, template, X, Y, Width, Height, Mask, RGBFormat);
  3357. * a0: struct BoardInfo *bi
  3358. * a1: struct RenderInfo *ri
  3359. * a2: struct Template *template
  3360. * d0.w: X
  3361. * d1.w: Y
  3362. * d2.w: Width
  3363. * d3.w: Height
  3364. * d4.w: Mask
  3365. * d7.l: RGBFormat
  3366. *
  3367. * This function is used to paint a template on the board memory using the blitter.
  3368. * It is called by BltPattern and BltTemplate. The template consists of a b/w image
  3369. * using a single plane of image data which will be expanded to the destination RGBFormat
  3370. * using ForeGround and BackGround pens as well as draw modes.
  3371. ***********************************************************************************/
  3372. static uae_u32 REGPARAM2 picasso_BlitTemplate(TrapContext *ctx)
  3373. {
  3374. uae_u8 inversion = 0;
  3375. uaecptr rinf = trap_get_areg(ctx, 1);
  3376. uaecptr tmpl = trap_get_areg(ctx, 2);
  3377. uae_u32 X = (uae_u16)trap_get_dreg(ctx, 0);
  3378. uae_u32 Y = (uae_u16)trap_get_dreg(ctx, 1);
  3379. uae_u32 W = (uae_u16)trap_get_dreg(ctx, 2);
  3380. uae_u32 H = (uae_u16)trap_get_dreg(ctx, 3);
  3381. uae_u16 Mask = (uae_u16)trap_get_dreg(ctx, 4);
  3382. struct Template tmp;
  3383. struct RenderInfo ri;
  3384. unsigned long rows;
  3385. int bitoffset;
  3386. uae_u8 *uae_mem, Bpp;
  3387. uae_u8 *tmpl_base;
  3388. uae_u32 result = 0;
  3389. if (NOBLITTER)
  3390. return 0;
  3391. if (CopyRenderInfoStructureA2U(ctx, rinf, &ri) && CopyTemplateStructureA2U(ctx, tmpl, &tmp)) {
  3392. if (!validatecoords(ctx, &ri, &X, &Y, &W, &H))
  3393. return 1;
  3394. Bpp = GetBytesPerPixel (ri.RGBFormat);
  3395. uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp; /* offset into address */
  3396. if (tmp.DrawMode & INVERS)
  3397. inversion = 1;
  3398. tmp.DrawMode &= 0x03;
  3399. if (Mask != 0xFF) {
  3400. if(Bpp > 1)
  3401. Mask = 0xFF;
  3402. if(tmp.DrawMode == COMP) {
  3403. write_log (_T("WARNING - BlitTemplate() has unhandled mask 0x%x with COMP DrawMode. Using fall-back routine.\n"), Mask);
  3404. return 0;
  3405. } else {
  3406. result = 1;
  3407. }
  3408. } else {
  3409. result = 1;
  3410. }
  3411. if(result) {
  3412. uae_u32 fgpen, bgpen;
  3413. bool indirect = trap_is_indirect();
  3414. P96TRACE((_T("BlitTemplate() xy(%d,%d), wh(%d,%d) draw 0x%x fg 0x%x bg 0x%x \n"),
  3415. X, Y, W, H, tmp.DrawMode, tmp.FgPen, tmp.BgPen));
  3416. bitoffset = tmp.XOffset % 8;
  3417. #if P96TRACING_ENABLED && P96TRACING_LEVEL > 0
  3418. DumpTemplate(&tmp, W, H);
  3419. #endif
  3420. fgpen = tmp.FgPen;
  3421. endianswap (&fgpen, Bpp);
  3422. bgpen = tmp.BgPen;
  3423. endianswap (&bgpen, Bpp);
  3424. uae_u8 *tmpl_buffer = NULL;
  3425. if (indirect) {
  3426. int tmpl_size = H * tmp.BytesPerRow * Bpp;
  3427. tmpl_buffer = xcalloc(uae_u8, tmpl_size + 1);
  3428. trap_get_bytes(ctx, tmpl_buffer, tmp.AMemory, tmpl_size);
  3429. tmpl_base = tmpl_buffer + tmp.XOffset / 8;
  3430. } else {
  3431. tmpl_base = tmp.Memory + tmp.XOffset / 8;
  3432. }
  3433. for (rows = 0; rows < H; rows++, uae_mem += ri.BytesPerRow, tmpl_base += tmp.BytesPerRow) {
  3434. unsigned long cols;
  3435. uae_u8 *uae_mem2 = uae_mem;
  3436. uae_u8 *tmpl_mem = tmpl_base;
  3437. unsigned int data;
  3438. data = *tmpl_mem;
  3439. for (cols = 0; cols < W; cols += 8, uae_mem2 += Bpp * 8) {
  3440. unsigned int byte;
  3441. long bits;
  3442. long max = W - cols;
  3443. if (max > 8)
  3444. max = 8;
  3445. data <<= 8;
  3446. data |= *++tmpl_mem;
  3447. byte = data >> (8 - bitoffset);
  3448. switch (tmp.DrawMode)
  3449. {
  3450. case JAM1:
  3451. {
  3452. for (bits = 0; bits < max; bits++) {
  3453. int bit_set = (byte & 0x80);
  3454. byte <<= 1;
  3455. if (inversion)
  3456. bit_set = !bit_set;
  3457. if (bit_set)
  3458. PixelWrite(uae_mem2, bits, fgpen, Bpp, Mask);
  3459. }
  3460. break;
  3461. }
  3462. case JAM2:
  3463. {
  3464. for (bits = 0; bits < max; bits++) {
  3465. int bit_set = (byte & 0x80);
  3466. byte <<= 1;
  3467. if (inversion)
  3468. bit_set = !bit_set;
  3469. PixelWrite(uae_mem2, bits, bit_set ? fgpen : bgpen, Bpp, Mask);
  3470. }
  3471. break;
  3472. }
  3473. case COMP:
  3474. {
  3475. for (bits = 0; bits < max; bits++) {
  3476. int bit_set = (byte & 0x80);
  3477. byte <<= 1;
  3478. if (bit_set) {
  3479. switch (Bpp)
  3480. {
  3481. case 1:
  3482. {
  3483. uae_u8 *addr = uae_mem2;
  3484. addr[bits] ^= 0xff;
  3485. }
  3486. break;
  3487. case 2:
  3488. {
  3489. uae_u16 *addr = (uae_u16 *)uae_mem2;
  3490. addr[bits] ^= 0xffff;
  3491. }
  3492. break;
  3493. case 3:
  3494. {
  3495. uae_u32 *addr = (uae_u32 *)(uae_mem2 + bits * 3);
  3496. do_put_mem_long (addr, do_get_mem_long (addr) ^ 0x00FFFFFF);
  3497. }
  3498. break;
  3499. case 4:
  3500. {
  3501. uae_u32 *addr = (uae_u32 *)uae_mem2;
  3502. addr[bits] ^= 0xffffffff;
  3503. }
  3504. break;
  3505. }
  3506. }
  3507. }
  3508. break;
  3509. }
  3510. }
  3511. }
  3512. }
  3513. result = 1;
  3514. xfree(tmpl_buffer);
  3515. }
  3516. }
  3517. return 1;
  3518. }
  3519. /*
  3520. * CalculateBytesPerRow:
  3521. * a0: struct BoardInfo
  3522. * d0: uae_u16 Width
  3523. * d7: RGBFTYPE RGBFormat
  3524. * This function calculates the amount of bytes needed for a line of
  3525. * "Width" pixels in the given RGBFormat.
  3526. */
  3527. static uae_u32 REGPARAM2 picasso_CalculateBytesPerRow (TrapContext *ctx)
  3528. {
  3529. uae_u16 width = trap_get_dreg(ctx, 0);
  3530. uae_u32 type = trap_get_dreg(ctx, 7);
  3531. int bpp = GetBytesPerPixel(type);
  3532. width = bpp * width;
  3533. return width;
  3534. }
  3535. /*
  3536. * SetDisplay:
  3537. * a0: struct BoardInfo
  3538. * d0: BOOL state
  3539. * This function enables and disables the video display.
  3540. *
  3541. * NOTE: return the opposite of the state
  3542. */
  3543. static uae_u32 REGPARAM2 picasso_SetDisplay (TrapContext *ctx)
  3544. {
  3545. int monid = currprefs.rtgboards[0].monitor_id;
  3546. struct picasso96_state_struct *state = &picasso96_state[monid];
  3547. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  3548. uae_u32 setstate = trap_get_dreg(ctx, 0);
  3549. P96TRACE_SETUP((_T("SetDisplay(%d)\n"), setstate));
  3550. resetpalette(state);
  3551. atomic_or(&vidinfo->picasso_state_change, PICASSO_STATE_SETDISPLAY);
  3552. return !setstate;
  3553. }
  3554. void init_hz_p96(int monid)
  3555. {
  3556. if (currprefs.win32_rtgvblankrate < 0 || isvsync_rtg ()) {
  3557. float rate = target_getcurrentvblankrate(monid);
  3558. if (rate < 0)
  3559. p96vblank = vblank_hz;
  3560. else
  3561. p96vblank = target_getcurrentvblankrate(monid);
  3562. } else if (currprefs.win32_rtgvblankrate == 0) {
  3563. p96vblank = vblank_hz;
  3564. } else {
  3565. p96vblank = currprefs.win32_rtgvblankrate;
  3566. }
  3567. if (p96vblank <= 0)
  3568. p96vblank = 60;
  3569. if (p96vblank >= 300)
  3570. p96vblank = 300;
  3571. p96syncrate = maxvpos_nom * vblank_hz / p96vblank;
  3572. write_log (_T("RTGFREQ: %d*%.4f = %.4f / %.1f = %d\n"), maxvpos_nom, vblank_hz, maxvpos_nom * vblank_hz, p96vblank, p96syncrate);
  3573. }
  3574. /* NOTE: Watch for those planeptrs of 0x00000000 and 0xFFFFFFFF for all zero / all one bitmaps !!!! */
  3575. static void PlanarToChunky(TrapContext *ctx, struct RenderInfo *ri, struct BitMap *bm,
  3576. unsigned long srcx, unsigned long srcy,
  3577. unsigned long dstx, unsigned long dsty,
  3578. unsigned long width, unsigned long height,
  3579. uae_u8 mask)
  3580. {
  3581. int j;
  3582. uae_u8 *PLANAR[8];
  3583. uaecptr APLANAR[8];
  3584. uae_u8 *image = ri->Memory + dstx * GetBytesPerPixel(ri->RGBFormat) + dsty * ri->BytesPerRow;
  3585. int Depth = bm->Depth;
  3586. unsigned long rows, bitoffset = srcx & 7;
  3587. long eol_offset;
  3588. bool indirect = trap_is_indirect();
  3589. /* Set up our bm->Planes[] pointers to the right horizontal offset */
  3590. for (j = 0; j < Depth; j++) {
  3591. if (indirect) {
  3592. uaecptr ap = bm->APlanes[j];
  3593. if (ap != 0 && ap != 0xffffffff)
  3594. ap += srcx / 8 + srcy * bm->BytesPerRow;
  3595. APLANAR[j] = ap;
  3596. if ((mask & (1 << j)) == 0)
  3597. APLANAR[j] = 0;
  3598. } else {
  3599. uae_u8 *p = bm->Planes[j];
  3600. if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
  3601. p += srcx / 8 + srcy * bm->BytesPerRow;
  3602. PLANAR[j] = p;
  3603. if ((mask & (1 << j)) == 0)
  3604. PLANAR[j] = &all_zeros_bitmap;
  3605. }
  3606. }
  3607. eol_offset = (long)bm->BytesPerRow - (long)((width + 7) >> 3);
  3608. for (rows = 0; rows < height; rows++, image += ri->BytesPerRow) {
  3609. unsigned long cols;
  3610. for (cols = 0; cols < width; cols += 8) {
  3611. int k;
  3612. uae_u32 a = 0, b = 0;
  3613. unsigned int msk = 0xFF;
  3614. long tmp = cols + 8 - width;
  3615. if (tmp > 0) {
  3616. msk <<= tmp;
  3617. b = do_get_mem_long ((uae_u32 *)(image + cols + 4));
  3618. if (tmp < 4)
  3619. b &= 0xFFFFFFFF >> (32 - tmp * 8);
  3620. else if (tmp > 4) {
  3621. a = do_get_mem_long ((uae_u32 *)(image + cols));
  3622. a &= 0xFFFFFFFF >> (64 - tmp * 8);
  3623. }
  3624. }
  3625. for (k = 0; k < Depth; k++) {
  3626. unsigned int data;
  3627. if (indirect) {
  3628. if (APLANAR[k] == 0)
  3629. data = 0;
  3630. else if (APLANAR[k] == 0xffffffff)
  3631. data = 0xFF;
  3632. else {
  3633. data = (uae_u8)(trap_get_word(ctx, APLANAR[k]) >> (8 - bitoffset));
  3634. APLANAR[k]++;
  3635. }
  3636. } else {
  3637. if (PLANAR[k] == &all_zeros_bitmap)
  3638. data = 0;
  3639. else if (PLANAR[k] == &all_ones_bitmap)
  3640. data = 0xFF;
  3641. else {
  3642. data = (uae_u8)(do_get_mem_word ((uae_u16 *)PLANAR[k]) >> (8 - bitoffset));
  3643. PLANAR[k]++;
  3644. }
  3645. }
  3646. data &= msk;
  3647. a |= p2ctab[data][0] << k;
  3648. b |= p2ctab[data][1] << k;
  3649. }
  3650. do_put_mem_long ((uae_u32 *)(image + cols), a);
  3651. do_put_mem_long ((uae_u32 *)(image + cols + 4), b);
  3652. }
  3653. for (j = 0; j < Depth; j++) {
  3654. if (indirect) {
  3655. if (APLANAR[j] != 0 && APLANAR[j] != 0xffffffff) {
  3656. APLANAR[j] += eol_offset;
  3657. }
  3658. } else {
  3659. if (PLANAR[j] != &all_zeros_bitmap && PLANAR[j] != &all_ones_bitmap) {
  3660. PLANAR[j] += eol_offset;
  3661. }
  3662. }
  3663. }
  3664. }
  3665. }
  3666. /*
  3667. * BlitPlanar2Chunky:
  3668. * a0: struct BoardInfo *bi
  3669. * a1: struct BitMap *bm - source containing planar information and assorted details
  3670. * a2: struct RenderInfo *ri - dest area and its details
  3671. * d0.w: SrcX
  3672. * d1.w: SrcY
  3673. * d2.w: DstX
  3674. * d3.w: DstY
  3675. * d4.w: SizeX
  3676. * d5.w: SizeY
  3677. * d6.b: MinTerm - uh oh!
  3678. * d7.b: Mask - uh oh!
  3679. *
  3680. * This function is currently used to blit from planar bitmaps within system memory to chunky bitmaps
  3681. * on the board. Watch out for plane pointers that are 0x00000000 (represents a plane with all bits "0")
  3682. * or 0xffffffff (represents a plane with all bits "1").
  3683. */
  3684. static uae_u32 REGPARAM2 picasso_BlitPlanar2Chunky (TrapContext *ctx)
  3685. {
  3686. uaecptr bm = trap_get_areg(ctx, 1);
  3687. uaecptr ri = trap_get_areg(ctx, 2);
  3688. unsigned long srcx = (uae_u16)trap_get_dreg(ctx, 0);
  3689. unsigned long srcy = (uae_u16)trap_get_dreg(ctx, 1);
  3690. unsigned long dstx = (uae_u16)trap_get_dreg(ctx, 2);
  3691. unsigned long dsty = (uae_u16)trap_get_dreg(ctx, 3);
  3692. unsigned long width = (uae_u16)trap_get_dreg(ctx, 4);
  3693. unsigned long height = (uae_u16)trap_get_dreg(ctx, 5);
  3694. uae_u8 minterm = trap_get_dreg(ctx, 6) & 0xFF;
  3695. uae_u8 mask = trap_get_dreg(ctx, 7) & 0xFF;
  3696. struct RenderInfo local_ri;
  3697. struct BitMap local_bm;
  3698. uae_u32 result = 0;
  3699. if (NOBLITTER)
  3700. return 0;
  3701. if (minterm != 0x0C) {
  3702. write_log (_T("ERROR - BlitPlanar2Chunky() has minterm 0x%x, which I don't handle. Using fall-back routine.\n"),
  3703. minterm);
  3704. } else if (CopyRenderInfoStructureA2U(ctx, ri, &local_ri) && CopyBitMapStructureA2U(ctx, bm, &local_bm)) {
  3705. P96TRACE((_T("BlitPlanar2Chunky(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n"),
  3706. srcx, srcy, dstx, dsty, width, height, minterm, mask, local_bm.Depth));
  3707. P96TRACE((_T("P2C - BitMap has %d BPR, %d rows\n"), local_bm.BytesPerRow, local_bm.Rows));
  3708. PlanarToChunky (ctx, &local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, mask);
  3709. result = 1;
  3710. }
  3711. return result;
  3712. }
  3713. /* NOTE: Watch for those planeptrs of 0x00000000 and 0xFFFFFFFF for all zero / all one bitmaps !!!! */
  3714. static void PlanarToDirect (TrapContext *ctx, struct RenderInfo *ri, struct BitMap *bm,
  3715. unsigned long srcx, unsigned long srcy,
  3716. unsigned long dstx, unsigned long dsty,
  3717. unsigned long width, unsigned long height, uae_u8 mask, uaecptr acim)
  3718. {
  3719. int j;
  3720. int bpp = GetBytesPerPixel (ri->RGBFormat);
  3721. uae_u8 *PLANAR[8];
  3722. uaecptr APLANAR[8];
  3723. uae_u8 *image = ri->Memory + dstx * bpp + dsty * ri->BytesPerRow;
  3724. int Depth = bm->Depth;
  3725. unsigned long rows;
  3726. long eol_offset;
  3727. bool indirect = trap_is_indirect();
  3728. int maxc = -1;
  3729. uae_u32 cim[256];
  3730. if(!bpp)
  3731. return;
  3732. /* Set up our bm->Planes[] pointers to the right horizontal offset */
  3733. for (j = 0; j < Depth; j++) {
  3734. if (indirect) {
  3735. uaecptr ap = bm->APlanes[j];
  3736. if (ap != 0 && ap != 0xffffffff)
  3737. ap += srcx / 8 + srcy * bm->BytesPerRow;
  3738. APLANAR[j] = ap;
  3739. if ((mask & (1 << j)) == 0)
  3740. APLANAR[j] = 0;
  3741. } else {
  3742. uae_u8 *p = bm->Planes[j];
  3743. if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
  3744. p += srcx / 8 + srcy * bm->BytesPerRow;
  3745. PLANAR[j] = p;
  3746. if ((mask & (1 << j)) == 0)
  3747. PLANAR[j] = &all_zeros_bitmap;
  3748. }
  3749. }
  3750. uae_u8 *planebuf = NULL;
  3751. int planebuf_width = (width + 1) & ~1;
  3752. if (indirect) {
  3753. planebuf = xmalloc(uae_u8, planebuf_width * Depth);
  3754. }
  3755. eol_offset = (long)bm->BytesPerRow - (long)((width + (srcx & 7)) >> 3);
  3756. for (rows = 0; rows < height; rows++, image += ri->BytesPerRow) {
  3757. unsigned long cols;
  3758. uae_u8 *image2 = image;
  3759. unsigned int bitoffs = 7 - (srcx & 7);
  3760. int i;
  3761. if (indirect) {
  3762. for (int k = 0; k < Depth; k++) {
  3763. if (APLANAR[k] != 0 && APLANAR[k] != 0xffffffff) {
  3764. PLANAR[k] = planebuf + planebuf_width *k;
  3765. trap_get_bytes(ctx, PLANAR[k], APLANAR[k], planebuf_width);
  3766. } else if (APLANAR[k] == 0) {
  3767. PLANAR[k] = &all_zeros_bitmap;
  3768. } else {
  3769. PLANAR[k] = &all_ones_bitmap;
  3770. }
  3771. }
  3772. }
  3773. for (cols = 0; cols < width; cols ++) {
  3774. int v = 0, k;
  3775. for (k = 0; k < Depth; k++) {
  3776. if (PLANAR[k] == &all_ones_bitmap)
  3777. v |= 1 << k;
  3778. else if (PLANAR[k] != &all_zeros_bitmap) {
  3779. v |= ((*PLANAR[k] >> bitoffs) & 1) << k;
  3780. }
  3781. }
  3782. // most operations use only low palette values
  3783. // do not fetch and convert whole palette unless needed
  3784. if (v > maxc) {
  3785. int vc = v;
  3786. if (vc < 3)
  3787. vc = 3;
  3788. else if (vc < 7)
  3789. vc = 7;
  3790. else if (vc < 15)
  3791. vc = 15;
  3792. else if (vc < 31)
  3793. vc = 32;
  3794. else if (vc < 63)
  3795. vc = 63;
  3796. else
  3797. vc = 255;
  3798. trap_get_longs(ctx, &cim[maxc + 1], acim + 4 + (maxc + 1) * 4, vc - maxc);
  3799. for (int i = maxc + 1; i <= vc; i++) {
  3800. endianswap(&cim[i], bpp);
  3801. }
  3802. maxc = vc;
  3803. }
  3804. switch (bpp)
  3805. {
  3806. case 2:
  3807. ((uae_u16 *)image2)[0] = (uae_u16)(cim[v]);
  3808. image2 += 2;
  3809. break;
  3810. case 3:
  3811. image2[0] = cim[v] >> 0;
  3812. image2[1] = cim[v] >> 8;
  3813. image2[2] = cim[v] >> 16;
  3814. image2 += 3;
  3815. break;
  3816. case 4:
  3817. ((uae_u32 *)image2)[0] = cim[v];
  3818. image2 += 4;
  3819. break;
  3820. }
  3821. bitoffs--;
  3822. bitoffs &= 7;
  3823. if (bitoffs == 7) {
  3824. int k;
  3825. for (k = 0; k < Depth; k++) {
  3826. if (PLANAR[k] != &all_zeros_bitmap && PLANAR[k] != &all_ones_bitmap) {
  3827. PLANAR[k]++;
  3828. if (indirect)
  3829. APLANAR[k]++;
  3830. }
  3831. }
  3832. }
  3833. }
  3834. for (i = 0; i < Depth; i++) {
  3835. if (PLANAR[i] != &all_zeros_bitmap && PLANAR[i] != &all_ones_bitmap) {
  3836. PLANAR[i] += eol_offset;
  3837. if (indirect)
  3838. APLANAR[i] += eol_offset;
  3839. }
  3840. }
  3841. }
  3842. if (planebuf)
  3843. xfree(planebuf);
  3844. }
  3845. /*
  3846. * BlitPlanar2Direct:
  3847. *
  3848. * Synopsis:
  3849. * BlitPlanar2Direct(bi, bm, ri, cim, SrcX, SrcY, DstX, DstY, SizeX, SizeY, MinTerm, Mask);
  3850. * Inputs:
  3851. * a0:struct BoardInfo *bi
  3852. * a1:struct BitMap *bm
  3853. * a2:struct RenderInfo *ri
  3854. * a3:struct ColorIndexMapping *cmi
  3855. * d0.w:SrcX
  3856. * d1.w:SrcY
  3857. * d2.w:DstX
  3858. * d3.w:DstY
  3859. * d4.w:SizeX
  3860. * d5.w:SizeY
  3861. * d6.b:MinTerm
  3862. * d7.b:Mask
  3863. *
  3864. * This function is currently used to blit from planar bitmaps within system memory to direct color
  3865. * bitmaps (15, 16, 24 or 32 bit) on the board. Watch out for plane pointers that are 0x00000000 (represents
  3866. * a plane with all bits "0") or 0xffffffff (represents a plane with all bits "1"). The ColorIndexMapping is
  3867. * used to map the color index of each pixel formed by the bits in the bitmap's planes to a direct color value
  3868. * which is written to the destination RenderInfo. The color mask and all colors within the mapping are words,
  3869. * triple bytes or longwords respectively similar to the color values used in FillRect(), BlitPattern() or
  3870. * BlitTemplate().
  3871. */
  3872. static uae_u32 REGPARAM2 picasso_BlitPlanar2Direct (TrapContext *ctx)
  3873. {
  3874. uaecptr bm = trap_get_areg(ctx, 1);
  3875. uaecptr ri = trap_get_areg(ctx, 2);
  3876. uaecptr cim = trap_get_areg(ctx, 3);
  3877. unsigned long srcx = (uae_u16)trap_get_dreg(ctx, 0);
  3878. unsigned long srcy = (uae_u16)trap_get_dreg(ctx, 1);
  3879. unsigned long dstx = (uae_u16)trap_get_dreg(ctx, 2);
  3880. unsigned long dsty = (uae_u16)trap_get_dreg(ctx, 3);
  3881. unsigned long width = (uae_u16)trap_get_dreg(ctx, 4);
  3882. unsigned long height = (uae_u16)trap_get_dreg(ctx, 5);
  3883. uae_u8 minterm = trap_get_dreg(ctx, 6);
  3884. uae_u8 Mask = trap_get_dreg(ctx, 7);
  3885. struct RenderInfo local_ri;
  3886. struct BitMap local_bm;
  3887. uae_u32 result = 0;
  3888. if (NOBLITTER)
  3889. return 0;
  3890. if (minterm != 0x0C) {
  3891. write_log (_T("WARNING - BlitPlanar2Direct() has unhandled op-code 0x%x. Using fall-back routine.\n"), minterm);
  3892. return 0;
  3893. }
  3894. if (CopyRenderInfoStructureA2U(ctx, ri, &local_ri) && CopyBitMapStructureA2U(ctx, bm, &local_bm)) {
  3895. Mask = 0xFF;
  3896. P96TRACE((_T("BlitPlanar2Direct(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n"),
  3897. srcx, srcy, dstx, dsty, width, height, minterm, Mask, local_bm.Depth));
  3898. PlanarToDirect(ctx, &local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, Mask, cim);
  3899. result = 1;
  3900. }
  3901. return result;
  3902. }
  3903. #include "statusline.h"
  3904. void picasso_statusline(int monid, uae_u8 *dst)
  3905. {
  3906. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  3907. struct picasso96_state_struct *state = &picasso96_state[monid];
  3908. int y, slx, sly;
  3909. int dst_height, dst_width, pitch;
  3910. dst_height = state->Height;
  3911. if (dst_height > vidinfo->height)
  3912. dst_height = vidinfo->height;
  3913. dst_width = state->Width;
  3914. if (dst_width > vidinfo->width)
  3915. dst_width = vidinfo->width;
  3916. pitch = vidinfo->rowbytes;
  3917. statusline_getpos(monid, &slx, &sly, state->Width, dst_height);
  3918. if (currprefs.gfx_api) {
  3919. statusline_render(monid, dst + sly * pitch, vidinfo->pixbytes, pitch, dst_width, dst_height, p96rc, p96gc, p96bc, NULL);
  3920. }
  3921. int m = statusline_get_multiplier(monid) / 100;
  3922. for (y = 0; y < TD_TOTAL_HEIGHT * m; y++) {
  3923. uae_u8 *buf = dst + (y + sly) * pitch;
  3924. draw_status_line_single(monid, buf, vidinfo->pixbytes, y, dst_width, p96rc, p96gc, p96bc, NULL);
  3925. }
  3926. }
  3927. static void copyrow (int monid, uae_u8 *src, uae_u8 *dst, int x, int y, int width, int srcbytesperrow, int srcpixbytes, int dx, int dy, int dstbytesperrow, int dstpixbytes, bool direct, int convert_mode, uae_u32 *p96_rgbx16p)
  3928. {
  3929. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  3930. struct picasso96_state_struct *state = &picasso96_state[monid];
  3931. int endx = x + width, endx4;
  3932. int dstpix = dstpixbytes;
  3933. int srcpix = srcpixbytes;
  3934. uae_u32 *clut = vidinfo->clut;
  3935. if (y >= vidinfo->splitypos && vidinfo->splitypos >= 0) {
  3936. src = gfxmem_banks[monid]->start + natmem_offset;
  3937. if (state->dualclut) {
  3938. clut += 256;
  3939. }
  3940. y -= vidinfo->splitypos;
  3941. }
  3942. uae_u8 *src2 = src + y * srcbytesperrow;
  3943. uae_u8 *dst2 = dst + dy * dstbytesperrow;
  3944. if (direct) {
  3945. memcpy (dst2 + x * dstpix, src2 + x * srcpix, width * dstpix);
  3946. return;
  3947. }
  3948. // native match?
  3949. if (currprefs.gfx_api) {
  3950. switch (convert_mode)
  3951. {
  3952. #ifdef WORDS_BIGENDIAN
  3953. case RGBFB_A8R8G8B8_32:
  3954. case RGBFB_R5G6B5_16:
  3955. #else
  3956. case RGBFB_B8G8R8A8_32:
  3957. case RGBFB_R5G6B5PC_16:
  3958. #endif
  3959. memcpy (dst2 + dx * dstpix, src2 + x * srcpix, width * dstpix);
  3960. return;
  3961. }
  3962. } else {
  3963. switch (convert_mode)
  3964. {
  3965. #ifdef WORDS_BIGENDIAN
  3966. case RGBFB_A8R8G8B8_32:
  3967. case RGBFB_R5G6B5_16:
  3968. #else
  3969. case RGBFB_B8G8R8A8_32:
  3970. case RGBFB_R5G6B5PC_16:
  3971. #endif
  3972. memcpy (dst2 + dx * dstpix, src2 + x * srcpix, width * dstpix);
  3973. return;
  3974. }
  3975. }
  3976. endx4 = endx & ~3;
  3977. switch (convert_mode)
  3978. {
  3979. /* 24bit->32bit */
  3980. case RGBFB_R8G8B8_32:
  3981. while (x < endx) {
  3982. ((uae_u32*)dst2)[dx] = (src2[x * 3 + 0] << 16) | (src2[x * 3 + 1] << 8) | (src2[x * 3 + 2] << 0);
  3983. x++;
  3984. dx++;
  3985. }
  3986. break;
  3987. case RGBFB_B8G8R8_32:
  3988. while (x < endx) {
  3989. ((uae_u32*)dst2)[dx] = ((uae_u32*)(src2 + x * 3))[0] & 0x00ffffff;
  3990. x++;
  3991. dx++;
  3992. }
  3993. break;
  3994. /* 32bit->32bit */
  3995. case RGBFB_R8G8B8A8_32:
  3996. while (x < endx) {
  3997. ((uae_u32*)dst2)[dx] = (src2[x * 4 + 0] << 16) | (src2[x * 4 + 1] << 8) | (src2[x * 4 + 2] << 0);
  3998. x++;
  3999. dx++;
  4000. }
  4001. break;
  4002. case RGBFB_A8R8G8B8_32:
  4003. while (x < endx) {
  4004. ((uae_u32*)dst2)[dx] = (src2[x * 4 + 1] << 16) | (src2[x * 4 + 2] << 8) | (src2[x * 4 + 3] << 0);
  4005. x++;
  4006. dx++;
  4007. }
  4008. break;
  4009. case RGBFB_A8B8G8R8_32:
  4010. while (x < endx) {
  4011. ((uae_u32*)dst2)[dx] = ((uae_u32*)src2)[x] >> 8;
  4012. x++;
  4013. dx++;
  4014. }
  4015. break;
  4016. /* 15/16bit->32bit */
  4017. case RGBFB_R5G6B5PC_32:
  4018. case RGBFB_R5G5B5PC_32:
  4019. case RGBFB_R5G6B5_32:
  4020. case RGBFB_R5G5B5_32:
  4021. case RGBFB_B5G6R5PC_32:
  4022. case RGBFB_B5G5R5PC_32:
  4023. {
  4024. while ((x & 3) && x < endx) {
  4025. ((uae_u32*)dst2)[dx] = p96_rgbx16p[((uae_u16*)src2)[x]];
  4026. x++;
  4027. dx++;
  4028. }
  4029. while (x < endx4) {
  4030. ((uae_u32*)dst2)[dx] = p96_rgbx16p[((uae_u16*)src2)[x]];
  4031. x++;
  4032. dx++;
  4033. ((uae_u32*)dst2)[dx] = p96_rgbx16p[((uae_u16*)src2)[x]];
  4034. x++;
  4035. dx++;
  4036. ((uae_u32*)dst2)[dx] = p96_rgbx16p[((uae_u16*)src2)[x]];
  4037. x++;
  4038. dx++;
  4039. ((uae_u32*)dst2)[dx] = p96_rgbx16p[((uae_u16*)src2)[x]];
  4040. x++;
  4041. dx++;
  4042. }
  4043. while (x < endx) {
  4044. ((uae_u32*)dst2)[dx] = p96_rgbx16p[((uae_u16*)src2)[x]];
  4045. x++;
  4046. dx++;
  4047. }
  4048. }
  4049. break;
  4050. /* 16/15bit->16bit */
  4051. case RGBFB_R5G5B5PC_16:
  4052. case RGBFB_R5G6B5_16:
  4053. case RGBFB_R5G5B5_16:
  4054. case RGBFB_B5G5R5PC_16:
  4055. case RGBFB_B5G6R5PC_16:
  4056. case RGBFB_R5G6B5PC_16:
  4057. {
  4058. while ((x & 3) && x < endx) {
  4059. ((uae_u16*)dst2)[dx] = (uae_u16)p96_rgbx16p[((uae_u16*)src2)[x]];
  4060. x++;
  4061. dx++;
  4062. }
  4063. while (x < endx4) {
  4064. ((uae_u16*)dst2)[dx] = (uae_u16)p96_rgbx16p[((uae_u16*)src2)[x]];
  4065. x++;
  4066. dx++;
  4067. ((uae_u16*)dst2)[dx] = (uae_u16)p96_rgbx16p[((uae_u16*)src2)[x]];
  4068. x++;
  4069. dx++;
  4070. ((uae_u16*)dst2)[dx] = (uae_u16)p96_rgbx16p[((uae_u16*)src2)[x]];
  4071. x++;
  4072. dx++;
  4073. ((uae_u16*)dst2)[dx] = (uae_u16)p96_rgbx16p[((uae_u16*)src2)[x]];
  4074. x++;
  4075. dx++;
  4076. }
  4077. while (x < endx) {
  4078. ((uae_u16*)dst2)[dx] = (uae_u16)p96_rgbx16p[((uae_u16*)src2)[x]];
  4079. x++;
  4080. dx++;
  4081. }
  4082. }
  4083. break;
  4084. /* 24bit->16bit */
  4085. case RGBFB_R8G8B8_16:
  4086. while (x < endx) {
  4087. uae_u8 r, g, b;
  4088. r = src2[x * 3 + 0];
  4089. g = src2[x * 3 + 1];
  4090. b = src2[x * 3 + 2];
  4091. ((uae_u16*)dst2)[dx] = p96_rgbx16p[(((r >> 3) & 0x1f) << 11) | (((g >> 2) & 0x3f) << 5) | (((b >> 3) & 0x1f) << 0)];
  4092. x++;
  4093. dx++;
  4094. }
  4095. break;
  4096. case RGBFB_B8G8R8_16:
  4097. while (x < endx) {
  4098. uae_u32 v;
  4099. v = ((uae_u32*)(&src2[x * 3]))[0] >> 8;
  4100. ((uae_u16*)dst2)[dx] = p96_rgbx16p[(((v >> (8 + 3)) & 0x1f) << 11) | (((v >> (0 + 2)) & 0x3f) << 5) | (((v >> (16 + 3)) & 0x1f) << 0)];
  4101. x++;
  4102. dx++;
  4103. }
  4104. break;
  4105. /* 32bit->16bit */
  4106. case RGBFB_R8G8B8A8_16:
  4107. while (x < endx) {
  4108. uae_u32 v;
  4109. v = ((uae_u32*)src2)[x];
  4110. ((uae_u16*)dst2)[dx] = p96_rgbx16p[(((v >> (0 + 3)) & 0x1f) << 11) | (((v >> (8 + 2)) & 0x3f) << 5) | (((v >> (16 + 3)) & 0x1f) << 0)];
  4111. x++;
  4112. dx++;
  4113. }
  4114. break;
  4115. case RGBFB_A8R8G8B8_16:
  4116. while (x < endx) {
  4117. uae_u32 v;
  4118. v = ((uae_u32*)src2)[x];
  4119. ((uae_u16*)dst2)[dx] = p96_rgbx16p[(((v >> (8 + 3)) & 0x1f) << 11) | (((v >> (16 + 2)) & 0x3f) << 5) | (((v >> (24 + 3)) & 0x1f) << 0)];
  4120. x++;
  4121. dx++;
  4122. }
  4123. break;
  4124. case RGBFB_A8B8G8R8_16:
  4125. while (x < endx) {
  4126. uae_u32 v;
  4127. v = ((uae_u32*)src2)[x];
  4128. ((uae_u16*)dst2)[dx] = p96_rgbx16p[(((v >> (24 + 3)) & 0x1f) << 11) | (((v >> (16 + 2)) & 0x3f) << 5) | (((v >> (8 + 3)) & 0x1f) << 0)];
  4129. x++;
  4130. dx++;
  4131. }
  4132. break;
  4133. case RGBFB_B8G8R8A8_16:
  4134. while (x < endx) {
  4135. uae_u32 v;
  4136. v = ((uae_u32*)src2)[x];
  4137. ((uae_u16*)dst2)[dx] = p96_rgbx16p[(((v >> (16 + 3)) & 0x1f) << 11) | (((v >> (8 + 2)) & 0x3f) << 5) | (((v >> (0 + 3)) & 0x1f) << 0)];
  4138. x++;
  4139. dx++;
  4140. }
  4141. break;
  4142. /* 8bit->32bit */
  4143. case RGBFB_CLUT_RGBFB_32:
  4144. {
  4145. while ((x & 3) && x < endx) {
  4146. ((uae_u32*)dst2)[dx] = clut[src2[x]];
  4147. x++;
  4148. dx++;
  4149. }
  4150. while (x < endx4) {
  4151. ((uae_u32*)dst2)[dx] = clut[src2[x]];
  4152. x++;
  4153. dx++;
  4154. ((uae_u32*)dst2)[dx] = clut[src2[x]];
  4155. x++;
  4156. dx++;
  4157. ((uae_u32*)dst2)[dx] = clut[src2[x]];
  4158. x++;
  4159. dx++;
  4160. ((uae_u32*)dst2)[dx] = clut[src2[x]];
  4161. x++;
  4162. dx++;
  4163. }
  4164. while (x < endx) {
  4165. ((uae_u32*)dst2)[dx] = clut[src2[x]];
  4166. x++;
  4167. dx++;
  4168. }
  4169. }
  4170. break;
  4171. /* 8bit->16bit */
  4172. case RGBFB_CLUT_RGBFB_16:
  4173. {
  4174. while ((x & 3) && x < endx) {
  4175. ((uae_u16*)dst2)[dx] = clut[src2[x]];
  4176. x++;
  4177. dx++;
  4178. }
  4179. while (x < endx4) {
  4180. ((uae_u16*)dst2)[dx] = clut[src2[x]];
  4181. x++;
  4182. dx++;
  4183. ((uae_u16*)dst2)[dx] = clut[src2[x]];
  4184. x++;
  4185. dx++;
  4186. ((uae_u16*)dst2)[dx] = clut[src2[x]];
  4187. x++;
  4188. dx++;
  4189. ((uae_u16*)dst2)[dx] = clut[src2[x]];
  4190. x++;
  4191. dx++;
  4192. }
  4193. while (x < endx) {
  4194. ((uae_u16*)dst2)[dx] = clut[src2[x]];
  4195. x++;
  4196. dx++;
  4197. }
  4198. }
  4199. break;
  4200. }
  4201. }
  4202. static uae_u16 yuvtorgb(uae_u8 yx, uae_u8 ux, uae_u8 vx)
  4203. {
  4204. int y = yx - 16;
  4205. int u = ux - 128;
  4206. int v = vx - 128;
  4207. int r = (298 * y + 409 * v + 128) >> (8 + 3);
  4208. int g = (298 * y - 100 * u - 208 * v + 128) >> (8 + 3);
  4209. int b = (298 * y + 516 * u + 128) >> (8 + 3);
  4210. if (r < 0)
  4211. r = 0;
  4212. if (r > 31)
  4213. r = 31;
  4214. if (g < 0)
  4215. g = 0;
  4216. if (g > 31)
  4217. g = 31;
  4218. if (b < 0)
  4219. b = 0;
  4220. if (b > 31)
  4221. b = 31;
  4222. return (r << 10) | (g << 5) | b;
  4223. }
  4224. #define CKCHECK if (!ck \
  4225. || (screenpixbytes == 4 && colorkey == ((uae_u32*)srcs)[dx]) \
  4226. || (screenpixbytes == 2 && (uae_u16)colorkey == ((uae_u16*)srcs)[dx]) \
  4227. || (screenpixbytes == 1 && (uae_u8)colorkey == ((uae_u8*)srcs)[dx]) \
  4228. || (screenpixbytes == 3 && ckbytes[0] == srcs[dx * 3 + 0] && ckbytes[1] == srcs[dx * 3 + 1] && ckbytes[2] == srcs[dx * 3 + 2]))
  4229. void copyrow_scale(int monid, uae_u8 *src, uae_u8 *src_screen, uae_u8 *dst,
  4230. int sx, int sy, int sxadd, int width, int srcbytesperrow, int srcpixbytes,
  4231. int screenbytesperrow, int screenpixbytes,
  4232. int dx, int dy, int dstwidth, int dstheight, int dstbytesperrow, int dstpixbytes,
  4233. bool ck, uae_u32 colorkey,
  4234. int convert_mode, uae_u32 *p96_rgbx16p, uae_u32 *clut, bool yuv_swap)
  4235. {
  4236. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  4237. uae_u8 *src2 = src + sy * srcbytesperrow;
  4238. uae_u8 *dst2 = dst + dy * dstbytesperrow;
  4239. uae_u8 *srcs = src_screen + dy * screenbytesperrow;
  4240. int endx, endx4;
  4241. int dstpix = dstpixbytes;
  4242. int srcpix = srcpixbytes;
  4243. int x;
  4244. uae_u8 ckbytes[3];
  4245. if (dx < 0 || dx >= dstwidth)
  4246. return;
  4247. if (dy < 0 || dy >= dstheight)
  4248. return;
  4249. if (dx + (width * 256) / sxadd > dstwidth) {
  4250. width = ((dstwidth - dx) * sxadd) / 256;
  4251. if (width <= 0)
  4252. return;
  4253. }
  4254. endx = (sx + width) << 8;
  4255. switch (convert_mode)
  4256. {
  4257. case RGBFB_Y4U2V2_32:
  4258. case RGBFB_Y4U2V2_16:
  4259. endx /= 2;
  4260. sxadd /= 2;
  4261. break;
  4262. case RGBFB_Y4U1V1_32:
  4263. case RGBFB_Y4U1V1_16:
  4264. endx /= 4;
  4265. sxadd /= 4;
  4266. break;
  4267. }
  4268. endx4 = endx & ~(3 << 8);
  4269. ckbytes[0] = colorkey >> 16;
  4270. ckbytes[1] = colorkey >> 8;
  4271. ckbytes[2] = colorkey >> 0;
  4272. switch (convert_mode)
  4273. {
  4274. /* 24bit->32bit */
  4275. case RGBFB_R8G8B8_32:
  4276. while (sx < endx) {
  4277. x = sx >> 8;
  4278. sx += sxadd;
  4279. CKCHECK
  4280. ((uae_u32*)dst2)[dx] = (src2[x * 3 + 0] << 16) | (src2[x * 3 + 1] << 8) | (src2[x * 3 + 2] << 0);
  4281. dx++;
  4282. }
  4283. break;
  4284. case RGBFB_B8G8R8_32:
  4285. while (sx < endx) {
  4286. x = sx >> 8;
  4287. sx += sxadd;
  4288. CKCHECK
  4289. ((uae_u32*)dst2)[dx] = ((uae_u32*)(src2 + x * 3))[0] & 0x00ffffff;
  4290. dx++;
  4291. }
  4292. break;
  4293. /* 32bit->32bit */
  4294. case RGBFB_R8G8B8A8_32:
  4295. while (sx < endx) {
  4296. x = sx >> 8;
  4297. sx += sxadd;
  4298. CKCHECK
  4299. ((uae_u32*)dst2)[dx] = (src2[x * 4 + 0] << 16) | (src2[x * 4 + 1] << 8) | (src2[x * 4 + 2] << 0);
  4300. dx++;
  4301. }
  4302. break;
  4303. case RGBFB_A8R8G8B8_32:
  4304. while (sx < endx) {
  4305. x = sx >> 8;
  4306. sx += sxadd;
  4307. CKCHECK
  4308. ((uae_u32*)dst2)[dx] = (src2[x * 4 + 1] << 16) | (src2[x * 4 + 2] << 8) | (src2[x * 4 + 3] << 0);
  4309. dx++;
  4310. }
  4311. break;
  4312. case RGBFB_A8B8G8R8_32:
  4313. while (sx < endx) {
  4314. x = sx >> 8;
  4315. sx += sxadd;
  4316. CKCHECK
  4317. ((uae_u32*)dst2)[dx] = ((uae_u32*)src2)[x] >> 8;
  4318. dx++;
  4319. }
  4320. break;
  4321. /* 15/16bit->32bit */
  4322. case RGBFB_R5G6B5PC_32:
  4323. case RGBFB_R5G5B5PC_32:
  4324. case RGBFB_R5G6B5_32:
  4325. case RGBFB_R5G5B5_32:
  4326. case RGBFB_B5G6R5PC_32:
  4327. case RGBFB_B5G5R5PC_32:
  4328. {
  4329. while ((sx & (3 << 8)) && sx < endx) {
  4330. x = sx >> 8;
  4331. sx += sxadd;
  4332. CKCHECK
  4333. ((uae_u32*)dst2)[dx] = p96_rgbx16p[((uae_u16*)src2)[x]];
  4334. dx++;
  4335. }
  4336. while (sx < endx4) {
  4337. x = sx >> 8;
  4338. sx += sxadd;
  4339. CKCHECK
  4340. ((uae_u32*)dst2)[dx] = p96_rgbx16p[((uae_u16*)src2)[x]];
  4341. dx++;
  4342. x = sx >> 8;
  4343. sx += sxadd;
  4344. CKCHECK
  4345. ((uae_u32*)dst2)[dx] = p96_rgbx16p[((uae_u16*)src2)[x]];
  4346. dx++;
  4347. x = sx >> 8;
  4348. sx += sxadd;
  4349. CKCHECK
  4350. ((uae_u32*)dst2)[dx] = p96_rgbx16p[((uae_u16*)src2)[x]];
  4351. dx++;
  4352. x = sx >> 8;
  4353. sx += sxadd;
  4354. CKCHECK
  4355. ((uae_u32*)dst2)[dx] = p96_rgbx16p[((uae_u16*)src2)[x]];
  4356. dx++;
  4357. }
  4358. while (sx < endx) {
  4359. x = sx >> 8;
  4360. sx += sxadd;
  4361. CKCHECK
  4362. ((uae_u32*)dst2)[dx] = p96_rgbx16p[((uae_u16*)src2)[x]];
  4363. dx++;
  4364. }
  4365. }
  4366. break;
  4367. case RGBFB_Y4U2V2_32:
  4368. {
  4369. uae_u32 outval1, outval2;
  4370. uae_u8 y0, y1, u, v;
  4371. bool docalc1 = false;
  4372. bool docalc2 = false;
  4373. int oldsx = -1;
  4374. uae_u32 val = ((uae_u32*)src2)[sx >> 8];
  4375. uae_u32 oldval = val ^ 1;
  4376. while (sx < endx) {
  4377. x = sx >> 8;
  4378. if (oldsx != x) {
  4379. uae_u32 val = ((uae_u32*)src2)[x];
  4380. if (val != oldval) {
  4381. oldval = val;
  4382. if (yuv_swap)
  4383. val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
  4384. y0 = val >> 8;
  4385. y1 = val >> 24;
  4386. u = val >> 0;
  4387. v = val >> 16;
  4388. if (y0 == y1) {
  4389. uae_u16 out = yuvtorgb(y0, u, v);
  4390. outval1 = p96_rgbx16p[out];
  4391. outval2 = outval1;
  4392. } else {
  4393. docalc1 = true;
  4394. docalc2 = true;
  4395. }
  4396. }
  4397. oldsx = x;
  4398. }
  4399. if ((sx & 255) < 128) {
  4400. CKCHECK
  4401. {
  4402. if (docalc1) {
  4403. uae_u16 out = yuvtorgb(y0, u, v);
  4404. outval1 = p96_rgbx16p[out];
  4405. docalc1 = false;
  4406. }
  4407. ((uae_u32*)dst2)[dx] = outval1;
  4408. }
  4409. } else {
  4410. CKCHECK
  4411. {
  4412. if (docalc2) {
  4413. uae_u16 out = yuvtorgb(y1, u, v);
  4414. outval2 = p96_rgbx16p[out];
  4415. docalc2 = false;
  4416. }
  4417. ((uae_u32*)dst2)[dx] = outval2;
  4418. }
  4419. }
  4420. sx += sxadd;
  4421. dx++;
  4422. }
  4423. }
  4424. break;
  4425. case RGBFB_Y4U1V1_32:
  4426. {
  4427. while (sx < endx) {
  4428. x = sx >> 8;
  4429. uae_u32 val = ((uae_u32*)src2)[x];
  4430. uae_u8 y0 = ((val >> 12) & 31) * 8;
  4431. uae_u8 y1 = ((val >> 17) & 31) * 8;
  4432. uae_u8 y2 = ((val >> 22) & 31) * 8;
  4433. uae_u8 y3 = ((val >> 27) & 31) * 8;
  4434. uae_s8 u = ((val >> 0) & 63) * 4;
  4435. uae_s8 v = ((val >> 6) & 63) * 4;
  4436. int fr = sx & 255;
  4437. if (fr >= 192) {
  4438. CKCHECK
  4439. {
  4440. uae_u16 out = yuvtorgb(y3, u, v);
  4441. ((uae_u32*)dst2)[dx] = p96_rgbx16p[out];
  4442. }
  4443. } else if (fr >= 128) {
  4444. CKCHECK
  4445. {
  4446. uae_u16 out = yuvtorgb(y2, u, v);
  4447. ((uae_u32*)dst2)[dx] = p96_rgbx16p[out];
  4448. }
  4449. } else if (fr >= 64) {
  4450. CKCHECK
  4451. {
  4452. uae_u16 out = yuvtorgb(y1, u, v);
  4453. ((uae_u32*)dst2)[dx] = p96_rgbx16p[out];
  4454. }
  4455. } else {
  4456. CKCHECK
  4457. {
  4458. uae_u16 out = yuvtorgb(y0, u, v);
  4459. ((uae_u32*)dst2)[dx] = p96_rgbx16p[out];
  4460. }
  4461. }
  4462. sx += sxadd;
  4463. dx++;
  4464. }
  4465. }
  4466. break;
  4467. /* 16/15bit->16bit */
  4468. case RGBFB_R5G5B5PC_16:
  4469. case RGBFB_R5G6B5_16:
  4470. case RGBFB_R5G5B5_16:
  4471. case RGBFB_B5G5R5PC_16:
  4472. case RGBFB_B5G6R5PC_16:
  4473. case RGBFB_R5G6B5PC_16:
  4474. {
  4475. while ((sx & (3 << 8)) && sx < endx) {
  4476. x = sx >> 8;
  4477. sx += sxadd;
  4478. CKCHECK
  4479. ((uae_u16*)dst2)[dx] = (uae_u16)p96_rgbx16p[((uae_u16*)src2)[x]];
  4480. dx++;
  4481. }
  4482. while (sx < endx4) {
  4483. x = sx >> 8;
  4484. sx += sxadd;
  4485. CKCHECK
  4486. ((uae_u16*)dst2)[dx] = (uae_u16)p96_rgbx16p[((uae_u16*)src2)[x]];
  4487. dx++;
  4488. x = sx >> 8;
  4489. sx += sxadd;
  4490. CKCHECK
  4491. ((uae_u16*)dst2)[dx] = (uae_u16)p96_rgbx16p[((uae_u16*)src2)[x]];
  4492. dx++;
  4493. x = sx >> 8;
  4494. sx += sxadd;
  4495. CKCHECK
  4496. ((uae_u16*)dst2)[dx] = (uae_u16)p96_rgbx16p[((uae_u16*)src2)[x]];
  4497. dx++;
  4498. x = sx >> 8;
  4499. sx += sxadd;
  4500. CKCHECK
  4501. ((uae_u16*)dst2)[dx] = (uae_u16)p96_rgbx16p[((uae_u16*)src2)[x]];
  4502. dx++;
  4503. }
  4504. while (sx < endx) {
  4505. x = sx >> 8;
  4506. sx += sxadd;
  4507. CKCHECK
  4508. ((uae_u16*)dst2)[dx] = (uae_u16)p96_rgbx16p[((uae_u16*)src2)[x]];
  4509. dx++;
  4510. }
  4511. }
  4512. break;
  4513. /* 8bit->16bit */
  4514. case RGBFB_CLUT_RGBFB_16:
  4515. {
  4516. while ((sx & (3 << 8)) && sx < endx) {
  4517. x = sx >> 8;
  4518. sx += sxadd;
  4519. CKCHECK
  4520. ((uae_u16*)dst2)[dx] = clut[src2[x]];
  4521. dx++;
  4522. }
  4523. while (sx < endx4) {
  4524. x = sx >> 8;
  4525. sx += sxadd;
  4526. CKCHECK
  4527. ((uae_u16*)dst2)[dx] = clut[src2[x]];
  4528. dx++;
  4529. x = sx >> 8;
  4530. sx += sxadd;
  4531. CKCHECK
  4532. ((uae_u16*)dst2)[dx] = clut[src2[x]];
  4533. dx++;
  4534. x = sx >> 8;
  4535. sx += sxadd;
  4536. CKCHECK
  4537. ((uae_u16*)dst2)[dx] = clut[src2[x]];
  4538. dx++;
  4539. x = sx >> 8;
  4540. sx += sxadd;
  4541. CKCHECK
  4542. ((uae_u16*)dst2)[dx] = clut[src2[x]];
  4543. dx++;
  4544. }
  4545. while (sx < endx) {
  4546. x = sx >> 8;
  4547. sx += sxadd;
  4548. CKCHECK
  4549. ((uae_u16*)dst2)[dx] = clut[src2[x]];
  4550. dx++;
  4551. }
  4552. }
  4553. break;
  4554. /* 8bit->32bit */
  4555. case RGBFB_CLUT_RGBFB_32:
  4556. {
  4557. while ((sx & (3 << 8)) && sx < endx) {
  4558. x = sx >> 8;
  4559. sx += sxadd;
  4560. CKCHECK
  4561. ((uae_u32*)dst2)[dx] = clut[src2[x]];
  4562. dx++;
  4563. }
  4564. while (sx < endx4) {
  4565. x = sx >> 8;
  4566. sx += sxadd;
  4567. CKCHECK
  4568. ((uae_u32*)dst2)[dx] = clut[src2[x]];
  4569. dx++;
  4570. x = sx >> 8;
  4571. sx += sxadd;
  4572. CKCHECK
  4573. ((uae_u32*)dst2)[dx] = clut[src2[x]];
  4574. dx++;
  4575. x = sx >> 8;
  4576. sx += sxadd;
  4577. CKCHECK
  4578. ((uae_u32*)dst2)[dx] = clut[src2[x]];
  4579. dx++;
  4580. x = sx >> 8;
  4581. sx += sxadd;
  4582. CKCHECK
  4583. ((uae_u32*)dst2)[dx] = clut[src2[x]];
  4584. dx++;
  4585. }
  4586. while (sx < endx) {
  4587. x = sx >> 8;
  4588. sx += sxadd;
  4589. CKCHECK
  4590. ((uae_u32*)dst2)[dx] = clut[src2[x]];
  4591. dx++;
  4592. }
  4593. }
  4594. break;
  4595. case RGBFB_Y4U2V2_16:
  4596. {
  4597. uae_u16 outval1, outval2;
  4598. uae_u8 y0, y1, u, v;
  4599. bool docalc1 = false;
  4600. bool docalc2 = false;
  4601. int oldsx = -1;
  4602. uae_u32 val = ((uae_u32*)src2)[sx >> 8];
  4603. uae_u32 oldval = val ^ 1;
  4604. while (sx < endx) {
  4605. x = sx >> 8;
  4606. if (x != oldsx) {
  4607. val = ((uae_u32*)src2)[x];
  4608. if (val != oldval) {
  4609. oldval = val;
  4610. if (yuv_swap)
  4611. val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
  4612. y0 = val >> 8;
  4613. y1 = val >> 24;
  4614. u = val >> 0;
  4615. v = val >> 16;
  4616. if (y0 == y1) {
  4617. uae_u16 out = yuvtorgb(y0, u, v);
  4618. outval1 = p96_rgbx16p[out];
  4619. outval2 = outval1;
  4620. } else {
  4621. docalc1 = true;
  4622. docalc2 = true;
  4623. }
  4624. }
  4625. oldsx = x;
  4626. }
  4627. if ((sx & 255) < 128) {
  4628. CKCHECK
  4629. {
  4630. if (docalc1) {
  4631. uae_u16 out = yuvtorgb(y0, u, v);
  4632. outval1 = p96_rgbx16p[out];
  4633. docalc1 = false;
  4634. }
  4635. ((uae_u16*)dst2)[dx] = outval1;
  4636. }
  4637. CKCHECK
  4638. {
  4639. if (docalc2) {
  4640. uae_u16 out = yuvtorgb(y1, u, v);
  4641. outval2 = p96_rgbx16p[out];
  4642. docalc2 = false;
  4643. }
  4644. ((uae_u16*)dst2)[dx] = outval2;
  4645. }
  4646. }
  4647. sx += sxadd;
  4648. dx++;
  4649. }
  4650. }
  4651. break;
  4652. case RGBFB_Y4U1V1_16:
  4653. {
  4654. while (sx < endx) {
  4655. x = sx >> 8;
  4656. uae_u32 val = ((uae_u32*)src2)[x];
  4657. uae_u8 y0 = ((val >> 12) & 31) * 8;
  4658. uae_u8 y1 = ((val >> 17) & 31) * 8;
  4659. uae_u8 y2 = ((val >> 22) & 31) * 8;
  4660. uae_u8 y3 = ((val >> 27) & 31) * 8;
  4661. uae_s8 u = ((val >> 0) & 63) * 4;
  4662. uae_s8 v = ((val >> 6) & 63) * 4;
  4663. int fr = sx & 255;
  4664. if (fr >= 192) {
  4665. CKCHECK
  4666. {
  4667. uae_u16 out = yuvtorgb(y3, u, v);
  4668. ((uae_u16*)dst2)[dx] = p96_rgbx16p[out];
  4669. }
  4670. } else if (fr >= 128) {
  4671. CKCHECK
  4672. {
  4673. uae_u16 out = yuvtorgb(y2, u, v);
  4674. ((uae_u16*)dst2)[dx] = p96_rgbx16p[out];
  4675. }
  4676. } else if (fr >= 64) {
  4677. CKCHECK
  4678. {
  4679. uae_u16 out = yuvtorgb(y1, u, v);
  4680. ((uae_u16*)dst2)[dx] = p96_rgbx16p[out];
  4681. }
  4682. } else {
  4683. CKCHECK
  4684. {
  4685. uae_u16 out = yuvtorgb(y0, u, v);
  4686. ((uae_u16*)dst2)[dx] = p96_rgbx16p[out];
  4687. }
  4688. }
  4689. sx += sxadd;
  4690. dx++;
  4691. }
  4692. }
  4693. break;
  4694. }
  4695. }
  4696. static void picasso_flushoverlay(int index, uae_u8 *src, int scr_offset, uae_u8 *dst)
  4697. {
  4698. int monid = currprefs.rtgboards[index].monitor_id;
  4699. struct picasso96_state_struct *state = &picasso96_state[monid];
  4700. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  4701. if (overlay_w <= 0)
  4702. return;
  4703. if (overlay_h <= 0)
  4704. return;
  4705. uae_u8 *vram_end = src + gfxmem_banks[0]->allocated_size;
  4706. uae_u8 *s = src + overlay_vram_offset;
  4707. uae_u8 *ss = src + scr_offset;
  4708. int mx = overlay_src_width_in * 256 / overlay_w;
  4709. int my = overlay_src_height_in * 256 / overlay_h;
  4710. int y = 0;
  4711. for (int dy = 0; dy < overlay_h; dy++) {
  4712. if (s + (y >> 8) * overlay_src_width_in * overlay_pix > vram_end)
  4713. break;
  4714. if (ss + (overlay_y + dy) * state->BytesPerRow > vram_end)
  4715. break;
  4716. if (dst + (overlay_y + dy) * vidinfo->rowbytes > vram_end)
  4717. break;
  4718. copyrow_scale(monid, s, ss, dst,
  4719. 0, (y >> 8), mx, overlay_src_width_in, overlay_src_width * overlay_pix, overlay_pix,
  4720. state->BytesPerRow, state->BytesPerPixel,
  4721. overlay_x, overlay_y + dy, vidinfo->width, vidinfo->height, vidinfo->rowbytes, vidinfo->pixbytes,
  4722. overlay_occlusion != 0, overlay_color,
  4723. overlay_convert, p96_rgbx16_ovl, overlay_clut, true);
  4724. y += my;
  4725. }
  4726. }
  4727. void fb_copyrow(int monid, uae_u8 *src, uae_u8 *dst, int x, int y, int width, int srcpixbytes, int dy)
  4728. {
  4729. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  4730. struct picasso96_state_struct *state = &picasso96_state[monid];
  4731. copyrow(monid, src, dst, x, y, width, 0, srcpixbytes,
  4732. x, dy, picasso_vidinfo[monid].rowbytes, picasso_vidinfo[monid].pixbytes,
  4733. state->RGBFormat == vidinfo->host_mode, vidinfo->picasso_convert, p96_rgbx16);
  4734. }
  4735. static void copyallinvert(int monid, uae_u8 *src, uae_u8 *dst, int pwidth, int pheight, int srcbytesperrow, int srcpixbytes, int dstbytesperrow, int dstpixbytes, bool direct, int mode_convert)
  4736. {
  4737. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  4738. int x, y, w;
  4739. w = pwidth * dstpixbytes;
  4740. if (direct) {
  4741. for (y = 0; y < pheight; y++) {
  4742. if (y == vidinfo->splitypos) {
  4743. src = gfxmem_banks[monid]->start + natmem_offset;
  4744. }
  4745. for (x = 0; x < w; x++) {
  4746. dst[x] = src[x] ^ 0xff;
  4747. }
  4748. dst += dstbytesperrow;
  4749. src += srcbytesperrow;
  4750. }
  4751. } else {
  4752. uae_u8 *src2 = src;
  4753. for (y = 0; y < pheight; y++) {
  4754. for (x = 0; x < w; x++)
  4755. src2[x] ^= 0xff;
  4756. copyrow(monid, src, dst, 0, y, pwidth, srcbytesperrow, srcpixbytes, 0, y, dstbytesperrow, dstpixbytes, direct, mode_convert, p96_rgbx16);
  4757. for (x = 0; x < w; x++)
  4758. src2[x] ^= 0xff;
  4759. src2 += srcbytesperrow;
  4760. }
  4761. }
  4762. }
  4763. static void copyall (int monid, uae_u8 *src, uae_u8 *dst, int pwidth, int pheight, int srcbytesperrow, int srcpixbytes, int dstbytesperrow, int dstpixbytes, bool direct, int mode_convert)
  4764. {
  4765. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  4766. int y;
  4767. if (direct) {
  4768. int w = pwidth * vidinfo->pixbytes;
  4769. for (y = 0; y < pheight; y++) {
  4770. if (y == vidinfo->splitypos) {
  4771. src = gfxmem_banks[monid]->start + natmem_offset;
  4772. }
  4773. memcpy (dst, src, w);
  4774. dst += dstbytesperrow;
  4775. src += srcbytesperrow;
  4776. }
  4777. } else {
  4778. for (y = 0; y < pheight; y++) {
  4779. copyrow(monid, src, dst, 0, y, pwidth, srcbytesperrow, srcpixbytes, 0, y, dstbytesperrow, dstpixbytes, direct, mode_convert, p96_rgbx16);
  4780. }
  4781. }
  4782. }
  4783. uae_u8 *uaegfx_getrtgbuffer(int monid, int *widthp, int *heightp, int *pitch, int *depth, uae_u8 *palette)
  4784. {
  4785. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  4786. struct picasso96_state_struct *state = &picasso96_state[monid];
  4787. uae_u8 *src = gfxmem_banks[monid]->start + natmem_offset;
  4788. int off = state->XYOffset - gfxmem_banks[monid]->start;
  4789. int width, height, pixbytes;
  4790. uae_u8 *dst;
  4791. int convert;
  4792. int hmode;
  4793. if (!vidinfo->extra_mem)
  4794. return NULL;
  4795. width = state->VirtualWidth;
  4796. height = state->VirtualHeight;
  4797. pixbytes = state->BytesPerPixel == 1 && palette ? 1 : 4;
  4798. if (!width || !height || !pixbytes)
  4799. return NULL;
  4800. dst = xmalloc (uae_u8, width * height * pixbytes);
  4801. if (!dst)
  4802. return NULL;
  4803. hmode = pixbytes == 1 ? RGBFB_CLUT : RGBFB_B8G8R8A8;
  4804. convert = getconvert (state->RGBFormat, pixbytes);
  4805. alloc_colors_picasso(8, 8, 8, 16, 8, 0, state->RGBFormat, p96_rgbx16);
  4806. if (pixbytes > 1 && hmode != convert) {
  4807. copyall (monid, src + off, dst, width, height, state->BytesPerRow, state->BytesPerPixel, width * pixbytes, pixbytes, false, convert);
  4808. } else {
  4809. uae_u8 *dstp = dst;
  4810. uae_u8 *srcp = src;
  4811. for (int y = 0; y < height; y++) {
  4812. memcpy (dstp, srcp, width * pixbytes);
  4813. dstp += width * pixbytes;
  4814. srcp += state->BytesPerRow;
  4815. }
  4816. }
  4817. if (pixbytes == 1) {
  4818. for (int i = 0; i < 256; i++) {
  4819. palette[i * 3 + 0] = state->CLUT[i].Red;
  4820. palette[i * 3 + 1] = state->CLUT[i].Green;
  4821. palette[i * 3 + 2] = state->CLUT[i].Blue;
  4822. }
  4823. }
  4824. gfx_set_picasso_colors(monid, state->RGBFormat);
  4825. *widthp = width;
  4826. *heightp = height;
  4827. *pitch = width * pixbytes;
  4828. *depth = pixbytes * 8;
  4829. return dst;
  4830. }
  4831. void uaegfx_freertgbuffer(int monid, uae_u8 *dst)
  4832. {
  4833. xfree (dst);
  4834. }
  4835. void picasso_invalidate(int monid, int x, int y, int w, int h)
  4836. {
  4837. DX_Invalidate(&AMonitors[monid], x, y, w, h);
  4838. }
  4839. static void picasso_flushpixels(int index, uae_u8 *src, int off, bool render)
  4840. {
  4841. int monid = currprefs.rtgboards[index].monitor_id;
  4842. struct picasso96_state_struct *state = &picasso96_state[monid];
  4843. uae_u8 *src_start[2];
  4844. uae_u8 *src_end[2];
  4845. ULONG_PTR gwwcnt;
  4846. int pwidth = state->Width > state->VirtualWidth ? state->VirtualWidth : state->Width;
  4847. int pheight = state->Height > state->VirtualHeight ? state->VirtualHeight : state->Height;
  4848. int maxy = -1;
  4849. int miny = pheight - 1;
  4850. int flushlines = 0, matchcount = 0;
  4851. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  4852. bool overlay_updated = false;
  4853. src_start[0] = src + (off & ~gwwpagemask[index]);
  4854. src_end[0] = src + ((off + state->BytesPerRow * pheight + gwwpagesize[index] - 1) & ~gwwpagemask[index]);
  4855. if (vidinfo->splitypos >= 0) {
  4856. src_end[0] = src + ((off + state->BytesPerRow * vidinfo->splitypos + gwwpagesize[index] - 1) & ~gwwpagemask[index]);
  4857. src_start[1] = src;
  4858. src_end[1] = src + ((state->BytesPerRow * (pheight - vidinfo->splitypos) + gwwpagesize[index] - 1) & ~gwwpagemask[index]);
  4859. } else {
  4860. src_start[1] = src_end[1] = 0;
  4861. }
  4862. #if 0
  4863. write_log(_T("%dx%d %dx%d %dx%d (%dx%d)\n"), state->Width, state->Width,
  4864. state->VirtualWidth, state->VirtualHeight,
  4865. picasso_vidinfo.width, picasso_vidinfo.height,
  4866. pwidth, pheight);
  4867. #endif
  4868. if (!vidinfo->extra_mem || !gwwbuf[index] || (src_start[0] >= src_end[0] && src_start[1] >= src_end[1])) {
  4869. return;
  4870. }
  4871. if (flashscreen) {
  4872. vidinfo->full_refresh = 1;
  4873. }
  4874. if (vidinfo->full_refresh || vidinfo->rtg_clear_flag)
  4875. vidinfo->full_refresh = -1;
  4876. uae_u8 *dstp = NULL;
  4877. for (;;) {
  4878. uae_u8 *dst = NULL;
  4879. bool dofull;
  4880. gwwcnt = 0;
  4881. if (doskip() && p96skipmode == 1) {
  4882. break;
  4883. }
  4884. if (!index && overlay_vram && overlay_active) {
  4885. ULONG ps;
  4886. gwwcnt = gwwbufsize[index];
  4887. uae_u8 *ovr_start = src + (overlay_vram_offset & ~gwwpagemask[index]);
  4888. uae_u8 *ovr_end = src + ((overlay_vram_offset + overlay_src_width * overlay_src_height * overlay_pix + gwwpagesize[index] - 1) & ~gwwpagemask[index]);
  4889. mman_GetWriteWatch(ovr_start, ovr_end - ovr_start, gwwbuf[index], &gwwcnt, &ps);
  4890. overlay_updated = gwwcnt > 0;
  4891. }
  4892. for (int split = 0; split < 2; split++) {
  4893. uae_u32 regionsize = src_end[split] - src_start[split];
  4894. if (src_start[split] == 0 && src_end[split] == 0) {
  4895. break;
  4896. }
  4897. if (vidinfo->full_refresh < 0 || overlay_updated) {
  4898. gwwcnt = regionsize / gwwpagesize[index] + 1;
  4899. vidinfo->full_refresh = 1;
  4900. for (int i = 0; i < gwwcnt; i++)
  4901. gwwbuf[index][i] = src_start[split] + i * gwwpagesize[index];
  4902. } else {
  4903. ULONG ps;
  4904. gwwcnt = gwwbufsize[index];
  4905. if (mman_GetWriteWatch(src_start[split], regionsize, gwwbuf[index], &gwwcnt, &ps))
  4906. continue;
  4907. }
  4908. matchcount += gwwcnt;
  4909. if (gwwcnt == 0) {
  4910. continue;
  4911. }
  4912. dofull = gwwcnt >= (regionsize / gwwpagesize[index]) * 80 / 100;
  4913. if (!dstp) {
  4914. dstp = gfx_lock_picasso(monid, dofull);
  4915. }
  4916. if (dstp == NULL) {
  4917. continue;
  4918. }
  4919. dst = dstp;
  4920. // safety check
  4921. if (pwidth > vidinfo->rowbytes / vidinfo->pixbytes) {
  4922. pwidth = vidinfo->rowbytes / vidinfo->pixbytes;
  4923. }
  4924. if (pheight > vidinfo->height) {
  4925. pheight = vidinfo->height;
  4926. }
  4927. if (!split && vidinfo->rtg_clear_flag) {
  4928. uae_u8 *p2 = dst;
  4929. for (int h = 0; h < vidinfo->height; h++) {
  4930. memset(p2, 0, vidinfo->width * vidinfo->pixbytes);
  4931. p2 += vidinfo->rowbytes;
  4932. }
  4933. vidinfo->rtg_clear_flag--;
  4934. }
  4935. dst += vidinfo->offset;
  4936. if (doskip() && p96skipmode == 2) {
  4937. continue;
  4938. }
  4939. if (dofull) {
  4940. if (flashscreen != 0) {
  4941. copyallinvert(monid, src + off, dst, pwidth, pheight,
  4942. state->BytesPerRow, state->BytesPerPixel,
  4943. vidinfo->rowbytes, vidinfo->pixbytes,
  4944. state->RGBFormat == vidinfo->host_mode, vidinfo->picasso_convert);
  4945. } else {
  4946. copyall(monid, src + off, dst, pwidth, pheight,
  4947. state->BytesPerRow, state->BytesPerPixel,
  4948. vidinfo->rowbytes, vidinfo->pixbytes,
  4949. state->RGBFormat == vidinfo->host_mode, vidinfo->picasso_convert);
  4950. }
  4951. miny = 0;
  4952. maxy = pheight;
  4953. flushlines = -1;
  4954. break;
  4955. }
  4956. if (split) {
  4957. off = 0;
  4958. }
  4959. for (int i = 0; i < gwwcnt; i++) {
  4960. uae_u8 *p = (uae_u8 *)gwwbuf[index][i];
  4961. if (p >= src_start[split] && p < src_end[split]) {
  4962. int y, x, realoffset;
  4963. if (p >= src + off) {
  4964. realoffset = p - (src + off);
  4965. } else {
  4966. realoffset = 0;
  4967. }
  4968. y = realoffset / state->BytesPerRow;
  4969. if (split) {
  4970. y += vidinfo->splitypos;
  4971. }
  4972. if (y < pheight) {
  4973. int w = (gwwpagesize[index] + state->BytesPerPixel - 1) / state->BytesPerPixel;
  4974. x = (realoffset % state->BytesPerRow) / state->BytesPerPixel;
  4975. if (x < pwidth) {
  4976. copyrow(monid, src + off, dst, x, y, pwidth - x,
  4977. state->BytesPerRow, state->BytesPerPixel,
  4978. x, y, vidinfo->rowbytes, vidinfo->pixbytes,
  4979. state->RGBFormat == vidinfo->host_mode, vidinfo->picasso_convert, p96_rgbx16);
  4980. flushlines++;
  4981. }
  4982. w = (gwwpagesize[index] - (state->BytesPerRow - x * state->BytesPerPixel) + state->BytesPerPixel - 1) / state->BytesPerPixel;
  4983. if (y < miny) {
  4984. miny = y;
  4985. }
  4986. y++;
  4987. while (y < pheight && w > 0) {
  4988. int maxw = w > pwidth ? pwidth : w;
  4989. copyrow(monid, src + off, dst, 0, y, maxw,
  4990. state->BytesPerRow, state->BytesPerPixel,
  4991. 0, y, vidinfo->rowbytes, vidinfo->pixbytes,
  4992. state->RGBFormat == vidinfo->host_mode, vidinfo->picasso_convert, p96_rgbx16);
  4993. w -= maxw;
  4994. y++;
  4995. flushlines++;
  4996. }
  4997. if (y > maxy) {
  4998. maxy = y;
  4999. }
  5000. }
  5001. }
  5002. }
  5003. }
  5004. break;
  5005. }
  5006. if (!index && overlay_vram && overlay_active && (flushlines || overlay_updated)) {
  5007. if (dstp == NULL) {
  5008. dstp = gfx_lock_picasso(monid, false);
  5009. }
  5010. if (dstp)
  5011. picasso_flushoverlay(index, src, off, dstp);
  5012. }
  5013. if (0 && flushlines) {
  5014. write_log (_T("%d:%d\n"), flushlines, matchcount);
  5015. }
  5016. if (currprefs.leds_on_screen & STATUSLINE_RTG) {
  5017. if (dstp == NULL) {
  5018. dstp = gfx_lock_picasso(monid, false);
  5019. }
  5020. if (dstp) {
  5021. if (softstatusline()) {
  5022. picasso_statusline(monid, dstp);
  5023. }
  5024. maxy = vidinfo->height;
  5025. if (miny > vidinfo->height - TD_TOTAL_HEIGHT)
  5026. miny = vidinfo->height - TD_TOTAL_HEIGHT;
  5027. }
  5028. }
  5029. if (maxy >= 0) {
  5030. if (doskip () && p96skipmode == 4) {
  5031. ;
  5032. } else {
  5033. picasso_invalidate(monid, 0, miny, pwidth, maxy - miny);
  5034. }
  5035. }
  5036. if (dstp || render) {
  5037. gfx_unlock_picasso(monid, render);
  5038. }
  5039. if (dstp && gwwcnt) {
  5040. vidinfo->full_refresh = 0;
  5041. }
  5042. }
  5043. static void render_thread(void *v)
  5044. {
  5045. render_thread_state = 1;
  5046. for (;;) {
  5047. int idx = read_comm_pipe_int_blocking(render_pipe);
  5048. if (idx == -1)
  5049. break;
  5050. idx &= 0xff;
  5051. int monid = currprefs.rtgboards[idx].monitor_id;
  5052. struct amigadisplay *ad = &adisplays[monid];
  5053. if (ad->picasso_on && ad->picasso_requested_on) {
  5054. lockrtg();
  5055. if (ad->picasso_requested_on) {
  5056. struct picasso96_state_struct *state = &picasso96_state[monid];
  5057. picasso_flushpixels(idx, gfxmem_banks[idx]->start + natmem_offset, state->XYOffset - gfxmem_banks[idx]->start, false);
  5058. ad->pending_render = true;
  5059. }
  5060. unlockrtg();
  5061. }
  5062. }
  5063. render_thread_state = -1;
  5064. }
  5065. extern addrbank gfxmem_bank;
  5066. MEMORY_FUNCTIONS(gfxmem);
  5067. addrbank gfxmem_bank = {
  5068. gfxmem_lget, gfxmem_wget, gfxmem_bget,
  5069. gfxmem_lput, gfxmem_wput, gfxmem_bput,
  5070. gfxmem_xlate, gfxmem_check, NULL, NULL, _T("RTG RAM"),
  5071. dummy_lgeti, dummy_wgeti,
  5072. ABFLAG_RAM | ABFLAG_RTG | ABFLAG_DIRECTACCESS, 0, 0
  5073. };
  5074. extern addrbank gfxmem2_bank;
  5075. MEMORY_FUNCTIONS(gfxmem2);
  5076. addrbank gfxmem2_bank = {
  5077. gfxmem2_lget, gfxmem2_wget, gfxmem2_bget,
  5078. gfxmem2_lput, gfxmem2_wput, gfxmem2_bput,
  5079. gfxmem2_xlate, gfxmem2_check, NULL, NULL, _T("RTG RAM #2"),
  5080. dummy_lgeti, dummy_wgeti,
  5081. ABFLAG_RAM | ABFLAG_RTG | ABFLAG_DIRECTACCESS, 0, 0
  5082. };
  5083. extern addrbank gfxmem3_bank;
  5084. MEMORY_FUNCTIONS(gfxmem3);
  5085. addrbank gfxmem3_bank = {
  5086. gfxmem3_lget, gfxmem3_wget, gfxmem3_bget,
  5087. gfxmem3_lput, gfxmem3_wput, gfxmem3_bput,
  5088. gfxmem3_xlate, gfxmem3_check, NULL, NULL, _T("RTG RAM #3"),
  5089. dummy_lgeti, dummy_wgeti,
  5090. ABFLAG_RAM | ABFLAG_RTG | ABFLAG_DIRECTACCESS, 0, 0
  5091. };
  5092. extern addrbank gfxmem4_bank;
  5093. MEMORY_FUNCTIONS(gfxmem4);
  5094. addrbank gfxmem4_bank = {
  5095. gfxmem4_lget, gfxmem4_wget, gfxmem4_bget,
  5096. gfxmem4_lput, gfxmem4_wput, gfxmem4_bput,
  5097. gfxmem4_xlate, gfxmem4_check, NULL, NULL, _T("RTG RAM #4"),
  5098. dummy_lgeti, dummy_wgeti,
  5099. ABFLAG_RAM | ABFLAG_RTG | ABFLAG_DIRECTACCESS, 0, 0
  5100. };
  5101. addrbank *gfxmem_banks[MAX_RTG_BOARDS];
  5102. /* Call this function first, near the beginning of code flow
  5103. * Place in InitGraphics() which seems reasonable...
  5104. * Also put it in reset_drawing() for safe-keeping. */
  5105. void InitPicasso96(int monid)
  5106. {
  5107. struct picasso96_state_struct *state = &picasso96_state[monid];
  5108. int i;
  5109. gfxmem_banks[0] = &gfxmem_bank;
  5110. gfxmem_banks[1] = &gfxmem2_bank;
  5111. gfxmem_banks[2] = &gfxmem3_bank;
  5112. gfxmem_banks[3] = &gfxmem4_bank;
  5113. //fastscreen
  5114. oldscr = 0;
  5115. //fastscreen
  5116. memset (state, 0, sizeof (struct picasso96_state_struct));
  5117. for (i = 0; i < 256; i++) {
  5118. p2ctab[i][0] = (((i & 128) ? 0x01000000 : 0)
  5119. | ((i & 64) ? 0x010000 : 0)
  5120. | ((i & 32) ? 0x0100 : 0)
  5121. | ((i & 16) ? 0x01 : 0));
  5122. p2ctab[i][1] = (((i & 8) ? 0x01000000 : 0)
  5123. | ((i & 4) ? 0x010000 : 0)
  5124. | ((i & 2) ? 0x0100 : 0)
  5125. | ((i & 1) ? 0x01 : 0));
  5126. }
  5127. }
  5128. #endif
  5129. static uae_u32 REGPARAM2 picasso_SetInterrupt (TrapContext *ctx)
  5130. {
  5131. uaecptr bi = trap_get_areg(ctx, 0);
  5132. uae_u32 onoff = trap_get_dreg(ctx, 0);
  5133. interrupt_enabled = onoff;
  5134. //write_log (_T("Picasso_SetInterrupt(%08x,%d)\n"), bi, onoff);
  5135. return onoff;
  5136. }
  5137. static uaecptr uaegfx_vblankname, uaegfx_portsname;
  5138. static void initvblankABI (TrapContext *ctx, uaecptr base, uaecptr ABI)
  5139. {
  5140. for (int i = 0; i < 22; i++)
  5141. trap_put_byte(ctx, ABI + PSSO_BoardInfo_HardInterrupt + i, trap_get_byte(ctx, base + CARD_PORTSIRQ + i));
  5142. ABI_interrupt = ABI;
  5143. }
  5144. static void initvblankirq (TrapContext *ctx, uaecptr base)
  5145. {
  5146. uaecptr p1 = base + CARD_VBLANKIRQ;
  5147. uaecptr p2 = base + CARD_PORTSIRQ;
  5148. uaecptr c = base + CARD_IRQCODE;
  5149. trap_put_word(ctx, p1 + 8, 0x0205);
  5150. trap_put_long(ctx, p1 + 10, uaegfx_vblankname);
  5151. trap_put_long(ctx, p1 + 14, base + CARD_IRQFLAG);
  5152. trap_put_long(ctx, p1 + 18, c);
  5153. trap_put_word(ctx, p2 + 8, 0x0205);
  5154. trap_put_long(ctx, p2 + 10, uaegfx_portsname);
  5155. trap_put_long(ctx, p2 + 14, base + CARD_IRQFLAG);
  5156. trap_put_long(ctx, p2 + 18, c);
  5157. trap_put_word(ctx, c, 0x4a11); c += 2; // tst.b (a1) CARD_IRQFLAG
  5158. trap_put_word(ctx, c, 0x670e); c += 2; // beq.s label
  5159. trap_put_word(ctx, c, 0x4211); c += 2; // clr.b (a1)
  5160. trap_put_long(ctx, c, 0x2c690008); c += 4; // move.l 8(a1),a6 CARD_IRQEXECBASE
  5161. trap_put_long(ctx, c, 0x22690004); c += 4; // move.l 4(a1),a1 CARD_IRQPTR
  5162. trap_put_long(ctx, c, 0x4eaeff4c); c += 4; // jsr Cause(a6)
  5163. trap_put_word(ctx, c, 0x7000); c += 2; // label: moveq #0,d0
  5164. trap_put_word(ctx, c, RTS); // rts
  5165. #if NEWTRAP
  5166. trap_call_add_areg(ctx, 1, p1);
  5167. trap_call_add_dreg(ctx, 0, 5);
  5168. trap_call_lib(ctx, trap_get_long(ctx, 4), -168); /* AddIntServer */
  5169. trap_call_add_areg(ctx, 1, p2);
  5170. trap_call_add_dreg(ctx, 0, 3);
  5171. trap_call_lib(ctx, trap_get_long(ctx, 4), -168); /* AddIntServer */
  5172. #else
  5173. trap_set_areg(ctx, 1, p1);
  5174. trap_set_dreg(ctx, 0, 5); /* VERTB */
  5175. CallLib (ctx, trap_get_long(ctx, 4), -168); /* AddIntServer */
  5176. trap_set_areg(ctx, 1, p2);
  5177. trap_set_dreg(ctx, 0, 3); /* PORTS */
  5178. CallLib (ctx, trap_get_long(ctx, 4), -168); /* AddIntServer */
  5179. #endif
  5180. }
  5181. static uae_u32 REGPARAM2 picasso_SetClock(TrapContext *ctx)
  5182. {
  5183. uaecptr bi = trap_get_areg(ctx, 0);
  5184. P96TRACE_SETUP((_T("SetClock\n")));
  5185. return 0;
  5186. }
  5187. static uae_u32 REGPARAM2 picasso_SetMemoryMode(TrapContext *ctx)
  5188. {
  5189. uaecptr bi = trap_get_areg(ctx, 0);
  5190. uae_u32 rgbformat = trap_get_dreg(ctx, 7);
  5191. P96TRACE_SETUP((_T("SetMemoryMode\n")));
  5192. return 0;
  5193. }
  5194. #if OVERLAY
  5195. #define OVERLAY_COOKIE 0x12345678
  5196. static uaecptr gettag(TrapContext *ctx, uaecptr p, uae_u32 *tagp, uae_u32 *valp)
  5197. {
  5198. for (;;) {
  5199. uae_u32 tag = trap_get_long(ctx, p);
  5200. uae_u32 val = trap_get_long(ctx, p + 4);
  5201. #if OVERLAY_DEBUG > 2
  5202. write_log(_T("TAG %08x: %08x %08x\n"), p, tag, val);
  5203. #endif
  5204. if (tag == TAG_DONE)
  5205. return 0;
  5206. if (tag == TAG_IGNORE) {
  5207. p += 8;
  5208. continue;
  5209. }
  5210. if (tag == TAG_SKIP) {
  5211. p += (val + 1) * 8;
  5212. continue;
  5213. }
  5214. if (tag == TAG_MORE) {
  5215. p = val;
  5216. continue;
  5217. }
  5218. *tagp = tag;
  5219. *valp = val;
  5220. return p + 8;
  5221. }
  5222. }
  5223. static void settag(TrapContext *ctx, uaecptr p, uae_u32 v)
  5224. {
  5225. trap_put_long(ctx, p, v);
  5226. #if OVERLAY_DEBUG > 2
  5227. write_log(_T(" - %08x -> %08x\n"), p, v);
  5228. #endif
  5229. }
  5230. static void overlaygettag(TrapContext *ctx, uae_u32 tag, uae_u32 val)
  5231. {
  5232. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[0];
  5233. switch (tag)
  5234. {
  5235. case FA_Active:
  5236. overlay_active = val;
  5237. break;
  5238. case FA_Occlusion:
  5239. overlay_occlusion = val;
  5240. break;
  5241. case FA_Left:
  5242. overlay_x = val;
  5243. break;
  5244. case FA_Top:
  5245. overlay_y = val;
  5246. break;
  5247. case FA_Width:
  5248. overlay_w = val;
  5249. break;
  5250. case FA_Height:
  5251. overlay_h = val;
  5252. break;
  5253. case FA_SourceWidth:
  5254. overlay_src_width_in = val;
  5255. break;
  5256. case FA_SourceHeight:
  5257. overlay_src_height_in = val;
  5258. break;
  5259. case FA_Format:
  5260. overlay_format = val;
  5261. break;
  5262. case FA_ModeFormat:
  5263. overlay_modeformat = val;
  5264. break;
  5265. case FA_Brightness:
  5266. overlay_brightness = val;
  5267. break;
  5268. case FA_ModeInfo:
  5269. overlay_modeinfo = val;
  5270. break;
  5271. case FA_Color:
  5272. overlay_color = val;
  5273. overlay_color_unswapped = val;
  5274. endianswap(&overlay_color, picasso96_state[0].BytesPerPixel);
  5275. break;
  5276. case FA_ClipLeft:
  5277. overlay_clipleft = val;
  5278. break;
  5279. case FA_ClipTop:
  5280. overlay_cliptop = val;
  5281. break;
  5282. case FA_ClipWidth:
  5283. overlay_clipwidth = val;
  5284. break;
  5285. case FA_ClipHeight:
  5286. overlay_clipheight = val;
  5287. break;
  5288. case FA_Colors32:
  5289. {
  5290. while(val) {
  5291. uae_u8 tmpbuf[256 * 3 * 4 + 4];
  5292. uae_u32 v = trap_get_long(ctx, val);
  5293. val += 4;
  5294. uae_u16 num = v >> 16;
  5295. if (num > 256)
  5296. break;
  5297. uae_u16 first = v & 0xffff;
  5298. trap_get_bytes(ctx, tmpbuf, val, num * 3 * 4 + 4);
  5299. for (int i = 0; i < num && (first + i) < 256; i++) {
  5300. overlay_clutc[first + i].Red = tmpbuf[i * 3 * 4 + 0];
  5301. overlay_clutc[first + i].Green = tmpbuf[i * 3 * 4 + 4];
  5302. overlay_clutc[first + i].Blue = tmpbuf[i * 3 * 4 + 8];
  5303. }
  5304. if (!tmpbuf[num])
  5305. break;
  5306. val += num * 3 * 4;
  5307. }
  5308. if (picasso_palette(overlay_clutc, overlay_clut))
  5309. vidinfo->full_refresh = 1;
  5310. }
  5311. break;
  5312. case FA_Colors:
  5313. {
  5314. while (val) {
  5315. uae_u8 tmpbuf[4 * 2];
  5316. trap_get_bytes(ctx, tmpbuf, val, 4 * 2);
  5317. uae_u16 idx = (tmpbuf[0] << 8) | tmpbuf[1];
  5318. if (idx >= 256)
  5319. break;
  5320. overlay_clutc[idx].Red = ((tmpbuf[3] & 15) << 4) | (tmpbuf[3] & 15);
  5321. overlay_clutc[idx].Green = ((tmpbuf[5] & 15) << 4) | (tmpbuf[5] & 15);
  5322. overlay_clutc[idx].Blue = ((tmpbuf[7] & 15) << 4) | (tmpbuf[7] & 15);
  5323. val += 4 * 2;
  5324. }
  5325. if (picasso_palette(overlay_clutc, overlay_clut))
  5326. vidinfo->full_refresh = 1;
  5327. }
  5328. break;
  5329. }
  5330. }
  5331. static void overlaysettag(TrapContext *ctx, uae_u32 tag, uae_u32 val)
  5332. {
  5333. switch (tag)
  5334. {
  5335. case FA_Active:
  5336. settag(ctx, val, overlay_active);
  5337. break;
  5338. case FA_Occlusion:
  5339. settag(ctx, val, overlay_occlusion);
  5340. break;
  5341. case FA_MinWidth:
  5342. case FA_MinHeight:
  5343. settag(ctx, val, 16);
  5344. break;
  5345. case FA_MaxWidth:
  5346. case FA_MaxHeight:
  5347. settag(ctx, val, 4096);
  5348. break;
  5349. case FA_Left:
  5350. settag(ctx, val, overlay_x);
  5351. break;
  5352. case FA_Top:
  5353. settag(ctx, val, overlay_y);
  5354. break;
  5355. case FA_Width:
  5356. settag(ctx, val, overlay_w);
  5357. break;
  5358. case FA_Height:
  5359. settag(ctx, val, overlay_h);
  5360. break;
  5361. case FA_SourceWidth:
  5362. settag(ctx, val, overlay_src_width_in);
  5363. break;
  5364. case FA_SourceHeight:
  5365. settag(ctx, val, overlay_src_height_in);
  5366. break;
  5367. case FA_BitMap:
  5368. settag(ctx, val, overlay_bitmap);
  5369. break;
  5370. case FA_Format:
  5371. settag(ctx, val, overlay_format);
  5372. break;
  5373. case FA_ModeFormat:
  5374. settag(ctx, val, overlay_modeformat);
  5375. break;
  5376. case FA_Brightness:
  5377. settag(ctx, val, overlay_brightness);
  5378. break;
  5379. case FA_ModeInfo:
  5380. settag(ctx, val, overlay_modeinfo);
  5381. break;
  5382. case FA_Color:
  5383. settag(ctx, val, overlay_color_unswapped);
  5384. break;
  5385. case FA_ClipLeft:
  5386. settag(ctx, val, overlay_clipleft);
  5387. break;
  5388. case FA_ClipTop:
  5389. settag(ctx, val, overlay_cliptop);
  5390. break;
  5391. case FA_ClipWidth:
  5392. settag(ctx, val, overlay_clipwidth);
  5393. break;
  5394. case FA_ClipHeight:
  5395. settag(ctx, val, overlay_clipheight);
  5396. break;
  5397. }
  5398. }
  5399. static uae_u32 REGPARAM2 picasso_SetFeatureAttrs(TrapContext *ctx)
  5400. {
  5401. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[0];
  5402. uaecptr bi = trap_get_areg(ctx, 0);
  5403. uaecptr featuredata = trap_get_areg(ctx, 1);
  5404. uaecptr tagp = trap_get_areg(ctx, 2);
  5405. uae_u32 type = trap_get_dreg(ctx, 0);
  5406. #if OVERLAY_DEBUG > 1
  5407. write_log(_T("picasso_SetFeatureAttrs %08x %d\n"), tagp, type);
  5408. #endif
  5409. for (;;) {
  5410. uae_u32 tag, val;
  5411. tagp = gettag(ctx, tagp, &tag, &val);
  5412. if (!tagp)
  5413. break;
  5414. #if OVERLAY_DEBUG > 1
  5415. write_log(_T("picasso_SetFeatureAttrs %08x tag %08x (%d) %08x\n"), tagp - 8, tag, tag & 0x7fffffff, val);
  5416. #endif
  5417. overlaygettag(ctx, tag, val);
  5418. }
  5419. #if OVERLAY_DEBUG > 1
  5420. write_log(_T("RTG Overlay: X=%d Y=%d W=%d H=%d Act=%d SrcW=%d SrcH=%d BPP=%d VRAM=%08x\n"),
  5421. overlay_x, overlay_y, overlay_w, overlay_h,
  5422. overlay_active, overlay_src_width_in, overlay_src_height_in,
  5423. overlay_pix, overlay_vram);
  5424. #endif
  5425. vidinfo->full_refresh = 1;
  5426. return 0;
  5427. }
  5428. static uae_u32 REGPARAM2 picasso_GetFeatureAttrs(TrapContext *ctx)
  5429. {
  5430. uaecptr bi = trap_get_areg(ctx, 0);
  5431. uaecptr featuredata = trap_get_areg(ctx, 1);
  5432. uaecptr tagp = trap_get_areg(ctx, 2);
  5433. uae_u32 type = trap_get_dreg(ctx, 0);
  5434. #if OVERLAY_DEBUG > 1
  5435. write_log(_T("picasso_GetFeatureAttrs %08x %d\n"), tagp, type);
  5436. #endif
  5437. for (;;) {
  5438. uae_u32 tag, val;
  5439. tagp = gettag(ctx, tagp, &tag, &val);
  5440. if (!tagp)
  5441. break;
  5442. overlaysettag(ctx, tag, val);
  5443. #if OVERLAY_DEBUG > 1
  5444. write_log(_T("picasso_GetFeatureAttrs %08x tag %08x (%d) %08x\n"), tagp, tag, tag & 0x7fffffff, val);
  5445. #endif
  5446. }
  5447. return 0;
  5448. }
  5449. // Tags from picassoiv driver..
  5450. static const uae_u32 ovltags[] = {
  5451. ABMA_RGBFormat, 0,
  5452. ABMA_Clear, 1,
  5453. ABMA_Displayable, 1,
  5454. ABMA_Visible, 1,
  5455. ABMA_Colors, 0,
  5456. ABMA_Colors32, 0,
  5457. ABMA_ConstantBytesPerRow, 0,
  5458. ABMA_NoMemory, 0,
  5459. ABMA_RenderFunc, 0,
  5460. ABMA_SaveFunc, 0,
  5461. ABMA_UserData, 0,
  5462. ABMA_Alignment, 0,
  5463. TAG_DONE, 0
  5464. };
  5465. #define ALLOC_TAG_SIZE (13 * 8)
  5466. // "VBInt PicassoIV (0)" -0x14
  5467. // AllocCardMem=274 AllocBitMap=506 SetColorArray=286
  5468. // CLUTEntry=578
  5469. static uae_u32 REGPARAM2 picasso_CreateFeature(TrapContext *ctx)
  5470. {
  5471. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[0];
  5472. struct picasso96_state_struct *state = &picasso96_state[0];
  5473. uaecptr bi = trap_get_areg(ctx, 0);
  5474. uae_u32 type = trap_get_dreg(ctx, 0);
  5475. uaecptr tagp = trap_get_areg(ctx, 1);
  5476. #if OVERLAY_DEBUG
  5477. write_log(_T("picasso_CreateFeature type %d %08x %08x\n"), type, bi, tagp);
  5478. #endif
  5479. if (type != SFT_MEMORYWINDOW)
  5480. return 0;
  5481. if (overlay_vram)
  5482. return 0;
  5483. memcpy(overlay_clutc, state->CLUT, sizeof(struct MyCLUTEntry) * 256);
  5484. overlay_src_width_in = -1;
  5485. overlay_src_height_in = -1;
  5486. overlay_format = 0;
  5487. for (;;) {
  5488. uae_u32 tag, val;
  5489. tagp = gettag(ctx, tagp, &tag, &val);
  5490. if (!tagp)
  5491. break;
  5492. #if OVERLAY_DEBUG
  5493. write_log(_T("picasso_CreateFeature tag %08x (%d) %08x\n"), tag, tag & 0x7fffffff, val);
  5494. #endif
  5495. overlaygettag(ctx, tag, val);
  5496. }
  5497. if (overlay_src_width_in < 16 || overlay_src_height_in < 16) {
  5498. #if OVERLAY_DEBUG
  5499. write_log(_T("picasso_CreateFeature overlay width or height too small (%d*%d)\n"), overlay_src_width, overlay_src_height);
  5500. #endif
  5501. return 0;
  5502. }
  5503. if (overlay_src_width_in > vidinfo->width || overlay_src_height_in > vidinfo->height) {
  5504. #if OVERLAY_DEBUG
  5505. write_log(_T("picasso_CreateFeature overlay width or height too large (%d*%d)\n"), overlay_src_width, overlay_src_height);
  5506. #endif
  5507. return 0;
  5508. }
  5509. if (overlay_format < RGBFB_CLUT || overlay_format >= RGBFB_MaxFormats) {
  5510. #if OVERLAY_DEBUG
  5511. write_log(_T("picasso_CreateFeature overlay unknown format %d\n"), overlay_format);
  5512. #endif
  5513. return 0;
  5514. }
  5515. overlay_pix = GetBytesPerPixel(overlay_format);
  5516. if (!overlay_pix) {
  5517. #if OVERLAY_DEBUG
  5518. write_log(_T("picasso_CreateFeature overlay bytes per bit is zero (format %d)\n"), overlay_format);
  5519. #endif
  5520. return 0;
  5521. }
  5522. uaecptr overlay_tagmem = uae_AllocMem(ctx, ALLOC_TAG_SIZE, 65536, trap_get_long(ctx, 4));
  5523. if (!overlay_tagmem)
  5524. return 0;
  5525. uaecptr func = trap_get_long(ctx, bi + PSSO_BoardInfo_AllocBitMap);
  5526. for (int i = 0; ovltags[i]; i += 2) {
  5527. trap_put_long(ctx, overlay_tagmem + i * 4 + 0, ovltags[i + 0]);
  5528. if (i == 0) {
  5529. trap_put_long(ctx, overlay_tagmem + i * 4 + 4, overlay_format);
  5530. } else {
  5531. trap_put_long(ctx, overlay_tagmem + i * 4 + 4, ovltags[i + 1]);
  5532. }
  5533. }
  5534. trap_call_add_areg(ctx, 0, bi);
  5535. trap_call_add_dreg(ctx, 0, overlay_src_width_in);
  5536. trap_call_add_dreg(ctx, 1, overlay_src_height_in);
  5537. trap_call_add_areg(ctx, 1, overlay_tagmem);
  5538. overlay_bitmap = trap_call_func(ctx, func);
  5539. uae_FreeMem(ctx, overlay_tagmem, ALLOC_TAG_SIZE, trap_get_long(ctx, 4));
  5540. if (!overlay_bitmap) {
  5541. return 0;
  5542. }
  5543. // probably should use GetBitMapAttr() but function is not documented enough.
  5544. overlay_src_width = trap_get_word(ctx, overlay_bitmap + 0) / overlay_pix;
  5545. overlay_src_height = trap_get_word(ctx, overlay_bitmap + 2);
  5546. overlay_vram = trap_get_long(ctx, overlay_bitmap + 8);
  5547. overlay_vram_offset = overlay_vram - gfxmem_banks[0]->start;
  5548. overlay_convert = getconvert(overlay_format, picasso_vidinfo[0].pixbytes);
  5549. if (!p96_rgbx16_ovl)
  5550. p96_rgbx16_ovl = xcalloc(uae_u32, 65536);
  5551. int of = overlay_format;
  5552. if (of == RGBFB_Y4U2V2 || of == RGBFB_Y4U1V1)
  5553. of = RGBFB_R5G5B5PC;
  5554. alloc_colors_picasso(8, 8, 8, 16, 8, 0, of, p96_rgbx16_ovl);
  5555. #if OVERLAY_DEBUG
  5556. write_log(_T("picasso_CreateFeature overlay bitmap %08x, vram %08x (%dx%d)\n"),
  5557. overlay_bitmap, overlay_vram, overlay_src_width, overlay_src_height);
  5558. #endif
  5559. picasso_palette(overlay_clutc, overlay_clut);
  5560. vidinfo->full_refresh = 1;
  5561. return OVERLAY_COOKIE;
  5562. }
  5563. static uae_u32 REGPARAM2 picasso_DeleteFeature(TrapContext *ctx)
  5564. {
  5565. uaecptr bi = trap_get_areg(ctx, 0);
  5566. uae_u32 type = trap_get_dreg(ctx, 0);
  5567. uaecptr featuredata = trap_get_areg(ctx, 1);
  5568. #if OVERLAY_DEBUG
  5569. write_log(_T("picasso_DeleteFeature type %d data %08x\n"), type, featuredata);
  5570. #endif
  5571. if (type != SFT_MEMORYWINDOW)
  5572. return 0;
  5573. if (featuredata != OVERLAY_COOKIE)
  5574. return 0;
  5575. if (!overlay_bitmap)
  5576. return 0;
  5577. uaecptr func = trap_get_long(ctx, bi + PSSO_BoardInfo_FreeBitMap);
  5578. trap_call_add_areg(ctx, 0, bi);
  5579. trap_call_add_areg(ctx, 1, overlay_bitmap);
  5580. trap_call_add_areg(ctx, 2, 0);
  5581. trap_call_func(ctx, func);
  5582. overlay_bitmap = 0;
  5583. overlay_vram = 0;
  5584. overlay_active = 0;
  5585. return 1;
  5586. }
  5587. #endif
  5588. #define PUTABI(func) \
  5589. if (ABI) \
  5590. trap_put_long(ctx, ABI + func, here ()); \
  5591. save_rom_absolute(ABI + func);
  5592. #define RTGCALL(func,funcdef,call) \
  5593. PUTABI (func); \
  5594. dl (0x48e78000); \
  5595. calltrap (deftrap (call)); \
  5596. dw (0x4a80); \
  5597. dl (0x4cdf0001);\
  5598. dw (0x6604); \
  5599. dw (0x2f28); \
  5600. dw (funcdef); \
  5601. dw (RTS);
  5602. #define RTGCALL2(func,call) \
  5603. PUTABI (func); \
  5604. calltrap (deftrap (call)); \
  5605. dw (RTS);
  5606. #define RTGCALL2X(func,call) \
  5607. PUTABI (func); \
  5608. calltrap (deftrap2 (call, TRAPFLAG_EXTRA_STACK, NULL)); \
  5609. dw (RTS);
  5610. #define RTGCALLDEFAULT(func,funcdef) \
  5611. PUTABI (func); \
  5612. dw (0x2f28); \
  5613. dw (funcdef); \
  5614. dw (RTS);
  5615. #define RTGCALLONLYDEFAULT(func,funcdef,unused) \
  5616. PUTABI (func); \
  5617. dw (0x2f28); \
  5618. dw (funcdef); \
  5619. dw (RTS);
  5620. #define RTGNONE(func) \
  5621. if (ABI) \
  5622. trap_put_long(ctx, ABI + func, start); \
  5623. save_rom_absolute(ABI + func);
  5624. static void inituaegfxfuncs(TrapContext *ctx, uaecptr start, uaecptr ABI)
  5625. {
  5626. if (uaegfx_old || !ABI)
  5627. return;
  5628. org (start);
  5629. dw (RTS);
  5630. /* ResolvePixelClock
  5631. move.l D0,gmi_PixelClock(a1) ; pass the pixelclock through
  5632. moveq #0,D0 ; index is 0
  5633. move.b #98,gmi_Numerator(a1) ; whatever
  5634. move.b #14,gmi_Denominator(a1) ; whatever
  5635. rts
  5636. */
  5637. PUTABI (PSSO_BoardInfo_ResolvePixelClock);
  5638. dl (0x2340002c);
  5639. dw (0x7000);
  5640. dl (0x137c0062); dw (0x002a);
  5641. dl (0x137c000e); dw (0x002b);
  5642. dw (RTS);
  5643. /* GetPixelClock
  5644. move.l #CLOCK,D0 ; fill in D0 with our one true pixel clock
  5645. rts
  5646. */
  5647. PUTABI (PSSO_BoardInfo_GetPixelClock);
  5648. dw (0x203c);
  5649. dl (100227260);
  5650. dw (RTS);
  5651. /* CalculateMemory
  5652. ; this is simple, because we're not supporting planar modes in UAE
  5653. move.l a1,d0
  5654. rts
  5655. */
  5656. PUTABI (PSSO_BoardInfo_CalculateMemory);
  5657. dw (0x2009);
  5658. dw (RTS);
  5659. /* GetCompatibleFormats
  5660. ; all formats can coexist without any problems, since we don't support planar stuff in UAE
  5661. move.l #RGBMASK_8BIT | RGBMASK_15BIT | RGBMASK_16BIT | RGBMASK_24BIT | RGBMASK_32BIT,d0
  5662. rts
  5663. */
  5664. PUTABI (PSSO_BoardInfo_GetCompatibleFormats);
  5665. dw (0x203c);
  5666. dl (RGBMASK_8BIT | RGBMASK_15BIT | RGBMASK_16BIT | RGBMASK_24BIT | RGBMASK_32BIT | (OVERLAY ? (RGBFF_Y4U2V2 | RGBFF_Y4U1V1) : 0));
  5667. dw (RTS);
  5668. /* CalculateBytesPerRow (optimized) */
  5669. PUTABI (PSSO_BoardInfo_CalculateBytesPerRow);
  5670. dl(0x0c400140); // cmp.w #320,d0
  5671. uaecptr addr = here();
  5672. dw(0);
  5673. calltrap (deftrap (picasso_CalculateBytesPerRow));
  5674. uaecptr addr2 = here();
  5675. org(addr);
  5676. dw(0x6500 | (addr2 - addr)); // bcs.s .l1
  5677. org(addr2);
  5678. dw(RTS);
  5679. dw(0x0c87); dl (0x00000010); // l1: cmp.l #$10,d7
  5680. dw(0x640a); // bcc.s .l2
  5681. dw(0x7200); // moveq #0,d1
  5682. dl(0x123b7010); // move.b table(pc,d7.w),d1
  5683. dw(0x6b04); // bmi.s l3
  5684. dw(0xe368); // lsl.w d1,d0
  5685. dw(RTS); // .l2
  5686. dw(0x3200); // .l3 move.w d0,d1
  5687. dw(0xd041); // add.w d1,d0
  5688. dw(0xd041); // add.w d1,d0
  5689. dw(RTS);
  5690. dl(0x0000ffff); // table
  5691. dl(0x01010202);
  5692. dl(0x02020101);
  5693. dl(0x01010100);
  5694. //RTGCALL2(PSSO_BoardInfo_SetClock, picasso_SetClock);
  5695. //RTGCALL2(PSSO_BoardInfo_SetMemoryMode, picasso_SetMemoryMode);
  5696. RTGNONE(PSSO_BoardInfo_SetClock);
  5697. RTGNONE(PSSO_BoardInfo_SetMemoryMode);
  5698. RTGNONE(PSSO_BoardInfo_SetWriteMask);
  5699. RTGNONE(PSSO_BoardInfo_SetClearMask);
  5700. RTGNONE(PSSO_BoardInfo_SetReadPlane);
  5701. #if 1
  5702. RTGNONE(PSSO_BoardInfo_WaitVerticalSync);
  5703. #else
  5704. PUTABI (PSSO_BoardInfo_WaitVerticalSync);
  5705. dl (0x48e7203e); // movem.l d2/a5/a6,-(sp)
  5706. dl (0x2c68003c);
  5707. dw (0x93c9);
  5708. dl (0x4eaefeda);
  5709. dw (0x2440);
  5710. dw (0x70ff);
  5711. dl (0x4eaefeb6);
  5712. dw (0x7400);
  5713. dw (0x1400);
  5714. dw (0x6b40);
  5715. dw (0x49f9);
  5716. dl (uaegfx_base + CARD_VSYNCLIST);
  5717. dw (0x47f9);
  5718. dl (uaegfx_base + CARD_VSYNCLIST + CARD_VSYNCMAX * 8);
  5719. dl (0x4eaeff88);
  5720. dw (0xb9cb);
  5721. dw (0x6606);
  5722. dl (0x4eaeff82);
  5723. dw (0x601c);
  5724. dw (0x4a94);
  5725. dw (0x6704);
  5726. dw (0x508c);
  5727. dw (0x60ee);
  5728. dw (0x288a);
  5729. dl (0x29420004);
  5730. dl (0x4eaeff82);
  5731. dw (0x7000);
  5732. dw (0x05c0);
  5733. dl (0x4eaefec2);
  5734. dw (0x4294);
  5735. dw (0x7000);
  5736. dw (0x1002);
  5737. dw (0x6b04);
  5738. dl (0x4eaefeb0);
  5739. dl (0x4cdf7c04);
  5740. dw (RTS);
  5741. #endif
  5742. RTGNONE(PSSO_BoardInfo_WaitBlitter);
  5743. #if 0
  5744. RTGCALL2(PSSO_BoardInfo_, picasso_);
  5745. RTGCALL(PSSO_BoardInfo_, PSSO_BoardInfo_Default, picasso_);
  5746. RTGCALLDEFAULT(PSSO_BoardInfo_, PSSO_BoardInfo_Default);
  5747. #endif
  5748. #if 0
  5749. RTGCALLONLYDEFAULT(PSSO_BoardInfo_BlitPlanar2Direct, PSSO_BoardInfo_BlitPlanar2DirectDefault, picasso_BlitPlanar2Direct);
  5750. RTGCALLONLYDEFAULT(PSSO_BoardInfo_FillRect, PSSO_BoardInfo_FillRectDefault, picasso_FillRect);
  5751. RTGCALLONLYDEFAULT(PSSO_BoardInfo_BlitRect, PSSO_BoardInfo_BlitRectDefault, picasso_BlitRect);
  5752. RTGCALLONLYDEFAULT(PSSO_BoardInfo_BlitPlanar2Chunky, PSSO_BoardInfo_BlitPlanar2ChunkyDefault, picasso_BlitPlanar2Chunky);
  5753. RTGCALLONLYDEFAULT(PSSO_BoardInfo_BlitTemplate, PSSO_BoardInfo_BlitTemplateDefault, picasso_BlitTemplate);
  5754. RTGCALLONLYDEFAULT(PSSO_BoardInfo_InvertRect, PSSO_BoardInfo_InvertRectDefault, picasso_InvertRect);
  5755. RTGCALLONLYDEFAULT(PSSO_BoardInfo_BlitRectNoMaskComplete, PSSO_BoardInfo_BlitRectNoMaskCompleteDefault, picasso_BlitRectNoMaskComplete);
  5756. RTGCALL(PSSO_BoardInfo_BlitPattern, PSSO_BoardInfo_BlitPatternDefault, picasso_BlitPattern);
  5757. RTGCALL2(PSSO_BoardInfo_SetSwitch, picasso_SetSwitch);
  5758. RTGCALL2(PSSO_BoardInfo_SetColorArray, picasso_SetColorArray);
  5759. RTGCALL2(PSSO_BoardInfo_SetDAC, picasso_SetDAC);
  5760. RTGCALL2(PSSO_BoardInfo_SetGC, picasso_SetGC);
  5761. RTGCALL2(PSSO_BoardInfo_SetPanning, picasso_SetPanning);
  5762. RTGCALL2(PSSO_BoardInfo_SetDisplay, picasso_SetDisplay);
  5763. RTGCALL2(PSSO_BoardInfo_SetSprite, picasso_SetSprite);
  5764. RTGCALL2(PSSO_BoardInfo_SetSpritePosition, picasso_SetSpritePosition);
  5765. RTGCALL2(PSSO_BoardInfo_SetSpriteImage, picasso_SetSpriteImage);
  5766. RTGCALL2(PSSO_BoardInfo_SetSpriteColor, picasso_SetSpriteColor);
  5767. RTGCALLDEFAULT(PSSO_BoardInfo_ScrollPlanar, PSSO_BoardInfo_ScrollPlanarDefault);
  5768. RTGCALLDEFAULT(PSSO_BoardInfo_UpdatePlanar, PSSO_BoardInfo_UpdatePlanarDefault);
  5769. RTGCALLDEFAULT(PSSO_BoardInfo_DrawLine, PSSO_BoardInfo_DrawLineDefault);
  5770. #else
  5771. RTGCALL(PSSO_BoardInfo_BlitPlanar2Direct, PSSO_BoardInfo_BlitPlanar2DirectDefault, picasso_BlitPlanar2Direct);
  5772. RTGCALL(PSSO_BoardInfo_FillRect, PSSO_BoardInfo_FillRectDefault, picasso_FillRect);
  5773. RTGCALL(PSSO_BoardInfo_BlitRect, PSSO_BoardInfo_BlitRectDefault, picasso_BlitRect);
  5774. RTGCALL(PSSO_BoardInfo_BlitPlanar2Chunky, PSSO_BoardInfo_BlitPlanar2ChunkyDefault, picasso_BlitPlanar2Chunky);
  5775. RTGCALL(PSSO_BoardInfo_BlitTemplate, PSSO_BoardInfo_BlitTemplateDefault, picasso_BlitTemplate);
  5776. RTGCALL(PSSO_BoardInfo_InvertRect, PSSO_BoardInfo_InvertRectDefault, picasso_InvertRect);
  5777. RTGCALL(PSSO_BoardInfo_BlitRectNoMaskComplete, PSSO_BoardInfo_BlitRectNoMaskCompleteDefault, picasso_BlitRectNoMaskComplete);
  5778. RTGCALL(PSSO_BoardInfo_BlitPattern, PSSO_BoardInfo_BlitPatternDefault, picasso_BlitPattern);
  5779. RTGCALL2(PSSO_BoardInfo_SetSwitch, picasso_SetSwitch);
  5780. RTGCALL2(PSSO_BoardInfo_SetColorArray, picasso_SetColorArray);
  5781. RTGCALL2(PSSO_BoardInfo_SetDAC, picasso_SetDAC);
  5782. RTGCALL2(PSSO_BoardInfo_SetGC, picasso_SetGC);
  5783. RTGCALL2(PSSO_BoardInfo_SetPanning, picasso_SetPanning);
  5784. RTGCALL2(PSSO_BoardInfo_SetDisplay, picasso_SetDisplay);
  5785. RTGCALL2(PSSO_BoardInfo_SetSprite, picasso_SetSprite);
  5786. RTGCALL2(PSSO_BoardInfo_SetSpritePosition, picasso_SetSpritePosition);
  5787. RTGCALL2(PSSO_BoardInfo_SetSpriteImage, picasso_SetSpriteImage);
  5788. RTGCALL2(PSSO_BoardInfo_SetSpriteColor, picasso_SetSpriteColor);
  5789. RTGCALLDEFAULT(PSSO_BoardInfo_ScrollPlanar, PSSO_BoardInfo_ScrollPlanarDefault);
  5790. RTGCALLDEFAULT(PSSO_BoardInfo_UpdatePlanar, PSSO_BoardInfo_UpdatePlanarDefault);
  5791. RTGCALLDEFAULT(PSSO_BoardInfo_DrawLine, PSSO_BoardInfo_DrawLineDefault);
  5792. #if OVERLAY
  5793. RTGCALL2(PSSO_BoardInfo_GetFeatureAttrs, picasso_GetFeatureAttrs);
  5794. RTGCALL2(PSSO_BoardInfo_SetFeatureAttrs, picasso_SetFeatureAttrs);
  5795. RTGCALL2X(PSSO_BoardInfo_CreateFeature, picasso_CreateFeature);
  5796. RTGCALL2X(PSSO_BoardInfo_DeleteFeature, picasso_DeleteFeature);
  5797. #endif
  5798. RTGCALL2(PSSO_SetSplitPosition, picasso_SetSplitPosition);
  5799. #endif
  5800. if (currprefs.rtg_hardwareinterrupt)
  5801. RTGCALL2(PSSO_BoardInfo_SetInterrupt, picasso_SetInterrupt);
  5802. write_log (_T("uaegfx.card magic code: %08X-%08X BI=%08X\n"), start, here (), ABI);
  5803. if (ABI && currprefs.rtg_hardwareinterrupt)
  5804. initvblankABI(ctx, uaegfx_base, ABI);
  5805. }
  5806. static void picasso_reset2(int monid)
  5807. {
  5808. struct picasso96_state_struct *state = &picasso96_state[monid];
  5809. if (!monid && currprefs.rtg_multithread) {
  5810. if (!render_pipe) {
  5811. InitializeCriticalSection(&render_cs);
  5812. render_pipe = xmalloc(smp_comm_pipe, 1);
  5813. init_comm_pipe(render_pipe, 10, 1);
  5814. }
  5815. if (render_thread_state <= 0) {
  5816. render_thread_state = 0;
  5817. uae_start_thread(_T("rtg"), render_thread, NULL, NULL);
  5818. }
  5819. }
  5820. lockrtg();
  5821. rtg_index = -1;
  5822. if (savestate_state != STATE_RESTORE) {
  5823. uaegfx_base = 0;
  5824. uaegfx_old = 0;
  5825. uaegfx_active = 0;
  5826. overlay_bitmap = 0;
  5827. overlay_vram = 0;
  5828. overlay_active = 0;
  5829. interrupt_enabled = 0;
  5830. reserved_gfxmem = 0;
  5831. resetpalette(state);
  5832. state->dualclut = false;
  5833. InitPicasso96(monid);
  5834. }
  5835. if (is_uaegfx_active() && currprefs.rtgboards[0].monitor_id > 0) {
  5836. close_rtg(currprefs.rtgboards[0].monitor_id, true);
  5837. }
  5838. for (int i = 0; i < MAX_AMIGADISPLAYS; i++) {
  5839. struct amigadisplay *ad = &adisplays[i];
  5840. ad->picasso_requested_on = false;
  5841. }
  5842. unlockrtg();
  5843. }
  5844. static void picasso_reset(int hardreset)
  5845. {
  5846. for (int i = 0; i < MAX_AMIGADISPLAYS; i++) {
  5847. picasso_reset2(i);
  5848. }
  5849. }
  5850. static void picasso_free(void)
  5851. {
  5852. if (render_thread_state > 0) {
  5853. write_comm_pipe_int(render_pipe, -1, 0);
  5854. while (render_thread_state >= 0) {
  5855. Sleep(10);
  5856. }
  5857. render_thread_state = 0;
  5858. }
  5859. }
  5860. void uaegfx_install_code (uaecptr start)
  5861. {
  5862. uaegfx_rom = start;
  5863. org (start);
  5864. inituaegfxfuncs(NULL, start, 0);
  5865. device_add_reset(picasso_reset);
  5866. device_add_hsync(picasso_handle_hsync);
  5867. device_add_exit(picasso_free);
  5868. }
  5869. #define UAEGFX_VERSION 3
  5870. #define UAEGFX_REVISION 4
  5871. static uae_u32 REGPARAM2 gfx_open(TrapContext *ctx)
  5872. {
  5873. trap_put_word(ctx, uaegfx_base + 32, trap_get_word(ctx, uaegfx_base + 32) + 1);
  5874. return uaegfx_base;
  5875. }
  5876. static uae_u32 REGPARAM2 gfx_close(TrapContext *ctx)
  5877. {
  5878. trap_put_word(ctx, uaegfx_base + 32, trap_get_word(ctx, uaegfx_base + 32) - 1);
  5879. return 0;
  5880. }
  5881. static uae_u32 REGPARAM2 gfx_expunge(TrapContext *ctx)
  5882. {
  5883. return 0;
  5884. }
  5885. static uaecptr uaegfx_card_install (TrapContext *ctx, uae_u32 extrasize)
  5886. {
  5887. uae_u32 functable, datatable, a2;
  5888. uaecptr openfunc, closefunc, expungefunc;
  5889. uaecptr findcardfunc, initcardfunc;
  5890. uaecptr exec = trap_get_long(ctx, 4);
  5891. if (uaegfx_old || !(gfxmem_bank.flags & ABFLAG_MAPPED))
  5892. return 0;
  5893. uaegfx_resid = ds (_T("UAE Graphics Card 3.4"));
  5894. uaegfx_vblankname = ds (_T("UAE Graphics Card VBLANK"));
  5895. uaegfx_portsname = ds (_T("UAE Graphics Card PORTS"));
  5896. /* Open */
  5897. openfunc = here ();
  5898. calltrap (deftrap (gfx_open)); dw (RTS);
  5899. /* Close */
  5900. closefunc = here ();
  5901. calltrap (deftrap (gfx_close)); dw (RTS);
  5902. /* Expunge */
  5903. expungefunc = here ();
  5904. calltrap (deftrap (gfx_expunge)); dw (RTS);
  5905. /* FindCard */
  5906. findcardfunc = here ();
  5907. calltrap (deftrap (picasso_FindCard)); dw (RTS);
  5908. /* InitCard */
  5909. initcardfunc = here ();
  5910. calltrap (deftrap (picasso_InitCard)); dw (RTS);
  5911. functable = here ();
  5912. dl (openfunc);
  5913. dl (closefunc);
  5914. dl (expungefunc);
  5915. dl (EXPANSION_nullfunc);
  5916. dl (findcardfunc);
  5917. dl (initcardfunc);
  5918. dl (0xFFFFFFFF); /* end of table */
  5919. datatable = makedatatable (uaegfx_resid, uaegfx_resname, 0x09, -50, UAEGFX_VERSION, UAEGFX_REVISION);
  5920. a2 = trap_get_areg(ctx, 2);
  5921. #if NEWTRAP
  5922. trap_call_add_areg(ctx, 0, functable);
  5923. trap_call_add_areg(ctx, 1, datatable);
  5924. trap_call_add_areg(ctx, 2, 0);
  5925. trap_call_add_dreg(ctx, 0, CARD_SIZEOF + extrasize);
  5926. trap_call_add_dreg(ctx, 1, 0);
  5927. uaegfx_base = trap_call_lib(ctx, exec, -0x54); /* MakeLibrary */
  5928. #else
  5929. trap_set_areg(ctx, 0, functable);
  5930. trap_set_areg(ctx, 1, datatable);
  5931. trap_set_areg(ctx, 2, 0);
  5932. trap_set_dreg(ctx, 0, CARD_SIZEOF + extrasize);
  5933. trap_set_dreg(ctx, 1, 0);
  5934. uaegfx_base = CallLib(ctx, exec, -0x54); /* MakeLibrary */
  5935. #endif
  5936. trap_set_areg(ctx, 2, a2);
  5937. if (!uaegfx_base)
  5938. return 0;
  5939. #if NEWTRAP
  5940. trap_call_add_areg(ctx, 1, uaegfx_base);
  5941. trap_call_lib(ctx, exec, -0x18c); /* AddLibrary */
  5942. #else
  5943. trap_set_areg(ctx, 1, uaegfx_base);
  5944. CallLib (ctx, exec, -0x18c); /* AddLibrary */
  5945. #endif
  5946. #if NEWTRAP
  5947. trap_call_add_areg(ctx, 1, EXPANSION_explibname);
  5948. trap_call_add_dreg(ctx, 0, 0);
  5949. uae_u32 lib = trap_call_lib(ctx, exec, -0x228); /* OpenLibrary */
  5950. #else
  5951. trap_set_areg(ctx, 1, EXPANSION_explibname);
  5952. trap_set_dreg(ctx, 0, 0);
  5953. uae_u32 lib = CallLib(ctx, exec, -0x228); /* OpenLibrary */
  5954. #endif
  5955. trap_put_long(ctx, uaegfx_base + CARD_EXPANSIONBASE, lib); /* OpenLibrary */
  5956. trap_put_long(ctx, uaegfx_base + CARD_EXECBASE, exec);
  5957. trap_put_long(ctx, uaegfx_base + CARD_IRQEXECBASE, exec);
  5958. trap_put_long(ctx, uaegfx_base + CARD_NAME, uaegfx_resname);
  5959. trap_put_long(ctx, uaegfx_base + CARD_RESLIST, uaegfx_base + CARD_SIZEOF);
  5960. trap_put_long(ctx, uaegfx_base + CARD_RESLISTSIZE, extrasize);
  5961. if (currprefs.rtg_hardwareinterrupt)
  5962. initvblankirq(ctx, uaegfx_base);
  5963. write_log (_T("uaegfx.card %d.%d init @%08X\n"), UAEGFX_VERSION, UAEGFX_REVISION, uaegfx_base);
  5964. uaegfx_active = 1;
  5965. return uaegfx_base;
  5966. }
  5967. uae_u32 picasso_demux (uae_u32 arg, TrapContext *ctx)
  5968. {
  5969. uae_u32 num = trap_get_long(ctx, trap_get_areg(ctx, 7) + 4);
  5970. if (uaegfx_base) {
  5971. if (num >= 16 && num <= 39) {
  5972. write_log (_T("uaelib: obsolete Picasso96 uaelib hook called, call ignored\n"));
  5973. return 0;
  5974. }
  5975. }
  5976. if (!uaegfx_old) {
  5977. write_log (_T("uaelib: uaelib hook in use\n"));
  5978. uaegfx_old = 1;
  5979. uaegfx_active = 1;
  5980. }
  5981. switch (num)
  5982. {
  5983. case 16: return picasso_FindCard (ctx);
  5984. case 17: return picasso_FillRect (ctx);
  5985. case 18: return picasso_SetSwitch (ctx);
  5986. case 19: return picasso_SetColorArray (ctx);
  5987. case 20: return picasso_SetDAC (ctx);
  5988. case 21: return picasso_SetGC (ctx);
  5989. case 22: return picasso_SetPanning (ctx);
  5990. case 23: return picasso_CalculateBytesPerRow (ctx);
  5991. case 24: return picasso_BlitPlanar2Chunky (ctx);
  5992. case 25: return picasso_BlitRect (ctx);
  5993. case 26: return picasso_SetDisplay (ctx);
  5994. case 27: return picasso_BlitTemplate (ctx);
  5995. case 28: return picasso_BlitRectNoMaskComplete (ctx);
  5996. case 29: return picasso_InitCard (ctx);
  5997. case 30: return picasso_BlitPattern (ctx);
  5998. case 31: return picasso_InvertRect (ctx);
  5999. case 32: return picasso_BlitPlanar2Direct (ctx);
  6000. //case 34: return picasso_WaitVerticalSync (ctx);
  6001. case 35: return gfxmem_bank.allocated_size ? 1 : 0;
  6002. case 36: return picasso_SetSprite (ctx);
  6003. case 37: return picasso_SetSpritePosition (ctx);
  6004. case 38: return picasso_SetSpriteImage (ctx);
  6005. case 39: return picasso_SetSpriteColor (ctx);
  6006. }
  6007. return 0;
  6008. }
  6009. static uae_u32 p96_restored_flags;
  6010. void restore_p96_finish (void)
  6011. {
  6012. struct amigadisplay *ad = &adisplays[0];
  6013. struct picasso96_state_struct *state = &picasso96_state[0];
  6014. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[0];
  6015. init_alloc (NULL, 0);
  6016. if (uaegfx_rom && boardinfo) {
  6017. inituaegfxfuncs(NULL, uaegfx_rom, boardinfo);
  6018. ad->picasso_requested_on = !!(p96_restored_flags & 1);
  6019. vidinfo->picasso_active = ad->picasso_requested_on;
  6020. if (overlay_vram) {
  6021. overlay_vram_offset = overlay_vram - gfxmem_banks[0]->start;
  6022. overlay_convert = getconvert(overlay_format, picasso_vidinfo[0].pixbytes);
  6023. if (!p96_rgbx16_ovl)
  6024. p96_rgbx16_ovl = xcalloc(uae_u32, 65536);
  6025. alloc_colors_picasso(8, 8, 8, 16, 8, 0, overlay_format, p96_rgbx16_ovl);
  6026. picasso_palette(overlay_clutc, overlay_clut);
  6027. overlay_color = overlay_color_unswapped;
  6028. overlay_pix = GetBytesPerPixel(overlay_format);
  6029. endianswap(&overlay_color, picasso96_state[0].BytesPerPixel);
  6030. }
  6031. if (cursorvisible) {
  6032. setspriteimage(NULL, boardinfo);
  6033. }
  6034. set_config_changed();
  6035. }
  6036. #if 0
  6037. if (picasso_requested_on) {
  6038. picasso_on = true;
  6039. set_gc_called = 1;
  6040. init_picasso_screen ();
  6041. init_hz_p96 ();
  6042. picasso_refresh();
  6043. }
  6044. #endif
  6045. }
  6046. uae_u8 *restore_p96 (uae_u8 *src)
  6047. {
  6048. struct amigadisplay *ad = &adisplays[0];
  6049. struct picasso96_state_struct *state = &picasso96_state[0];
  6050. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[0];
  6051. uae_u32 flags;
  6052. int i;
  6053. if (restore_u32 () != 2)
  6054. return src;
  6055. InitPicasso96(0);
  6056. p96_restored_flags = flags = restore_u32 ();
  6057. hwsprite = !!(flags & 8);
  6058. cursorvisible = !!(flags & 16);
  6059. init_picasso_screen_called = 0;
  6060. set_gc_called = !!(flags & 2);
  6061. vidinfo->set_panning_called = !!(flags & 4);
  6062. interrupt_enabled = !!(flags & 32);
  6063. changed_prefs.rtgboards[0].rtgmem_size = restore_u32 ();
  6064. state->Address = restore_u32 ();
  6065. state->RGBFormat = (RGBFTYPE)restore_u32 ();
  6066. state->Width = restore_u16 ();
  6067. state->Height = restore_u16 ();
  6068. state->VirtualWidth = restore_u16 ();
  6069. state->VirtualHeight = restore_u16 ();
  6070. state->XOffset = restore_u16 ();
  6071. state->YOffset = restore_u16 ();
  6072. state->GC_Depth = restore_u8 ();
  6073. state->GC_Flags = restore_u8 ();
  6074. state->BytesPerRow = restore_u16 ();
  6075. state->BytesPerPixel = restore_u8 ();
  6076. uaegfx_base = restore_u32 ();
  6077. uaegfx_rom = restore_u32 ();
  6078. boardinfo = restore_u32 ();
  6079. for (i = 0; i < 4; i++)
  6080. cursorrgb[i] = restore_u32 ();
  6081. if (flags & 64) {
  6082. for (i = 0; i < 256; i++) {
  6083. state->CLUT[i].Red = restore_u8 ();
  6084. state->CLUT[i].Green = restore_u8 ();
  6085. state->CLUT[i].Blue = restore_u8 ();
  6086. }
  6087. }
  6088. if (flags & 128) {
  6089. overlay_bitmap = restore_u32();
  6090. overlay_vram = restore_u32();
  6091. overlay_format = restore_u32();
  6092. overlay_modeformat = restore_u32();
  6093. overlay_modeinfo = restore_u32();
  6094. overlay_color_unswapped = restore_u32();
  6095. overlay_active = restore_u8();
  6096. overlay_occlusion = restore_u8();
  6097. overlay_x = restore_u16();
  6098. overlay_y = restore_u16();
  6099. overlay_w = restore_u16();
  6100. overlay_h = restore_u16();
  6101. overlay_src_width_in = restore_u16();
  6102. overlay_src_height_in = restore_u16();
  6103. overlay_src_width = restore_u16();
  6104. overlay_src_height = restore_u16();
  6105. overlay_clipleft = restore_u16();
  6106. overlay_cliptop = restore_u16();
  6107. overlay_clipwidth = restore_u16();
  6108. overlay_clipheight = restore_u16();
  6109. overlay_brightness = restore_u16();
  6110. for (i = 0; i < 256; i++) {
  6111. overlay_clutc[i].Red = restore_u8();
  6112. overlay_clutc[i].Green = restore_u8();
  6113. overlay_clutc[i].Blue = restore_u8();
  6114. }
  6115. }
  6116. state->HostAddress = NULL;
  6117. picasso_SetPanningInit(state);
  6118. state->Extent = state->Address + state->BytesPerRow * state->VirtualHeight;
  6119. return src;
  6120. }
  6121. uae_u8 *save_p96 (int *len, uae_u8 *dstptr)
  6122. {
  6123. struct amigadisplay *ad = &adisplays[0];
  6124. struct picasso96_state_struct *state = &picasso96_state[0];
  6125. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[0];
  6126. uae_u8 *dstbak, *dst;
  6127. int i;
  6128. if (currprefs.rtgboards[0].rtgmem_size == 0)
  6129. return NULL;
  6130. if (dstptr)
  6131. dstbak = dst = dstptr;
  6132. else
  6133. dstbak = dst = xmalloc (uae_u8, 2 * 3 * 256 + 1000);
  6134. save_u32 (2);
  6135. save_u32 ((ad->picasso_on ? 1 : 0) | (set_gc_called ? 2 : 0) | (vidinfo->set_panning_called ? 4 : 0) |
  6136. (hwsprite ? 8 : 0) | (cursorvisible ? 16 : 0) | (interrupt_enabled ? 32 : 0) | 64 | 128);
  6137. save_u32 (currprefs.rtgboards[0].rtgmem_size);
  6138. save_u32 (state->Address);
  6139. save_u32 (state->RGBFormat);
  6140. save_u16 (state->Width);
  6141. save_u16 (state->Height);
  6142. save_u16 (state->VirtualWidth);
  6143. save_u16 (state->VirtualHeight);
  6144. save_u16 (state->XOffset);
  6145. save_u16 (state->YOffset);
  6146. save_u8 (state->GC_Depth);
  6147. save_u8 (state->GC_Flags);
  6148. save_u16 (state->BytesPerRow);
  6149. save_u8 (state->BytesPerPixel);
  6150. save_u32 (uaegfx_base);
  6151. save_u32 (uaegfx_rom);
  6152. save_u32 (boardinfo);
  6153. for (i = 0; i < 4; i++)
  6154. save_u32 (cursorrgb[i]);
  6155. for (i = 0; i < 256; i++) {
  6156. save_u8 (state->CLUT[i].Red);
  6157. save_u8 (state->CLUT[i].Green);
  6158. save_u8 (state->CLUT[i].Blue);
  6159. }
  6160. // overlay
  6161. save_u32(overlay_bitmap);
  6162. save_u32(overlay_vram);
  6163. save_u32(overlay_format);
  6164. save_u32(overlay_modeformat);
  6165. save_u32(overlay_modeinfo);
  6166. save_u32(overlay_color_unswapped);
  6167. save_u8(overlay_active);
  6168. save_u8(overlay_occlusion);
  6169. save_u16(overlay_x);
  6170. save_u16(overlay_y);
  6171. save_u16(overlay_w);
  6172. save_u16(overlay_h);
  6173. save_u16(overlay_src_width_in);
  6174. save_u16(overlay_src_height_in);
  6175. save_u16(overlay_src_width);
  6176. save_u16(overlay_src_height);
  6177. save_u16(overlay_clipleft);
  6178. save_u16(overlay_cliptop);
  6179. save_u16(overlay_clipwidth);
  6180. save_u16(overlay_clipheight);
  6181. save_u16(overlay_brightness);
  6182. for (i = 0; i < 256; i++) {
  6183. save_u8(overlay_clutc[i].Red);
  6184. save_u8(overlay_clutc[i].Green);
  6185. save_u8(overlay_clutc[i].Blue);
  6186. }
  6187. *len = dst - dstbak;
  6188. return dstbak;
  6189. }
  6190. #endif