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

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

unix.superglobalmegacorp.com

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