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