|
|
1.1 root 1: /*
2: * UAE - The U*nix Amiga Emulator
3: *
4: * Picasso96 Support Module
5: *
6: * Copyright 1997 Brian King <[email protected], [email protected]>
7: *
8: * Theory of operation:
9: * On the Amiga side, a Picasso card consists mainly of a memory area that
10: * contains the frame buffer. On the UAE side, we allocate a block of memory
11: * that will hold the frame buffer. This block is in normal memory, it is
12: * never directly on the graphics card. All graphics operations, which are
13: * mainly reads and writes into this block and a few basic operations like
14: * filling a rectangle, operate on this block of memory.
15: * Since the memory is not on the graphics card, some work must be done to
16: * synchronize the display with the data in the Picasso frame buffer. There
17: * are various ways to do this. One possibility is to allocate a second
18: * buffer of the same size, and perform all write operations twice. Since
19: * we never read from the second buffer, it can actually be placed in video
20: * memory. The X11 driver could be made to use the Picasso frame buffer as
21: * the data buffer of an XImage, which could then be XPutImage()d from time
22: * to time. Another possibility is to translate all Picasso accesses into
23: * Xlib (or GDI, or whatever your graphics system is) calls. This possibility
24: * is a bit tricky, since there is a risk of generating very many single pixel
25: * accesses which may be rather slow.
26: *
27: * TODO:
28: * - add panning capability
1.1.1.3 root 29: * - we want to add a manual switch to override SetSwitch for hardware banging
30: * programs started from a Picasso workbench.
1.1 root 31: */
32:
33: #include "sysconfig.h"
34: #include "sysdeps.h"
35:
36: #include "config.h"
37: #include "options.h"
38: #include "threaddep/penguin.h"
39: #include "uae.h"
40: #include "memory.h"
41: #include "custom.h"
42: #include "readcpu.h"
43: #include "newcpu.h"
44: #include "xwin.h"
45: #include "picasso96.h"
46:
47: #ifdef PICASSO96
48:
1.1.1.4 root 49: /*#define P96TRACING_ENABLED */
50: #ifdef P96TRACING_ENABLED
51: #define P96TRACE(x) do { write_log x; } while(0)
52: #else
53: #define P96TRACE(x)
54: #endif
55:
1.1 root 56: static uae_u32 gfxmem_lget (uaecptr) REGPARAM;
57: static uae_u32 gfxmem_wget (uaecptr) REGPARAM;
58: static uae_u32 gfxmem_bget (uaecptr) REGPARAM;
59: static void gfxmem_lput (uaecptr, uae_u32) REGPARAM;
60: static void gfxmem_wput (uaecptr, uae_u32) REGPARAM;
61: static void gfxmem_bput (uaecptr, uae_u32) REGPARAM;
62: static int gfxmem_check (uaecptr addr, uae_u32 size) REGPARAM;
63: static uae_u8 *gfxmem_xlate (uaecptr addr) REGPARAM;
64:
65: static void write_gfx_long (uaecptr addr, uae_u32 value);
66: static void write_gfx_word (uaecptr addr, uae_u16 value);
67: static void write_gfx_byte (uaecptr addr, uae_u8 value);
68:
1.1.1.4 root 69: static uae_u8 all_ones_bitmap, all_zeros_bitmap;
1.1 root 70:
71: struct picasso96_state_struct picasso96_state;
72: struct picasso_vidbuf_description picasso_vidinfo;
73:
74: /* These are the maximum resolutions... They are filled in by GetSupportedResolutions() */
75: /* have to fill this in, otherwise problems occur
76: * @@@ ??? what problems?
77: */
78: struct ScreenResolution planar = { 320, 240 };
79: struct ScreenResolution chunky = { 640, 480 };
80: struct ScreenResolution hicolour = { 640, 480 };
81: struct ScreenResolution truecolour = { 640, 480 };
1.1.1.4 root 82: struct ScreenResolution alphacolour = { 640, 480 };
1.1 root 83:
84: uae_u16 picasso96_pixel_format = RGBFF_CHUNKY;
85:
86: struct PicassoResolution DisplayModes[MAX_PICASSO_MODES];
87:
88: static int mode_count = 0;
89:
90: static uae_u32 p2ctab[256][2];
91:
92: /*
93: * Debugging dumps
94: */
95:
96: static void DumpModeInfoStructure (uaecptr amigamodeinfoptr)
97: {
1.1.1.2 root 98: write_log ("ModeInfo Structure Dump:\n");
99: write_log (" Node.ln_Succ = 0x%x\n", get_long (amigamodeinfoptr));
100: write_log (" Node.ln_Pred = 0x%x\n", get_long (amigamodeinfoptr + 4));
101: write_log (" Node.ln_Type = 0x%x\n", get_byte (amigamodeinfoptr + 8));
102: write_log (" Node.ln_Pri = %d\n", get_byte (amigamodeinfoptr + 9));
103: /*write_log (" Node.ln_Name = %s\n", uaememptr->Node.ln_Name); */
104: write_log (" OpenCount = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_OpenCount));
105: write_log (" Active = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Active));
106: write_log (" Width = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_Width));
107: write_log (" Height = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_Height));
108: write_log (" Depth = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Depth));
109: write_log (" Flags = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Flags));
110: write_log (" HorTotal = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorTotal));
111: write_log (" HorBlankSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorBlankSize));
112: write_log (" HorSyncStart = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorSyncStart));
113: write_log (" HorSyncSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorSyncSize));
114: write_log (" HorSyncSkew = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_HorSyncSkew));
115: write_log (" HorEnableSkew = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_HorEnableSkew));
116: write_log (" VerTotal = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerTotal));
117: write_log (" VerBlankSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerBlankSize));
118: write_log (" VerSyncStart = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerSyncStart));
119: write_log (" VerSyncSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerSyncSize));
120: write_log (" Clock = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_first_union));
121: write_log (" ClockDivide = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_second_union));
122: write_log (" PixelClock = %d\n", get_long (amigamodeinfoptr + PSSO_ModeInfo_PixelClock));
1.1 root 123: }
124:
125: static void DumpLibResolutionStructure (uaecptr amigalibresptr)
126: {
127: int i;
128: uaecptr amigamodeinfoptr;
1.1.1.8 ! root 129: struct LibResolution *uaememptr = (struct LibResolution *) get_mem_bank (amigalibresptr).xlateaddr (amigalibresptr);
! 130:
1.1 root 131: return;
132:
1.1.1.2 root 133: write_log ("LibResolution Structure Dump:\n");
1.1 root 134:
135: if (get_long (amigalibresptr + PSSO_LibResolution_DisplayID) == 0xFFFFFFFF) {
1.1.1.2 root 136: write_log (" Finished With LibResolutions...\n");
1.1 root 137: } else {
1.1.1.2 root 138: write_log (" Name = %s\n", uaememptr->P96ID);
139: write_log (" DisplayID = 0x%x\n", get_long (amigalibresptr + PSSO_LibResolution_DisplayID));
140: write_log (" Width = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Width));
141: write_log (" Height = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Height));
142: write_log (" Flags = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Flags));
1.1 root 143: for (i = 0; i < MAXMODES; i++) {
1.1.1.8 ! root 144: amigamodeinfoptr = get_long (amigalibresptr + PSSO_LibResolution_Modes + i * 4);
1.1.1.2 root 145: write_log (" ModeInfo[%d] = 0x%x\n", i, amigamodeinfoptr);
1.1 root 146: if (amigamodeinfoptr)
1.1.1.2 root 147: DumpModeInfoStructure (amigamodeinfoptr);
1.1 root 148: }
1.1.1.2 root 149: write_log (" BoardInfo = 0x%x\n", get_long (amigalibresptr + PSSO_LibResolution_BoardInfo));
1.1 root 150: }
151: }
152:
1.1.1.4 root 153: static char binary_byte[9];
1.1 root 154:
155: static char *BuildBinaryString (uae_u8 value)
156: {
157: int i;
158: for (i = 0; i < 8; i++) {
159: binary_byte[i] = (value & (1 << (7 - i))) ? '#' : '.';
160: }
1.1.1.4 root 161: binary_byte[8] = '\0';
1.1 root 162: return binary_byte;
163: }
164:
165: static void DumpPattern (struct Pattern *patt)
166: {
167: uae_u8 *mem;
168: int row, col;
169: for (row = 0; row < (1 << patt->Size); row++) {
170: mem = patt->Memory + row * 2;
171: for (col = 0; col < 2; col++) {
1.1.1.2 root 172: write_log ("%s", BuildBinaryString (*mem++));
1.1 root 173: }
1.1.1.2 root 174: write_log ("\n");
1.1 root 175: }
176: }
177:
178: static void DumpTemplate (struct Template *tmp, uae_u16 w, uae_u16 h)
179: {
180: uae_u8 *mem = tmp->Memory;
181: int row, col, width;
182: width = (w + 7) >> 3;
1.1.1.2 root 183: write_log ("xoffset = %d, bpr = %d\n", tmp->XOffset, tmp->BytesPerRow);
1.1 root 184: for (row = 0; row < h; row++) {
185: mem = tmp->Memory + row * tmp->BytesPerRow;
186: for (col = 0; col < width; col++) {
1.1.1.2 root 187: write_log ("%s", BuildBinaryString (*mem++));
1.1 root 188: }
1.1.1.2 root 189: write_log ("\n");
1.1 root 190: }
191: }
192:
193: static void ShowSupportedResolutions (void)
194: {
195: int i;
1.1.1.8 ! root 196:
1.1 root 197: return;
198:
199: for (i = 0; i < mode_count; i++)
1.1.1.2 root 200: write_log ("%s\n", DisplayModes[i].name);
201: }
202:
203: static uae_u8 GetBytesPerPixel (uae_u32 RGBfmt)
204: {
205: switch (RGBfmt) {
1.1.1.8 ! root 206: case RGBFB_CLUT:
1.1.1.2 root 207: return 1;
208:
1.1.1.8 ! root 209: case RGBFB_A8R8G8B8:
! 210: case RGBFB_A8B8G8R8:
! 211: case RGBFB_R8G8B8A8:
! 212: case RGBFB_B8G8R8A8:
1.1.1.2 root 213: return 4;
214:
1.1.1.8 ! root 215: case RGBFB_B8G8R8:
! 216: case RGBFB_R8G8B8:
1.1.1.2 root 217: return 3;
218:
1.1.1.8 ! root 219: case RGBFB_R5G5B5:
! 220: case RGBFB_R5G6B5:
! 221: case RGBFB_R5G6B5PC:
! 222: case RGBFB_R5G5B5PC:
! 223: case RGBFB_B5G6R5PC:
! 224: case RGBFB_B5G5R5PC:
1.1.1.2 root 225: return 2;
1.1.1.8 ! root 226: default:
1.1.1.2 root 227: write_log ("ERROR - GetBytesPerPixel() was unsuccessful with 0x%x?!\n", RGBfmt);
228: return 0;
229: }
1.1 root 230: }
231:
232: /*
233: * Amiga <-> native structure conversion functions
234: */
235:
236: static int CopyRenderInfoStructureA2U (uaecptr amigamemptr, struct RenderInfo *ri)
237: {
238: uaecptr memp = get_long (amigamemptr + PSSO_RenderInfo_Memory);
239:
1.1.1.4 root 240: if (valid_address (memp, PSSO_RenderInfo_sizeof)) {
1.1 root 241: ri->Memory = get_real_address (memp);
242: ri->BytesPerRow = get_word (amigamemptr + PSSO_RenderInfo_BytesPerRow);
243: ri->RGBFormat = get_long (amigamemptr + PSSO_RenderInfo_RGBFormat);
244: return 1;
245: }
1.1.1.2 root 246: write_log ("ERROR - Invalid RenderInfo memory area...\n");
1.1 root 247: return 0;
248: }
249:
250: static int CopyPatternStructureA2U (uaecptr amigamemptr, struct Pattern *pattern)
251: {
252: uaecptr memp = get_long (amigamemptr + PSSO_Pattern_Memory);
1.1.1.4 root 253: if (valid_address (memp, PSSO_Pattern_sizeof)) {
1.1 root 254: pattern->Memory = get_real_address (memp);
255: pattern->XOffset = get_word (amigamemptr + PSSO_Pattern_XOffset);
256: pattern->YOffset = get_word (amigamemptr + PSSO_Pattern_YOffset);
257: pattern->FgPen = get_long (amigamemptr + PSSO_Pattern_FgPen);
258: pattern->BgPen = get_long (amigamemptr + PSSO_Pattern_BgPen);
259: pattern->Size = get_byte (amigamemptr + PSSO_Pattern_Size);
260: pattern->DrawMode = get_byte (amigamemptr + PSSO_Pattern_DrawMode);
261: return 1;
262: }
1.1.1.2 root 263: write_log ("ERROR - Invalid Pattern memory area...\n");
1.1 root 264: return 0;
265: }
266:
267: static void CopyColorIndexMappingA2U (uaecptr amigamemptr, struct ColorIndexMapping *cim)
268: {
269: int i;
270: cim->ColorMask = get_long (amigamemptr);
271: for (i = 0; i < 256; i++, amigamemptr += 4)
272: cim->Colors[i] = get_long (amigamemptr + 4);
273: }
274:
275: static int CopyBitMapStructureA2U (uaecptr amigamemptr, struct BitMap *bm)
276: {
277: int i;
278:
279: bm->BytesPerRow = get_word (amigamemptr + PSSO_BitMap_BytesPerRow);
280: bm->Rows = get_word (amigamemptr + PSSO_BitMap_Rows);
281: bm->Flags = get_byte (amigamemptr + PSSO_BitMap_Flags);
282: bm->Depth = get_byte (amigamemptr + PSSO_BitMap_Depth);
283:
284: for (i = 0; i < bm->Depth; i++) {
1.1.1.8 ! root 285: uaecptr plane = get_long (amigamemptr + PSSO_BitMap_Planes + i * 4);
1.1 root 286: switch (plane) {
1.1.1.8 ! root 287: case 0:
1.1 root 288: bm->Planes[i] = &all_zeros_bitmap;
289: break;
1.1.1.8 ! root 290: case 0xFFFFFFFF:
1.1 root 291: bm->Planes[i] = &all_ones_bitmap;
292: break;
1.1.1.8 ! root 293: default:
1.1 root 294: if (valid_address (plane, bm->BytesPerRow * bm->Rows))
295: bm->Planes[i] = get_real_address (plane);
296: else
297: return 0;
298: break;
299: }
300: }
301: return 1;
302: }
303:
304: static int CopyTemplateStructureA2U (uaecptr amigamemptr, struct Template *tmpl)
305: {
306: uaecptr memp = get_long (amigamemptr + PSSO_Template_Memory);
307:
1.1.1.8 ! root 308: if (valid_address (memp, 1 /* FIXME */ )) {
1.1 root 309: tmpl->Memory = get_real_address (memp);
310: tmpl->BytesPerRow = get_word (amigamemptr + PSSO_Template_BytesPerRow);
311: tmpl->XOffset = get_byte (amigamemptr + PSSO_Template_XOffset);
312: tmpl->DrawMode = get_byte (amigamemptr + PSSO_Template_DrawMode);
313: tmpl->FgPen = get_long (amigamemptr + PSSO_Template_FgPen);
314: tmpl->BgPen = get_long (amigamemptr + PSSO_Template_BgPen);
315: return 1;
316: }
1.1.1.2 root 317: write_log ("ERROR - Invalid Template memory area...\n");
1.1 root 318: return 0;
319: }
320:
321: static void CopyLibResolutionStructureU2A (struct LibResolution *libres, uaecptr amigamemptr)
322: {
323: char *uaememptr = 0;
324: int i;
325:
1.1.1.8 ! root 326: uaememptr = gfxmem_xlate (amigamemptr); /* I know that amigamemptr is inside my gfxmem chunk, so I can just do the xlate() */
! 327: memset (uaememptr, 0, PSSO_LibResolution_sizeof); /* zero out our LibResolution structure */
1.1.1.3 root 328: strcpy (uaememptr + PSSO_LibResolution_P96ID, libres->P96ID);
1.1.1.2 root 329: put_long (amigamemptr + PSSO_LibResolution_DisplayID, libres->DisplayID);
330: put_word (amigamemptr + PSSO_LibResolution_Width, libres->Width);
331: put_word (amigamemptr + PSSO_LibResolution_Height, libres->Height);
332: put_word (amigamemptr + PSSO_LibResolution_Flags, libres->Flags);
1.1 root 333: for (i = 0; i < MAXMODES; i++)
1.1.1.8 ! root 334: put_long (amigamemptr + PSSO_LibResolution_Modes + i * 4, libres->Modes[i]);
1.1 root 335: #if 0
1.1.1.2 root 336: put_long (amigamemptr, libres->Node.ln_Succ);
337: put_long (amigamemptr + 4, libres->Node.ln_Pred);
338: put_byte (amigamemptr + 8, libres->Node.ln_Type);
339: put_byte (amigamemptr + 9, libres->Node.ln_Pri);
1.1 root 340: #endif
1.1.1.2 root 341: put_long (amigamemptr + 10, amigamemptr + PSSO_LibResolution_P96ID);
342: put_long (amigamemptr + PSSO_LibResolution_BoardInfo, libres->BoardInfo);
1.1 root 343: }
344:
345: /* list is Amiga address of list, in correct endian format for UAE
346: * node is Amiga address of node, in correct endian format for UAE */
347: static void AmigaListAddTail (uaecptr list, uaecptr node)
348: {
349: uaecptr amigamemptr = 0;
350:
351: if (get_long (list + 8) == list) {
352: /* Empty list - set it up */
1.1.1.8 ! root 353: put_long (list, node); /* point the lh_Head to our new node */
! 354: put_long (list + 4, 0); /* set the lh_Tail to NULL */
! 355: put_long (list + 8, node); /* point the lh_TailPred to our new node */
1.1 root 356:
357: /* Adjust the new node - don't rely on it being zeroed out */
1.1.1.8 ! root 358: put_long (node, 0); /* ln_Succ */
! 359: put_long (node + 4, 0); /* ln_Pred */
1.1 root 360: } else {
1.1.1.8 ! root 361: amigamemptr = get_long (list + 8); /* get the lh_TailPred contents */
1.1 root 362:
1.1.1.8 ! root 363: put_long (list + 8, node); /* point the lh_TailPred to our new node */
1.1 root 364:
365: /* Adjust the previous lh_TailPred node */
1.1.1.8 ! root 366: put_long (amigamemptr, node); /* point the ln_Succ to our new node */
1.1 root 367:
368: /* Adjust the new node - don't rely on it being zeroed out */
1.1.1.8 ! root 369: put_long (node, 0); /* ln_Succ */
! 370: put_long (node + 4, amigamemptr); /* ln_Pred */
1.1 root 371: }
372: }
373:
374: /*
375: * Functions to perform an action on the real screen
376: */
377:
378: /*
379: * Fill a rectangle on the screen. src points to the start of a line of the
380: * filled rectangle in the frame buffer; it can be used as a memcpy source if
381: * there is no OS specific function to fill the rectangle.
382: */
383:
1.1.1.8 ! root 384: static void do_fillrect (uae_u8 * src, int x, int y, int width, int height)
1.1 root 385: {
386: uae_u8 *dst;
387: /* Try OS specific fillrect function here; and return if successful. */
388:
389: DX_Invalidate (y, y + height - 1);
1.1.1.8 ! root 390: if (!picasso_vidinfo.extra_mem)
1.1 root 391: return;
392:
393: width *= picasso96_state.BytesPerPixel;
1.1.1.2 root 394: dst = gfx_lock_picasso ();
1.1 root 395: if (!dst)
1.1.1.2 root 396: goto out;
1.1 root 397:
1.1.1.8 ! root 398: dst += y * picasso_vidinfo.rowbytes + x * picasso_vidinfo.pixbytes;
1.1.1.2 root 399: if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
400: while (height-- > 0) {
401: memcpy (dst, src, width);
402: dst += picasso_vidinfo.rowbytes;
403: }
404: } else {
405: int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
406: if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
407: abort ();
408:
409: while (height-- > 0) {
410: int i;
411: switch (psiz) {
1.1.1.8 ! root 412: case 2:
1.1.1.2 root 413: for (i = 0; i < width; i++)
1.1.1.8 ! root 414: *((uae_u16 *) dst + i) = picasso_vidinfo.clut[src[i]];
1.1.1.2 root 415: break;
1.1.1.8 ! root 416: case 4:
1.1.1.2 root 417: for (i = 0; i < width; i++)
1.1.1.8 ! root 418: *((uae_u32 *) dst + i) = picasso_vidinfo.clut[src[i]];
1.1.1.2 root 419: break;
1.1.1.8 ! root 420: default:
! 421: abort ();
1.1.1.2 root 422: }
423: dst += picasso_vidinfo.rowbytes;
424: }
1.1 root 425: }
1.1.1.8 ! root 426: out:
1.1.1.2 root 427: gfx_unlock_picasso ();
1.1 root 428: }
429:
430: /*
431: * This routine modifies the real screen buffer after a blit has been
432: * performed in the save area. If can_do_blit is nonzero, the blit can
433: * be performed within the real screen buffer; otherwise, this routine
434: * must do it by hand using the data in the save area, pointed to by
435: * srcp.
436: */
437:
1.1.1.8 ! root 438: static void do_blit (uae_u8 * srcp, unsigned long src_rowbytes,
! 439: int srcx, int srcy, int dstx, int dsty, int width, int height, int can_do_blit)
1.1 root 440: {
441: uae_u8 *dstp;
442: /* If this RenderInfo points at something else than the currently visible
443: * screen, we must ignore the blit. */
444: if (can_do_blit) {
445: /*
446: * Call OS blitting function that can do it in video memory.
447: * Should return if it was successful
448: */
449: }
450:
451: DX_Invalidate (dsty, dsty + height - 1);
1.1.1.8 ! root 452: if (!picasso_vidinfo.extra_mem)
1.1 root 453: return;
454:
1.1.1.2 root 455: dstp = gfx_lock_picasso ();
1.1 root 456: if (dstp == 0)
1.1.1.2 root 457: goto out;
1.1 root 458:
459: /* The areas can't overlap: the source is always in the Picasso frame buffer,
460: * and the destination is a different buffer owned by the graphics code. */
461:
1.1.1.2 root 462: dstp += dsty * picasso_vidinfo.rowbytes + dstx * picasso_vidinfo.pixbytes;
463: if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
464: width *= picasso96_state.BytesPerPixel;
465: while (height-- > 0) {
466: memcpy (dstp, srcp, width);
467: srcp += src_rowbytes;
468: dstp += picasso_vidinfo.rowbytes;
469: }
470: } else {
471: int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
472: if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
473: abort ();
474:
475: while (height-- > 0) {
476: int i;
477: switch (psiz) {
1.1.1.8 ! root 478: case 2:
1.1.1.2 root 479: for (i = 0; i < width; i++)
1.1.1.8 ! root 480: *((uae_u16 *) dstp + i) = picasso_vidinfo.clut[srcp[i]];
1.1.1.2 root 481: break;
1.1.1.8 ! root 482: case 4:
1.1.1.2 root 483: for (i = 0; i < width; i++)
1.1.1.8 ! root 484: *((uae_u32 *) dstp + i) = picasso_vidinfo.clut[srcp[i]];
1.1.1.2 root 485: break;
1.1.1.8 ! root 486: default:
! 487: abort ();
1.1.1.2 root 488: }
489: srcp += src_rowbytes;
490: dstp += picasso_vidinfo.rowbytes;
491: }
1.1 root 492: }
1.1.1.8 ! root 493: out:
1.1.1.2 root 494: gfx_unlock_picasso ();
1.1 root 495: }
496:
497: /*
498: * Invert a rectangle on the screen. src and src_rowbytes describe the
499: * inverted rectangle in the frame buffer, so that do_blit can be used if
500: * there is no OS specific function to fill the rectangle.
501: */
502:
1.1.1.8 ! root 503: static void do_invertrect (uae_u8 * src, unsigned long src_rowbytes, int x, int y, int width, int height)
1.1 root 504: {
1.1.1.2 root 505: /* TODO: Try OS specific invertrect function here; and return if successful. */
1.1 root 506:
507: do_blit (src, src_rowbytes, 0, 0, x, y, width, height, 0);
508: }
509:
510: static uaecptr wgfx_linestart;
511: static uaecptr wgfx_lineend;
512: static uaecptr wgfx_min, wgfx_max;
513: static unsigned long wgfx_y;
514:
515: static void wgfx_do_flushline (void)
516: {
517: uae_u8 *src, *dstp;
518:
519: DX_Invalidate (wgfx_y, wgfx_y);
1.1.1.8 ! root 520: if (!picasso_vidinfo.extra_mem)
1.1 root 521: goto out;
522:
1.1.1.2 root 523: dstp = gfx_lock_picasso ();
1.1 root 524: if (dstp == 0)
525: goto out;
526: /*printf("flushing %d (%x %x %x)\n", wgfx_y, wgfx_linestart, wgfx_min, wgfx_max); */
1.1.1.2 root 527: src = gfxmemory + wgfx_min;
1.1 root 528:
1.1.1.2 root 529: if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
530: dstp += wgfx_y * picasso_vidinfo.rowbytes + wgfx_min - wgfx_linestart;
531: memcpy (dstp, src, wgfx_max - wgfx_min);
532: } else {
533: int width = wgfx_max - wgfx_min;
534: int i;
535: int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
536:
537: if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
538: abort ();
539:
540: dstp += wgfx_y * picasso_vidinfo.rowbytes + (wgfx_min - wgfx_linestart) * psiz;
541: switch (psiz) {
1.1.1.8 ! root 542: case 2:
1.1.1.2 root 543: for (i = 0; i < width; i++)
1.1.1.8 ! root 544: *((uae_u16 *) dstp + i) = picasso_vidinfo.clut[src[i]];
1.1.1.2 root 545: break;
1.1.1.8 ! root 546: case 4:
1.1.1.2 root 547: for (i = 0; i < width; i++)
1.1.1.8 ! root 548: *((uae_u32 *) dstp + i) = picasso_vidinfo.clut[src[i]];
1.1.1.2 root 549: break;
1.1.1.8 ! root 550: default:
! 551: abort ();
1.1.1.2 root 552: }
553: }
1.1 root 554:
1.1.1.8 ! root 555: out:
1.1.1.2 root 556: gfx_unlock_picasso ();
1.1 root 557: wgfx_linestart = 0xFFFFFFFF;
558: }
559:
1.1.1.7 root 560: STATIC_INLINE void wgfx_flushline (void)
1.1 root 561: {
1.1.1.8 ! root 562: if (wgfx_linestart == 0xFFFFFFFF || !picasso_on)
1.1 root 563: return;
564: wgfx_do_flushline ();
565: }
566:
567: static int renderinfo_is_current_screen (struct RenderInfo *ri)
568: {
1.1.1.8 ! root 569: if (!picasso_on)
1.1 root 570: return 0;
1.1.1.3 root 571: if (ri->Memory != gfxmemory + (picasso96_state.Address - gfxmem_start))
1.1 root 572: return 0;
1.1.1.3 root 573:
1.1 root 574: return 1;
575: }
576:
577: /* Clear our screen, since we've got a new Picasso screen-mode, and refresh with the proper contents
1.1.1.2 root 578: * This is called on several occasions:
579: * 1. Amiga-->Picasso transition, via SetSwitch()
580: * 2. Picasso-->Picasso transition, via SetPanning().
581: * 3. whenever the graphics code notifies us that the screen contents have been lost.
582: */
583: void picasso_refresh (void)
1.1 root 584: {
585: struct RenderInfo ri;
586:
1.1.1.8 ! root 587: if (!picasso_on)
1.1 root 588: return;
589:
590: /* Make sure that the first time we show a Picasso video mode, we don't blit any crap.
591: * We can do this by checking if we have an Address yet. */
592: if (picasso96_state.Address) {
593: /* blit the stuff from our static frame-buffer to the gfx-card */
594: uae_u8 *ptr = gfxmemory + (picasso96_state.Address - gfxmem_start);
595: ri.BytesPerRow = picasso96_state.BytesPerRow;
596: ri.RGBFormat = picasso96_state.RGBFormat;
1.1.1.8 ! root 597: do_blit (ptr, picasso96_state.BytesPerRow, 0, 0, 0, 0, picasso96_state.Width, picasso96_state.Height, 0);
1.1.1.2 root 598: write_log ("picasso_refresh() successful.\n");
1.1 root 599: } else
1.1.1.2 root 600: write_log ("ERROR - picasso_refresh() can't refresh!\n");
1.1 root 601: }
602:
603: /*
604: * BOOL FindCard(struct BoardInfo *bi); and
605: *
606: * FindCard is called in the first stage of the board initialisation and
607: * configuration and is used to look if there is a free and unconfigured
608: * board of the type the driver is capable of managing. If it finds one,
609: * it immediately reserves it for use by Picasso96, usually by clearing
610: * the CDB_CONFIGME bit in the flags field of the ConfigDev struct of
611: * this expansion card. But this is only a common example, a driver can
612: * do whatever it wants to mark this card as used by the driver. This
613: * mechanism is intended to ensure that a board is only configured and
614: * used by one driver. FindBoard also usually fills some fields of the
615: * BoardInfo struct supplied by the caller, the rtg.library, for example
616: * the MemoryBase, MemorySize and RegisterBase fields.
617: */
618: uae_u32 picasso_FindCard (void)
619: {
1.1.1.2 root 620: uaecptr AmigaBoardInfo = m68k_areg (regs, 0);
1.1 root 621: /* NOTES: See BoardInfo struct definition in Picasso96 dev info */
622:
1.1.1.2 root 623: if (allocated_gfxmem && !picasso96_state.CardFound) {
1.1 root 624: /* Fill in MemoryBase, MemorySize */
1.1.1.2 root 625: put_long (AmigaBoardInfo + PSSO_BoardInfo_MemoryBase, gfxmem_start);
1.1 root 626: /* size of memory, minus a 32K chunk: 16K for pattern bitmaps, 16K for resolution list */
1.1.1.2 root 627: put_long (AmigaBoardInfo + PSSO_BoardInfo_MemorySize, allocated_gfxmem - 32768);
1.1 root 628:
1.1.1.8 ! root 629: picasso96_state.CardFound = 1; /* mark our "card" as being found */
1.1 root 630: return -1;
631: } else
632: return 0;
633: }
634:
635: static void FillBoardInfo (uaecptr amigamemptr, struct LibResolution *res, struct PicassoResolution *dm)
636: {
637: char *uaememptr;
638: switch (dm->depth) {
1.1.1.8 ! root 639: case 1:
1.1 root 640: res->Modes[CHUNKY] = amigamemptr;
641: break;
1.1.1.8 ! root 642: case 2:
1.1 root 643: res->Modes[HICOLOR] = amigamemptr;
644: break;
1.1.1.8 ! root 645: case 3:
1.1 root 646: res->Modes[TRUECOLOR] = amigamemptr;
647: break;
1.1.1.8 ! root 648: default:
1.1 root 649: res->Modes[TRUEALPHA] = amigamemptr;
650: break;
651: }
1.1.1.8 ! root 652: uaememptr = gfxmem_xlate (amigamemptr); /* I know that amigamemptr is inside my gfxmem chunk, so I can just do the xlate() */
! 653: memset (uaememptr, 0, PSSO_ModeInfo_sizeof); /* zero out our ModeInfo struct */
1.1 root 654:
1.1.1.2 root 655: put_word (amigamemptr + PSSO_ModeInfo_Width, dm->res.width);
656: put_word (amigamemptr + PSSO_ModeInfo_Height, dm->res.height);
657: put_byte (amigamemptr + PSSO_ModeInfo_Depth, dm->depth * 8);
658: put_byte (amigamemptr + PSSO_ModeInfo_Flags, 0);
659: put_word (amigamemptr + PSSO_ModeInfo_HorTotal, dm->res.width);
660: put_word (amigamemptr + PSSO_ModeInfo_HorBlankSize, 0);
661: put_word (amigamemptr + PSSO_ModeInfo_HorSyncStart, 0);
662: put_word (amigamemptr + PSSO_ModeInfo_HorSyncSize, 0);
663: put_byte (amigamemptr + PSSO_ModeInfo_HorSyncSkew, 0);
664: put_byte (amigamemptr + PSSO_ModeInfo_HorEnableSkew, 0);
665:
666: put_word (amigamemptr + PSSO_ModeInfo_VerTotal, dm->res.height);
667: put_word (amigamemptr + PSSO_ModeInfo_VerBlankSize, 0);
668: put_word (amigamemptr + PSSO_ModeInfo_VerSyncStart, 0);
669: put_word (amigamemptr + PSSO_ModeInfo_VerSyncSize, 0);
1.1 root 670:
1.1.1.2 root 671: put_byte (amigamemptr + PSSO_ModeInfo_first_union, 98);
672: put_byte (amigamemptr + PSSO_ModeInfo_second_union, 14);
1.1 root 673:
1.1.1.2 root 674: put_long (amigamemptr + PSSO_ModeInfo_PixelClock, dm->res.width * dm->res.height * dm->refresh);
1.1 root 675: }
676:
1.1.1.4 root 677: static uae_u32 AssignModeID (int i, int count)
678: {
679: if (DisplayModes[i].res.width == 320 && DisplayModes[i].res.height == 200)
680: return 0x50001000;
681: else if (DisplayModes[i].res.width == 320 && DisplayModes[i].res.height == 240)
682: return 0x50011000;
683: else if (DisplayModes[i].res.width == 640 && DisplayModes[i].res.height == 400)
684: return 0x50021000;
685: else if (DisplayModes[i].res.width == 640 && DisplayModes[i].res.height == 480)
686: return 0x50031000;
687: else if (DisplayModes[i].res.width == 800 && DisplayModes[i].res.height == 600)
688: return 0x50041000;
689: else if (DisplayModes[i].res.width == 1024 && DisplayModes[i].res.height == 768)
690: return 0x50051000;
691: else if (DisplayModes[i].res.width == 1152 && DisplayModes[i].res.height == 864)
692: return 0x50061000;
693: else if (DisplayModes[i].res.width == 1280 && DisplayModes[i].res.height == 1024)
694: return 0x50071000;
695: else if (DisplayModes[i].res.width == 1600 && DisplayModes[i].res.height == 1280)
696: return 0x50081000;
697:
698: return 0x50091000 + count * 0x10000;
699: }
700:
1.1 root 701: /****************************************
702: * InitCard()
703: *
704: * a2: BoardInfo structure ptr - Amiga-based address in Intel endian-format
705: *
706: * Job - fill in the following structure members:
707: * gbi_RGBFormats: the pixel formats that the host-OS of UAE supports
708: * If UAE is running in a window, it should ONLY report the pixel format of the host-OS desktop
709: * If UAE is running full-screen, it should report ALL pixel formats that the host-OS can handle in full-screen
710: * NOTE: If full-screen, and the user toggles to windowed-mode, all hell will break loose visually. Must inform
711: * user that they're doing something stupid (unless their desktop and full-screen colour modes match).
712: * gbi_SoftSpriteFlags: should be the same as above for now, until actual cursor support is added
713: * gbi_BitsPerCannon: could be 6 or 8 or ???, depending on the host-OS gfx-card
714: * gbi_MaxHorResolution: fill this in for all modes (even if you don't support them)
715: * gbi_MaxVerResolution: fill this in for all modes (even if you don't support them)
716: */
717: uae_u32 picasso_InitCard (void)
718: {
719: struct LibResolution res;
720: int i;
721: int ModeInfoStructureCount = 1, LibResolutionStructureCount = 0;
722: uaecptr amigamemptr = 0;
1.1.1.2 root 723: uaecptr AmigaBoardInfo = m68k_areg (regs, 2);
1.1.1.8 ! root 724: put_word (AmigaBoardInfo + PSSO_BoardInfo_BitsPerCannon, DX_BitsPerCannon ());
1.1.1.2 root 725: put_word (AmigaBoardInfo + PSSO_BoardInfo_RGBFormats, picasso96_pixel_format);
726: put_word (AmigaBoardInfo + PSSO_BoardInfo_SoftSpriteFlags, picasso96_pixel_format);
727: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 0, planar.width);
728: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 2, chunky.width);
729: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 4, hicolour.width);
730: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 6, truecolour.width);
731: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 8, alphacolour.width);
732: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 0, planar.height);
733: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 2, chunky.height);
734: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 4, hicolour.height);
735: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 6, truecolour.height);
736: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 8, alphacolour.height);
1.1 root 737:
738: for (i = 0; i < mode_count;) {
739: int j = i;
740: /* Add a LibResolution structure to the ResolutionsList MinList in our BoardInfo */
1.1.1.4 root 741: res.DisplayID = AssignModeID (i, LibResolutionStructureCount);
1.1 root 742: res.BoardInfo = AmigaBoardInfo;
743: res.Width = DisplayModes[i].res.width;
744: res.Height = DisplayModes[i].res.height;
745: res.Flags = P96F_PUBLIC;
746: res.P96ID[0] = 'P';
747: res.P96ID[1] = '9';
748: res.P96ID[2] = '6';
749: res.P96ID[3] = '-';
750: res.P96ID[4] = '0';
751: res.P96ID[5] = ':';
752: strcpy (res.Name, "uaegfx:");
1.1.1.3 root 753: strncat (res.Name, DisplayModes[i].name, strchr (DisplayModes[i].name, ',') - DisplayModes[i].name);
1.1 root 754: res.Modes[PLANAR] = 0;
755: res.Modes[CHUNKY] = 0;
756: res.Modes[HICOLOR] = 0;
757: res.Modes[TRUECOLOR] = 0;
758: res.Modes[TRUEALPHA] = 0;
759:
760: do {
761: /* Handle this display mode's depth */
1.1.1.2 root 762: amigamemptr = gfxmem_start + allocated_gfxmem - (PSSO_ModeInfo_sizeof * ModeInfoStructureCount++);
1.1.1.8 ! root 763: FillBoardInfo (amigamemptr, &res, &DisplayModes[i]);
1.1 root 764: i++;
765: } while (i < mode_count
766: && DisplayModes[i].res.width == DisplayModes[j].res.width
767: && DisplayModes[i].res.height == DisplayModes[j].res.height);
768:
1.1.1.2 root 769: amigamemptr = gfxmem_start + allocated_gfxmem - 16384 + (PSSO_LibResolution_sizeof * LibResolutionStructureCount++);
1.1 root 770: CopyLibResolutionStructureU2A (&res, amigamemptr);
1.1.1.8 ! root 771: DumpLibResolutionStructure (amigamemptr);
1.1 root 772: AmigaListAddTail (AmigaBoardInfo + PSSO_BoardInfo_ResolutionsList, amigamemptr);
773: }
774:
775: return 0;
776: }
777:
778: extern int x_size, y_size;
779:
780: /*
781: * SetSwitch:
782: * a0: struct BoardInfo
783: * d0.w: BOOL state
784: * this function should set a board switch to let the Amiga signal pass
785: * through when supplied with a 0 in d0 and to show the board signal if
786: * a 1 is passed in d0. You should remember the current state of the
787: * switch to avoid unneeded switching. If your board has no switch, then
788: * simply supply a function that does nothing except a RTS.
789: *
790: * NOTE: Return the opposite of the switch-state. BDK
791: */
792: uae_u32 picasso_SetSwitch (void)
793: {
1.1.1.2 root 794: uae_u16 flag = m68k_dreg (regs, 0) & 0xFFFF;
1.1 root 795:
796: /* Do not switch immediately. Tell the custom chip emulation about the
797: * desired state, and wait for custom.c to call picasso_enablescreen
798: * whenever it is ready to change the screen state. */
799: picasso_requested_on = !!flag;
1.1.1.8 ! root 800: write_log ("SetSwitch() - trying to show %s screen\n", flag ? "picasso96" : "amiga");
1.1 root 801:
802: /* Put old switch-state in D0 */
803: return !flag;
804: }
805:
806: void picasso_enablescreen (int on)
807: {
808: wgfx_linestart = 0xFFFFFFFF;
809: picasso_refresh ();
1.1.1.8 ! root 810: write_log ("SetSwitch() - showing %s screen\n", on ? "picasso96" : "amiga");
1.1 root 811: }
812:
813: /*
814: * SetColorArray:
815: * a0: struct BoardInfo
816: * d0.w: startindex
817: * d1.w: count
818: * when this function is called, your driver has to fetch "count" color
819: * values starting at "startindex" from the CLUT field of the BoardInfo
820: * structure and write them to the hardware. The color values are always
821: * between 0 and 255 for each component regardless of the number of bits
822: * per cannon your board has. So you might have to shift the colors
823: * before writing them to the hardware.
824: */
825: uae_u32 picasso_SetColorArray (void)
826: {
827: /* Fill in some static UAE related structure about this new CLUT setting
828: * We need this for CLUT-based displays, and for mapping CLUT to hi/true colour */
1.1.1.2 root 829: uae_u16 start = m68k_dreg (regs, 0);
830: uae_u16 count = m68k_dreg (regs, 1);
1.1 root 831: int i;
1.1.1.2 root 832: uaecptr boardinfo = m68k_areg (regs, 0);
1.1 root 833: uaecptr clut = boardinfo + PSSO_BoardInfo_CLUT + start * 3;
1.1.1.2 root 834: int changed = 0;
1.1 root 835:
836: for (i = start; i < start + count; i++) {
1.1.1.2 root 837: int r = get_byte (clut);
838: int g = get_byte (clut + 1);
839: int b = get_byte (clut + 2);
840:
1.1.1.8 ! root 841: changed |= (picasso96_state.CLUT[i].Red != r || picasso96_state.CLUT[i].Green != g || picasso96_state.CLUT[i].Blue != b);
! 842:
! 843: picasso96_state.CLUT[i].Red = r;
1.1.1.2 root 844: picasso96_state.CLUT[i].Green = g;
845: picasso96_state.CLUT[i].Blue = b;
1.1 root 846: clut += 3;
847: }
1.1.1.2 root 848: if (changed) {
849: DX_SetPalette (start, count);
1.1 root 850: }
1.1.1.2 root 851: /*write_log ("SetColorArray(%d,%d)\n", start, count); */
1.1.1.4 root 852: return 1;
1.1 root 853: }
854:
855: /*
856: * SetDAC:
857: * a0: struct BoardInfo
858: * d7: RGBFTYPE RGBFormat
859: * This function is called whenever the RGB format of the display changes,
860: * e.g. from chunky to TrueColor. Usually, all you have to do is to set
861: * the RAMDAC of your board accordingly.
862: */
863: uae_u32 picasso_SetDAC (void)
864: {
865: /* Fill in some static UAE related structure about this new DAC setting
866: * Lets us keep track of what pixel format the Amiga is thinking about in our frame-buffer */
867:
1.1.1.2 root 868: write_log ("SetDAC()\n");
1.1.1.4 root 869: return 1;
1.1 root 870: }
871:
1.1.1.6 root 872: static int set_gc_called = 0;
873: static int set_panning_called = 0;
874:
875: static void init_picasso_screen (void)
876: {
1.1.1.8 ! root 877: if (!set_gc_called)
1.1.1.6 root 878: return;
879:
880: if (set_panning_called)
881: picasso96_state.Extent = picasso96_state.Address + (picasso96_state.BytesPerRow * picasso96_state.Height);
882:
1.1.1.8 ! root 883: gfx_set_picasso_modeinfo (picasso96_state.Width, picasso96_state.Height, picasso96_state.GC_Depth, picasso96_state.RGBFormat);
1.1.1.6 root 884: DX_SetPalette (0, 256);
885:
886: wgfx_linestart = 0xFFFFFFFF;
887: picasso_refresh ();
888: }
889:
1.1 root 890: /*
891: * SetGC:
892: * a0: struct BoardInfo
893: * a1: struct ModeInfo
894: * d0: BOOL Border
895: * This function is called whenever another ModeInfo has to be set. This
896: * function simply sets up the CRTC and TS registers to generate the
897: * timing used for that screen mode. You should not set the DAC, clocks
898: * or linear start adress. They will be set when appropriate by their
899: * own functions.
900: */
901: uae_u32 picasso_SetGC (void)
902: {
903: /* Fill in some static UAE related structure about this new ModeInfo setting */
1.1.1.2 root 904: uaecptr modeinfo = m68k_areg (regs, 1);
1.1 root 905:
906: picasso96_state.Width = get_word (modeinfo + PSSO_ModeInfo_Width);
1.1.1.8 ! root 907: picasso96_state.VirtualWidth = picasso96_state.Width; /* in case SetPanning doesn't get called */
1.1 root 908:
909: picasso96_state.Height = get_word (modeinfo + PSSO_ModeInfo_Height);
910: picasso96_state.VirtualHeight = picasso96_state.Height;
911:
912: picasso96_state.GC_Depth = get_byte (modeinfo + PSSO_ModeInfo_Depth);
913: picasso96_state.GC_Flags = get_byte (modeinfo + PSSO_ModeInfo_Flags);
914:
1.1.1.2 root 915: write_log ("SetGC(%d,%d,%d)\n", picasso96_state.Width, picasso96_state.Height, picasso96_state.GC_Depth);
1.1 root 916:
1.1.1.8 ! root 917: set_gc_called = 1; /* @@@ when do we need to reset this? */
1.1.1.6 root 918: init_picasso_screen ();
1.1.1.4 root 919: return 1;
1.1 root 920: }
921:
922: /*
923: * SetPanning:
924: * a0: struct BoardInfo
925: * a1: UBYTE *Memory
926: * d0: uae_u16 Width
927: * d1: WORD XOffset
928: * d2: WORD YOffset
929: * d7: RGBFTYPE RGBFormat
930: * This function sets the view origin of a display which might also be
931: * overscanned. In register a1 you get the start address of the screen
932: * bitmap on the Amiga side. You will have to subtract the starting
933: * address of the board memory from that value to get the memory start
934: * offset within the board. Then you get the offset in pixels of the
935: * left upper edge of the visible part of an overscanned display. From
936: * these values you will have to calculate the LinearStartingAddress
937: * fields of the CRTC registers.
938:
939: * NOTE: SetPanning() can be used to know when a Picasso96 screen is
940: * being opened. Better to do the appropriate clearing of the
941: * background here than in SetSwitch() derived functions,
942: * because SetSwitch() is not called for subsequent Picasso screens.
943: */
944: uae_u32 picasso_SetPanning (void)
945: {
1.1.1.2 root 946: uae_u16 Width = m68k_dreg (regs, 0);
947: uaecptr start_of_screen = m68k_areg (regs, 1);
1.1 root 948:
1.1.1.8 ! root 949: picasso96_state.Address = start_of_screen; /* Amiga-side address */
! 950: picasso96_state.XOffset = (uae_s16) m68k_dreg (regs, 1);
! 951: picasso96_state.YOffset = (uae_s16) m68k_dreg (regs, 2);
1.1 root 952: picasso96_state.VirtualWidth = Width;
1.1.1.2 root 953: picasso96_state.RGBFormat = m68k_dreg (regs, 7);
954: picasso96_state.BytesPerPixel = GetBytesPerPixel (picasso96_state.RGBFormat);
1.1 root 955: picasso96_state.BytesPerRow = Width * picasso96_state.BytesPerPixel;
956:
1.1.1.6 root 957: set_panning_called = 1;
1.1.1.2 root 958: write_log ("SetPanning(%d, %d, %d) Start 0x%x, BPR %d\n",
1.1.1.8 ! root 959: Width, picasso96_state.XOffset, picasso96_state.YOffset, start_of_screen, picasso96_state.BytesPerRow);
1.1 root 960:
1.1.1.6 root 961: init_picasso_screen ();
1.1 root 962:
1.1.1.4 root 963: return 1;
1.1 root 964: }
965:
1.1.1.8 ! root 966: static void do_xor8 (uae_u8 * ptr, long len, uae_u32 val)
1.1 root 967: {
968: int i;
969: #if 0 && defined ALIGN_POINTER_TO32
1.1.1.8 ! root 970: int align_adjust = ALIGN_POINTER_TO32 (ptr);
1.1 root 971: int len2;
972:
973: len -= align_adjust;
974: while (align_adjust) {
975: *ptr ^= val;
976: ptr++;
977: align_adjust--;
978: }
979: len2 = len >> 2;
980: len -= len2 << 2;
981: for (i = 0; i < len2; i++, ptr += 4) {
1.1.1.8 ! root 982: *(uae_u32 *) ptr ^= val;
1.1 root 983: }
984: while (len) {
985: *ptr ^= val;
986: ptr++;
987: len--;
988: }
989: return;
990: #endif
991: for (i = 0; i < len; i++, ptr++) {
992: do_put_mem_byte (ptr, do_get_mem_byte (ptr) ^ val);
993: }
994: }
995:
996: /*
997: * InvertRect:
998: *
999: * Inputs:
1000: * a0:struct BoardInfo *bi
1001: * a1:struct RenderInfo *ri
1002: * d0.w:X
1003: * d1.w:Y
1004: * d2.w:Width
1005: * d3.w:Height
1006: * d4.l:Mask
1007: * d7.l:RGBFormat
1008: *
1009: * This function is used to invert a rectangular area on the board. It is called by BltBitMap,
1010: * BltPattern and BltTemplate.
1011: */
1012: uae_u32 picasso_InvertRect (void)
1013: {
1.1.1.2 root 1014: uaecptr renderinfo = m68k_areg (regs, 1);
1.1.1.8 ! root 1015: unsigned long X = (uae_u16) m68k_dreg (regs, 0);
! 1016: unsigned long Y = (uae_u16) m68k_dreg (regs, 1);
! 1017: unsigned long Width = (uae_u16) m68k_dreg (regs, 2);
! 1018: unsigned long Height = (uae_u16) m68k_dreg (regs, 3);
1.1.1.2 root 1019: uae_u32 mask = m68k_dreg (regs, 4);
1020: int Bpp = GetBytesPerPixel (m68k_dreg (regs, 7));
1.1 root 1021: uae_u32 xorval;
1.1.1.5 root 1022: unsigned int lines;
1.1 root 1023: struct RenderInfo ri;
1024: uae_u8 *uae_mem, *rectstart;
1.1.1.5 root 1025: unsigned long width_in_bytes;
1.1 root 1026:
1027: wgfx_flushline ();
1028:
1.1.1.8 ! root 1029: if (!CopyRenderInfoStructureA2U (renderinfo, &ri))
1.1 root 1030: return 0;
1031:
1.1.1.8 ! root 1032: /*write_log ("InvertRect %d %lx\n", Bpp, (long)mask); */
1.1 root 1033:
1034: /* ??? Brian? mask used to be 32 bit, but it appears that only 8 bit
1035: * values are passed to this function. This code here seems to work
1036: * much better... */
1037: if (mask != 0xFF && Bpp > 8) {
1.1.1.2 root 1038: write_log ("InvertRect: not obeying mask 0x%x properly with Bpp %d.\n", mask, Bpp);
1.1 root 1039: mask = 0xFF;
1040: }
1041: if ((mask & ~0xFF) != 0) {
1.1.1.2 root 1042: write_log ("InvertRect: mask has high bits set!\n");
1.1 root 1043: }
1044: xorval = 0x01010101 * (mask & 0xFF);
1045: width_in_bytes = Bpp * Width;
1.1.1.8 ! root 1046: rectstart = uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
1.1 root 1047:
1.1.1.2 root 1048: for (lines = 0; lines < Height; lines++, uae_mem += ri.BytesPerRow)
1.1 root 1049: do_xor8 (uae_mem, width_in_bytes, xorval);
1.1.1.2 root 1050:
1.1 root 1051: if (renderinfo_is_current_screen (&ri)) {
1052: if (mask == 0xFF)
1053: do_invertrect (rectstart, ri.BytesPerRow, X, Y, Width, Height);
1054: else
1055: do_blit (rectstart, ri.BytesPerRow, 0, 0, X, Y, Width, Height, 0);
1056: }
1057:
1.1.1.8 ! root 1058: return 1; /* 1 if supported, 0 otherwise */
1.1 root 1059: }
1060:
1061: /***********************************************************
1062: FillRect:
1063: ***********************************************************
1064: * a0: struct BoardInfo *
1065: * a1: struct RenderInfo *
1066: * d0: WORD X
1067: * d1: WORD Y
1068: * d2: WORD Width
1069: * d3: WORD Height
1070: * d4: uae_u32 Pen
1071: * d5: UBYTE Mask
1072: * d7: uae_u32 RGBFormat
1073: ***********************************************************/
1074: uae_u32 picasso_FillRect (void)
1075: {
1.1.1.2 root 1076: uaecptr renderinfo = m68k_areg (regs, 1);
1.1.1.8 ! root 1077: unsigned long X = (uae_u16) m68k_dreg (regs, 0);
! 1078: unsigned long Y = (uae_u16) m68k_dreg (regs, 1);
! 1079: unsigned long Width = (uae_u16) m68k_dreg (regs, 2);
! 1080: unsigned long Height = (uae_u16) m68k_dreg (regs, 3);
1.1.1.2 root 1081: uae_u32 Pen = m68k_dreg (regs, 4);
1.1.1.8 ! root 1082: uae_u8 Mask = (uae_u8) m68k_dreg (regs, 5);
1.1.1.2 root 1083: uae_u32 RGBFormat = m68k_dreg (regs, 7);
1.1 root 1084:
1085: uae_u8 *src, *dst;
1086: uae_u8 *start, *oldstart;
1087: unsigned long lines, cols;
1088: int Bpp;
1089: struct RenderInfo ri;
1090:
1091: wgfx_flushline ();
1092:
1.1.1.8 ! root 1093: if (!CopyRenderInfoStructureA2U (renderinfo, &ri) || Y == 0xFFFF)
1.1 root 1094: return 0;
1095:
1096: if (ri.RGBFormat != RGBFormat)
1.1.1.2 root 1097: write_log ("Weird Stuff!\n");
1.1 root 1098:
1.1.1.2 root 1099: Bpp = GetBytesPerPixel (RGBFormat);
1.1 root 1100:
1.1.1.2 root 1101: /*write_log ("FillRect(%d, %d, %d, %d) Pen 0x%x BPP %d BPR %d Mask 0x%x\n",
1.1.1.8 ! root 1102: X, Y, Width, Height, Pen, Bpp, ri.BytesPerRow, Mask); */
1.1 root 1103:
1104: if (Mask == 0xFF) {
1105: /* Do our virtual frame-buffer memory. First, we do a single line fill by hand */
1.1.1.8 ! root 1106: oldstart = start = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
1.1 root 1107: switch (Bpp) {
1.1.1.8 ! root 1108: case 1:
1.1 root 1109: memset (start, Pen, Width);
1110: break;
1.1.1.8 ! root 1111: case 2:
1.1 root 1112: for (cols = 0; cols < Width; cols++) {
1.1.1.8 ! root 1113: do_put_mem_word ((uae_u16 *) start, Pen);
1.1 root 1114: start += 2;
1115: }
1116: break;
1.1.1.8 ! root 1117: case 3:
1.1 root 1118: for (cols = 0; cols < Width; cols++) {
1119: do_put_mem_byte (start, Pen & 0x000000FF);
1120: start++;
1.1.1.8 ! root 1121: *(uae_u16 *) (start) = (Pen & 0x00FFFF00) >> 8;
! 1122: start += 2;
1.1 root 1123: }
1124: break;
1.1.1.8 ! root 1125: case 4:
1.1 root 1126: for (cols = 0; cols < Width; cols++) {
1127: /**start = Pen; */
1.1.1.8 ! root 1128: do_put_mem_long ((uae_u32 *) start, Pen);
1.1 root 1129: start += 4;
1130: }
1131: break;
1132: }
1133: src = oldstart;
1134: dst = src + ri.BytesPerRow;
1135: /* next, we do the remaining line fills via memcpy() */
1136: for (lines = 0; lines < (Height - 1); lines++, dst += ri.BytesPerRow)
1.1.1.2 root 1137: memcpy (dst, src, Width * Bpp);
1.1 root 1138:
1.1.1.2 root 1139: if (renderinfo_is_current_screen (&ri))
1.1 root 1140: do_fillrect (src, X, Y, Width, Height);
1.1.1.2 root 1141:
1.1 root 1142: return 1;
1143: }
1144:
1145: /* We get here only if Mask != 0xFF */
1146: if (Bpp != 1) {
1147: write_log ("Picasso: mask != 0xFF in truecolor mode!\n");
1148: return 0;
1149: }
1150: Pen &= Mask;
1151: Mask = ~Mask;
1152:
1.1.1.8 ! root 1153: oldstart = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
1.1.1.5 root 1154: {
1155: uae_u8 *start = oldstart;
1156: uae_u8 *end = start + Height * ri.BytesPerRow;
1157: for (; start != end; start += ri.BytesPerRow) {
1158: uae_u8 *p = start;
1159: unsigned long cols;
1160: for (cols = 0; cols < Width; cols++) {
1161: uae_u32 tmpval = do_get_mem_byte (p + cols) & Mask;
1162: do_put_mem_byte (p + cols, Pen | tmpval);
1163: }
1.1 root 1164: }
1165: }
1166: if (renderinfo_is_current_screen (&ri))
1167: do_blit (oldstart, ri.BytesPerRow, 0, 0, X, Y, Width, Height, 0);
1168:
1169: return 1;
1170: }
1171:
1172: /*
1173: * BlitRect() is a generic (any chunky pixel format) rectangle copier
1174: * NOTE: If dstri is NULL, then we're only dealing with one RenderInfo area, and called from picasso_BlitRect()
1175: */
1176: static void BlitRect (struct RenderInfo *ri, struct RenderInfo *dstri,
1.1.1.5 root 1177: unsigned long srcx, unsigned long srcy, unsigned long dstx, unsigned long dsty,
1178: unsigned long width, unsigned long height, uae_u8 mask)
1.1 root 1179: {
1180: uae_u8 *src, *dst, *tmp, *tmp2, *tmp3;
1.1.1.5 root 1181: unsigned long lines;
1.1.1.8 ! root 1182: uae_u8 Bpp = GetBytesPerPixel (ri->RGBFormat);
1.1 root 1183: uae_u8 *blitsrc;
1184: unsigned long total_width = width * Bpp;
1185: unsigned long linewidth = (total_width + 15) & ~15;
1186: int cant_blit = 1;
1187:
1188: /*
1189: * If we have no destination RenderInfo, then we're dealing with a single-buffer action, called
1190: * from picasso_BlitRect(). The code up to the DX_xxxxx() functions deals with the frame-buffer,
1191: * while the DX_ functions actually deal with the visible screen.
1192: *
1193: * If we have a destination RenderInfo, then we've been called from picasso_BlitRectNoMaskComplete()
1194: * and we need to put the results on the screen from the frame-buffer.
1195: */
1196: if (dstri == NULL) {
1197: dstri = ri;
1198: cant_blit = 0;
1199: }
1200:
1201: /* Do our virtual frame-buffer memory first */
1.1.1.8 ! root 1202: src = ri->Memory + srcx * Bpp + srcy * ri->BytesPerRow;
! 1203: dst = dstri->Memory + dstx * Bpp + dsty * dstri->BytesPerRow;
1.1 root 1204: blitsrc = dst;
1205: if (mask != 0xFF && Bpp > 1)
1.1.1.2 root 1206: write_log ("ERROR - not obeying BlitRect() mask 0x%x properly with Bpp %d.\n", mask, Bpp);
1.1 root 1207:
1208: if (mask == 0xFF || Bpp > 1) {
1209: /* handle normal case efficiently */
1210: if (ri->Memory == dstri->Memory && dsty == srcy) {
1.1.1.5 root 1211: unsigned long i;
1.1 root 1212: for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
1213: memmove (dst, src, total_width);
1214: } else if (dsty < srcy) {
1.1.1.5 root 1215: unsigned long i;
1.1 root 1216: for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
1217: memcpy (dst, src, total_width);
1218: } else {
1.1.1.5 root 1219: unsigned long i;
1.1.1.8 ! root 1220: src += (height - 1) * ri->BytesPerRow;
! 1221: dst += (height - 1) * dstri->BytesPerRow;
1.1 root 1222: for (i = 0; i < height; i++, src -= ri->BytesPerRow, dst -= dstri->BytesPerRow)
1223: memcpy (dst, src, total_width);
1224: }
1225: if (renderinfo_is_current_screen (dstri))
1.1.1.8 ! root 1226: do_blit (blitsrc, dstri->BytesPerRow, srcx, srcy, dstx, dsty, width, height, !cant_blit);
1.1 root 1227: return;
1228: }
1229:
1.1.1.8 ! root 1230: tmp3 = tmp2 = tmp = xmalloc (linewidth * height); /* allocate enough memory for the src-rect */
1.1 root 1231: if (!tmp)
1232: return;
1233:
1234: /* copy the src-rect into our temporary buffer space */
1235: for (lines = 0; lines < height; lines++, src += ri->BytesPerRow, tmp2 += linewidth) {
1236: memcpy (tmp2, src, total_width);
1237: }
1238:
1239: /* copy the temporary buffer to the destination */
1240: for (lines = 0; lines < height; lines++, dst += dstri->BytesPerRow, tmp += linewidth) {
1.1.1.5 root 1241: unsigned long cols;
1.1 root 1242: for (cols = 0; cols < width; cols++) {
1243: dst[cols] &= ~mask;
1244: dst[cols] |= tmp[cols] & mask;
1245: }
1246: }
1247: if (renderinfo_is_current_screen (dstri))
1.1.1.8 ! root 1248: do_blit (blitsrc, dstri->BytesPerRow, srcx, srcy, dstx, dsty, width, height, 0);
1.1 root 1249: /* free the temp-buf */
1250: free (tmp3);
1251:
1252: }
1253:
1254: /***********************************************************
1255: BlitRect:
1256: ***********************************************************
1257: * a0: struct BoardInfo
1258: * a1: struct RenderInfo
1259: * d0: WORD SrcX
1260: * d1: WORD SrcY
1261: * d2: WORD DstX
1262: * d3: WORD DstY
1263: * d4: WORD Width
1264: * d5: WORD Height
1265: * d6: UBYTE Mask
1266: * d7: uae_u32 RGBFormat
1267: ***********************************************************/
1268: uae_u32 picasso_BlitRect (void)
1269: {
1.1.1.2 root 1270: uaecptr renderinfo = m68k_areg (regs, 1);
1.1.1.8 ! root 1271: unsigned long srcx = (uae_u16) m68k_dreg (regs, 0);
! 1272: unsigned long srcy = (uae_u16) m68k_dreg (regs, 1);
! 1273: unsigned long dstx = (uae_u16) m68k_dreg (regs, 2);
! 1274: unsigned long dsty = (uae_u16) m68k_dreg (regs, 3);
! 1275: unsigned long width = (uae_u16) m68k_dreg (regs, 4);
! 1276: unsigned long height = (uae_u16) m68k_dreg (regs, 5);
! 1277: uae_u8 Mask = (uae_u8) m68k_dreg (regs, 6);
1.1 root 1278:
1279: struct RenderInfo ri;
1280:
1281: wgfx_flushline ();
1282:
1.1.1.8 ! root 1283: if (!CopyRenderInfoStructureA2U (renderinfo, &ri))
1.1 root 1284: return 0;
1285:
1.1.1.8 ! root 1286: BlitRect (&ri, NULL, srcx, srcy, dstx, dsty, width, height, Mask);
1.1.1.2 root 1287: /*write_log ("BlitRect(%d, %d, %d, %d, %d, %d, 0x%x)\n", srcx, srcy, dstx, dsty, width, height, Mask); */
1.1 root 1288:
1289: return 1;
1290: }
1291:
1292: /***********************************************************
1293: BlitRectNoMaskComplete:
1294: ***********************************************************
1295: * a0: struct BoardInfo
1296: * a1: struct RenderInfo (src)
1297: * a2: struct RenderInfo (dst)
1298: * d0: WORD SrcX
1299: * d1: WORD SrcY
1300: * d2: WORD DstX
1301: * d3: WORD DstY
1302: * d4: WORD Width
1303: * d5: WORD Height
1304: * d6: UBYTE OpCode
1305: * d7: uae_u32 RGBFormat
1306: * NOTE: MUST return 0 in D0 if we're not handling this operation
1307: * because the RGBFormat or opcode aren't supported.
1308: * OTHERWISE return 1
1309: ***********************************************************/
1310: uae_u32 picasso_BlitRectNoMaskComplete (void)
1311: {
1.1.1.2 root 1312: uaecptr srcri = m68k_areg (regs, 1);
1313: uaecptr dstri = m68k_areg (regs, 2);
1.1.1.8 ! root 1314: unsigned long srcx = (uae_u16) m68k_dreg (regs, 0);
! 1315: unsigned long srcy = (uae_u16) m68k_dreg (regs, 1);
! 1316: unsigned long dstx = (uae_u16) m68k_dreg (regs, 2);
! 1317: unsigned long dsty = (uae_u16) m68k_dreg (regs, 3);
! 1318: unsigned long width = (uae_u16) m68k_dreg (regs, 4);
! 1319: unsigned long height = (uae_u16) m68k_dreg (regs, 5);
1.1.1.2 root 1320: uae_u8 OpCode = m68k_dreg (regs, 6);
1321: uae_u32 RGBFmt = m68k_dreg (regs, 7);
1.1 root 1322: struct RenderInfo src_ri, dst_ri;
1323:
1324: wgfx_flushline ();
1325:
1.1.1.8 ! root 1326: if (!CopyRenderInfoStructureA2U (srcri, &src_ri)
! 1327: || !CopyRenderInfoStructureA2U (dstri, &dst_ri))
1.1 root 1328: return 0;
1329:
1.1.1.2 root 1330: /*write_log ("BlitRectNoMaskComplete() op 0x%2x, Bpp %d, xy(%4d,%4d) --> xy(%4d,%4d), wh(%4d,%4d)\n",
1.1.1.8 ! root 1331: OpCode, Bpp, srcx, srcy, dstx, dsty, width, height); */
1.1.1.2 root 1332: /*write_log ("-- src mem 0x%x BPR %d, dst mem 0x%x BPR %d, screen-mem 0x%x - 0x%x\n",
1.1.1.8 ! root 1333: src_ri.Memory, src_ri.BytesPerRow, dst_ri.Memory, dst_ri.BytesPerRow, picasso96_state.Address, picasso96_state.Extent); */
1.1 root 1334:
1335: switch (OpCode) {
1.1.1.8 ! root 1336: case 0x0C:
1.1.1.2 root 1337: BlitRect (&src_ri, &dst_ri, srcx, srcy, dstx, dsty, width, height, 0xFF);
1.1 root 1338: return 1;
1339:
1.1.1.8 ! root 1340: default:
1.1 root 1341: /* FOR NOW! */
1342: return 0;
1343: }
1344: }
1345:
1346: /* This utility function is used both by BlitTemplate() and BlitPattern() */
1.1.1.8 ! root 1347: STATIC_INLINE void PixelWrite1 (uae_u8 * mem, int bits, uae_u32 fgpen, uae_u32 mask)
1.1 root 1348: {
1349: if (mask != 0xFF)
1350: fgpen = (fgpen & mask) | (do_get_mem_byte (mem + bits) & ~mask);
1351: do_put_mem_byte (mem + bits, fgpen);
1352: }
1353:
1.1.1.8 ! root 1354: STATIC_INLINE void PixelWrite2 (uae_u8 * mem, int bits, uae_u32 fgpen)
1.1 root 1355: {
1.1.1.8 ! root 1356: do_put_mem_word (((uae_u16 *) mem) + bits, fgpen);
1.1 root 1357: }
1358:
1.1.1.8 ! root 1359: STATIC_INLINE void PixelWrite3 (uae_u8 * mem, int bits, uae_u32 fgpen)
1.1 root 1360: {
1.1.1.8 ! root 1361: do_put_mem_byte (mem + bits * 3, fgpen & 0x000000FF);
! 1362: *(uae_u16 *) (mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
1.1 root 1363: }
1364:
1.1.1.8 ! root 1365: STATIC_INLINE void PixelWrite4 (uae_u8 * mem, int bits, uae_u32 fgpen)
1.1 root 1366: {
1.1.1.8 ! root 1367: do_put_mem_long (((uae_u32 *) mem) + bits, fgpen);
1.1 root 1368: }
1369:
1.1.1.8 ! root 1370: STATIC_INLINE void PixelWrite (uae_u8 * mem, int bits, uae_u32 fgpen, uae_u8 Bpp, uae_u32 mask)
1.1 root 1371: {
1372: switch (Bpp) {
1373: case 1:
1374: if (mask != 0xFF)
1375: fgpen = (fgpen & mask) | (do_get_mem_byte (mem + bits) & ~mask);
1376: do_put_mem_byte (mem + bits, fgpen);
1377: break;
1378: case 2:
1.1.1.8 ! root 1379: do_put_mem_word (((uae_u16 *) mem) + bits, fgpen);
1.1 root 1380: break;
1381: case 3:
1.1.1.8 ! root 1382: do_put_mem_byte (mem + bits * 3, fgpen & 0x000000FF);
! 1383: *(uae_u16 *) (mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
1.1 root 1384: break;
1385: case 4:
1.1.1.8 ! root 1386: do_put_mem_long (((uae_u32 *) mem) + bits, fgpen);
1.1 root 1387: break;
1388: }
1389: }
1390:
1391: /*
1392: * BlitPattern:
1393: *
1394: * Synopsis:BlitPattern(bi, ri, pattern, X, Y, Width, Height, Mask, RGBFormat);
1395: * Inputs:
1396: * a0:struct BoardInfo *bi
1397: * a1:struct RenderInfo *ri
1398: * a2:struct Pattern *pattern
1399: * d0.w:X
1400: * d1.w:Y
1401: * d2.w:Width
1402: * d3.w:Height
1403: * d4.w:Mask
1404: * d7.l:RGBFormat
1405: *
1406: * This function is used to paint a pattern on the board memory using the blitter. It is called by
1407: * BltPattern, if a AreaPtrn is used with positive AreaPtSz. The pattern consists of a b/w image
1408: * using a single plane of image data which will be expanded repeatedly to the destination RGBFormat
1409: * using ForeGround and BackGround pens as well as draw modes. The width of the pattern data is
1410: * always 16 pixels (one word) and the height is calculated as 2^Size. The data must be shifted up
1411: * and to the left by XOffset and YOffset pixels at the beginning.
1412: */
1413: uae_u32 picasso_BlitPattern (void)
1414: {
1.1.1.2 root 1415: uaecptr rinf = m68k_areg (regs, 1);
1416: uaecptr pinf = m68k_areg (regs, 2);
1.1.1.8 ! root 1417: unsigned long X = (uae_u16) m68k_dreg (regs, 0);
! 1418: unsigned long Y = (uae_u16) m68k_dreg (regs, 1);
! 1419: unsigned long W = (uae_u16) m68k_dreg (regs, 2);
! 1420: unsigned long H = (uae_u16) m68k_dreg (regs, 3);
! 1421: uae_u8 Mask = (uae_u8) m68k_dreg (regs, 4);
1.1.1.2 root 1422: uae_u32 RGBFmt = m68k_dreg (regs, 7);
1.1 root 1423:
1.1.1.3 root 1424: uae_u8 Bpp = GetBytesPerPixel (RGBFmt);
1.1 root 1425: int inversion = 0;
1426: struct RenderInfo ri;
1427: struct Pattern pattern;
1.1.1.5 root 1428: unsigned long rows;
1.1.1.2 root 1429: uae_u32 fgpen;
1.1 root 1430: uae_u8 *uae_mem, *frame_buffer_UAM;
1431: int xshift;
1.1.1.2 root 1432: unsigned long ysize_mask;
1.1 root 1433:
1434: wgfx_flushline ();
1435:
1.1.1.8 ! root 1436: if (!CopyRenderInfoStructureA2U (rinf, &ri)
! 1437: || !CopyPatternStructureA2U (pinf, &pattern))
1.1 root 1438: return 0;
1439:
1.1.1.8 ! root 1440: Bpp = GetBytesPerPixel (ri.RGBFormat);
! 1441: uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp; /* offset with address */
1.1 root 1442:
1443: if (pattern.DrawMode & INVERS)
1444: inversion = 1;
1445:
1446: pattern.DrawMode &= 0x03;
1447: if (Mask != 0xFF) {
1448: if (Bpp > 1)
1.1.1.2 root 1449: write_log ("ERROR - not obeying BlitPattern() mask 0x%x properly with Bpp %d.\n", Mask, Bpp);
1.1 root 1450: else if (pattern.DrawMode == COMP) {
1.1.1.2 root 1451: write_log ("ERROR - Unsupported Mask value 0x%x with COMP Draw in BlitPattern(), using fallback method.\n", Mask);
1.1 root 1452: return 0;
1453: }
1454: }
1455:
1.1.1.2 root 1456: /* write_log ("BlitPattern() xy(%d,%d), wh(%d,%d) draw 0x%x, off(%d,%d), ph %d\n",
1.1.1.8 ! root 1457: X, Y, W, H, pattern.DrawMode, pattern.XOffset, pattern.YOffset, 1 << pattern.Size); */
1.1 root 1458: #ifdef _DEBUG
1.1.1.8 ! root 1459: DumpPattern (&pattern);
1.1 root 1460: #endif
1461: ysize_mask = (1 << pattern.Size) - 1;
1462: xshift = pattern.XOffset & 15;
1463:
1464: for (rows = 0; rows < H; rows++, uae_mem += ri.BytesPerRow) {
1.1.1.5 root 1465: unsigned long prow = (rows + pattern.YOffset) & ysize_mask;
1.1.1.8 ! root 1466: unsigned int d = do_get_mem_word (((uae_u16 *) pattern.Memory) + prow);
1.1 root 1467: uae_u8 *uae_mem2 = uae_mem;
1.1.1.5 root 1468: unsigned long cols;
1.1 root 1469:
1470: if (xshift != 0)
1471: d = (d << xshift) | (d >> (16 - xshift));
1472:
1473: for (cols = 0; cols < W; cols += 16, uae_mem2 += Bpp << 4) {
1474: long bits;
1475: long max = W - cols;
1476: unsigned int data = d;
1477:
1478: if (max > 16)
1479: max = 16;
1.1.1.8 ! root 1480:
1.1 root 1481: for (bits = 0; bits < max; bits++) {
1482: int bit_set = data & 0x8000;
1483: data <<= 1;
1484: switch (pattern.DrawMode) {
1.1.1.8 ! root 1485: case JAM1:
1.1 root 1486: if (inversion)
1487: bit_set = !bit_set;
1488: if (bit_set)
1.1.1.2 root 1489: PixelWrite (uae_mem2, bits, pattern.FgPen, Bpp, Mask);
1.1 root 1490: break;
1.1.1.8 ! root 1491: case JAM2:
1.1 root 1492: if (inversion)
1493: bit_set = !bit_set;
1494: if (bit_set)
1.1.1.2 root 1495: PixelWrite (uae_mem2, bits, pattern.FgPen, Bpp, Mask);
1.1 root 1496: else
1.1.1.2 root 1497: PixelWrite (uae_mem2, bits, pattern.BgPen, Bpp, Mask);
1.1 root 1498: break;
1.1.1.8 ! root 1499: case COMP:
1.1 root 1500: if (bit_set) {
1501: fgpen = pattern.FgPen;
1502:
1503: switch (Bpp) {
1.1.1.8 ! root 1504: case 1:
1.1 root 1505: {
1506: uae_u8 *addr = uae_mem2 + bits;
1507: do_put_mem_byte (addr, do_get_mem_byte (addr) ^ fgpen);
1508: }
1509: break;
1.1.1.8 ! root 1510: case 2:
1.1 root 1511: {
1.1.1.8 ! root 1512: uae_u16 *addr = ((uae_u16 *) uae_mem2) + bits;
1.1 root 1513: do_put_mem_word (addr, do_get_mem_word (addr) ^ fgpen);
1514: }
1515: break;
1.1.1.8 ! root 1516: case 3:
1.1 root 1517: {
1.1.1.8 ! root 1518: uae_u32 *addr = (uae_u32 *) (uae_mem2 + bits * 3);
1.1 root 1519: do_put_mem_long (addr, do_get_mem_long (addr) ^ (fgpen & 0x00FFFFFF));
1520: }
1521: break;
1.1.1.8 ! root 1522: case 4:
1.1 root 1523: {
1.1.1.8 ! root 1524: uae_u32 *addr = ((uae_u32 *) uae_mem2) + bits;
1.1 root 1525: do_put_mem_long (addr, do_get_mem_long (addr) ^ fgpen);
1526: }
1527: break;
1528: }
1529: }
1530: break;
1531: }
1532: }
1533: }
1534: }
1535:
1.1.1.8 ! root 1536: frame_buffer_UAM = ri.Memory + X * picasso96_state.BytesPerPixel + Y * ri.BytesPerRow;
1.1 root 1537: if (renderinfo_is_current_screen (&ri))
1538: do_blit (frame_buffer_UAM, ri.BytesPerRow, 0, 0, X, Y, W, H, 0);
1539:
1540: return 1;
1541: }
1542:
1543: /*************************************************
1544: BlitTemplate:
1545: **************************************************
1546: * Synopsis: BlitTemplate(bi, ri, template, X, Y, Width, Height, Mask, RGBFormat);
1547: * a0: struct BoardInfo *bi
1548: * a1: struct RenderInfo *ri
1549: * a2: struct Template *template
1550: * d0.w: X
1551: * d1.w: Y
1552: * d2.w: Width
1553: * d3.w: Height
1554: * d4.w: Mask
1555: * d7.l: RGBFormat
1556: *
1557: * This function is used to paint a template on the board memory using the blitter.
1558: * It is called by BltPattern and BltTemplate. The template consists of a b/w image
1559: * using a single plane of image data which will be expanded to the destination RGBFormat
1560: * using ForeGround and BackGround pens as well as draw modes.
1561: ***********************************************************************************/
1562: uae_u32 picasso_BlitTemplate (void)
1563: {
1564: uae_u8 inversion = 0;
1.1.1.2 root 1565: uaecptr rinf = m68k_areg (regs, 1);
1566: uaecptr tmpl = m68k_areg (regs, 2);
1.1.1.8 ! root 1567: unsigned long X = (uae_u16) m68k_dreg (regs, 0);
! 1568: unsigned long Y = (uae_u16) m68k_dreg (regs, 1);
! 1569: unsigned long W = (uae_u16) m68k_dreg (regs, 2);
! 1570: unsigned long H = (uae_u16) m68k_dreg (regs, 3);
! 1571: uae_u16 Mask = (uae_u16) m68k_dreg (regs, 4);
1.1 root 1572: struct Template tmp;
1573: struct RenderInfo ri;
1.1.1.5 root 1574: unsigned long rows;
1.1 root 1575: int bitoffset;
1.1.1.2 root 1576: uae_u32 fgpen;
1577: uae_u8 *uae_mem, Bpp, *frame_buffer_UAM;
1.1 root 1578: uae_u8 *tmpl_base;
1579:
1580: wgfx_flushline ();
1581:
1.1.1.8 ! root 1582: if (!CopyRenderInfoStructureA2U (rinf, &ri)
! 1583: || !CopyTemplateStructureA2U (tmpl, &tmp))
1.1 root 1584: return 0;
1585:
1.1.1.8 ! root 1586: Bpp = GetBytesPerPixel (ri.RGBFormat);
! 1587: uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp; /* offset into address */
1.1 root 1588:
1589: if (tmp.DrawMode & INVERS)
1590: inversion = 1;
1591:
1592: tmp.DrawMode &= 0x03;
1593: if (Mask != 0xFF) {
1594: if (Bpp > 1)
1.1.1.2 root 1595: write_log ("ERROR - not obeying BlitTemplate() mask 0x%x properly with Bpp %d.\n", Mask, Bpp);
1.1 root 1596: else if (tmp.DrawMode == COMP) {
1.1.1.2 root 1597: write_log ("ERROR - Unsupported Mask value 0x%x with COMP Draw in BlitTemplate(), using fallback method.\n", Mask);
1.1 root 1598: return 0;
1599: }
1600: }
1601:
1.1.1.2 root 1602: /*write_log ("BlitTemplate() xy(%d,%d), wh(%d,%d) draw 0x%x fg 0x%x bg 0x%x \n",
1.1.1.8 ! root 1603: X, Y, W, H, tmp.DrawMode, tmp.FgPen, tmp.BgPen); */
1.1 root 1604:
1605: bitoffset = tmp.XOffset % 8;
1606:
1607: #ifdef _DEBUG
1.1.1.8 ! root 1608: DumpTemplate (&tmp, W, H);
1.1 root 1609: #endif
1610:
1.1.1.8 ! root 1611: tmpl_base = tmp.Memory + tmp.XOffset / 8;
1.1 root 1612:
1613: for (rows = 0; rows < H; rows++, uae_mem += ri.BytesPerRow, tmpl_base += tmp.BytesPerRow) {
1.1.1.5 root 1614: unsigned long cols;
1.1 root 1615: uae_u8 *tmpl_mem = tmpl_base;
1616: uae_u8 *uae_mem2 = uae_mem;
1617: unsigned int data = *tmpl_mem;
1618:
1619: for (cols = 0; cols < W; cols += 8, uae_mem2 += Bpp << 3) {
1620: unsigned int byte;
1621: long bits;
1622: long max = W - cols;
1623:
1624: if (max > 8)
1625: max = 8;
1626:
1627: data <<= 8;
1628: data |= *++tmpl_mem;
1629:
1630: byte = data >> (8 - bitoffset);
1631:
1632: for (bits = 0; bits < max; bits++) {
1633: int bit_set = (byte & 0x80);
1634: byte <<= 1;
1635: switch (tmp.DrawMode) {
1.1.1.8 ! root 1636: case JAM1:
1.1 root 1637: if (inversion)
1638: bit_set = !bit_set;
1639: if (bit_set) {
1640: fgpen = tmp.FgPen;
1.1.1.8 ! root 1641: PixelWrite (uae_mem2, bits, fgpen, Bpp, Mask);
1.1 root 1642: }
1643: break;
1.1.1.8 ! root 1644: case JAM2:
1.1 root 1645: if (inversion)
1646: bit_set = !bit_set;
1647: fgpen = tmp.BgPen;
1648: if (bit_set)
1649: fgpen = tmp.FgPen;
1650:
1.1.1.8 ! root 1651: PixelWrite (uae_mem2, bits, fgpen, Bpp, Mask);
1.1 root 1652: break;
1.1.1.8 ! root 1653: case COMP:
1.1 root 1654: if (bit_set) {
1655: fgpen = tmp.FgPen;
1656:
1657: switch (Bpp) {
1.1.1.8 ! root 1658: case 1:
1.1 root 1659: {
1660: uae_u8 *addr = uae_mem2 + bits;
1661: do_put_mem_byte (addr, do_get_mem_byte (addr) ^ fgpen);
1662: }
1663: break;
1.1.1.8 ! root 1664: case 2:
1.1 root 1665: {
1.1.1.8 ! root 1666: uae_u16 *addr = ((uae_u16 *) uae_mem2) + bits;
1.1 root 1667: do_put_mem_word (addr, do_get_mem_word (addr) ^ fgpen);
1668: }
1669: break;
1.1.1.8 ! root 1670: case 3:
1.1 root 1671: {
1.1.1.8 ! root 1672: uae_u32 *addr = (uae_u32 *) (uae_mem2 + bits * 3);
1.1 root 1673: do_put_mem_long (addr, do_get_mem_long (addr) ^ (fgpen & 0x00FFFFFF));
1674: }
1675: break;
1.1.1.8 ! root 1676: case 4:
1.1 root 1677: {
1.1.1.8 ! root 1678: uae_u32 *addr = ((uae_u32 *) uae_mem2) + bits;
1.1 root 1679: do_put_mem_long (addr, do_get_mem_long (addr) ^ fgpen);
1680: }
1681: break;
1682: }
1683: }
1684: break;
1685: }
1686: }
1687: }
1688: }
1689:
1.1.1.8 ! root 1690: frame_buffer_UAM = ri.Memory + X * picasso96_state.BytesPerPixel + Y * ri.BytesPerRow;
1.1 root 1691: if (renderinfo_is_current_screen (&ri))
1692: do_blit (frame_buffer_UAM, ri.BytesPerRow, 0, 0, X, Y, W, H, 0);
1693:
1694: return 1;
1695: }
1696:
1697: /*
1698: * CalculateBytesPerRow:
1699: * a0: struct BoardInfo
1700: * d0: uae_u16 Width
1701: * d7: RGBFTYPE RGBFormat
1702: * This function calculates the amount of bytes needed for a line of
1703: * "Width" pixels in the given RGBFormat.
1704: */
1705: uae_u32 picasso_CalculateBytesPerRow (void)
1706: {
1.1.1.2 root 1707: uae_u16 width = m68k_dreg (regs, 0);
1708: uae_u32 type = m68k_dreg (regs, 7);
1.1 root 1709:
1.1.1.8 ! root 1710: width = GetBytesPerPixel (type) * width;
1.1.1.2 root 1711: /*write_log ("CalculateBytesPerRow() = %d\n",width); */
1.1 root 1712:
1713: return width;
1714: }
1715:
1716: /*
1717: * SetDisplay:
1718: * a0: struct BoardInfo
1719: * d0: BOOL state
1720: * This function enables and disables the video display.
1721: *
1722: * NOTE: return the opposite of the state
1723: */
1724: uae_u32 picasso_SetDisplay (void)
1725: {
1.1.1.2 root 1726: uae_u32 state = m68k_dreg (regs, 0);
1727: write_log ("SetDisplay(%d)\n", state);
1.1 root 1728: return !state;
1729: }
1730:
1731: /*
1732: * WaitVerticalSync:
1733: * a0: struct BoardInfo
1734: * This function waits for the next horizontal retrace.
1735: */
1736: uae_u32 picasso_WaitVerticalSync (void)
1737: {
1.1.1.8 ! root 1738: /*write_log ("WaitVerticalSync()\n"); */
1.1 root 1739: return 1;
1740: }
1741:
1742: /* NOTE: Watch for those planeptrs of 0x00000000 and 0xFFFFFFFF for all zero / all one bitmaps !!!! */
1.1.1.8 ! root 1743: static void PlanarToChunky (struct RenderInfo *ri, struct BitMap *bm,
! 1744: unsigned long srcx, unsigned long srcy,
! 1745: unsigned long dstx, unsigned long dsty, unsigned long width, unsigned long height, uae_u8 mask)
1.1 root 1746: {
1.1.1.2 root 1747: int j;
1.1 root 1748:
1.1.1.8 ! root 1749: uae_u8 *PLANAR[8], *image = ri->Memory + dstx * GetBytesPerPixel (ri->RGBFormat) + dsty * ri->BytesPerRow;
1.1 root 1750: int Depth = bm->Depth;
1.1.1.5 root 1751: unsigned long rows, bitoffset = srcx & 7;
1.1 root 1752: long eol_offset;
1753:
1754: /* if (mask != 0xFF)
1.1.1.8 ! root 1755: write_log ("P2C - pixel-width = %d, bit-offset = %d\n", width, bitoffset); */
1.1.1.5 root 1756:
1.1 root 1757: /* Set up our bm->Planes[] pointers to the right horizontal offset */
1758: for (j = 0; j < Depth; j++) {
1759: uae_u8 *p = bm->Planes[j];
1760: if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
1.1.1.8 ! root 1761: p += srcx / 8 + srcy * bm->BytesPerRow;
1.1 root 1762: PLANAR[j] = p;
1763: if ((mask & (1 << j)) == 0)
1764: PLANAR[j] = &all_zeros_bitmap;
1765: }
1.1.1.8 ! root 1766: eol_offset = (long) bm->BytesPerRow - (long) ((width + 7) >> 3);
1.1 root 1767: for (rows = 0; rows < height; rows++, image += ri->BytesPerRow) {
1.1.1.5 root 1768: unsigned long cols;
1.1 root 1769:
1770: for (cols = 0; cols < width; cols += 8) {
1771: int k;
1772: uae_u32 a = 0, b = 0;
1773: unsigned int msk = 0xFF;
1774: long tmp = cols + 8 - width;
1775: if (tmp > 0) {
1776: msk <<= tmp;
1.1.1.8 ! root 1777: b = do_get_mem_long ((uae_u32 *) (image + cols + 4));
1.1 root 1778: if (tmp < 4)
1779: b &= 0xFFFFFFFF >> (32 - tmp * 8);
1780: else if (tmp > 4) {
1.1.1.8 ! root 1781: a = do_get_mem_long ((uae_u32 *) (image + cols));
1.1 root 1782: a &= 0xFFFFFFFF >> (64 - tmp * 8);
1783: }
1784: }
1785: for (k = 0; k < Depth; k++) {
1786: unsigned int data;
1787: if (PLANAR[k] == &all_zeros_bitmap)
1788: data = 0;
1789: else if (PLANAR[k] == &all_ones_bitmap)
1790: data = 0xFF;
1791: else {
1.1.1.8 ! root 1792: data = (uae_u8) (do_get_mem_word ((uae_u16 *) PLANAR[k]) >> (8 - bitoffset));
1.1 root 1793: PLANAR[k]++;
1794: }
1795: data &= msk;
1796: a |= p2ctab[data][0] << k;
1797: b |= p2ctab[data][1] << k;
1798: }
1.1.1.8 ! root 1799: do_put_mem_long ((uae_u32 *) (image + cols), a);
! 1800: do_put_mem_long ((uae_u32 *) (image + cols + 4), b);
1.1 root 1801: }
1802: for (j = 0; j < Depth; j++) {
1803: if (PLANAR[j] != &all_zeros_bitmap && PLANAR[j] != &all_ones_bitmap) {
1804: PLANAR[j] += eol_offset;
1805: }
1806: }
1807: }
1808: }
1809:
1810: /*
1811: * BlitPlanar2Chunky:
1812: * a0: struct BoardInfo *bi
1813: * a1: struct BitMap *bm - source containing planar information and assorted details
1814: * a2: struct RenderInfo *ri - dest area and its details
1815: * d0.w: SrcX
1816: * d1.w: SrcY
1817: * d2.w: DstX
1818: * d3.w: DstY
1819: * d4.w: SizeX
1820: * d5.w: SizeY
1821: * d6.b: MinTerm - uh oh!
1822: * d7.b: Mask - uh oh!
1823: *
1824: * This function is currently used to blit from planar bitmaps within system memory to chunky bitmaps
1825: * on the board. Watch out for plane pointers that are 0x00000000 (represents a plane with all bits "0")
1826: * or 0xffffffff (represents a plane with all bits "1").
1827: */
1828: uae_u32 picasso_BlitPlanar2Chunky (void)
1829: {
1.1.1.2 root 1830: uaecptr bm = m68k_areg (regs, 1);
1831: uaecptr ri = m68k_areg (regs, 2);
1.1.1.8 ! root 1832: unsigned long srcx = (uae_u16) m68k_dreg (regs, 0);
! 1833: unsigned long srcy = (uae_u16) m68k_dreg (regs, 1);
! 1834: unsigned long dstx = (uae_u16) m68k_dreg (regs, 2);
! 1835: unsigned long dsty = (uae_u16) m68k_dreg (regs, 3);
! 1836: unsigned long width = (uae_u16) m68k_dreg (regs, 4);
! 1837: unsigned long height = (uae_u16) m68k_dreg (regs, 5);
1.1.1.2 root 1838: uae_u8 minterm = m68k_dreg (regs, 6) & 0xFF;
1839: uae_u8 mask = m68k_dreg (regs, 7) & 0xFF;
1.1 root 1840: struct RenderInfo local_ri;
1841: struct BitMap local_bm;
1842:
1843: wgfx_flushline ();
1844:
1845: if (minterm != 0x0C) {
1.1.1.8 ! root 1846: write_log ("ERROR - BlitPlanar2Chunky() has minterm 0x%x, which I don't handle. Using fall-back routine.\n", minterm);
1.1 root 1847: return 0;
1848: }
1.1.1.8 ! root 1849: if (!CopyRenderInfoStructureA2U (ri, &local_ri)
! 1850: || !CopyBitMapStructureA2U (bm, &local_bm))
1.1 root 1851: return 0;
1852:
1.1.1.2 root 1853: /*write_log ("BlitPlanar2Chunky(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n",
1.1.1.8 ! root 1854: srcx, srcy, dstx, dsty, width, height, minterm, mask, local_bm.Depth);
! 1855: write_log ("P2C - BitMap has %d BPR, %d rows\n", local_bm.BytesPerRow, local_bm.Rows); */
1.1.1.2 root 1856: PlanarToChunky (&local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, mask);
1.1 root 1857: if (renderinfo_is_current_screen (&local_ri))
1858: do_blit (local_ri.Memory + dstx * GetBytesPerPixel (local_ri.RGBFormat) + dsty * local_ri.BytesPerRow,
1.1.1.8 ! root 1859: local_ri.BytesPerRow, 0, 0, dstx, dsty, width, height, 0);
1.1 root 1860:
1.1.1.4 root 1861: return 1;
1.1 root 1862: }
1863:
1864: /* NOTE: Watch for those planeptrs of 0x00000000 and 0xFFFFFFFF for all zero / all one bitmaps !!!! */
1.1.1.8 ! root 1865: static void PlanarToDirect (struct RenderInfo *ri, struct BitMap *bm,
! 1866: unsigned long srcx, unsigned long srcy,
! 1867: unsigned long dstx, unsigned long dsty,
! 1868: unsigned long width, unsigned long height, uae_u8 mask, struct ColorIndexMapping *cim)
1.1 root 1869: {
1870: int j;
1.1.1.8 ! root 1871: int bpp = GetBytesPerPixel (ri->RGBFormat);
1.1 root 1872: uae_u8 *PLANAR[8];
1873: uae_u8 *image = ri->Memory + dstx * bpp + dsty * ri->BytesPerRow;
1874: int Depth = bm->Depth;
1.1.1.5 root 1875: unsigned long rows;
1.1 root 1876: long eol_offset;
1877:
1878: /* Set up our bm->Planes[] pointers to the right horizontal offset */
1879: for (j = 0; j < Depth; j++) {
1880: uae_u8 *p = bm->Planes[j];
1881: if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
1.1.1.8 ! root 1882: p += srcx / 8 + srcy * bm->BytesPerRow;
1.1 root 1883: PLANAR[j] = p;
1884: if ((mask & (1 << j)) == 0)
1885: PLANAR[j] = &all_zeros_bitmap;
1886: }
1887:
1.1.1.8 ! root 1888: eol_offset = (long) bm->BytesPerRow - (long) ((width + (srcx & 7)) >> 3);
1.1 root 1889: for (rows = 0; rows < height; rows++, image += ri->BytesPerRow) {
1.1.1.5 root 1890: unsigned long cols;
1.1 root 1891: uae_u8 *image2 = image;
1892: unsigned int bitoffs = 7 - (srcx & 7);
1893: int i;
1894:
1.1.1.8 ! root 1895: for (cols = 0; cols < width; cols++) {
1.1 root 1896: int v = 0, k;
1897: for (k = 0; k < Depth; k++) {
1898: if (PLANAR[k] == &all_ones_bitmap)
1899: v |= 1 << k;
1900: else if (PLANAR[k] != &all_zeros_bitmap) {
1901: v |= ((*PLANAR[k] >> bitoffs) & 1) << k;
1902: }
1903: }
1904:
1905: switch (bpp) {
1.1.1.8 ! root 1906: case 2:
! 1907: do_put_mem_word ((uae_u16 *) image2, cim->Colors[v]);
1.1 root 1908: image2 += 2;
1909: break;
1.1.1.8 ! root 1910: case 3:
1.1 root 1911: do_put_mem_byte (image2++, cim->Colors[v] & 0x000000FF);
1.1.1.8 ! root 1912: do_put_mem_word ((uae_u16 *) image2, (cim->Colors[v] & 0x00FFFF00) >> 8);
1.1 root 1913: image2 += 2;
1914: break;
1.1.1.8 ! root 1915: case 4:
! 1916: do_put_mem_long ((uae_u32 *) image2, cim->Colors[v]);
1.1 root 1917: image2 += 4;
1918: break;
1919: }
1920: bitoffs--;
1921: bitoffs &= 7;
1922: if (bitoffs == 7) {
1923: int k;
1924: for (k = 0; k < Depth; k++) {
1925: if (PLANAR[k] != &all_zeros_bitmap && PLANAR[k] != &all_ones_bitmap) {
1926: PLANAR[k]++;
1927: }
1928: }
1929: }
1930: }
1931:
1932: for (i = 0; i < Depth; i++) {
1933: if (PLANAR[i] != &all_zeros_bitmap && PLANAR[i] != &all_ones_bitmap) {
1934: PLANAR[i] += eol_offset;
1935: }
1936: }
1937: }
1938: }
1939:
1940: /*
1941: * BlitPlanar2Direct:
1942: *
1943: * Synopsis:
1944: * BlitPlanar2Direct(bi, bm, ri, cim, SrcX, SrcY, DstX, DstY, SizeX, SizeY, MinTerm, Mask);
1945: * Inputs:
1946: * a0:struct BoardInfo *bi
1947: * a1:struct BitMap *bm
1948: * a2:struct RenderInfo *ri
1949: * a3:struct ColorIndexMapping *cmi
1950: * d0.w:SrcX
1951: * d1.w:SrcY
1952: * d2.w:DstX
1953: * d3.w:DstY
1954: * d4.w:SizeX
1955: * d5.w:SizeY
1956: * d6.b:MinTerm
1957: * d7.b:Mask
1958: *
1959: * This function is currently used to blit from planar bitmaps within system memory to direct color
1960: * bitmaps (15, 16, 24 or 32 bit) on the board. Watch out for plane pointers that are 0x00000000 (represents
1961: * a plane with all bits "0") or 0xffffffff (represents a plane with all bits "1"). The ColorIndexMapping is
1962: * used to map the color index of each pixel formed by the bits in the bitmap's planes to a direct color value
1963: * which is written to the destination RenderInfo. The color mask and all colors within the mapping are words,
1964: * triple bytes or longwords respectively similar to the color values used in FillRect(), BlitPattern() or
1965: * BlitTemplate().
1966: */
1967: uae_u32 picasso_BlitPlanar2Direct (void)
1968: {
1.1.1.2 root 1969: uaecptr bm = m68k_areg (regs, 1);
1970: uaecptr ri = m68k_areg (regs, 2);
1971: uaecptr cim = m68k_areg (regs, 3);
1.1.1.8 ! root 1972: unsigned long srcx = (uae_u16) m68k_dreg (regs, 0);
! 1973: unsigned long srcy = (uae_u16) m68k_dreg (regs, 1);
! 1974: unsigned long dstx = (uae_u16) m68k_dreg (regs, 2);
! 1975: unsigned long dsty = (uae_u16) m68k_dreg (regs, 3);
! 1976: unsigned long width = (uae_u16) m68k_dreg (regs, 4);
! 1977: unsigned long height = (uae_u16) m68k_dreg (regs, 5);
1.1.1.2 root 1978: uae_u8 minterm = m68k_dreg (regs, 6);
1979: uae_u8 Mask = m68k_dreg (regs, 7);
1.1 root 1980: struct RenderInfo local_ri;
1981: struct BitMap local_bm;
1982: struct ColorIndexMapping local_cim;
1983:
1984: wgfx_flushline ();
1985:
1986: if (minterm != 0x0C) {
1.1.1.8 ! root 1987: write_log ("ERROR - BlitPlanar2Direct() has op-code 0x%x, which I don't handle. Using fall-back routine.\n", minterm);
1.1 root 1988: return 0;
1989: }
1990: if (Mask != 0xFF) {
1.1.1.2 root 1991: write_log ("ERROR - Unsupported Mask value 0x%x in BlitPlanar2Direct(), using fallback method.\n", Mask);
1.1 root 1992: return 0;
1993: }
1.1.1.8 ! root 1994: if (!CopyRenderInfoStructureA2U (ri, &local_ri)
! 1995: || !CopyBitMapStructureA2U (bm, &local_bm))
1.1 root 1996: return 0;
1997:
1998: CopyColorIndexMappingA2U (cim, &local_cim);
1.1.1.2 root 1999: /* write_log ("BlitPlanar2Direct(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n",
1.1.1.8 ! root 2000: srcx, srcy, dstx, dsty, width, height, minterm, Mask, local_bm.Depth); */
1.1.1.2 root 2001: PlanarToDirect (&local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, Mask, &local_cim);
1.1 root 2002: if (renderinfo_is_current_screen (&local_ri))
2003: do_blit (local_ri.Memory + dstx * GetBytesPerPixel (local_ri.RGBFormat) + dsty * local_ri.BytesPerRow,
1.1.1.8 ! root 2004: local_ri.BytesPerRow, 0, 0, dstx, dsty, width, height, 0);
1.1 root 2005: return 1;
2006: }
2007:
2008: /* @@@ - Work to be done here!
2009: *
2010: * The address is the offset into our Picasso96 frame-buffer (pointed to by gfxmem_start)
2011: * where the value was put.
2012: *
2013: * Porting work: on some machines you may not need these functions, ie. if the memory for the
2014: * Picasso96 frame-buffer is directly viewable or directly blittable. On Win32 with DirectX,
2015: * this is not the case. So I provide some write-through functions (as per Mathias' orders!)
2016: */
2017: static void write_gfx_long (uaecptr addr, uae_u32 value)
2018: {
2019: uaecptr oldaddr = addr;
2020: int x, xbytes, y;
2021: uae_u8 *dst;
2022:
2023: if (!picasso_on)
2024: return;
2025:
2026: /*
2027: * Several writes to successive memory locations are a common access pattern.
2028: * Try to optimize it.
2029: */
2030: if (addr >= wgfx_linestart && addr + 4 <= wgfx_lineend) {
2031: if (addr < wgfx_min)
2032: wgfx_min = addr;
2033: if (addr + 4 > wgfx_max)
2034: wgfx_max = addr + 4;
2035: return;
2036: } else
2037: wgfx_flushline ();
2038:
2039: addr += gfxmem_start;
2040: /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
2041: if (addr < picasso96_state.Address || addr + 4 > picasso96_state.Extent)
2042: return;
2043:
2044: addr -= picasso96_state.Address;
2045: y = addr / picasso96_state.BytesPerRow;
2046:
2047: #if 0
2048: DX_Invalidate (y, y);
1.1.1.8 ! root 2049: if (!picasso_vidinfo.extra_mem)
1.1 root 2050: return;
2051:
2052: xbytes = addr - y * picasso96_state.BytesPerRow;
2053: x = xbytes / picasso96_state.BytesPerPixel;
2054:
2055: if (x < picasso96_state.Width && y < picasso96_state.Height) {
1.1.1.2 root 2056: dst = gfx_lock_picasso ();
1.1 root 2057: if (dst) {
1.1.1.8 ! root 2058: do_put_mem_long ((uae_u32 *) (dst + y * picasso_vidinfo.rowbytes + xbytes), value);
1.1.1.2 root 2059: gfx_unlock_picasso ();
1.1 root 2060: }
2061: }
2062: #else
2063: if (y >= picasso96_state.Height)
2064: return;
2065: wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
2066: wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
2067: wgfx_y = y;
2068: wgfx_min = oldaddr;
2069: wgfx_max = oldaddr + 4;
2070: #endif
2071: }
2072:
2073: static void write_gfx_word (uaecptr addr, uae_u16 value)
2074: {
2075: uaecptr oldaddr = addr;
2076: int x, xbytes, y;
2077: uae_u8 *dst;
2078:
2079: if (!picasso_on)
2080: return;
2081:
2082: /*
2083: * Several writes to successive memory locations are a common access pattern.
2084: * Try to optimize it.
2085: */
2086: if (addr >= wgfx_linestart && addr + 2 <= wgfx_lineend) {
2087: if (addr < wgfx_min)
2088: wgfx_min = addr;
2089: if (addr + 2 > wgfx_max)
2090: wgfx_max = addr + 2;
2091: return;
2092: } else
2093: wgfx_flushline ();
2094:
2095: addr += gfxmem_start;
2096: /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
2097: if (addr < picasso96_state.Address || addr + 2 > picasso96_state.Extent)
2098: return;
2099:
2100: addr -= picasso96_state.Address;
2101: y = addr / picasso96_state.BytesPerRow;
2102:
2103: #if 0
2104: DX_Invalidate (y, y);
1.1.1.8 ! root 2105: if (!picasso_vidinfo.extra_mem)
1.1 root 2106: return;
2107:
2108: xbytes = addr - y * picasso96_state.BytesPerRow;
2109: x = xbytes / picasso96_state.BytesPerPixel;
2110:
2111: if (x < picasso96_state.Width && y < picasso96_state.Height) {
1.1.1.2 root 2112: dst = gfx_lock_picasso ();
1.1 root 2113: if (dst) {
1.1.1.8 ! root 2114: do_put_mem_word ((uae_u16 *) (dst + y * picasso_vidinfo.rowbytes + xbytes), value);
1.1.1.2 root 2115: gfx_unlock_picasso ();
1.1 root 2116: }
2117: }
2118: #else
2119: if (y >= picasso96_state.Height)
2120: return;
2121: wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
2122: wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
2123: wgfx_y = y;
2124: wgfx_min = oldaddr;
2125: wgfx_max = oldaddr + 2;
2126: #endif
2127: }
2128:
2129: static void write_gfx_byte (uaecptr addr, uae_u8 value)
2130: {
2131: uaecptr oldaddr = addr;
2132: int x, xbytes, y;
2133: uae_u8 *dst;
2134:
2135: if (!picasso_on)
2136: return;
2137:
2138: /*
2139: * Several writes to successive memory locations are a common access pattern.
2140: * Try to optimize it.
2141: */
2142: if (addr >= wgfx_linestart && addr + 4 <= wgfx_lineend) {
2143: if (addr < wgfx_min)
2144: wgfx_min = addr;
2145: if (addr + 1 > wgfx_max)
2146: wgfx_max = addr + 1;
2147: return;
2148: } else
2149: wgfx_flushline ();
2150:
2151: addr += gfxmem_start;
2152: /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
2153: if (addr < picasso96_state.Address || addr + 1 > picasso96_state.Extent)
2154: return;
2155:
2156: addr -= picasso96_state.Address;
2157: y = addr / picasso96_state.BytesPerRow;
2158:
2159: #if 0
2160: DX_Invalidate (y, y);
1.1.1.8 ! root 2161: if (!picasso_vidinfo.extra_mem)
1.1 root 2162: return;
2163:
2164: xbytes = addr - y * picasso96_state.BytesPerRow;
2165: x = xbytes / picasso96_state.BytesPerPixel;
2166:
2167: if (x < picasso96_state.Width && y < picasso96_state.Height) {
1.1.1.2 root 2168: dst = gfx_lock_picasso ();
1.1 root 2169: if (dst) {
1.1.1.8 ! root 2170: *(uae_u8 *) (dst + y * picasso_vidinfo.rowbytes + xbytes) = value;
1.1.1.2 root 2171: gfx_unlock_picasso ();
1.1 root 2172: }
2173: }
2174: #else
2175: if (y >= picasso96_state.Height)
2176: return;
2177: wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
2178: wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
2179: wgfx_y = y;
2180: wgfx_min = oldaddr;
2181: wgfx_max = oldaddr + 1;
2182: #endif
2183: }
2184:
2185: static uae_u32 REGPARAM2 gfxmem_lget (uaecptr addr)
2186: {
2187: uae_u32 *m;
2188: addr -= gfxmem_start & gfxmem_mask;
2189: addr &= gfxmem_mask;
1.1.1.8 ! root 2190: m = (uae_u32 *) (gfxmemory + addr);
! 2191: return do_get_mem_long (m);
1.1 root 2192: }
2193:
2194: static uae_u32 REGPARAM2 gfxmem_wget (uaecptr addr)
2195: {
2196: uae_u16 *m;
2197: addr -= gfxmem_start & gfxmem_mask;
2198: addr &= gfxmem_mask;
1.1.1.8 ! root 2199: m = (uae_u16 *) (gfxmemory + addr);
! 2200: return do_get_mem_word (m);
1.1 root 2201: }
2202:
2203: static uae_u32 REGPARAM2 gfxmem_bget (uaecptr addr)
2204: {
2205: addr -= gfxmem_start & gfxmem_mask;
2206: addr &= gfxmem_mask;
2207: return gfxmemory[addr];
2208: }
2209:
2210: static void REGPARAM2 gfxmem_lput (uaecptr addr, uae_u32 l)
2211: {
2212: uae_u32 *m;
2213: addr -= gfxmem_start & gfxmem_mask;
2214: addr &= gfxmem_mask;
1.1.1.8 ! root 2215: m = (uae_u32 *) (gfxmemory + addr);
! 2216: do_put_mem_long (m, l);
1.1 root 2217:
2218: /* write the long-word to our displayable memory */
1.1.1.8 ! root 2219: write_gfx_long (addr, l);
1.1 root 2220: }
2221:
2222: static void REGPARAM2 gfxmem_wput (uaecptr addr, uae_u32 w)
2223: {
2224: uae_u16 *m;
2225: addr -= gfxmem_start & gfxmem_mask;
2226: addr &= gfxmem_mask;
1.1.1.8 ! root 2227: m = (uae_u16 *) (gfxmemory + addr);
! 2228: do_put_mem_word (m, (uae_u16) w);
1.1 root 2229:
2230: /* write the word to our displayable memory */
1.1.1.8 ! root 2231: write_gfx_word (addr, (uae_u16) w);
1.1 root 2232: }
2233:
2234: static void REGPARAM2 gfxmem_bput (uaecptr addr, uae_u32 b)
2235: {
2236: addr -= gfxmem_start & gfxmem_mask;
2237: addr &= gfxmem_mask;
2238: gfxmemory[addr] = b;
2239:
2240: /* write the byte to our displayable memory */
1.1.1.8 ! root 2241: write_gfx_byte (addr, (uae_u8) b);
1.1 root 2242: }
2243:
2244: static int REGPARAM2 gfxmem_check (uaecptr addr, uae_u32 size)
2245: {
2246: addr -= gfxmem_start & gfxmem_mask;
2247: addr &= gfxmem_mask;
1.1.1.2 root 2248: return (addr + size) < allocated_gfxmem;
1.1 root 2249: }
2250:
2251: static uae_u8 REGPARAM2 *gfxmem_xlate (uaecptr addr)
2252: {
2253: addr -= gfxmem_start & gfxmem_mask;
2254: addr &= gfxmem_mask;
2255: return gfxmemory + addr;
2256: }
2257:
2258: addrbank gfxmem_bank = {
2259: gfxmem_lget, gfxmem_wget, gfxmem_bget,
2260: gfxmem_lput, gfxmem_wput, gfxmem_bput,
2261: gfxmem_xlate, gfxmem_check
2262: };
2263:
2264: static int resolution_compare (const void *a, const void *b)
2265: {
1.1.1.8 ! root 2266: struct PicassoResolution *ma = (struct PicassoResolution *) a;
! 2267: struct PicassoResolution *mb = (struct PicassoResolution *) b;
1.1 root 2268: if (ma->res.width > mb->res.width)
2269: return -1;
2270: if (ma->res.width < mb->res.width)
2271: return 1;
2272: if (ma->res.height > mb->res.height)
2273: return -1;
2274: if (ma->res.height < mb->res.height)
2275: return 1;
2276: return ma->depth - mb->depth;
2277: }
1.1.1.8 ! root 2278:
1.1 root 2279: /* Call this function first, near the beginning of code flow
2280: * NOTE: Don't stuff it in InitGraphics() which seems reasonable...
2281: * Instead, put it in customreset() for safe-keeping. */
2282: void InitPicasso96 (void)
2283: {
2284: static int first_time = 1;
2285:
1.1.1.8 ! root 2286: memset (&picasso96_state, 0, sizeof (struct picasso96_state_struct));
1.1.1.2 root 2287:
1.1 root 2288: if (first_time) {
2289: int i;
2290:
2291: for (i = 0; i < 256; i++) {
2292: p2ctab[i][0] = (((i & 128) ? 0x01000000 : 0)
2293: | ((i & 64) ? 0x010000 : 0)
2294: | ((i & 32) ? 0x0100 : 0)
2295: | ((i & 16) ? 0x01 : 0));
2296: p2ctab[i][1] = (((i & 8) ? 0x01000000 : 0)
2297: | ((i & 4) ? 0x010000 : 0)
2298: | ((i & 2) ? 0x0100 : 0)
2299: | ((i & 1) ? 0x01 : 0));
2300: }
2301: mode_count = DX_FillResolutions (&picasso96_pixel_format);
1.1.1.8 ! root 2302: qsort (DisplayModes, mode_count, sizeof (struct PicassoResolution), resolution_compare);
1.1 root 2303:
2304: for (i = 0; i < mode_count; i++) {
1.1.1.8 ! root 2305: sprintf (DisplayModes[i].name, "%dx%d, %d-bit, %d Hz",
! 2306: DisplayModes[i].res.width, DisplayModes[i].res.height, DisplayModes[i].depth * 8, DisplayModes[i].refresh);
1.1 root 2307: switch (DisplayModes[i].depth) {
1.1.1.8 ! root 2308: case 1:
1.1 root 2309: if (DisplayModes[i].res.width > chunky.width)
2310: chunky.width = DisplayModes[i].res.width;
2311: if (DisplayModes[i].res.height > chunky.height)
2312: chunky.height = DisplayModes[i].res.height;
2313: break;
1.1.1.8 ! root 2314: case 2:
1.1 root 2315: if (DisplayModes[i].res.width > hicolour.width)
2316: hicolour.width = DisplayModes[i].res.width;
2317: if (DisplayModes[i].res.height > hicolour.height)
2318: hicolour.height = DisplayModes[i].res.height;
2319: break;
1.1.1.8 ! root 2320: case 3:
1.1 root 2321: if (DisplayModes[i].res.width > truecolour.width)
2322: truecolour.width = DisplayModes[i].res.width;
2323: if (DisplayModes[i].res.height > truecolour.height)
2324: truecolour.height = DisplayModes[i].res.height;
2325: break;
1.1.1.8 ! root 2326: case 4:
1.1 root 2327: if (DisplayModes[i].res.width > alphacolour.width)
2328: alphacolour.width = DisplayModes[i].res.width;
2329: if (DisplayModes[i].res.height > alphacolour.height)
2330: alphacolour.height = DisplayModes[i].res.height;
2331: break;
2332: }
2333: }
1.1.1.2 root 2334: ShowSupportedResolutions ();
1.1 root 2335:
2336: first_time = 0;
2337: }
2338: }
2339:
2340: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.