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