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