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