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