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