Annotation of uae/src/picasso96.c, revision 1.1.1.11

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.