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