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