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