]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
imported winuaesrc1400b7.zip
authorToni Wilen <twilen@winuae.net>
Sat, 17 Feb 2007 14:44:07 +0000 (16:44 +0200)
committerToni Wilen <twilen@winuae.net>
Mon, 22 Feb 2010 19:31:45 +0000 (21:31 +0200)
18 files changed:
ar.c
audio.c
cdtv.c
expansion.c
fpp.c
include/filesys.h
include/memory.h
memory.c
od-win32/dxwrap.c
od-win32/hardfile_win32.c
od-win32/mman.c
od-win32/picasso96_win.c
od-win32/picasso96_win.h
od-win32/picasso96_xp_win.c [new file with mode: 0755]
od-win32/win32.h
od-win32/win32gfx.c
od-win32/win32gui.c
od-win32/winuaechangelog.txt

diff --git a/ar.c b/ar.c
index 810c6428bc378b73eb63424b8950200ce5076cd3..e19cf5a2510142cc0523d5015672601943377eb4 100755 (executable)
--- a/ar.c
+++ b/ar.c
@@ -343,14 +343,14 @@ STATIC_INLINE int ar3a (uaecptr addr, uae_u8 b, int writing)
 /*    write_log_debug("ARSTATUS armode:%d, Reading %d from address %p, PC=%p\n", armode, armemory_rom[addr], addr, m68k_getpc()); */
 /*     }        */
 
-    if (armodel == 1 ) /* With AR1. It is always a read. Actually, it is a strobe on exit of the AR.
+    if (armodel == 1) /* With AR1. It is always a read. Actually, it is a strobe on exit of the AR.
                          * but, it is also read during the checksum routine. */
     {
-       if ( addr < 2)
+       if (addr < 2)
        {
-           if ( is_ar_pc_in_rom() )
+           if (is_ar_pc_in_rom())
            {
-               if ( ar_wait_pop )
+               if (ar_wait_pop)
                {
                    action_replay_flag = ACTION_REPLAY_WAIT_PC;
 /*                 write_log_debug("SP %p\n", m68k_areg(regs,7));  */
@@ -378,7 +378,7 @@ STATIC_INLINE int ar3a (uaecptr addr, uae_u8 b, int writing)
     }
 
 #ifdef ACTION_REPLAY_HIDE_CARTRIDGE
-    if (addr >= 8 )
+    if (addr >= 8)
        return armemory_rom[addr];
 
     if (action_replay_flag != ACTION_REPLAY_ACTIVE)
@@ -550,6 +550,9 @@ void REGPARAM2 arram_lput (uaecptr addr, uae_u32 l)
 {
     uae_u32 *m;
 
+#ifdef JIT
+    special_mem |= S_WRITE;
+#endif
     addr -= arram_start;
     addr &= arram_mask;
     m = (uae_u32 *)(armemory_ram + addr);
@@ -585,6 +588,9 @@ void REGPARAM2 arram_wput (uaecptr addr, uae_u32 w)
 
 void REGPARAM2 arram_bput (uaecptr addr, uae_u32 b)
 {
+#ifdef JIT
+    special_mem |= S_WRITE;
+#endif
     addr -= arram_start;
     addr &= arram_mask;
     armemory_ram[addr] = b;
@@ -987,8 +993,8 @@ void hrtmon_hide(void)
     HRTCFG *cfg = (HRTCFG*)hrtmemory;
     if (!ar1200 && cfg->entered)
        return;
-    hrtmon_flag = ACTION_REPLAY_IDLE;
     cartridge_exit();
+    hrtmon_flag = ACTION_REPLAY_IDLE;
     unset_special (&regs, SPCFLAG_ACTION_REPLAY);
     //write_log ("HRTMON: Exit\n");
 }
@@ -1043,89 +1049,88 @@ static void action_replay_patch(void)
  * Else, it returns the calculated checksum.
  * Note: Will be wrong if the checksum is zero, but i'll take my chances on that not happenning ;)
  */
-static uae_u32 action_replay_calculate_checksum()
-{
-       uae_u32* checksum_end;
-       uae_u32* checksum_start;
-       uae_u8   checksum_start_offset[] = {0, 0, 4, 0x7c};
-       uae_u32 checksum = 0;
-       uae_u32 stored_checksum;
-
-       /* All models: The checksum is calculated right upto the long checksum in the rom.
-        * AR1: The checksum starts at offset 0.
-        * AR1: The checksum is the last non-zero long in the rom.
-        * AR2: The checksum starts at offset 4.
-        * AR2: The checksum is the last Long in the rom.
-        * AR3: The checksum starts at offset 0x7c.
-        * AR3: The checksum is the last Long in the rom.
-        *
-   * Checksums: (This is a good way to compare roms. I have two with different md5sums,
-        * but the same checksum, so the difference must be in the first four bytes.)
-        * 3.17 0xf009bfc9
-        * 3.09 0xd34d04a7
-        * 2.14 0xad839d36
-        * 2.14 0xad839d36
-        * 1.15 0xee12116
+static uae_u32 action_replay_calculate_checksum(void)
+{
+    uae_u32* checksum_end;
+    uae_u32* checksum_start;
+    uae_u8   checksum_start_offset[] = { 0, 0, 4, 0x7c };
+    uae_u32 checksum = 0;
+    uae_u32 stored_checksum;
+
+    /* All models: The checksum is calculated right upto the long checksum in the rom.
+     * AR1: The checksum starts at offset 0.
+     * AR1: The checksum is the last non-zero long in the rom.
+     * AR2: The checksum starts at offset 4.
+     * AR2: The checksum is the last Long in the rom.
+     * AR3: The checksum starts at offset 0x7c.
+     * AR3: The checksum is the last Long in the rom.
+     *
+     * Checksums: (This is a good way to compare roms. I have two with different md5sums,
+     * but the same checksum, so the difference must be in the first four bytes.)
+     * 3.17 0xf009bfc9
+     * 3.09 0xd34d04a7
+     * 2.14 0xad839d36
+     * 2.14 0xad839d36
+     * 1.15 0xee12116
    */
 
-       if (!armemory_rom)
-           return 0; /* If there is no rom then i guess the checksum is ok */
+    if (!armemory_rom)
+        return 0; /* If there is no rom then i guess the checksum is ok */
 
-       checksum_start = (uae_u32*)&armemory_rom[checksum_start_offset[armodel]];
-       checksum_end = (uae_u32*)&armemory_rom[ar_rom_file_size];
+    checksum_start = (uae_u32*)&armemory_rom[checksum_start_offset[armodel]];
+    checksum_end = (uae_u32*)&armemory_rom[ar_rom_file_size];
 
-       /* Search for first non-zero Long starting from the end of the rom. */
-       /* Assume long alignment, (will always be true for AR2 and AR3 and the AR1 rom i've got). */
-       /* If anyone finds an AR1 rom with a word-aligned checksum, then this code will have to be modified. */ 
-       while (! *(--checksum_end) );
+    /* Search for first non-zero Long starting from the end of the rom. */
+    /* Assume long alignment, (will always be true for AR2 and AR3 and the AR1 rom i've got). */
+    /* If anyone finds an AR1 rom with a word-aligned checksum, then this code will have to be modified. */ 
+    while (! *(--checksum_end));
 
-       if ( armodel == 1)
-       {
-               uae_u16* rom_ptr_word;
-               uae_s16  sign_extended_word;
+    if (armodel == 1)
+    {
+       uae_u16* rom_ptr_word;
+       uae_s16  sign_extended_word;
 
-               rom_ptr_word = (uae_u16*)checksum_start;
-               while ( rom_ptr_word != (uae_u16*)checksum_end )
-               {
-                               sign_extended_word = (uae_s16)do_get_mem_word (rom_ptr_word);
-                               /* When the word is cast on the following line, it will get sign-extended. */
-                               checksum += (uae_u32)sign_extended_word;
-                               rom_ptr_word++;
-               }
+       rom_ptr_word = (uae_u16*)checksum_start;
+       while (rom_ptr_word != (uae_u16*)checksum_end)
+       {
+           sign_extended_word = (uae_s16)do_get_mem_word (rom_ptr_word);
+           /* When the word is cast on the following line, it will get sign-extended. */
+           checksum += (uae_u32)sign_extended_word;
+           rom_ptr_word++;
        }
-       else
+    }
+    else
+    {
+       uae_u32* rom_ptr_long;
+       rom_ptr_long = checksum_start;
+       while (rom_ptr_long != checksum_end)
        {
-               uae_u32* rom_ptr_long;
-
-               rom_ptr_long = checksum_start;
-               while ( rom_ptr_long != checksum_end )
-               {
-                       checksum += do_get_mem_long (rom_ptr_long);
-                       rom_ptr_long++;
-               }
+           checksum += do_get_mem_long (rom_ptr_long);
+           rom_ptr_long++;
        }
+    }
 
-       stored_checksum = do_get_mem_long(checksum_end); 
+    stored_checksum = do_get_mem_long(checksum_end); 
 
-       return checksum == stored_checksum ? 0 : checksum;
+    return checksum == stored_checksum ? 0 : checksum;
 }
 
 /* Returns 0 on error. */
 static uae_u8* get_checksum_location()
 {
-       uae_u32* checksum_end;
+    uae_u32* checksum_end;
 
-       /* See action_replay_calculate_checksum() for checksum info. */
+    /* See action_replay_calculate_checksum() for checksum info. */
 
-       if (!armemory_rom)
-               return 0;
+    if (!armemory_rom)
+       return 0;
 
-       checksum_end = (uae_u32*)&armemory_rom[ar_rom_file_size];
+    checksum_end = (uae_u32*)&armemory_rom[ar_rom_file_size];
 
-       /* Search for first non-zero Long starting from the end of the rom. */
-       while (! *(--checksum_end) );
+    /* Search for first non-zero Long starting from the end of the rom. */
+    while (! *(--checksum_end));
 
-       return (uae_u8*)checksum_end;
+    return (uae_u8*)checksum_end;
 }
 
 
@@ -1133,16 +1138,16 @@ static uae_u8* get_checksum_location()
 /* Useful if you want to patch the rom.*/
 static void action_replay_fixup_checksum(uae_u32 new_checksum)
 {
-       uae_u32* checksum = (uae_u32*)get_checksum_location();
-       if ( checksum )
-       {
-               do_put_mem_long(checksum, new_checksum);
-       }
-       else
-       {
-               write_log("Unable to locate Checksum in ROM.\n");
-       }
-       return;
+    uae_u32* checksum = (uae_u32*)get_checksum_location();
+    if (checksum)
+    {
+       do_put_mem_long(checksum, new_checksum);
+    }
+    else
+    {
+       write_log("Unable to locate Checksum in ROM.\n");
+    }
+    return;
 }
 
 /* Longword search on word boundary
@@ -1151,18 +1156,16 @@ static void action_replay_fixup_checksum(uae_u32 new_checksum)
  */
 static uae_u8* find_absolute_long(uae_u8* start_addr, uae_u8* end_addr, uae_u32 search_value)
 {
-       uae_u8* addr;
+    uae_u8* addr;
 
-       for ( addr = start_addr; addr < end_addr; )
-       {
-               if ( do_get_mem_long((uae_u32*)addr) == search_value )
-               {
-/*                     write_log_debug("Found %p at offset %p.\n", search_value, addr - start_addr);*/
-                       return addr;
-               }
-               addr+=2;
+    for (addr = start_addr; addr < end_addr;) {
+       if (do_get_mem_long((uae_u32*)addr) == search_value) {
+/*         write_log_debug("Found %p at offset %p.\n", search_value, addr - start_addr);*/
+           return addr;
        }
-       return 0;
+       addr += 2;
+    }
+    return 0;
 }
 
 /* word search on word boundary
@@ -1173,18 +1176,16 @@ static uae_u8* find_absolute_long(uae_u8* start_addr, uae_u8* end_addr, uae_u32
  */
 static uae_u8* find_relative_word(uae_u8* start_addr, uae_u8* end_addr, uae_u16 search_addr)
 {
-       uae_u8* addr;
+    uae_u8* addr;
 
-       for ( addr = start_addr; addr < end_addr; )
-       {
-               if ( do_get_mem_word((uae_u16*)addr) == (uae_u16)(search_addr - (uae_u16)(addr-start_addr)) )
-               {
-/*                     write_log_debug("Found %p at offset %p.\n", search_addr, addr - start_addr);*/
-                       return addr;
-               }
-               addr+=2;
+    for (addr = start_addr; addr < end_addr;) {
+       if (do_get_mem_word((uae_u16*)addr) == (uae_u16)(search_addr - (uae_u16)(addr - start_addr))) {
+/*         write_log_debug("Found %p at offset %p.\n", search_addr, addr - start_addr);*/
+           return addr;
        }
-       return 0;
+       addr += 2;
+    }
+    return 0;
 }
 
 /* Disable rom test */
@@ -1193,7 +1194,7 @@ static uae_u8* find_relative_word(uae_u8* start_addr, uae_u8* end_addr, uae_u16
  * and only disables it if the surounding bytes are what it expects.
  */
 
-static void disable_rom_test()
+static void disable_rom_test(void)
 {
     uae_u8* addr;
 
@@ -1212,36 +1213,31 @@ static void disable_rom_test()
  * 40EC96 41F9 0041 FFFC lea (0x41fffc),a0
  */
 
-       if ( armodel == 1)
-       {
-         uae_u16 search_value_rel = end_addr - start_addr;
-               addr = find_relative_word(start_addr, end_addr, search_value_rel);
+    if (armodel == 1) {
+       uae_u16 search_value_rel = end_addr - start_addr;
+       addr = find_relative_word(start_addr, end_addr, search_value_rel);
 
-               if ( addr )
-               {
-                       if ( do_get_mem_word((uae_u16*)(addr-6)) == 0x6100 && /* bsr.w */
-                                        do_get_mem_word((uae_u16*)(addr-2)) == 0x41fa )  /* lea relative */
-                       {
-                               write_log("Patching to disable ROM TEST.\n");
-                               do_put_mem_word((uae_u16*)(addr-6), 0x4e75); /* rts */
-                       }
-               }
+       if (addr) {
+           if (do_get_mem_word((uae_u16*)(addr-6)) == 0x6100 && /* bsr.w */
+                do_get_mem_word((uae_u16*)(addr-2)) == 0x41fa)  /* lea relative */
+           {
+               write_log("Patching to disable ROM TEST.\n");
+               do_put_mem_word((uae_u16*)(addr-6), 0x4e75); /* rts */
+           }
        }
-       else
-       {
-         uae_u32 search_value_abs = arrom_start + end_addr - start_addr;
-               addr = find_absolute_long(start_addr, end_addr, search_value_abs);
+    } else {
+       uae_u32 search_value_abs = arrom_start + end_addr - start_addr;
+       addr = find_absolute_long(start_addr, end_addr, search_value_abs);
 
-               if ( addr )
-               {
-                       if ( do_get_mem_word((uae_u16*)(addr-6)) == 0x6100 && /* bsr.w */
-                                        do_get_mem_word((uae_u16*)(addr-2)) == 0x41f9 )  /* lea absolute */
-                       {
-                               write_log("Patching to disable ROM TEST.\n");
-                               do_put_mem_word((uae_u16*)(addr-6), 0x4e75); /* rts */
-                       }
-               }
+       if (addr) {
+           if (do_get_mem_word((uae_u16*)(addr-6)) == 0x6100 && /* bsr.w */
+               do_get_mem_word((uae_u16*)(addr-2)) == 0x41f9)  /* lea absolute */
+           {
+               write_log("Patching to disable ROM TEST.\n");
+               do_put_mem_word((uae_u16*)(addr-6), 0x4e75); /* rts */
+           }
        }
+    }
 }
 
 /* After we have calculated the checksum, and verified the rom is ok,
@@ -1254,14 +1250,10 @@ static void action_replay_checksum_info(void)
 {
     if (!armemory_rom)
        return;
-    if ( action_replay_calculate_checksum() == 0 )
-    {
+    if (action_replay_calculate_checksum() == 0)
        write_log("Action Replay Checksum is OK.\n");
-    }
     else
-    {
        write_log("Action Replay Checksum is INVALID.\n");
-    }
     disable_rom_test();
 }
 
@@ -1297,52 +1289,46 @@ static void action_replay_unsetbanks (void)
 /* param to allow us to unload the cart. Currently we know it is safe if we are doing a reset to unload it.*/
 int action_replay_unload(int in_memory_reset)
 {
-       char* state[] =
-       {
-               "ACTION_REPLAY_WAIT_PC", 
-               "ACTION_REPLAY_INACTIVE",
-               "ACTION_REPLAY_WAITRESET",
-               "0",
-               "ACTION_REPLAY_IDLE",
-               "ACTION_REPLAY_ACTIVATE",
-               "ACTION_REPLAY_ACTIVE",
-               "ACTION_REPLAY_DORESET",
-               "ACTION_REPLAY_HIDE",
-       };
-
-       write_log_debug("Action Replay State:(%s)\nHrtmon State:(%s)\n", state[action_replay_flag+3],state[hrtmon_flag+3] );
+    char* state[] =
+    {
+       "ACTION_REPLAY_WAIT_PC", 
+       "ACTION_REPLAY_INACTIVE",
+       "ACTION_REPLAY_WAITRESET",
+       "0",
+       "ACTION_REPLAY_IDLE",
+       "ACTION_REPLAY_ACTIVATE",
+       "ACTION_REPLAY_ACTIVE",
+       "ACTION_REPLAY_DORESET",
+       "ACTION_REPLAY_HIDE",
+    };
+
+    write_log_debug("Action Replay State:(%s)\nHrtmon State:(%s)\n", state[action_replay_flag+3],state[hrtmon_flag+3]);
        
-       if ( armemory_rom && armodel == 1 )
-       {
-               if ( is_ar_pc_in_ram() || is_ar_pc_in_rom() || action_replay_flag == ACTION_REPLAY_WAIT_PC )
-               {
-                       write_log("Can't Unload Action Replay 1. It is Active.\n");
-                       return 0;
-               }
+    if (armemory_rom && armodel == 1) {
+       if (is_ar_pc_in_ram() || is_ar_pc_in_rom() || action_replay_flag == ACTION_REPLAY_WAIT_PC) {
+           write_log("Can't Unload Action Replay 1. It is Active.\n");
+           return 0;
        }
-       else
-       {
-               if ( action_replay_flag != ACTION_REPLAY_IDLE && action_replay_flag != ACTION_REPLAY_INACTIVE )
-               {
-                       write_log("Can't Unload Action Replay. It is Active.\n");
-                       return 0; /* Don't unload it whilst it's active, or it will crash the amiga if not the emulator */
-               }
-               if ( hrtmon_flag != ACTION_REPLAY_IDLE && hrtmon_flag != ACTION_REPLAY_INACTIVE )
-               {
-                       write_log("Can't Unload Hrtmon. It is Active.\n");
-                       return 0; /* Don't unload it whilst it's active, or it will crash the amiga if not the emulator */
-               }
+    } else {
+       if (action_replay_flag != ACTION_REPLAY_IDLE && action_replay_flag != ACTION_REPLAY_INACTIVE) {
+           write_log("Can't Unload Action Replay. It is Active.\n");
+           return 0; /* Don't unload it whilst it's active, or it will crash the amiga if not the emulator */
+       }
+       if (hrtmon_flag != ACTION_REPLAY_IDLE && hrtmon_flag != ACTION_REPLAY_INACTIVE) {
+           write_log("Can't Unload Hrtmon. It is Active.\n");
+           return 0; /* Don't unload it whilst it's active, or it will crash the amiga if not the emulator */
        }
+    }
 
-       unset_special(&regs, SPCFLAG_ACTION_REPLAY); /* This shouldn't be necessary here, but just in case. */
-       action_replay_flag = ACTION_REPLAY_INACTIVE;
-       hrtmon_flag = ACTION_REPLAY_INACTIVE;
-       action_replay_unsetbanks();
-       action_replay_unmap_banks();
-       hrtmon_unmap_banks();
-       /* Make sure you unmap everything before you call action_replay_cleanup() */
-       action_replay_cleanup();
-       return 1;
+    unset_special(&regs, SPCFLAG_ACTION_REPLAY); /* This shouldn't be necessary here, but just in case. */
+    action_replay_flag = ACTION_REPLAY_INACTIVE;
+    hrtmon_flag = ACTION_REPLAY_INACTIVE;
+    action_replay_unsetbanks();
+    action_replay_unmap_banks();
+    hrtmon_unmap_banks();
+    /* Make sure you unmap everything before you call action_replay_cleanup() */
+    action_replay_cleanup();
+    return 1;
 }
 
 
@@ -1355,8 +1341,7 @@ int action_replay_load(void)
     action_replay_flag = ACTION_REPLAY_INACTIVE;
     write_log_debug("Entered action_replay_load()\n");
     /* Don't load a rom if one is already loaded. Use action_replay_unload() first. */
-    if (armemory_rom || hrtmemory)
-    {
+    if (armemory_rom || hrtmemory) {
        write_log("action_replay_load() ROM already loaded.\n");
        return 0;
     }
@@ -1562,7 +1547,7 @@ void action_replay_version(void)
     if (!armemory_rom)
        return;
 
-    if ( armodel == 1 )
+    if (armodel == 1)
            return; /* no support yet. */
 
     /* Extract Version string */
@@ -1605,7 +1590,7 @@ void action_replay_version(void)
        }
     }
 
-    if ( iArVersionMajor > 0 )
+    if (iArVersionMajor > 0)
     {
        write_log("Version of cart is '%d.%.02d', date is '%s'\n", iArVersionMajor, iArVersionMinor, sArDate);
     }
diff --git a/audio.c b/audio.c
index 9e64f734528b122c23da0030c5932be27fa0fac0..d9d0f98d8d44fd11e8e913a39a323fc45b3f0ebc 100755 (executable)
--- a/audio.c
+++ b/audio.c
@@ -55,7 +55,8 @@ STATIC_INLINE int isaudio(void)
 
 static int debugchannel (int ch)
 {
-    if ((1 << ch) & DEBUG_CHANNEL_MASK) return 1;
+    if ((1 << ch) & DEBUG_CHANNEL_MASK)
+       return 1;
     return 0;
 }
 
@@ -1310,6 +1311,7 @@ void set_audio(void)
        }
     }
     next_sample_evtime = scaled_sample_evtime;
+    last_cycles = get_cycles () - 1;
     compute_vsynctime ();
 
     mixed_mul1 = MIXED_STEREO_MAX / 2 - ((currprefs.sound_stereo_separation * 3) / 2);
@@ -1367,7 +1369,7 @@ void set_audio(void)
        sample_prehandler = anti_prehandler;
     }
 
-    audio_event_reset();
+    audio_activate ();
 
     if (currprefs.produce_sound == 0) {
        eventtab[ev_audio].active = 0;
@@ -1585,6 +1587,7 @@ void AUDxPER (int nr, uae_u16 v)
     if (per < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
        per = maxhpos * CYCLE_UNIT / 2;
     else if (per < 4 * CYCLE_UNIT)
+        /* smaller value would cause extremely high cpu usage */
        per = 4 * CYCLE_UNIT;
 
    if (audio_channel[nr].per == PERIOD_MAX - 1 && per != PERIOD_MAX - 1) {
diff --git a/cdtv.c b/cdtv.c
index d6d68c34dd7b31575ec2eb8569148403171ddbc5..4f63013a6b20f0b4e1dc824ff4d3a8169cbdbdc6 100755 (executable)
--- a/cdtv.c
+++ b/cdtv.c
@@ -10,7 +10,7 @@
   */
 
 //#define CDTV_DEBUG
-#define CDTV_DEBUG_CMD
+//#define CDTV_DEBUG_CMD
 //#define CDTV_DEBUG_6525
 
 #include "sysconfig.h"
index 028e3c028e08500ed26463a450b808221e292f40..a1b59dca91ea51657c996a473c45e271ecf69e21 100755 (executable)
@@ -274,7 +274,7 @@ static void REGPARAM2 expamem_wput (uaecptr addr, uae_u32 value)
                    value = z3fastmem_start >> 16;
                } else {
                    // Z3 P96 RAM
-                   value = (z3fastmem_start + (currprefs.z3fastmem_size + 0xffffff) & ~0xffffff) >> 16;
+                   value = p96ram_start >> 16;
                }
                chipmem_wput (regs.regs[11] + 0x20, value);
                chipmem_wput (regs.regs[11] + 0x28, value);
@@ -907,10 +907,16 @@ static void expamem_init_z3fastmem (void)
  *  Fake Graphics Card (ZORRO III) - BDK
  */
 
+uaecptr p96ram_start;
+int p96mode = 0;
+
 static void expamem_map_gfxcard (void)
 {
     gfxmem_start = (expamem_hi | (expamem_lo >> 4)) << 16;
-    map_banks (&gfxmem_bank, gfxmem_start >> 16, allocated_gfxmem >> 16, 0);
+    if (p96mode)
+       map_banks (&gfxmem_bankx, gfxmem_start >> 16, allocated_gfxmem >> 16, allocated_gfxmem);
+    else
+       map_banks (&gfxmem_bank, gfxmem_start >> 16, allocated_gfxmem >> 16, allocated_gfxmem);
     write_log ("UAEGFX-card: mapped @$%lx, %d MB RTG RAM\n", gfxmem_start, allocated_gfxmem / 0x100000);
 }
 
@@ -1019,7 +1025,8 @@ static void allocate_expamem (void)
 
     z3fastmem_bank.baseaddr = z3fastmem;
     fastmem_bank.baseaddr = fastmemory;
-    gfxmem_bank.baseaddr = gfxmemory;
+    gfxmem_bank.baseaddr = NULL;
+    gfxmem_bankx.baseaddr = gfxmemory;
 
 #ifdef SAVESTATE
     if (savestate_state == STATE_RESTORE) {
@@ -1036,8 +1043,12 @@ static void allocate_expamem (void)
 #ifdef PICASSO96
        if (allocated_gfxmem > 0 && gfxmem_start > 0) {
            restore_ram (p96_filepos, gfxmemory);
-           map_banks (&gfxmem_bank, gfxmem_start >> 16, currprefs.gfxmem_size >> 16,
-               allocated_gfxmem);
+           if (p96mode)
+               map_banks (&gfxmem_bankx, gfxmem_start >> 16, currprefs.gfxmem_size >> 16,
+                   allocated_gfxmem);
+           else
+               map_banks (&gfxmem_bank, gfxmem_start >> 16, currprefs.gfxmem_size >> 16,
+                   allocated_gfxmem);
        }
 #endif
     }
@@ -1140,12 +1151,12 @@ void expansion_init (void)
     allocate_expamem ();
 
 #ifdef FILESYS
-    filesysory = (uae_u8 *) mapped_malloc (0x10000, "filesys");
+    filesysory = mapped_malloc (0x10000, "filesys");
     if (!filesysory) {
        write_log ("virtual memory exhausted (filesysory)!\n");
        exit (0);
     }
-    filesys_bank.baseaddr = (uae_u8*)filesysory;
+    filesys_bank.baseaddr = filesysory;
 #endif
 }
 
diff --git a/fpp.c b/fpp.c
index 7f76f9373cd94e124b6d3fa1579435cab0439a76..3aeb8475e4a63a3db9576e198ef99eeceb5b8d9c 100755 (executable)
--- a/fpp.c
+++ b/fpp.c
@@ -946,12 +946,14 @@ void fpp_opp (uae_u32 opcode, struct regstruct *regs, uae_u16 extra)
        write_log ("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra, m68k_getpc (regs) - 4);
 #endif
     switch ((extra >> 13) & 0x7) {
+
     case 3:
        if (put_fp_value (regs, regs->fp[(extra >> 7) & 7], opcode, extra) == 0) {
            m68k_setpc (regs, m68k_getpc (regs) - 4);
            op_illg (opcode, regs);
        }
        return;
+
     case 4:
     case 5:
        if ((opcode & 0x38) == 0) {
@@ -1066,6 +1068,7 @@ void fpp_opp (uae_u32 opcode, struct regstruct *regs, uae_u16 extra)
                m68k_areg (regs, opcode & 7) = ad - 12;
        }
        return;
+
     case 6:
     case 7:
     {
@@ -1174,6 +1177,7 @@ void fpp_opp (uae_u32 opcode, struct regstruct *regs, uae_u16 extra)
        }
     }
     return;
+
     case 0:
     case 2: /* Extremely common */
        reg = (extra >> 7) & 7;
@@ -1258,7 +1262,9 @@ void fpp_opp (uae_u32 opcode, struct regstruct *regs, uae_u16 extra)
            op_illg (opcode, regs);
            return;
        }
+
        switch (extra & 0x7f) {
+
        case 0x00: /* FMOVE */
        case 0x40: /* Explicit rounding. This is just a quick fix. */
        case 0x44: /* Same for all other cases that have three choices */
index 90e300b6fe0f01c9fb5d2720d6991309c7b1b43a..8ab025579ee0c8b238da3500eb9e8c415b157e97 100755 (executable)
@@ -31,6 +31,7 @@ struct hardfiledata {
     unsigned int heads;
     uae_u64 size2;
     uae_u64 offset2;
+    int warned;
 };
 
 #define FILESYS_VIRTUAL 0
index 9bc3c9ca549bb465a99f42b745a4ccfd669d4de7..d4384b2f597fc4e47734dd9ab080595b1144977d 100755 (executable)
@@ -57,6 +57,7 @@ extern void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v);
 #define cardmem_start 0x00E00000
 #define kickmem_start 0x00F80000
 extern uaecptr z3fastmem_start;
+extern uaecptr p96ram_start;
 extern uaecptr fastmem_start;
 extern uaecptr a3000lmem_start, a3000hmem_start;
 
@@ -106,7 +107,7 @@ extern addrbank cia_bank;
 extern addrbank rtarea_bank;
 extern addrbank expamem_bank;
 extern addrbank fastmem_bank;
-extern addrbank gfxmem_bank;
+extern addrbank gfxmem_bank, gfxmem_bankx;
 extern addrbank gayle_bank;
 extern addrbank mbres_bank;
 extern addrbank akiko_bank;
index c6a6bf6e579505679e42cab4aeb9ca575e3aace4..ce537efeb98e36b465cd5dccfc1df2e5172cabb0 100755 (executable)
--- a/memory.c
+++ b/memory.c
@@ -123,6 +123,7 @@ static struct romdata roms[] = {
     { "A1000 bootstrap ROM", 0, 0, 0, 0, "A1000\0", 0x62f11c04, 8192, 23, 0, 0, ROMTYPE_KICK },
     { "A1000 bootstrap ROM", 0, 0, 0, 0, "A1000\0", 0x0b1ad2d0, 65536, 24, 0, 0, ROMTYPE_KICK },
 
+    { "Action Replay Mk I v1.00", 1, 0, 1, 0, "AR\0", 0x2d921771, 65536, 52, 0, 0, ROMTYPE_AR },
     { "Action Replay Mk I v1.50", 1, 50, 1, 50, "AR\0", 0xd4ce0675, 65536, 25, 0, 0, ROMTYPE_AR },
     { "Action Replay Mk II v2.05", 2, 5, 2, 5, "AR\0", 0x1287301f , 131072, 26, 0, 0, ROMTYPE_AR },
     { "Action Replay Mk II v2.12", 2, 12, 2, 12, "AR\0", 0x804d0361 , 131072, 27, 0, 0, ROMTYPE_AR },
index aafc70ddbf95c7e07545c79d6d38fc4b1287bb2f..9969192159d7850af482595b2a44f7f310fe1b02 100755 (executable)
@@ -313,7 +313,7 @@ int DirectDraw_SurfaceLock(surface_type_e surface_type)
     if (surface_type == lockable_surface)
        surface_type = DirectDraw_GetLockableType();
 
-    switch( surface_type )
+    switch(surface_type)
     {
        case primary_surface:
            DirectDrawState.primary.desc.dwSize = sizeof(DDSURFACEDESC2);
index 56d38806ef1b516de3297a03e36c60fc8a1bc73d..89aa99df7856a48d3b3c008ee45df05e4beec719 100755 (executable)
@@ -81,7 +81,7 @@ static void rdbdump (HANDLE *h, uae_u64 offset, uae_u8 *buf, int blocksize)
     cnt++;
 }
 
-static int safetycheck (HANDLE *h, uae_u64 offset, uae_u8 *buf, int blocksize)
+static int safetycheck (HANDLE *h, uae_u64 offset, uae_u8 *buf, int blocksize, int dowarn)
 {
     int i, j, blocks = 63, empty = 1;
     DWORD outlen, high;
@@ -120,7 +120,8 @@ static int safetycheck (HANDLE *h, uae_u64 offset, uae_u8 *buf, int blocksize)
        write_log ("hd accepted (empty)\n");
        return 1;
     }
-    gui_message_id (IDS_HARDDRIVESAFETYWARNING);
+    if (dowarn)
+       gui_message_id (IDS_HARDDRIVESAFETYWARNING);
     return 2;
 }
 
@@ -189,10 +190,11 @@ int hdf_open (struct hardfiledata *hfd, char *name)
            }
            hfd->blocksize = udi->bytespersector;
            if (hfd->offset == 0) {
-               if (!safetycheck (hfd->handle, 0, hfd->cache, hfd->blocksize)) {
+               if (!safetycheck (hfd->handle, 0, hfd->cache, hfd->blocksize, hfd->warned ? 0 : 1)) {
                    hdf_close (hfd);
                    return 0;
                }
+               hfd->warned = 1;
            }
            hfd->handle_valid = HDF_HANDLE_WIN32;
        }
@@ -884,7 +886,7 @@ Return Value:
            udi->offset = udi->offset2 = pi->StartingOffset.QuadPart;
            udi->size = udi->size2 = pi->PartitionLength.QuadPart;
            write_log ("used\n");
-           if (safetycheck (hDevice, udi->offset, buffer, dg.BytesPerSector)) {
+           if (safetycheck (hDevice, udi->offset, buffer, dg.BytesPerSector, 1)) {
                sprintf (udi->device_name, "HD_P#%d_%s", pi->PartitionNumber, orgname);
                udi++;
                (*index2)++;
@@ -903,7 +905,7 @@ Return Value:
        write_log ("no MBR partition table detected, checking for RDB\n");
     }
 
-    i = safetycheck (hDevice, 0, buffer, dg.BytesPerSector);
+    i = safetycheck (hDevice, 0, buffer, dg.BytesPerSector, 1);
     if (!i) {
        ret = 1;
        goto end;
index 3d2c7009c53e446db8c65d4fe35fe97f78323429..4612032c3b4a465bf646d931557328b24fe21d29 100755 (executable)
@@ -16,6 +16,8 @@
 
 static struct shmid_ds shmids[MAX_SHMID];
 
+extern int p96mode;
+
 uae_u8 *natmem_offset = NULL;
 #ifdef CPU_64_BIT
 int max_allowed_mman = 2048;
@@ -23,6 +25,9 @@ int max_allowed_mman = 2048;
 int max_allowed_mman = 512;
 #endif
 
+static uae_u8 *p96mem_offset;
+static uae_u8 *p96fakeram;
+
 void cache_free(void *cache)
 {
     VirtualFree (cache, 0, MEM_RELEASE);
@@ -105,6 +110,13 @@ void init_shm(void)
     }
     if (os_winnt) {
        natmem_offset = blah;
+       if (p96mode) {
+           p96mem_offset = VirtualAlloc(natmem_offset + size + add, 128 * 1024 * 1024, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_EXECUTE_READWRITE);
+           if (!p96mem_offset) {
+               write_log("NATMEM: failed to allocate special Picasso96 GFX RAM\n");
+               p96mode = 0;
+           }
+       }
     } else {
        VirtualFree(blah, 0, MEM_RELEASE);
        while (address < (LPBYTE)0xa0000000) {
@@ -153,7 +165,7 @@ void mapped_free(uae_u8 *mem)
     }
 }
 
-static key_t get_next_shmkey( void )
+static key_t get_next_shmkey(void)
 {
     key_t result = -1;
     int i;
@@ -167,7 +179,7 @@ static key_t get_next_shmkey( void )
     return result;
 }
 
-STATIC_INLINE key_t find_shmkey( key_t key )
+STATIC_INLINE key_t find_shmkey(key_t key)
 {
     int result = -1;
     if(shmids[key].key == key) {
@@ -232,8 +244,18 @@ void *shmat(int shmid, void *shmaddr, int shmflg)
            got = TRUE;
        }
        if(!strcmp(shmids[shmid].name,"gfx")) {
-           shmaddr=natmem_offset + currprefs.z3fastmem_start + ((currprefs.z3fastmem_size + 0xffffff) & ~0xffffff);
            got = TRUE;
+           if (p96mode) {
+               p96ram_start = p96mem_offset - natmem_offset;
+               shmaddr = natmem_offset + p96ram_start;
+           } else {
+               p96ram_start = currprefs.z3fastmem_start + ((currprefs.z3fastmem_size + 0xffffff) & ~0xffffff);
+               VirtualFree(shmaddr, os_winnt ? size : 0, os_winnt ? MEM_DECOMMIT : MEM_RELEASE);
+               xfree(p96fakeram);
+               result = p96fakeram = xcalloc (size + 4096, 1);
+               shmids[shmid].attached = result;
+               return result;
+           }
        }
        if(!strcmp(shmids[shmid].name,"bogo")) {
            shmaddr=natmem_offset+0x00C00000;
@@ -267,7 +289,7 @@ void *shmat(int shmid, void *shmaddr, int shmflg)
        if (got == FALSE) {
            if (shmaddr)
                VirtualFree(shmaddr, os_winnt ? size : 0, os_winnt ? MEM_DECOMMIT : MEM_RELEASE);
-           result = VirtualAlloc(shmaddr, size, os_winnt ? MEM_COMMIT : (MEM_RESERVE | MEM_COMMIT),
+           result = VirtualAlloc(shmaddr, size, os_winnt ? MEM_COMMIT : (MEM_RESERVE | MEM_COMMIT | (p96mode ? MEM_WRITE_WATCH : 0)),
                PAGE_EXECUTE_READWRITE);
            if (result == NULL) {
                result = (void*)-1;
index 7bd2c80dc3776d1e040cab95de7e5eb551b0e69f..80c8bb7794927dde79a83cbda6c4d8739f72a007 100755 (executable)
@@ -54,8 +54,11 @@ int p96hack_vpos, p96hack_vpos2, p96refresh_active;
 int have_done_picasso; /* For the JIT compiler */
 static int vsyncgfxwrite = 0; 
 static int p96syncrate, vsyncgfxcount;
-static int p96hsync_counter;
-
+int p96hsync_counter, palette_changed;
+#if defined(X86_MSVC_ASSEMBLY)
+#define SWAPSPEEDUP
+#endif
+#ifdef PICASSO96
 #ifdef DEBUG // Change this to _DEBUG for debugging
 #define P96TRACING_ENABLED 1
 #define P96TRACING_LEVEL 1
@@ -64,26 +67,20 @@ static int p96hsync_counter;
 #define PIXEL_LOCK    //and scrollable screens
 #define MAXFLUSHPIXEL 3200 //pixel draw in a lock
 static void flushpixels(void);
-static int pixelcount, palette_changed;
-struct pixel32{
-    uaecptr addr;
-    uae_u32 value;
-    int size;
-};
-static struct pixel32 pixelbase[MAXFLUSHPIXEL + 2];
 #ifdef P96TRACING_ENABLED
 #define P96TRACE(x) do { write_log x; } while(0)
 #else
 #define P96TRACE(x)
 #endif
-#define P96TRACEX(x) do { write_log x; } while(0)
 
 #define GetBytesPerPixel(x) GetBytesPerPixel2(x,__FILE__,__LINE__)
 
 #if defined(JIT)
+#define P96_SM_RW special_mem |= PIC_READ | PIC_WRITE;
 #define P96_SM_R special_mem |= PIC_READ;
 #define P96_SM_W special_mem |= PIC_WRITE;
 #else
+#define P96_SM_RW
 #define P96_SM_R
 #define P96_SM_W
 #endif
@@ -151,38 +148,39 @@ static int set_gc_called = 0;
 //fastscreen
 static uaecptr oldscr = 0;
 #ifdef _DEBUG
-static void PICASSO96_Unlock2(char *filename, int linenum)
+void PICASSO96_Unlock2(char *filename, int linenum)
 #else
-static void PICASSO96_Unlock(void)
+void PICASSO96_Unlock(void)
 #endif
 {
 #ifdef LOCK_UNLOCK_MADNESS
 #if defined(P96TRACING_ENABLED) && P96TRACING_LEVEL > 1
     // This format of output lets you double-click and jump to file/line
-    write_log("%s(%d) : calling P96 UNLOCK with picasso_on=%d\n", filename, linenum, picasso_on);
+    write_log( "%s(%d) : calling P96 UNLOCK with picasso_on=%d\n", filename, linenum, picasso_on);
 #endif
-    if(picasso_on) {
+    if(picasso_on)
+    {
 #ifdef PIXEL_LOCK
        flushpixels();
 #endif 
        gfx_unlock_picasso ();
-       picasso96_state.HostAddress = NULL;
     }
 #endif
 }
 
 #ifdef _DEBUG
-static void PICASSO96_Lock2(char *filename, int linenum)
+void PICASSO96_Lock2(char *filename, int linenum)
 #else
-static void PICASSO96_Lock(void)
+void PICASSO96_Lock(void)
 #endif
 {
 #ifdef LOCK_UNLOCK_MADNESS
 #if defined(P96TRACING_ENABLED) && P96TRACING_LEVEL > 1
     // This format of output lets you double-click and jump to file/line
-    write_log( "%s(%d) : calling P96 LOCK with picasso_on=%d\n", filename, linenum, picasso_on );
+    write_log( "%s(%d) : calling P96 LOCK with picasso_on=%d\n", filename, linenum, picasso_on);
 #endif
-    if(picasso_on) {
+    if(picasso_on)
+    {
        picasso96_state.HostAddress = gfx_lock_picasso ();
     }
 #endif
@@ -306,7 +304,6 @@ static void DumpLine( struct Line *line )
        write_log("Line->Xorigin = %d\n", line->Xorigin);
        write_log("Line->Yorigin = %d\n", line->Yorigin);
     }
-}
 #endif
 
 static void ShowSupportedResolutions (void)
@@ -348,10 +345,13 @@ static uae_u8 GetBytesPerPixel2(uae_u32 RGBfmt, char *file, int line)
        return 2;
     default:
        write_log ("ERROR - GetBytesPerPixel() from %s@%d was unsuccessful with 0x%x?!\n", file, line, RGBfmt);
-       if(!bFailure) {
+       if(!bFailure)
+       {
            bFailure = TRUE;
            return GetBytesPerPixel(picasso_vidinfo.rgbformat);
-       } else {
+       }
+       else
+       {
            abort();
        }
     }
@@ -415,7 +415,7 @@ static int CopyBitMapStructureA2U (uaecptr amigamemptr, struct BitMap *bm)
        bm->Depth = 8;
     
     for (i = 0; i < bm->Depth; i++) {
-       uaecptr plane = get_long (amigamemptr + PSSO_BitMap_Planes + i * 4);
+       uaecptr plane = get_long (amigamemptr + PSSO_BitMap_Planes + i*4);
        switch (plane) {
        case 0:
            bm->Planes[i] = &all_zeros_bitmap;
@@ -519,26 +519,29 @@ static void AmigaListAddTail (uaecptr l, uaecptr n)
 * filled rectangle in the frame buffer; it can be used as a memcpy source if
 * there is no OS specific function to fill the rectangle.
 */
-static void do_fillrect(uae_u8 *src, unsigned int x, unsigned int y, unsigned int width, unsigned int height, uae_u32 pen, int Bpp, RGBFTYPE rgbtype)
+static void do_fillrect(uae_u8 *src, unsigned int x, unsigned int y,
+                   unsigned int width, unsigned int height,
+                   uae_u32 pen, int Bpp, RGBFTYPE rgbtype)
 {
     uae_u8 *dst;
-    int orig_width = width;
-    int orig_height = height;
-
+   
     /* Try OS specific fillrect function here; and return if successful.  Make sure we adjust for
-     * the pen values if we're doing 8-bit display-emulation on a 16-bit or higher screen. */
+    * the pen values if we're doing 8-bit display-emulation on a 16-bit or higher screen. */
 #ifdef PIXEL_LOCK
-    flushpixels(); 
+     flushpixels(); 
 #endif
 
-    if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
+    if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat)
+    {
        if(DX_Fill(x, y, width, height, pen, rgbtype))
            return;
-    } else {   
+    }
+    else
+    {   
        if(DX_Fill(x, y, width, height, picasso_vidinfo.clut[src[0]], rgbtype))
           return;
     }
-
+   
     P96TRACE(("P96_WARNING: do_fillrect() using fall-back routine!\n"));
     
     if(y + height > picasso_vidinfo.height)
@@ -546,9 +549,10 @@ static void do_fillrect(uae_u8 *src, unsigned int x, unsigned int y, unsigned in
     if(x + width > picasso_vidinfo.width)
        width = picasso_vidinfo.width - x;
 
+    DX_Invalidate (x, y, width, height);
     if (! picasso_vidinfo.extra_mem)
        return;
-    
+
 #ifdef LOCK_UNLOCK_MADNESS
     PICASSO96_Lock();
     dst = picasso96_state.HostAddress;
@@ -613,9 +617,8 @@ out:;
 #ifndef        LOCK_UNLOCK_MADNESS
     gfx_unlock_picasso ();
 #else
-    PICASSO96_Unlock();
+     PICASSO96_Unlock();
 #endif
-    DX_Invalidate (x, y, orig_width, orig_height);
 }
 
 /*
@@ -626,13 +629,11 @@ out:;
 * the RenderInfo data and our coordinates.
 */
 static void do_blit(struct RenderInfo *ri, int Bpp, 
-                   unsigned int srcx, unsigned int srcy,
-                   unsigned int dstx, unsigned int dsty,
-                   unsigned int width, unsigned int height,
-                   BLIT_OPCODE opcode, int can_do_blit)
+           unsigned int srcx, unsigned int srcy, unsigned int dstx, unsigned int dsty,
+           unsigned int width, unsigned int height, BLIT_OPCODE opcode, int can_do_blit)
 {
     uae_u8 *dstp, *srcp;
-    int orig_width, orig_height;
+    int orig_height = height;
 
     if(picasso96_state.BigAssBitmap && can_do_blit) {
        srcx = dstx;
@@ -642,14 +643,14 @@ static void do_blit(struct RenderInfo *ri, int Bpp,
     if (picasso96_state.XOffset < 0)
        can_do_blit = 0;
     
-    dstx = dstx - picasso96_state.XOffset;
-    dsty = dsty - picasso96_state.YOffset;
+    dstx=dstx - picasso96_state.XOffset;
+    dsty=dsty - picasso96_state.YOffset;
     if((int)dstx <= 0) {
        srcx = srcx - dstx;
        dstx = 0;
     }
     if((int)dsty <= 0) {
-       srcy = srcy - dsty;
+       srcy = srcy-dsty;
        dsty = 0;
     }
 
@@ -670,30 +671,24 @@ static void do_blit(struct RenderInfo *ri, int Bpp,
     if(dstx + width >= picasso_vidinfo.width)
        width = picasso_vidinfo.width - dstx;
 
-    orig_height = height;
-    orig_width = width;
-
-    if (can_do_blit)  {
+    if (can_do_blit) 
+    {
        //
        // Call OS blitting function that can do it in video memory.
        // Should return if it was successful
        //
        if(DX_Blit(srcx, srcy, dstx, dsty, width, height, opcode))
            return;
-       srcx = dstx;
-       srcy = dsty;
-    }
-    if (opcode != BLIT_SRC) {
-       write_log("do_blit() opcode = %d!\n", opcode);
-       return;
+       srcx = dstx;   
+        srcy = dsty; 
     }
-
 #ifdef LOCK_UNLOCK_MADNESS
     PICASSO96_Lock();
 #endif
 
     srcp = ri->Memory + srcx * Bpp + srcy * ri->BytesPerRow;
 
+    DX_Invalidate (dstx, dsty, width, height);
     if (! picasso_vidinfo.extra_mem)
     {
     #ifdef LOCK_UNLOCK_MADNESS
@@ -708,7 +703,8 @@ static void do_blit(struct RenderInfo *ri, int Bpp,
 #else
     dstp = gfx_lock_picasso ();
 #endif
-    if (dstp == 0) {
+    if (dstp == 0)
+    {
        write_log ("WARNING: do_blit() couldn't lock\n");
        goto out;
     }
@@ -716,9 +712,9 @@ static void do_blit(struct RenderInfo *ri, int Bpp,
     /* The areas can't overlap: the source is always in the Picasso frame buffer,
     * and the destination is a different buffer owned by the graphics code.  */
     dstp += dsty * picasso_vidinfo.rowbytes + dstx * picasso_vidinfo.pixbytes;
-    P96TRACE(("do_blit with srcp %p, dstp %p, dst_rowbytes %d, srcx %d, srcy %d, dstx %d, dsty %d, w %d, h %d, dst_pixbytes %d\n",
+    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",
        srcp, dstp, picasso_vidinfo.rowbytes, srcx, srcy, dstx, dsty, width, height, picasso_vidinfo.pixbytes));
-    P96TRACE(("gfxmem is at %p\n", gfxmemory));
+    P96TRACE(("gfxmem is at 0x%x\n",gfxmemory));
        
     if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) 
     {
@@ -763,13 +759,13 @@ static void do_blit(struct RenderInfo *ri, int Bpp,
            dstp += picasso_vidinfo.rowbytes;
        }
     }
-    out:;
+    out:
 #ifndef LOCK_UNLOCK_MADNESS
     gfx_unlock_picasso ();
 #else
     PICASSO96_Unlock();
 #endif
-    DX_Invalidate (dstx, dsty, orig_width, orig_height);
+    ;
 }
 
 /*
@@ -777,7 +773,7 @@ static void do_blit(struct RenderInfo *ri, int Bpp,
 * so that do_blit can be used if
 * there is no OS specific function to invert the rectangle.
 */
-static void do_invertrect(struct RenderInfo *ri, int Bpp, int x, int y, int width, int height)
+static void do_invertrect( struct RenderInfo *ri, int Bpp, int x, int y, int width, int height)
 {
    /* if(DX_InvertRect(x, y, width, height))
        return;*/  //deactivate in 0.8.20 
@@ -785,7 +781,6 @@ static void do_invertrect(struct RenderInfo *ri, int Bpp, int x, int y, int widt
     do_blit (ri, Bpp, x, y, x, y, width, height, BLIT_SRC, 0);
 }
 
-#if 0
 static uaecptr wgfx_linestart;
 static uaecptr wgfx_lineend;
 static uaecptr wgfx_min, wgfx_max;
@@ -796,22 +791,22 @@ static void wgfx_do_flushline (void)
     uae_u8 *src, *dstp;
 
     /* Mark these lines as "dirty" */
+    DX_Invalidate (0, wgfx_y, picasso_vidinfo.width, 1);
 
     if (! picasso_vidinfo.extra_mem) /* The "out" will flush the dirty lines directly */
        goto out;
     
 #ifdef LOCK_UNLOCK_MADNESS
     dstp = picasso96_state.HostAddress;
+
 #else
     dstp = gfx_lock_picasso ();
 #endif
      if (dstp == 0)
        goto out;
-
 #if P96TRACING_LEVEL > 0
     P96TRACE(("flushing %d\n", wgfx_y));
 #endif
-
     src = gfxmemory + wgfx_min;
     
     if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat)
@@ -820,7 +815,7 @@ static void wgfx_do_flushline (void)
        P96TRACE(("flushing type-a\n"));
 #endif
        dstp += wgfx_y * picasso_vidinfo.rowbytes + wgfx_min - wgfx_linestart;
-       memcpy (dstp, src, wgfx_max - wgfx_min);
+               memcpy (dstp, src, wgfx_max - wgfx_min);
     }
     else
     {
@@ -855,7 +850,6 @@ out:
 #ifndef LOCK_UNLOCK_MADNESS
     gfx_unlock_picasso ();
 #endif
-    DX_Invalidate (0, wgfx_y, -1, 1);
 
     wgfx_linestart = 0xFFFFFFFF;
 }
@@ -866,7 +860,6 @@ STATIC_INLINE void wgfx_flushline (void)
        return;
     wgfx_do_flushline ();
 }
-#endif
 
 static int renderinfo_is_current_screen (struct RenderInfo *ri)
 {
@@ -881,7 +874,9 @@ static int renderinfo_is_current_screen (struct RenderInfo *ri)
 /*
 * Fill a rectangle in the screen.
 */
-static void do_fillrect_frame_buffer(struct RenderInfo *ri, int X, int Y, int Width, int Height, uae_u32 Pen, int Bpp, RGBFTYPE RGBFormat)
+STATIC_INLINE void do_fillrect_frame_buffer(struct RenderInfo *ri, int X, int Y,
+                                           int Width, int Height, uae_u32 Pen, int Bpp,
+                                           RGBFTYPE RGBFormat)
 {
     int cols;
     uae_u8 *start, *oldstart;
@@ -938,17 +933,17 @@ static void do_fillrect_frame_buffer(struct RenderInfo *ri, int X, int Y, int Wi
 
 void picasso_handle_vsync (void)
 {
-    flushpixels();
+    DX_Invalidate(-1, -1, -1, -1); //so a flushpixel is done every vsync if pixel are in buffer
     PICASSO96_Unlock();
     if (palette_changed) {
        DX_SetPalette (0,256);
        palette_changed = 0;
     }
 
-    if (vsyncgfxwrite == 1) {
+    if (vsyncgfxwrite==1) {
        static long blitcount;
        vsyncgfxcount++;
-       if (vsyncgfxcount > 1) {
+       if (vsyncgfxcount>1) {
            if (picasso_on) {
                if (picasso96_state.RGBFormat == picasso_vidinfo.rgbformat
                    || picasso96_state.RGBFormat == RGBFB_CHUNKY) { 
@@ -980,13 +975,12 @@ void picasso_refresh (int call_setpalette)
     struct RenderInfo ri;
     static int beamcon0_before, p96refresh_was;
     
-    if (! picasso_on)
-       return;
+    if (! picasso_on)return;
     {  //for higher P96 mousedraw rate
        /* HACK */
        extern uae_u16 vtotal;
        if (p96hack_vpos2) {
-           vtotal = p96hack_vpos2;
+           vtotal=p96hack_vpos2;
            beamcon0_before = new_beamcon0;
            new_beamcon0 |= 0x80;
            p96refresh_active = 1;
@@ -1001,9 +995,9 @@ void picasso_refresh (int call_setpalette)
                /* HACK until ntsc timing is fixed.. */
     } //end for higher P96 mousedraw rate
     have_done_picasso = 1;
-
+    
     /* Make sure that the first time we show a Picasso video mode, we don't blit any crap.
-     * We can do this by checking if we have an Address yet.  */
+    * We can do this by checking if we have an Address yet.  */
     if (picasso96_state.Address) {
        unsigned int width, height;
 
@@ -1043,11 +1037,10 @@ void picasso_refresh (int call_setpalette)
 /*
 * Functions to perform an action on the frame-buffer
 */
-static void do_blitrect_frame_buffer(struct RenderInfo *ri, struct RenderInfo *dstri,
-                                   unsigned long srcx, unsigned long srcy,
-                                   unsigned long dstx, unsigned long dsty,
-                                   unsigned long width, unsigned long height,
-                                   uae_u8 mask, BLIT_OPCODE opcode)
+STATIC_INLINE void do_blitrect_frame_buffer(struct RenderInfo *ri, struct
+RenderInfo *dstri, unsigned long srcx, unsigned long srcy,
+    unsigned long dstx, unsigned long dsty, unsigned long width, unsigned
+long height, uae_u8 mask, BLIT_OPCODE opcode)
 {
     
     uae_u8 *src, *dst, *tmp, *tmp2, *tmp3;
@@ -1069,7 +1062,7 @@ static void do_blitrect_frame_buffer(struct RenderInfo *ri, struct RenderInfo *d
        if(opcode == BLIT_SRC)
        {
            /* handle normal case efficiently */
-           if (ri->Memory == dstri->Memory && dsty == srcy)
+           if (ri->Memory == dstri->Memory && dsty == srcy) 
            {
                unsigned long i;
                for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
@@ -1080,158 +1073,304 @@ static void do_blitrect_frame_buffer(struct RenderInfo *ri, struct RenderInfo *d
                unsigned long i;
                for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
                    memcpy (dst, src, total_width);
-           }
+               }
            else
            {
                unsigned long i;
-               src += (height - 1) * ri->BytesPerRow;
-               dst += (height - 1) * dstri->BytesPerRow;
+               src += (height-1) * ri->BytesPerRow;
+               dst += (height-1) * dstri->BytesPerRow;
                for (i = 0; i < height; i++, src -= ri->BytesPerRow, dst -= dstri->BytesPerRow)
                    memcpy (dst, src, total_width);
            }
            return;
        }
-       else
-       {
-           uae_u8 *src2;
-           uae_u8 *dst2;
-           unsigned int y;
-
+    else
+    {
+       uae_u8 *src2 = src;
+       uae_u8 *dst2 = dst;
+       uae_u32 *src2_32 = (uae_u32*)src;
+       uae_u32 *dst2_32 = (uae_u32*)dst;
+       unsigned int y;
+       
            for(y = 0; y < height; y++) /* Vertical lines */
            {
-               uae_u8 *bound = src + total_width - 4;
-               uae_u32 *src2_32;
-               uae_u32 *dst2_32;
-               //copy now the longs
-               for(src2_32 = (uae_u32*)src, dst2_32 = (uae_u32*)dst; src2_32 < (uae_u32*)bound; src2_32++, dst2_32++) /* Horizontal bytes */
+           uae_u8 *bound = src + total_width - 4;
+           //copy now the longs
+           for(src2_32 = (uae_u32*)src, dst2_32 = (uae_u32*)dst; src2_32 < (uae_u32*)bound; src2_32++, dst2_32++) /* Horizontal bytes */
+           {
+               switch(opcode)
                {
-                   switch(opcode)
+               case BLIT_FALSE:
+               *dst2_32 = 0;
+               break;
+               case BLIT_NOR:
+               *dst2_32 = ~(*src2_32 | *dst2_32);
+               break;
+               case BLIT_ONLYDST:
+               *dst2_32 = *dst2_32 & ~(*src2_32);
+               break;
+               case BLIT_NOTSRC:
+               *dst2_32 = ~(*src2_32);
+               break;
+               case BLIT_ONLYSRC:
+               *dst2_32 = *src2_32 & ~(*dst2_32);
+               break;
+               case BLIT_NOTDST:
+               *dst2_32 = ~(*dst2_32);
+               break;
+               case BLIT_EOR:
+               *dst2_32 = *src2_32 ^ *dst2_32;
+               break;
+               case BLIT_NAND:
+               *dst2_32 = ~(*src2_32 & *dst2_32);
+               break;
+               case BLIT_AND:
+               *dst2_32 = *src2_32 & *dst2_32;
+               break;
+               case BLIT_NEOR:
+               *dst2_32 = ~(*src2_32 ^ *dst2_32);
+               break;
+               case BLIT_DST:
+               write_log( "do_blitrect_frame_buffer shouldn't get BLIT_DST!\n");
+               break;
+               case BLIT_NOTONLYSRC:
+               *dst2_32 = ~(*src2_32) | *dst2_32;
+               break;
+               case BLIT_SRC:
+               write_log( "do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n");
+               break;
+               case BLIT_NOTONLYDST:
+               *dst2_32 = ~(*dst2_32) | *src2_32;
+               break;
+               case BLIT_OR:
+               *dst2_32 = *src2_32 | *dst2_32;
+               break;
+               case BLIT_TRUE:
+               *dst2_32 = 0xFFFFFFFF;
+               break;
+               case 30: //code for swap source with dest in byte
+               {           
+                   uae_u32 temp;
+                   temp = *src2_32;
+                   *src2_32 = *dst2_32;
+                   *dst2_32 = temp;
+               }
+               break;
+               case BLIT_LAST:
+               write_log( "do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n");
+               break;
+               } /* switch opcode */
+           }// for end
+           //now copy the rest few bytes
+           for(src2 = (uae_u8*)src2_32, dst2 = (uae_u8*)dst2_32; src2 < src + total_width; src2++, dst2++) /* Horizontal bytes */
+           {
+               switch( opcode )
+               {
+               case BLIT_FALSE:
+               *dst2 = 0;
+               break;
+               case BLIT_NOR:
+               *dst2 = ~(*src2 | *dst2);
+               break;
+               case BLIT_ONLYDST:
+               *dst2 = *dst2 & ~(*src2);
+               break;
+               case BLIT_NOTSRC:
+               *dst2 = ~(*src2);
+               break;
+               case BLIT_ONLYSRC:
+               *dst2 = *src2 & ~(*dst2);
+               break;
+               case BLIT_NOTDST:
+               *dst2 = ~(*dst2);
+               break;
+               case BLIT_EOR:
+               *dst2 = *src2 ^ *dst2;
+               break;
+               case BLIT_NAND:
+               *dst2 = ~(*src2 & *dst2);
+               break;
+               case BLIT_AND:
+               *dst2 = *src2 & *dst2;
+               break;
+               case BLIT_NEOR:
+               *dst2 = ~(*src2 ^ *dst2);
+               break;
+               case BLIT_DST:
+               write_log( "do_blitrect_frame_buffer shouldn't get BLIT_DST!\n");
+               break;
+               case BLIT_NOTONLYSRC:
+               *dst2 = ~(*src2) | *dst2;
+               break;
+               case BLIT_SRC:
+               write_log( "do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n");
+               break;
+               case BLIT_NOTONLYDST:
+               *dst2 = ~(*dst2) | *src2;
+               break;
+               case BLIT_OR:
+               *dst2 = *src2 | *dst2;
+               break;
+               case BLIT_TRUE:
+               *dst2 = 0xFF;
+               break;
+               case BLIT_LAST:
+               write_log( "do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n");
+               break;
+               case 30: //code for swap source with dest in long
                    {
-                   case BLIT_FALSE:
-                   *dst2_32 = 0;
-                   break;
-                   case BLIT_NOR:
-                   *dst2_32 = ~(*src2_32 | *dst2_32);
-                   break;
-                   case BLIT_ONLYDST:
-                   *dst2_32 = *dst2_32 & ~(*src2_32);
-                   break;
-                   case BLIT_NOTSRC:
-                   *dst2_32 = ~(*src2_32);
-                   break;
-                   case BLIT_ONLYSRC:
-                   *dst2_32 = *src2_32 & ~(*dst2_32);
-                   break;
-                   case BLIT_NOTDST:
-                   *dst2_32 = ~(*dst2_32);
-                   break;
-                   case BLIT_EOR:
-                   *dst2_32 = *src2_32 ^ *dst2_32;
-                   break;
-                   case BLIT_NAND:
-                   *dst2_32 = ~(*src2_32 & *dst2_32);
-                   break;
-                   case BLIT_AND:
-                   *dst2_32 = *src2_32 & *dst2_32;
-                   break;
-                   case BLIT_NEOR:
-                   *dst2_32 = ~(*src2_32 ^ *dst2_32);
-                   break;
-                   case BLIT_DST:
-                   write_log( "do_blitrect_frame_buffer shouldn't get BLIT_DST!\n");
-                   break;
-                   case BLIT_NOTONLYSRC:
-                   *dst2_32 = ~(*src2_32) | *dst2_32;
-                   break;
-                   case BLIT_SRC:
-                   write_log( "do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n");
-                   break;
-                   case BLIT_NOTONLYDST:
-                   *dst2_32 = ~(*dst2_32) | *src2_32;
-                   break;
-                   case BLIT_OR:
-                   *dst2_32 = *src2_32 | *dst2_32;
-                   break;
-                   case BLIT_TRUE:
-                   *dst2_32 = 0xFFFFFFFF;
-                   break;
-                   case 30: //code for swap source with dest in byte
-                   {       
-                       uae_u32 temp;
-                       temp = *src2_32;
-                       *src2_32 = *dst2_32;
-                       *dst2_32 = temp;
+                   uae_u8 temp;
+                   temp = *src2;
+                   *src2 = *dst2;
+                   *dst2 = temp;
                    }
-                   break;
-                   case BLIT_LAST:
-                   write_log( "do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n");
-                   break;
-                   } /* switch opcode */
-               }// for end
-               //now copy the rest few bytes
-               for(src2 = (uae_u8*)src2_32, dst2 = (uae_u8*)dst2_32; src2 < src + total_width; src2++, dst2++) /* Horizontal bytes */
+               break;
+               } /* switch opcode */
+           } /* for width */
+           src += ri->BytesPerRow;
+           dst += dstri->BytesPerRow;
+           } /* for height */
+       }
+       return;
+    }
+
+    tmp3 = tmp2 = tmp = xmalloc (linewidth * height); /* allocate enough
+memory for the src-rect        */
+    if (!tmp)
+       return;
+
+    /* copy the src-rect into our temporary buffer space */
+    for (lines = 0; lines < height; lines++, src += ri->BytesPerRow, tmp2 += linewidth) 
+    {
+       memcpy (tmp2, src, total_width);
+    }
+
+    /* copy the temporary buffer to the destination */
+    for (lines = 0; lines < height; lines++, dst += dstri->BytesPerRow, tmp += linewidth) 
+    {
+       unsigned long cols;
+       for (cols = 0; cols < width; cols++) 
+       {
+           dst[cols] &= ~mask;
+           dst[cols] |= tmp[cols] & mask;
+       }
+    }
+    /* free the temp-buf */
+    free (tmp3);
+} 
+
+#if 0
+/*
+* Functions to perform an action on the frame-buffer
+*/
+STATIC_INLINE void do_blitrect_frame_buffer( struct RenderInfo *ri, struct RenderInfo *dstri, unsigned long srcx, unsigned long srcy,
+    unsigned long dstx, unsigned long dsty, unsigned long width, unsigned long height, uae_u8 mask, BLIT_OPCODE opcode )
+{
+    
+    uae_u8 *src, *dst, *tmp, *tmp2, *tmp3;
+    uae_u8 Bpp = GetBytesPerPixel(ri->RGBFormat);
+    unsigned long total_width = width * Bpp;
+    unsigned long linewidth = (total_width + 15) & ~15;
+    unsigned long lines;
+    int can_do_visible_blit = 0;
+
+    src = ri->Memory + srcx*Bpp + srcy*ri->BytesPerRow;
+    dst = dstri->Memory + dstx*Bpp + dsty*dstri->BytesPerRow;
+    if (mask != 0xFF && Bpp > 1)
+    {
+       write_log ("WARNING - BlitRect() has mask 0x%x with Bpp %d.\n", mask, Bpp);
+    }
+    
+    if (mask == 0xFF || Bpp > 1) 
+    {
+       if( opcode == BLIT_SRC )
+       {
+           /* handle normal case efficiently */
+           if (ri->Memory == dstri->Memory && dsty == srcy) 
+           {
+               unsigned long i;
+               for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
+                   memmove (dst, src, total_width);
+           }
+           else if (dsty < srcy) 
+           {
+               unsigned long i;
+               for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
+                   memcpy (dst, src, total_width);
+           }
+           else
+           {
+               unsigned long i;
+               src += (height-1) * ri->BytesPerRow;
+               dst += (height-1) * dstri->BytesPerRow;
+               for (i = 0; i < height; i++, src -= ri->BytesPerRow, dst -= dstri->BytesPerRow)
+                   memcpy (dst, src, total_width);
+           }
+           return;
+       }
+       else
+       {
+           uae_u8 *src2 = src;
+           uae_u8 *dst2 = dst;
+           unsigned int y;
+           
+           for( y = 0; y < height; y++ ) /* Vertical lines */
+           {
+               for( src2 = src, dst2 = dst; src2 < src + total_width; src2++, dst2++ ) /* Horizontal bytes */
                {
-                   switch(opcode)
+                   switch( opcode )
                    {
                    case BLIT_FALSE:
-                   *dst2 = 0;
-                   break;
+                       *dst2 = 0;
+                       break;
                    case BLIT_NOR:
-                   *dst2 = ~(*src2 | *dst2);
-                   break;
+                       *dst2 = ~(*src2 | *dst2);
+                       break;
                    case BLIT_ONLYDST:
-                   *dst2 = *dst2 & ~(*src2);
-                   break;
+                       *dst2 = *dst2 & ~(*src2);
+                       break;
                    case BLIT_NOTSRC:
-                   *dst2 = ~(*src2);
-                   break;
+                       *dst2 = ~(*src2);
+                       break;
                    case BLIT_ONLYSRC:
-                   *dst2 = *src2 & ~(*dst2);
-                   break;
+                       *dst2 = *src2 & ~(*dst2);
+                       break;
                    case BLIT_NOTDST:
-                   *dst2 = ~(*dst2);
-                   break;
+                       *dst2 = ~(*dst2);
+                       break;
                    case BLIT_EOR:
-                   *dst2 = *src2 ^ *dst2;
-                   break;
+                       *dst2 = *src2 ^ *dst2;
+                       break;
                    case BLIT_NAND:
-                   *dst2 = ~(*src2 & *dst2);
-                   break;
+                       *dst2 = ~(*src2 & *dst2);
+                       break;
                    case BLIT_AND:
-                   *dst2 = *src2 & *dst2;
-                   break;
+                       *dst2 = *src2 & *dst2;
+                       break;
                    case BLIT_NEOR:
-                   *dst2 = ~(*src2 ^ *dst2);
-                   break;
+                       *dst2 = ~(*src2 ^ *dst2);
+                       break;
                    case BLIT_DST:
-                   write_log("do_blitrect_frame_buffer shouldn't get BLIT_DST!\n");
-                   break;
+                       write_log( "do_blitrect_frame_buffer shouldn't get BLIT_DST!\n" );
+                       break;
                    case BLIT_NOTONLYSRC:
-                   *dst2 = ~(*src2) | *dst2;
-                   break;
+                       *dst2 = ~(*src2) | *dst2;
+                       break;
                    case BLIT_SRC:
-                   write_log("do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n");
-                   break;
+                       write_log( "do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n" );
+                       break;
                    case BLIT_NOTONLYDST:
-                   *dst2 = ~(*dst2) | *src2;
-                   break;
+                       *dst2 = ~(*dst2) | *src2;
+                       break;
                    case BLIT_OR:
-                   *dst2 = *src2 | *dst2;
-                   break;
+                       *dst2 = *src2 | *dst2;
+                       break;
                    case BLIT_TRUE:
-                   *dst2 = 0xFF;
-                   break;
+                       *dst2 = 0xFF;
+                       break;
                    case BLIT_LAST:
-                   write_log("do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n");
-                   break;
-                   case 30: //code for swap source with dest in long
-                   {
-                       uae_u8 temp;
-                       temp = *src2;
-                       *src2 = *dst2;
-                       *dst2 = temp;
-                   }
-                   break;
+                       write_log( "do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n" );
+                       break;
                    } /* switch opcode */
                } /* for width */
                src += ri->BytesPerRow;
@@ -1239,11 +1378,11 @@ static void do_blitrect_frame_buffer(struct RenderInfo *ri, struct RenderInfo *d
            } /* for height */
        }
        return;
-    }
+       }
 
     tmp3 = tmp2 = tmp = xmalloc (linewidth * height); /* allocate enough memory for the src-rect */
     if (!tmp)
-        return;
+       return;
 
     /* copy the src-rect into our temporary buffer space */
     for (lines = 0; lines < height; lines++, src += ri->BytesPerRow, tmp2 += linewidth) 
@@ -1252,7 +1391,7 @@ static void do_blitrect_frame_buffer(struct RenderInfo *ri, struct RenderInfo *d
     }
 
     /* copy the temporary buffer to the destination */
-    for (lines = 0; lines < height; lines++, dst += dstri->BytesPerRow, tmp+= linewidth) 
+    for (lines = 0; lines < height; lines++, dst += dstri->BytesPerRow, tmp += linewidth) 
     {
        unsigned long cols;
        for (cols = 0; cols < width; cols++) 
@@ -1262,8 +1401,9 @@ static void do_blitrect_frame_buffer(struct RenderInfo *ri, struct RenderInfo *d
        }
     }
     /* free the temp-buf */
-    xfree (tmp3);
-} 
+    free (tmp3);
+}
+#endif
 
 /*
 DrawLine: 
@@ -1329,25 +1469,25 @@ to account for possible screen panning.
 uae_u32 picasso_SetSpritePosition (void)
 {
     uae_u32 result = 0;
-    uaecptr bi = m68k_areg(regs, 0);
-    uae_u16 MouseX  = get_word(bi + PSSO_BoardInfo_MouseX) - picasso96_state.XOffset;
-    uae_u16 MouseY  = get_word(bi + PSSO_BoardInfo_MouseY) - picasso96_state.YOffset;
+    uaecptr bi = m68k_areg( regs, 0 );
+    uae_u16 MouseX  = get_word( bi + PSSO_BoardInfo_MouseX ) - picasso96_state.XOffset;
+    uae_u16 MouseY  = get_word( bi + PSSO_BoardInfo_MouseY ) - picasso96_state.YOffset;
     
     // Keep these around, because we don't want flickering
     static uae_u16 OldMouseX = -1;
     static uae_u16 OldMouseY = -1;
 
     // Bounds check MouseX and MouseY here, because sometimes they seem to go negative...
-    if((uae_s16)MouseX < 0)
+    if( (uae_s16)MouseX < 0 )
        MouseX = 0;
-    if((uae_s16)MouseY < 0)
+    if( (uae_s16)MouseY < 0 )
        MouseY = 0;
 
-    if((MouseX != OldMouseX) || (MouseY != OldMouseY))
+    if( ( MouseX != OldMouseX ) || ( MouseY != OldMouseY ) )
     {
-       result = DX_MoveCursor(MouseX, MouseY);
+       result = DX_MoveCursor( MouseX, MouseY );
        write_log ("SetSpritePosition() - moving cursor to (%d,%d), result = %d\n", MouseX, MouseY, result);
-       if(result)
+       if( result )
        {
            OldMouseX = MouseX;
            OldMouseY = MouseY;
@@ -1692,7 +1832,7 @@ uae_u32 REGPARAM2 picasso_SetSwitch (struct regstruct *regs)
     * desired state, and wait for custom.c to call picasso_enablescreen
     * whenever it is ready to change the screen state.  */
     picasso_requested_on = flag;
-    write_log ("SetSwitch() - trying to show %s screen\n", flag ? "picasso96" : "amiga");
+    write_log ("SetSwitch() - trying to show %s screen\n", flag ? "picasso96":"amiga");
     
     /* Put old switch-state in D0 */
 
@@ -1701,9 +1841,7 @@ uae_u32 REGPARAM2 picasso_SetSwitch (struct regstruct *regs)
 
 void picasso_enablescreen (int on)
 {  
-#if 0
     wgfx_linestart = 0xFFFFFFFF;
-#endif
     picasso_refresh (1);
     write_log ("SetSwitch() from threadid %d - showing %s screen\n", GetCurrentThreadId(), on ? "picasso96": "amiga");
     checkrtglibrary();
@@ -1767,19 +1905,21 @@ uae_u32 REGPARAM2 picasso_SetDAC (struct regstruct *regs)
 }
 
 
-static void init_picasso_screen(void)
+static void init_picasso_screen( void )
 {
-    if(set_panning_called) {
-       picasso96_state.Extent = picasso96_state.Address + (picasso96_state.BytesPerRow * picasso96_state.VirtualHeight);
+    if(set_panning_called)
+    {
+       picasso96_state.Extent = picasso96_state.Address + picasso96_state.BytesPerRow * picasso96_state.VirtualHeight;
     }
-    if (set_gc_called) {
+    if (set_gc_called)
+    {  
        gfx_set_picasso_modeinfo (picasso96_state.Width, picasso96_state.Height,
            picasso96_state.GC_Depth, picasso96_state.RGBFormat);
     }
     if((picasso_vidinfo.width == picasso96_state.Width) &&
        (picasso_vidinfo.height == picasso96_state.Height) &&
        (picasso_vidinfo.depth == (picasso96_state.GC_Depth >> 3)) &&
-       (picasso_vidinfo.selected_rgbformat == picasso96_state.RGBFormat)) 
+       (picasso_vidinfo.selected_rgbformat == picasso96_state.RGBFormat))
     {
        DX_SetPalette (0, 256);
        picasso_refresh (1); 
@@ -1848,7 +1988,7 @@ uae_u32 REGPARAM2 picasso_SetPanning (struct regstruct *regs)
     uae_u16 Width = m68k_dreg (regs, 0);
     uaecptr start_of_screen = m68k_areg (regs, 1);
     uaecptr bi = m68k_areg(regs, 0);
-    uaecptr bmeptr = get_long(bi + PSSO_BoardInfo_BitMapExtra);  /* Get our BoardInfo ptr's BitMapExtra ptr */
+    uaecptr bmeptr = get_long( bi + PSSO_BoardInfo_BitMapExtra );  /* Get our BoardInfo ptr's BitMapExtra ptr */
     uae_u16 bme_width, bme_height;
 
     if(oldscr == 0) {
@@ -1859,15 +1999,17 @@ uae_u32 REGPARAM2 picasso_SetPanning (struct regstruct *regs)
        oldscr = start_of_screen;
     }
 
-    bme_width = get_word(bmeptr + PSSO_BitMapExtra_Width);
-    bme_height = get_word(bmeptr + PSSO_BitMapExtra_Height);
+    bme_width = get_word( bmeptr + PSSO_BitMapExtra_Width );
+    bme_height = get_word( bmeptr + PSSO_BitMapExtra_Height );
     
     picasso96_state.Address = start_of_screen; /* Amiga-side address */
     picasso96_state.XOffset = (uae_s16)(m68k_dreg (regs, 1) & 0xFFFF);
     picasso96_state.YOffset = (uae_s16)(m68k_dreg (regs, 2) & 0xFFFF);
+    picasso96_state.XYOffset = picasso96_state.Address + (picasso96_state.XOffset * picasso96_state.BytesPerPixel)
+       + (picasso96_state.YOffset * picasso96_state.BytesPerRow);
     picasso96_state.VirtualWidth = bme_width;
     picasso96_state.VirtualHeight = bme_height;
-    if((bme_width > Width) || (bme_height > picasso96_state.Height)) // NOTE: These were != instead of > before...
+    if((bme_width > Width) || (bme_height > picasso96_state.Height))
        picasso96_state.BigAssBitmap = 1;
     else
        picasso96_state.BigAssBitmap = 0;
@@ -1947,9 +2089,7 @@ uae_u32 REGPARAM2 picasso_InvertRect (struct regstruct *regs)
     unsigned long width_in_bytes;
     uae_u32 result = 0;
 
-#ifdef PIXEL_LOCK
-    flushpixels();
-#endif
+  
 #ifndef LOCK_UNLOCK_MADNESS
     wgfx_flushline ();    
 #endif
@@ -1959,11 +2099,13 @@ uae_u32 REGPARAM2 picasso_InvertRect (struct regstruct *regs)
        P96TRACE(("InvertRect %dbpp 0x%lx\n", Bpp, (long)mask));
     
        if (mask != 0xFF && Bpp > 1) 
+       {
            mask = 0xFF;
+       }
 
        xorval = 0x01010101 * (mask & 0xFF);
        width_in_bytes = Bpp * Width;
-       rectstart = uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
+       rectstart = uae_mem = ri.Memory + Y*ri.BytesPerRow + X*Bpp;
     
        for (lines = 0; lines < Height; lines++, uae_mem += ri.BytesPerRow)
            do_xor8 (uae_mem, width_in_bytes, xorval);
@@ -2012,9 +2154,10 @@ uae_u32 REGPARAM2 picasso_FillRect (struct regstruct *regs)
     struct RenderInfo ri;
     uae_u32 result = 0;
 
-#ifdef PIXEL_LOCK
-    flushpixels();
-#endif
+    if (Width * Height <= 2500)
+       return 0;
+    P96_SM_RW;
+
 #ifndef LOCK_UNLOCK_MADNESS
     wgfx_flushline ();
 #endif
@@ -2029,7 +2172,7 @@ uae_u32 REGPARAM2 picasso_FillRect (struct regstruct *regs)
        P96TRACE(("FillRect(%d, %d, %d, %d) Pen 0x%x BPP %d BPR %d Mask 0x%x\n",
            X, Y, Width, Height, Pen, Bpp, ri.BytesPerRow, Mask));
     
-       if(Bpp > 1)
+       if( Bpp > 1 )
            Mask = 0xFF;
     
        if (Mask == 0xFF) 
@@ -2040,9 +2183,9 @@ uae_u32 REGPARAM2 picasso_FillRect (struct regstruct *regs)
                uaecptr addr;
                if(renderinfo_is_current_screen(&ri))
                {
-                   uae_u32 diff = gfxmem_start - (uae_u32)gfxmemory; /* xxx this is sooo wrong.. */
+                   uae_u32 diff = gfxmem_start - (uae_u32)gfxmemory;
                    addr = ri.Memory + X * Bpp + Y * ri.BytesPerRow + diff;
-                   if(Width == 1)
+                   if( Width == 1 )
                    {
                        for(i = 0; i < Height; i++)
                        {
@@ -2058,9 +2201,9 @@ uae_u32 REGPARAM2 picasso_FillRect (struct regstruct *regs)
                    {
                        for(i = 0; i < Width; i++)
                        {
-                           if(Bpp == 4)
+                           if( Bpp == 4 )
                                gfxmem_lput(addr + (i * Bpp), Pen);
-                           else if(Bpp == 2)
+                           else if( Bpp == 2 )
                                gfxmem_wput(addr + (i * Bpp), Pen);
                            else
                                gfxmem_bput(addr + (i * Bpp), Pen);
@@ -2069,6 +2212,7 @@ uae_u32 REGPARAM2 picasso_FillRect (struct regstruct *regs)
                    return 1;
                }
            }
+
            /* Do the fill-rect in the frame-buffer */
            do_fillrect_frame_buffer(&ri, X, Y, Width, Height, Pen, Bpp, RGBFormat);
            /* Now we do the on-screen display, if renderinfo points to it */
@@ -2077,18 +2221,10 @@ uae_u32 REGPARAM2 picasso_FillRect (struct regstruct *regs)
                src = ri.Memory + X * Bpp + Y * ri.BytesPerRow;
                X = X - picasso96_state.XOffset;
                Y = Y - picasso96_state.YOffset;            
-               if((int)X < 0) {
-                   Width = Width + X;
-                   X = 0;
-               }
-               if((int)Width < 1)
-                   return 1;
-               if((int)Y < 0) {
-                   Height = Height + Y;
-                   Y = 0;
-               }
-               if((int)Height < 1)
-                   return 1;
+               if((int)X < 0){ Width = Width + X; X = 0; }
+               if((int)Width < 1) return 1;
+               if((int)Y < 0) { Height = Height + Y; Y = 0; }
+               if((int)Height < 1) return 1;
                /* Argh - why does P96Speed do this to me, with FillRect only?! */
                if((X < picasso96_state.Width) &&
                    (Y < picasso96_state.Height))
@@ -2109,7 +2245,7 @@ uae_u32 REGPARAM2 picasso_FillRect (struct regstruct *regs)
            /* We get here only if Mask != 0xFF */
            if (Bpp != 1) 
            {
-               write_log("WARNING - FillRect() has unhandled mask 0x%x with Bpp %d. Using fall-back routine.\n", Mask, Bpp);
+               write_log( "WARNING - FillRect() has unhandled mask 0x%x with Bpp %d. Using fall-back routine.\n", Mask, Bpp );
            }
            else
            {
@@ -2179,7 +2315,7 @@ struct blitdata
     BLIT_OPCODE opcode;
 } blitrectdata;
 
-static int BlitRectHelper(void)
+STATIC_INLINE int BlitRectHelper( void )
 {
     struct RenderInfo *ri = blitrectdata.ri;
     struct RenderInfo *dstri = blitrectdata.dstri;
@@ -2193,11 +2329,13 @@ static int BlitRectHelper(void)
     BLIT_OPCODE opcode = blitrectdata.opcode;
     
     uae_u8 Bpp = GetBytesPerPixel(ri->RGBFormat);
+    unsigned long total_width = width * Bpp;
+    unsigned long linewidth = (total_width + 15) & ~15;
     int can_do_visible_blit = 0;
-
+    
     if(opcode == BLIT_DST)
     {
-       write_log("WARNING: BlitRect() being called with opcode of BLIT_DST\n");
+       write_log( "WARNING: BlitRect() being called with opcode of BLIT_DST\n" );
        return 1;
     }
     
@@ -2209,10 +2347,13 @@ static int BlitRectHelper(void)
     * If we have a destination RenderInfo, then we've been called from picasso_BlitRectNoMaskComplete()
     * and we need to put the results on the screen from the frame-buffer.
     */
+    //if (dstri->Memory == ri->Memory)
     if (dstri == NULL || dstri->Memory == ri->Memory)
     {
        if(mask != 0xFF && Bpp > 1) 
+       {
            mask = 0xFF;
+       }
        dstri = ri;
        can_do_visible_blit = 1;
     }
@@ -2238,21 +2379,24 @@ static int BlitRectHelper(void)
     {
        P96TRACE(("Did not do_blit 1 in BlitRect()\n"));
     }
-
+    
     return 1;
 }
 
-static int BlitRect (uaecptr ri, uaecptr dstri,
+STATIC_INLINE int BlitRect (uaecptr ri, uaecptr dstri,
                unsigned long srcx, unsigned long srcy, unsigned long dstx, unsigned long dsty,
                unsigned long width, unsigned long height, uae_u8 mask, BLIT_OPCODE opcode)
 {
     /* Set up the params */
     CopyRenderInfoStructureA2U(ri, &blitrectdata.ri_struct);
     blitrectdata.ri = &blitrectdata.ri_struct;
-    if(dstri) {
+    if(dstri)
+    {
        CopyRenderInfoStructureA2U(dstri, &blitrectdata.dstri_struct);
        blitrectdata.dstri = &blitrectdata.dstri_struct;
-    } else {
+    }
+    else
+    {
        blitrectdata.dstri = NULL;
     }
     blitrectdata.srcx = srcx;
@@ -2290,17 +2434,17 @@ uae_u32 REGPARAM2 picasso_BlitRect (struct regstruct *regs)
     unsigned long dsty = (uae_u16)m68k_dreg (regs, 3);
     unsigned long width = (uae_u16)m68k_dreg (regs, 4);
     unsigned long height = (uae_u16)m68k_dreg (regs, 5);
-    uae_u8 Mask = (uae_u8)m68k_dreg (regs, 6);
+    uae_u8  Mask = (uae_u8)m68k_dreg (regs, 6);
     uae_u32 result = 0;
 
-#ifdef PIXEL_LOCK
-    flushpixels();
-#endif
+    P96_SM_RW;
+   
 #ifndef LOCK_UNLOCK_MADNESS
     wgfx_flushline ();    
 #endif
+    
     P96TRACE(("BlitRect(%d, %d, %d, %d, %d, %d, 0x%x)\n", srcx, srcy, dstx, dsty, width, height, Mask));
-    result = BlitRect(renderinfo, 0, srcx, srcy, dstx, dsty, width, height, Mask, BLIT_SRC);
+    result = BlitRect(renderinfo, (uaecptr)NULL, srcx, srcy, dstx, dsty, width, height, Mask, BLIT_SRC);
 
     return result;
 }
@@ -2337,9 +2481,8 @@ uae_u32 REGPARAM2 picasso_BlitRectNoMaskComplete (struct regstruct *regs)
     uae_u32 RGBFmt = m68k_dreg (regs, 7);
     uae_u32 result = 0;
 
-#ifdef PIXEL_LOCK
-    flushpixels();
-#endif
+    P96_SM_RW;
+    
 #ifndef LOCK_UNLOCK_MADNESS
     wgfx_flushline ();   
 #endif
@@ -2367,8 +2510,8 @@ STATIC_INLINE void PixelWrite2(uae_u8 *mem, int bits, uae_u32 fgpen)
 
 STATIC_INLINE void PixelWrite3(uae_u8 *mem, int bits, uae_u32 fgpen)
 {
-    do_put_mem_byte (mem + bits * 3, fgpen & 0x000000FF);
-    *(uae_u16 *)(mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
+    do_put_mem_byte (mem + bits*3, fgpen & 0x000000FF);
+    *(uae_u16 *)(mem + bits*3+1) = (fgpen & 0x00FFFF00) >> 8;
 }
 
 STATIC_INLINE void PixelWrite4(uae_u8 *mem, int bits, uae_u32 fgpen)
@@ -2388,8 +2531,8 @@ STATIC_INLINE void PixelWrite(uae_u8 *mem, int bits, uae_u32 fgpen, uae_u8 Bpp,
        do_put_mem_word (((uae_u16 *)mem) + bits, (uae_u16)fgpen);
        break;
     case 3:
-       do_put_mem_byte (mem + bits * 3, (uae_u8)fgpen);
-       *(uae_u16 *)(mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
+       do_put_mem_byte (mem + bits*3, (uae_u8)fgpen);
+       *(uae_u16 *)(mem + bits*3+1) = (fgpen & 0x00FFFF00) >> 8;
        break;
     case 4:
        do_put_mem_long (((uae_u32 *)mem) + bits, fgpen);
@@ -2440,9 +2583,8 @@ uae_u32 REGPARAM2 picasso_BlitPattern (struct regstruct *regs)
     unsigned long ysize_mask;
     uae_u32 result = 0;
 
-#ifdef PIXEL_LOCK
-    flushpixels();
-#endif
+    P96_SM_RW;
+   
 #ifndef LOCK_UNLOCK_MADNESS
     wgfx_flushline ();
 #endif
@@ -2536,7 +2678,7 @@ uae_u32 REGPARAM2 picasso_BlitPattern (struct regstruct *regs)
                                case 2:
                                    {
                                        uae_u16 *addr = ((uae_u16 *)uae_mem2) + bits;
-                                       do_put_mem_word (addr, (uae_u16)( do_get_mem_word (addr) ^ fgpen));
+                                       do_put_mem_word (addr, (uae_u16)(do_get_mem_word (addr) ^ fgpen));
                                    }
                                    break;
                                case 3:
@@ -2558,15 +2700,13 @@ uae_u32 REGPARAM2 picasso_BlitPattern (struct regstruct *regs)
                    }
                }
            }
-           #ifdef PIXEL_LOCK
-           flushpixels();
-           #endif
-
+    
            /* If we need to update a second-buffer (extra_mem is set), then do it only if visible! */
            if (picasso_vidinfo.extra_mem && renderinfo_is_current_screen (&ri)) {
-               if (vsyncgfxwrite==0)
+               if (vsyncgfxwrite == 0)
                    do_blit(&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0);
            }
+
            result = 1;
        }
     }
@@ -2612,9 +2752,10 @@ uae_u32 REGPARAM2 picasso_BlitTemplate (struct regstruct *regs)
     uae_u8 *tmpl_base;
     uae_u32 result = 0;
 
-#ifdef PIXEL_LOCK
-    flushpixels();
-#endif
+//  if (W * H <= 2500)
+//     return 0;
+    P96_SM_RW;
+
 #ifndef LOCK_UNLOCK_MADNESS
     wgfx_flushline ();
 #endif
@@ -2746,17 +2887,16 @@ uae_u32 REGPARAM2 picasso_BlitTemplate (struct regstruct *regs)
                }
            }
            
-           #ifdef PIXEL_LOCK
-           flushpixels();
-           #endif
            /* If we need to update a second-buffer (extra_mem is set), then do it only if visible! */
            if(picasso_vidinfo.extra_mem && renderinfo_is_current_screen(&ri)) {
                if (vsyncgfxwrite == 0)
                    do_blit(&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0);
            }
+           
            result = 1;
        }
-}    
+    }    
+
     return 1;
 }
 
@@ -2846,7 +2986,7 @@ static void PlanarToChunky(struct RenderInfo *ri, struct BitMap *bm,
     for (j = 0; j < Depth; j++) {
        uae_u8 *p = bm->Planes[j];
        if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
-           p += srcx / 8 + srcy * bm->BytesPerRow;
+           p += srcx/8 + srcy*bm->BytesPerRow;
        PLANAR[j] = p;
        if ((mask & (1 << j)) == 0)
            PLANAR[j] = &all_zeros_bitmap;
@@ -2929,9 +3069,8 @@ uae_u32 REGPARAM2 picasso_BlitPlanar2Chunky (struct regstruct *regs)
     struct BitMap local_bm;
     uae_u32 result = 0;
 
-#ifdef PIXEL_LOCK
-    flushpixels();
-#endif
+    P96_SM_RW;
+   
 #ifndef LOCK_UNLOCK_MADNESS
     wgfx_flushline ();
 #endif
@@ -2980,7 +3119,7 @@ static void PlanarToDirect(struct RenderInfo *ri, struct BitMap *bm,
     for (j = 0; j < Depth; j++) {
        uae_u8 *p = bm->Planes[j];
        if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
-           p += srcx / 8 + srcy * bm->BytesPerRow;
+           p += srcx/8 + srcy*bm->BytesPerRow;
        PLANAR[j] = p;
        if ((mask & (1 << j)) == 0)
            PLANAR[j] = &all_zeros_bitmap;
@@ -3009,7 +3148,7 @@ static void PlanarToDirect(struct RenderInfo *ri, struct BitMap *bm,
                image2 += 2;
                break;
            case 3:
-               do_put_mem_byte (image2++, (uae_u8)cim->Colors[v]);
+               do_put_mem_byte (image2++, (uae_u8)cim->Colors[v] );
                do_put_mem_word ((uae_u16 *)image2, (uae_u16)((cim->Colors[v] & 0x00FFFF00) >> 8));
                image2 += 2;
                break;
@@ -3083,15 +3222,13 @@ uae_u32 REGPARAM2 picasso_BlitPlanar2Direct (struct regstruct *regs)
     struct ColorIndexMapping local_cim;
     uae_u32 result = 0;
 
-#ifdef PIXEL_LOCK
-    flushpixels();
-#endif
+    P96_SM_RW;
+    
 #ifndef LOCK_UNLOCK_MADNESS
     wgfx_flushline ();
 #endif
     
-    if (minterm != 0x0C)
-    {
+    if (minterm != 0x0C) {
        write_log ("WARNING - BlitPlanar2Direct() has unhandled op-code 0x%x. Using fall-back routine.\n",
            minterm);
     }
@@ -3103,16 +3240,11 @@ uae_u32 REGPARAM2 picasso_BlitPlanar2Direct (struct regstruct *regs)
        P96TRACE(("BlitPlanar2Direct(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n",
            srcx, srcy, dstx, dsty, width, height, minterm, Mask, local_bm.Depth));
        PlanarToDirect (&local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, Mask, &local_cim);
-       #ifdef PIXEL_LOCK
-       flushpixels();
-       #endif
-       if (renderinfo_is_current_screen (&local_ri)) {
+       if (renderinfo_is_current_screen (&local_ri))
            if (!vsyncgfxwrite)
                do_blit(&local_ri, GetBytesPerPixel(local_ri.RGBFormat), dstx, dsty, dstx, dsty, width, height, BLIT_SRC, 0);
-       }
        result = 1;
     }
-
     return result;
 }
 
@@ -3127,212 +3259,256 @@ uae_u32 REGPARAM2 picasso_BlitPlanar2Direct (struct regstruct *regs)
 */
 #ifdef PIXEL_LOCK
 
-struct frect
-{
-    int top, left, right, bottom;
-    int first;
+static int pixelcount;
+
+struct pixel32 {
+    uaecptr addr;
+    uae_u32 value;
+    int size;
 };
+static struct pixel32 pixelbase[MAXFLUSHPIXEL + 2];
 
-STATIC_INLINE init_refresh(struct frect *r)
+static void flushpixels_paletted(uae_u8 *dst)
 {
-    r->first = 1;
-    r->left = picasso96_state.Width * picasso96_state.BytesPerPixel;
-    r->top = picasso96_state.Height;
-    r->right = -1;
-    r->bottom = -1;
-}
+    int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
+    int i;
 
-STATIC_INLINE flush_it(struct frect *r)
-{
-    if (r->right >= 0 && r->bottom >= 0) {
-       DX_Invalidate (r->left / picasso96_state.BytesPerPixel, r->top,
-           (r->right - r->left) / picasso96_state.BytesPerPixel + 1, (r->bottom - r->top) + 1);
+    if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
+    {
+        write_log ("ERROR - flushpixels() has non RGBFB_CHUNKY mode!\n");
+       return;
     }
-    init_refresh(r);
-}
+    if (!picasso_vidinfo.extra_mem)
+       return;
 
-#define FLUSH_MIN 30
-STATIC_INLINE void flush_refresh(int x, int y, struct frect *r)
-{
-    if (x < r->left) {
-       if (!r->first && r->left - x > FLUSH_MIN) {
-           flush_it(r);
-           flush_refresh(x, y, r);
-           return;
+    for (i = 0; i < pixelcount; i++)
+    { 
+        uaecptr addr = pixelbase[i].addr;
+        uae_u32 value = pixelbase[i].value;    
+        int y = addr / picasso96_state.BytesPerRow;
+        int xbytes = addr % picasso96_state.BytesPerRow;
+                  
+       if (xbytes < picasso96_state.Width * picasso96_state.BytesPerPixel && y < picasso96_state.Height)
+       {       
+           if(psiz == 4)
+           {
+               uae_u8 *addr = dst + y * picasso_vidinfo.rowbytes + xbytes * 4;
+               switch (pixelbase[i].size)
+               {
+                   case 4:
+                   {
+                       *(uae_u32 *)addr = picasso_vidinfo.clut[value & 0xff];
+                       addr += 4;
+                       *(uae_u32 *)addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+                       addr += 4;
+                       *(uae_u32 *)addr = picasso_vidinfo.clut[(value >> 16) & 0xff];
+                       addr += 4;
+                       *(uae_u32 *)addr = picasso_vidinfo.clut[(value >> 24) & 0xff];
+                       break;
+                   }
+                   case 2:
+                   {
+                       *(uae_u32 *)addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+                       addr += 4;
+                       *(uae_u32 *)addr = picasso_vidinfo.clut[value & 0xff];
+                       break;
+                   }
+                   case 1:
+                   {
+                       *(uae_u32 *)addr = picasso_vidinfo.clut[value & 0xff];
+                       break;
+                   }
+               }
        }
-       r->left = x;
-    }
-    if (y < r->top) {
-       if (!r->first && r->top - y > FLUSH_MIN) {
-           flush_it(r);
-           flush_refresh(x, y, r);
-           return;
+       else
+       {
+               uae_u8 *addr = dst + y * picasso_vidinfo.rowbytes + xbytes * 2;
+
+               switch (pixelbase[i].size)
+               {
+                   case 4:
+                   {
+                       *(uae_u16 *)addr = picasso_vidinfo.clut[value & 0xff];
+                       addr += 2;
+                       *(uae_u16 *)addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+                       addr += 2;
+                       *(uae_u16 *)addr = picasso_vidinfo.clut[(value >> 16) & 0xff];
+                       addr += 2;
+                       *(uae_u16 *)addr = picasso_vidinfo.clut[(value >> 24) & 0xff];
+                       break;
+                   }
+                   case 2:
+                   {
+                       *(uae_u16 *)addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+                       addr += 2;
+                       *(uae_u16 *)addr = picasso_vidinfo.clut[value & 0xff];
+                       break;
+                   }
+                   case 1:
+                   {
+                       *(uae_u16 *)addr = picasso_vidinfo.clut[value & 0xff];
+                       break;
+                   }   
+               }
+           }
        }
-       r->top = y;
     }
-    if (x > r->right) {
-       if (!r->first && x - r->right > FLUSH_MIN) {
-           flush_it(r);
-           flush_refresh(x, y, r);
-           return;
+}
+
+static void **gwwbuf;
+static int gwwbufsize;
+extern uae_u8 *natmem_offset;
+extern int p96mode;
+
+static void flushpixels_rgbx(uae_u8 *dst)
+{
+    int i, j;
+    int rowwidth_src = picasso_vidinfo.width * picasso_vidinfo.pixbytes;
+    int rowwidth_dst = picasso96_state.Width * picasso96_state.BytesPerPixel;
+    ULONG ps;
+    ULONG_PTR gwwcnt;
+
+    if (!picasso_vidinfo.extra_mem)
+        return;
+    if (!gwwbuf) {
+       gwwbufsize = allocated_gfxmem / 4096 + 1;
+       gwwbuf = xmalloc (gwwbufsize * sizeof (void*));
+    }
+    gwwcnt = gwwbufsize;
+    if (GetWriteWatch(WRITE_WATCH_FLAG_RESET, p96ram_start + natmem_offset, allocated_gfxmem, gwwbuf, &gwwcnt, &ps))
+       return;
+    for (i = 0; i < gwwcnt; i++) {
+       uae_u8 *p = gwwbuf[i];
+       uaecptr addr = p - p96ram_start - natmem_offset;
+       for (j = 0; j < ps / 4; j++) {
+           int xbytes, y;
+           uae_u32 *dst2;
+           y = addr / picasso96_state.BytesPerRow;                
+           xbytes = addr % picasso96_state.BytesPerRow;
+           dst2 = (uae_u32*)(dst + y * picasso_vidinfo.rowbytes + xbytes);
+           if (xbytes < rowwidth_dst && y < picasso96_state.Height)
+               *dst2 = ((uae_u32*)p)[0];
+           addr += 4;
+           p += 4;
        }
-       r->right = x;
     }
-    if (y > r->bottom) {
-       if (!r->first && y - r->bottom > FLUSH_MIN) {
-           flush_it(r);
-           flush_refresh(x, y, r);
-           return;
+}
+
+static void flushpixels_rgb(uae_u8 *dst)
+{
+    uaecptr xminaddr = 0, xmaxaddr = 0;
+    uae_u8 *ydestaddr;
+    int i;
+    int rowwidth_src = picasso_vidinfo.width * picasso_vidinfo.pixbytes;
+    int rowwidth_dst = picasso96_state.Width * picasso96_state.BytesPerPixel;
+
+    if (!picasso_vidinfo.extra_mem)
+        return;
+
+    for (i = 0; i < pixelcount; i++)
+    { 
+        uaecptr addr = pixelbase[i].addr;
+        uae_u32 value = pixelbase[i].value;
+        if(addr > xminaddr && addr < xmaxaddr)
+        {
+           switch (pixelbase[i].size)
+           {
+               case 4:
+               #ifdef SWAPSPEEDUP
+               *(uae_u32 *)(ydestaddr + addr) = value;
+               #else      
+               do_put_mem_long ((uae_u32 *)(ydestaddr + addr), value);
+               #endif                    
+               break;;
+               case 2:
+               do_put_mem_word ((uae_u16 *)(ydestaddr + addr), value);
+               break;
+               case 1:
+               *(uae_u8 *)(ydestaddr + addr) = value;
+               break;
+           }
        }
-       r->bottom = y;
+       else
+       {
+           int xbytes, y;
+           y = addr / picasso96_state.BytesPerRow;                
+           xbytes = addr % picasso96_state.BytesPerRow;
+           xminaddr = y * picasso96_state.BytesPerRow;     
+           xmaxaddr = xminaddr + rowwidth_src;
+           ydestaddr = dst + y * picasso_vidinfo.rowbytes - xminaddr;
+                  
+           if (xbytes < rowwidth_dst && y < picasso96_state.Height)
+           {           
+               switch (pixelbase[i].size)
+               {
+                   case 4:
+                   #ifdef SWAPSPEEDUP
+                   *(uae_u32 *)(ydestaddr + addr) = value;
+                   #else          
+                   do_put_mem_long ((uae_u32 *)(ydestaddr + addr), value);
+                   #endif                        
+                   break;;
+                   case 2:
+                   do_put_mem_word ((uae_u16 *)(ydestaddr + addr), value);
+                   break;
+                   case 1:
+                   *(uae_u8 *)(ydestaddr + addr) = value;
+                   break;
+               }
+           }
+           else 
+           {
+               xmaxaddr = 0;
+           }
+       }   
     }
-    r->first = 0;
 }
 
 static void flushpixels(void)
 {
-    int i;
     uae_u8 *dst;
     int lock = 0;
-    int needrefresh;
-    struct frect r;
     
-    if (pixelcount == 0)
+    if (pixelcount == 0 && p96mode == 0)
        return;
     if (!picasso_on) {
        pixelcount = 0;
        return;
     }
-    needrefresh = DirectDraw_GetLockableType() == secondary_surface;
-
+    DX_Invalidate (-1, -1, -1, -1);
+#ifndef        _DEBUG
     if(DirectDraw_IsLocked() == FALSE) {
        dst = gfx_lock_picasso ();
        lock = 1;
-    } else {
+    } else 
+#endif
        dst = picasso96_state.HostAddress;
-    }
-    if (!dst)
-       goto out;
-
-    init_refresh(&r);
-
-    if(picasso_vidinfo.rgbformat != picasso96_state.RGBFormat) {
-
-       int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
-       if (picasso96_state.RGBFormat != RGBFB_CHUNKY) {
-           write_log ("ERROR - flushpixels() has non RGBFB_CHUNKY mode!\n");
-           goto out;
-       }
-       for (i = 0; i < pixelcount; i++) { 
-           int i2 = pixelbase[i].size;
-           uaecptr addr = pixelbase[i].addr;
-           uae_u32 value = pixelbase[i].value; 
-           int y = addr / picasso96_state.BytesPerRow;
-           int xbytes = addr % picasso96_state.BytesPerRow;
-
-           if (! picasso_vidinfo.extra_mem)
-               break;
-                  
-           if (xbytes < picasso96_state.Width * picasso96_state.BytesPerPixel && y < picasso96_state.Height) { 
-               if(psiz == 4) {
-                   uae_u8 *addr;
-                          
-                   addr = dst + y * picasso_vidinfo.rowbytes + (xbytes * 4);
-                   if (i2 == 4) {
-                       *(uae_u32 *) addr = picasso_vidinfo.clut[((value)&0xff)];
-                       addr += 4;
-                       *(uae_u32 *) addr = picasso_vidinfo.clut[((value>>8)&0xff)];
-                       addr += 4;
-                       *(uae_u32 *) addr = picasso_vidinfo.clut[((value>>16)&0xff)];
-                       addr += 4;
-                       *(uae_u32 *) addr = picasso_vidinfo.clut[((value>>24)&0xff)];
-                       break;
-                   } else if (i2 == 2) {
-                       *(uae_u32 *) addr = picasso_vidinfo.clut[((value>>8)&0xff)];
-                       addr += 4;
-                       *(uae_u32 *) addr = picasso_vidinfo.clut[((value)&0xff)];
-                       break;
-                   } else if (i2 == 1) {
-                       *(uae_u32 *) addr = picasso_vidinfo.clut[(value&0xff)];
-                       break;
-                   }
-               } else {
-                   uae_u8 *addr;
-                          
-                   addr = dst + y * picasso_vidinfo.rowbytes + (xbytes * 2);
-                   if (i2 == 4) {
-                       *(uae_u16 *) addr = picasso_vidinfo.clut[((value)&0xff)];
-                       addr += 2;
-                       *(uae_u16 *) addr = picasso_vidinfo.clut[((value>>8)&0xff)];
-                       addr += 2;
-                       *(uae_u16 *) addr = picasso_vidinfo.clut[((value>>16)&0xff)];
-                       addr += 2;
-                       *(uae_u16 *) addr = picasso_vidinfo.clut[((value>>24)&0xff)];
-                       break;
-                   } else if (i2 == 2) {
-                       *(uae_u16 *) addr = picasso_vidinfo.clut[((value>>8)&0xff)];
-                       addr+=2;
-                       *(uae_u16 *) addr = picasso_vidinfo.clut[((value)&0xff)];
-                       break;
-                   } else if (i2 == 1) {
-                       *(uae_u16 *) addr = picasso_vidinfo.clut[(value&0xff)];
-                       break;
-                   }
-               }
-               if (needrefresh)
-                   flush_refresh(xbytes, y, &r);
-           }
-       }
-
-    } else {
-
-       for (i = 0;i < pixelcount; i++) { 
-           uaecptr addr = pixelbase[i].addr;
-           uae_u32 value = pixelbase[i].value;
-           int y = addr / picasso96_state.BytesPerRow;
-           int xbytes = addr % picasso96_state.BytesPerRow;
-           uae_u8 *p = dst + y * picasso_vidinfo.rowbytes + xbytes;
-    
-           if (! picasso_vidinfo.extra_mem)
-               continue;
-
-           if (xbytes < picasso96_state.Width * picasso96_state.BytesPerPixel && y < picasso96_state.Height) {         
-               switch (pixelbase[i].size)
-               {
-                   case 1:
-                   *(uae_u8 *)p = value;
-                   break;
-                   case 2:
-                   do_put_mem_word ((uae_u16 *)p, value);
-                   break;
-                   case 4:  
-    #ifdef SWAPSPEEDUP
-                   *(uae_u32 *)p = value;
-    #else
-                   do_put_mem_long ((uae_u32 *)p, value);       
-    #endif     
-                   break;
-               }
-               if (needrefresh)
-                   flush_refresh(xbytes, y, &r);
-           }
+    if (dst) {
+       if (p96mode) {
+           if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat)
+               flushpixels_rgbx(dst);
+       } else {
+           if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat)
+               flushpixels_rgb(dst);
+           else
+               flushpixels_paletted(dst);
        }
     }
-out:;
     if(lock)
-        gfx_unlock_picasso();
-    pixelcount = 0;
-    flush_it(&r);
+       gfx_unlock_picasso();
+    pixelcount=0;
 }
 #endif
 
-static void write_gfx_x (uaecptr addr, uae_u32 value, int size)
+STATIC_INLINE void write_gfx_x (uaecptr addr, uae_u32 value, int size)
 {
-    uaecptr oldaddr = addr;
+#ifndef PIXEL_LOCK
     int y;
+    uaecptr oldaddr = addr;
 #ifdef LOCK_UNLOCK_MADNESS
     int x, xbytes;
     uae_u8 *dst;
+#endif
 #endif
 
     if (!picasso_on)
@@ -3342,8 +3518,7 @@ static void write_gfx_x (uaecptr addr, uae_u32 value, int size)
     addr += gfxmem_start;
     /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
     if (addr >= picasso96_state.Address && addr + size < picasso96_state.Extent) {
-       addr -= picasso96_state.Address + (picasso96_state.XOffset * picasso96_state.BytesPerPixel)
-           + (picasso96_state.YOffset * picasso96_state.BytesPerRow);
+       addr -= picasso96_state.XYOffset;
        if (pixelcount > MAXFLUSHPIXEL)
            flushpixels();
        pixelbase[pixelcount].addr = addr;
@@ -3351,7 +3526,7 @@ static void write_gfx_x (uaecptr addr, uae_u32 value, int size)
        pixelbase[pixelcount++].size = size;
     }
     return;
-#endif
+#else
 #ifndef LOCK_UNLOCK_MADNESS   
     /*
      * Several writes to successive memory locations are a common access pattern.
@@ -3369,7 +3544,7 @@ static void write_gfx_x (uaecptr addr, uae_u32 value, int size)
 
     addr += gfxmem_start;
     /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
-    if (addr < picasso96_state.Address || addr + size > picasso96_state.Extent)
+    if (addr < picasso96_state.Address || addr + size >= picasso96_state.Extent)
        return;
     addr -= picasso96_state.Address + (picasso96_state.XOffset * picasso96_state.BytesPerPixel)
        + (picasso96_state.YOffset * picasso96_state.BytesPerRow);
@@ -3386,7 +3561,6 @@ static void write_gfx_x (uaecptr addr, uae_u32 value, int size)
     
     if (x < picasso96_state.Width && y < picasso96_state.Height) {
        dst = picasso96_state.HostAddress;
-       //dst = gfx_lock_picasso ();
        if (dst) {
            switch (size)
            {
@@ -3400,7 +3574,6 @@ static void write_gfx_x (uaecptr addr, uae_u32 value, int size)
                do_put_mem_long ((uae_u32 *)(dst + y * picasso_vidinfo.rowbytes + xbytes), value);       
                break;
            }
-           //gfx_unlock_picasso ();
        }
     }
 #else
@@ -3412,28 +3585,33 @@ static void write_gfx_x (uaecptr addr, uae_u32 value, int size)
     wgfx_min = oldaddr;
     wgfx_max = oldaddr + size;
 #endif
+#endif
 }
 
 static uae_u32 REGPARAM2 gfxmem_lget (uaecptr addr)
 {
-    uae_u8 *m;
+    uae_u32 *m;
+
+    P96_SM_R;
     addr -= gfxmem_start & gfxmem_mask;
     addr &= gfxmem_mask;
-    m = gfxmemory + addr;
-    return do_get_mem_long((uae_u32*)m);
+    m = (uae_u32 *)(gfxmemory + addr);
+    return do_get_mem_long(m);
 }
 
 static uae_u32 REGPARAM2 gfxmem_wget (uaecptr addr)
 {
-    uae_u8 *m;
+    uae_u16 *m;
+    P96_SM_R;
     addr -= gfxmem_start & gfxmem_mask;
     addr &= gfxmem_mask;
-    m = gfxmemory + addr;
-    return do_get_mem_word((uae_u16*)m);
+    m = (uae_u16 *)(gfxmemory + addr);
+    return do_get_mem_word(m);
 }
 
 static uae_u32 REGPARAM2 gfxmem_bget (uaecptr addr)
 {
+    P96_SM_R;
     addr -= gfxmem_start & gfxmem_mask;
     addr &= gfxmem_mask;
     return gfxmemory[addr];
@@ -3441,7 +3619,7 @@ static uae_u32 REGPARAM2 gfxmem_bget (uaecptr addr)
 
 static void REGPARAM2 gfxmem_lput (uaecptr addr, uae_u32 l)
 {
-    uae_u8 *m;
+    uae_u32 *m;
 #ifdef SWAPSPEEDUP
     __asm {         //byteswap now
        mov eax,l
@@ -3452,12 +3630,11 @@ static void REGPARAM2 gfxmem_lput (uaecptr addr, uae_u32 l)
     P96_SM_W;
     addr -= gfxmem_start & gfxmem_mask;
     addr &= gfxmem_mask;
-
-    m = gfxmemory + addr;
+    m = (uae_u32 *)(gfxmemory + addr);
 #ifdef SWAPSPEEDUP
     *m = l;
 #else
-    do_put_mem_long((uae_u32*)m, l);
+    do_put_mem_long(m, l);
 #endif
     /* write the long-word to our displayable memory */
     if (vsyncgfxwrite == 0)
@@ -3466,12 +3643,12 @@ static void REGPARAM2 gfxmem_lput (uaecptr addr, uae_u32 l)
 
 static void REGPARAM2 gfxmem_wput (uaecptr addr, uae_u32 w)
 {
-    uae_u8 *m;
+    uae_u16 *m;
     P96_SM_W;
     addr -= gfxmem_start & gfxmem_mask;
     addr &= gfxmem_mask;
-    m = gfxmemory + addr;
-    do_put_mem_word((uae_u16*)m, w);
+    m = (uae_u16 *)(gfxmemory + addr);
+    do_put_mem_word(m, (uae_u16)w);
     
     /* write the word to our displayable memory */
     if (vsyncgfxwrite == 0)
@@ -3490,6 +3667,58 @@ static void REGPARAM2 gfxmem_bput (uaecptr addr, uae_u32 b)
        write_gfx_x(addr, b, 1);
 }
 
+
+static uae_u32 REGPARAM2 gfxmem_lgetx (uaecptr addr)
+{
+    uae_u32 *m;
+
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+    m = (uae_u32 *)(gfxmemory + addr);
+    return do_get_mem_long(m);
+}
+
+static uae_u32 REGPARAM2 gfxmem_wgetx (uaecptr addr)
+{
+    uae_u16 *m;
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+    m = (uae_u16 *)(gfxmemory + addr);
+    return do_get_mem_word(m);
+}
+
+static uae_u32 REGPARAM2 gfxmem_bgetx (uaecptr addr)
+{
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+    return gfxmemory[addr];
+}
+
+static void REGPARAM2 gfxmem_lputx (uaecptr addr, uae_u32 l)
+{
+    uae_u32 *m;
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+    m = (uae_u32 *)(gfxmemory + addr);
+    do_put_mem_long(m, l);
+}
+
+static void REGPARAM2 gfxmem_wputx (uaecptr addr, uae_u32 w)
+{
+    uae_u16 *m;
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+    m = (uae_u16 *)(gfxmemory + addr);
+    do_put_mem_word(m, (uae_u16)w);
+}
+
+static void REGPARAM2 gfxmem_bputx (uaecptr addr, uae_u32 b)
+{
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+    gfxmemory[addr] = b;
+}
+
 static int REGPARAM2 gfxmem_check (uaecptr addr, uae_u32 size)
 {
     addr -= gfxmem_start & gfxmem_mask;
@@ -3511,6 +3740,12 @@ addrbank gfxmem_bank = {
     dummy_lgeti, dummy_wgeti, ABFLAG_RAM
 };
 
+addrbank gfxmem_bankx = {
+    gfxmem_lgetx, gfxmem_wgetx, gfxmem_bgetx,
+    gfxmem_lputx, gfxmem_wputx, gfxmem_bputx,
+    gfxmem_xlate, gfxmem_check, NULL, "RTG RAM",
+    dummy_lgeti, dummy_wgeti, ABFLAG_RAM
+};
 /* Call this function first, near the beginning of code flow
 * Place in InitGraphics() which seems reasonable...
 * Also put it in reset_drawing() for safe-keeping.  */
@@ -3520,7 +3755,7 @@ void InitPicasso96 (void)
     pixelcount = 0;
     palette_changed = 0;
 //fastscreen
-    oldscr = 0;
+    oldscr=0;
 //fastscreen
     memset (&picasso96_state, 0, sizeof(struct picasso96_state_struct));
     
@@ -3586,3 +3821,5 @@ uae_u8 *save_p96 (int *len, uae_u8 *dstptr)
 }
 
 #endif
+
+#endif
index 18d3afd8de305c42dccc86406816470252a2515e..35ceadac242c315d2fe27b96f2f95be091fb5e25 100755 (executable)
@@ -473,6 +473,7 @@ struct picasso96_state_struct
     // support NO direct access all the time to gfx Card
     // everytime windows can remove your surface from card so the mainrender place
     // must be in memory
+    long               XYOffset;
 };
 
 extern void InitPicasso96 (void);
diff --git a/od-win32/picasso96_xp_win.c b/od-win32/picasso96_xp_win.c
new file mode 100755 (executable)
index 0000000..36b4304
--- /dev/null
@@ -0,0 +1,3695 @@
+/*
+* UAE - The U*nix Amiga Emulator
+*
+* Picasso96 Support Module
+*
+* Copyright 1997-2001 Brian King <Brian_King@CodePoet.com>
+* Copyright 2000-2001 Bernd Roesch <>
+*
+* Theory of operation:
+* On the Amiga side, a Picasso card consists mainly of a memory area that
+* contains the frame buffer.  On the UAE side, we allocate a block of memory
+* that will hold the frame buffer.  This block is in normal memory, it is
+* never directly on the graphics card. All graphics operations, which are
+* mainly reads and writes into this block and a few basic operations like
+* filling a rectangle, operate on this block of memory.
+* Since the memory is not on the graphics card, some work must be done to
+* synchronize the display with the data in the Picasso frame buffer.  There
+* are various ways to do this. One possibility is to allocate a second
+* buffer of the same size, and perform all write operations twice.  Since
+* we never read from the second buffer, it can actually be placed in video
+* memory.  The X11 driver could be made to use the Picasso frame buffer as
+* the data buffer of an XImage, which could then be XPutImage()d from time
+* to time.  Another possibility is to translate all Picasso accesses into
+* Xlib (or GDI, or whatever your graphics system is) calls.  This possibility
+* is a bit tricky, since there is a risk of generating very many single pixel
+* accesses which may be rather slow.
+*
+* TODO:
+* - we want to add a manual switch to override SetSwitch for hardware banging
+*   programs started from a Picasso workbench.
+*/
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include "options.h"
+#include "threaddep/thread.h"
+#include "memory.h" 
+#include "custom.h"
+#include "events.h"
+#include "newcpu.h"
+#include "xwin.h"
+#include "savestate.h"
+#include "autoconf.h"
+#include "traps.h"
+
+#if defined(PICASSO96)
+
+#include "dxwrap.h"
+#include "picasso96_win.h"
+#include "win32gfx.h"
+
+int p96hack_vpos, p96hack_vpos2, p96refresh_active; 
+int have_done_picasso; /* For the JIT compiler */
+static int vsyncgfxwrite = 0; 
+static int p96syncrate, vsyncgfxcount;
+static int p96hsync_counter;
+
+#ifdef DEBUG // Change this to _DEBUG for debugging
+#define P96TRACING_ENABLED 1
+#define P96TRACING_LEVEL 1
+#endif
+#define LOCK_UNLOCK_MADNESS //need for 7 times faster linedraw
+#define PIXEL_LOCK    //and scrollable screens
+#define MAXFLUSHPIXEL 3200 //pixel draw in a lock
+static void flushpixels(void);
+static int pixelcount, palette_changed;
+struct pixel32{
+    uaecptr addr;
+    uae_u32 value;
+    int size;
+};
+static struct pixel32 pixelbase[MAXFLUSHPIXEL + 2];
+#ifdef P96TRACING_ENABLED
+#define P96TRACE(x) do { write_log x; } while(0)
+#else
+#define P96TRACE(x)
+#endif
+#define P96TRACEX(x) do { write_log x; } while(0)
+
+#define GetBytesPerPixel(x) GetBytesPerPixel2(x,__FILE__,__LINE__)
+
+#if defined(JIT)
+#define P96_SM_R special_mem |= PIC_READ;
+#define P96_SM_W special_mem |= PIC_WRITE;
+#else
+#define P96_SM_R
+#define P96_SM_W
+#endif
+
+static uae_u32 REGPARAM2 gfxmem_lget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM2 gfxmem_wget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM2 gfxmem_bget (uaecptr) REGPARAM;
+static void REGPARAM2 gfxmem_lput (uaecptr, uae_u32) REGPARAM;
+static void REGPARAM2 gfxmem_wput (uaecptr, uae_u32) REGPARAM;
+static void REGPARAM2 gfxmem_bput (uaecptr, uae_u32) REGPARAM;
+static int REGPARAM2 gfxmem_check (uaecptr addr, uae_u32 size) REGPARAM;
+static uae_u8 *REGPARAM2 gfxmem_xlate (uaecptr addr) REGPARAM;
+
+static uae_u8 all_ones_bitmap, all_zeros_bitmap; /* yuk */
+
+struct picasso96_state_struct picasso96_state;
+struct picasso_vidbuf_description picasso_vidinfo;
+
+/* These are the maximum resolutions... They are filled in by GetSupportedResolutions() */
+/* have to fill this in, otherwise problems occur on the Amiga side P96 s/w which expects
+/* data here. */
+static struct ScreenResolution planar = { 320, 240 };
+static struct ScreenResolution chunky = { 640, 480 };
+static struct ScreenResolution hicolour = { 640, 480 };
+static struct ScreenResolution truecolour = { 640, 480 };
+static struct ScreenResolution alphacolour = { 640, 480 };
+
+#include "win32gui.h"
+#include "resource.h"
+#define UAE_RTG_LIBRARY_VERSION 40
+#define UAE_RTG_LIBRARY_REVISION 3993
+static void checkrtglibrary(void)
+{
+    uae_u32 v;
+    static int checked = FALSE;
+
+    if (checked)
+       return;
+    v = get_long (4); // execbase
+    v += 378; // liblist
+    while ((v = get_long(v))) {
+       uae_u32 v2 = get_long(v + 10); // name
+       uae_u8 *p;
+       addrbank *b = &get_mem_bank(v2);
+       if (!b || !b->check (v2, 12))
+           continue;
+       p = b->xlateaddr(v2);
+       if (!memcmp(p, "rtg.library\0", 12)) {
+           uae_u16 ver = get_word(v + 20);
+           uae_u16 rev = get_word(v + 22);
+           if (ver * 10000 + rev < UAE_RTG_LIBRARY_VERSION * 10000 + UAE_RTG_LIBRARY_REVISION) {
+               char msg[2000];
+               WIN32GUI_LoadUIString(IDS_OLDRTGLIBRARY, msg, sizeof(msg));
+               gui_message(msg, ver, rev, UAE_RTG_LIBRARY_VERSION, UAE_RTG_LIBRARY_REVISION);
+           } else {
+               write_log("P96: rtg.library %d.%d detected\n", ver, rev);
+           }
+           checked = TRUE;
+       }
+    }
+}
+
+static uae_u32 p2ctab[256][2];
+static int set_gc_called = 0;
+//fastscreen
+static uaecptr oldscr = 0;
+#ifdef _DEBUG
+static void PICASSO96_Unlock2(char *filename, int linenum)
+#else
+static void PICASSO96_Unlock(void)
+#endif
+{
+#ifdef LOCK_UNLOCK_MADNESS
+#if defined(P96TRACING_ENABLED) && P96TRACING_LEVEL > 1
+    // This format of output lets you double-click and jump to file/line
+    write_log("%s(%d) : calling P96 UNLOCK with picasso_on=%d\n", filename, linenum, picasso_on);
+#endif
+    if(picasso_on) {
+#ifdef PIXEL_LOCK
+       flushpixels();
+#endif 
+       gfx_unlock_picasso ();
+       picasso96_state.HostAddress = NULL;
+    }
+#endif
+}
+
+#ifdef _DEBUG
+static void PICASSO96_Lock2(char *filename, int linenum)
+#else
+static void PICASSO96_Lock(void)
+#endif
+{
+#ifdef LOCK_UNLOCK_MADNESS
+#if defined(P96TRACING_ENABLED) && P96TRACING_LEVEL > 1
+    // This format of output lets you double-click and jump to file/line
+    write_log( "%s(%d) : calling P96 LOCK with picasso_on=%d\n", filename, linenum, picasso_on );
+#endif
+    if(picasso_on) {
+       picasso96_state.HostAddress = gfx_lock_picasso ();
+    }
+#endif
+}
+
+#ifdef P96TRACING_ENABLED
+/*
+* Debugging dumps
+*/
+static void DumpModeInfoStructure (uaecptr amigamodeinfoptr)
+{
+    write_log ("ModeInfo Structure Dump:\n");
+    write_log ("  Node.ln_Succ  = 0x%x\n", get_long (amigamodeinfoptr));
+    write_log ("  Node.ln_Pred  = 0x%x\n", get_long (amigamodeinfoptr + 4));
+    write_log ("  Node.ln_Type  = 0x%x\n", get_byte (amigamodeinfoptr + 8));
+    write_log ("  Node.ln_Pri   = %d\n", get_byte (amigamodeinfoptr + 9));
+    /*write_log ("  Node.ln_Name  = %s\n", uaememptr->Node.ln_Name); */
+    write_log ("  OpenCount     = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_OpenCount));
+    write_log ("  Active        = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Active));
+    write_log ("  Width         = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_Width));
+    write_log ("  Height        = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_Height));
+    write_log ("  Depth         = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Depth));
+    write_log ("  Flags         = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Flags));
+    write_log ("  HorTotal      = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorTotal));
+    write_log ("  HorBlankSize  = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorBlankSize));
+    write_log ("  HorSyncStart  = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorSyncStart));
+    write_log ("  HorSyncSize   = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorSyncSize));
+    write_log ("  HorSyncSkew   = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_HorSyncSkew));
+    write_log ("  HorEnableSkew = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_HorEnableSkew));
+    write_log ("  VerTotal      = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerTotal));
+    write_log ("  VerBlankSize  = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerBlankSize));
+    write_log ("  VerSyncStart  = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerSyncStart));
+    write_log ("  VerSyncSize   = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerSyncSize));
+    write_log ("  Clock         = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_first_union));
+    write_log ("  ClockDivide   = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_second_union));
+    write_log ("  PixelClock    = %d\n", get_long (amigamodeinfoptr + PSSO_ModeInfo_PixelClock));
+}
+
+static void DumpLibResolutionStructure (uaecptr amigalibresptr)
+{
+    int i;
+    uaecptr amigamodeinfoptr;
+    struct LibResolution *uaememptr = (struct LibResolution *)get_mem_bank(amigalibresptr).xlateaddr(amigalibresptr);
+    
+    write_log ("LibResolution Structure Dump:\n");
+    
+    if (get_long (amigalibresptr + PSSO_LibResolution_DisplayID) == 0xFFFFFFFF) {
+       write_log ("  Finished With LibResolutions...\n");
+    } else {
+       write_log ("  Name      = %s\n", uaememptr->P96ID);
+       write_log ("  DisplayID = 0x%x\n", get_long (amigalibresptr + PSSO_LibResolution_DisplayID));
+       write_log ("  Width     = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Width));
+       write_log ("  Height    = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Height));
+       write_log ("  Flags     = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Flags));
+       for (i = 0; i < MAXMODES; i++) {
+           amigamodeinfoptr = get_long (amigalibresptr + PSSO_LibResolution_Modes + i*4);
+           write_log ("  ModeInfo[%d] = 0x%x\n", i, amigamodeinfoptr);
+           if (amigamodeinfoptr)
+               DumpModeInfoStructure (amigamodeinfoptr);
+       }
+       write_log ("  BoardInfo = 0x%x\n", get_long (amigalibresptr + PSSO_LibResolution_BoardInfo));
+    }
+}
+
+static char binary_byte[9] = { 0,0,0,0,0,0,0,0,0 };
+
+static char *BuildBinaryString (uae_u8 value)
+{
+    int i;
+    for (i = 0; i < 8; i++) {
+       binary_byte[i] = (value & (1 << (7 - i))) ? '#' : '.';
+    }
+    return binary_byte;
+}
+
+static void DumpPattern (struct Pattern *patt)
+{
+    uae_u8 *mem;
+    int row, col;
+    for (row = 0; row < (1 << patt->Size); row++) {
+       mem = patt->Memory + row * 2;
+       for (col = 0; col < 2; col++) {
+           write_log ("%s ", BuildBinaryString (*mem++));
+       }
+       write_log ("\n");
+    }
+}
+
+static void DumpTemplate (struct Template *tmp, unsigned long w, unsigned long h)
+{
+    uae_u8 *mem = tmp->Memory;
+    unsigned int row, col, width;
+    width = (w + 7) >> 3;
+    write_log ("xoffset = %d, bpr = %d\n", tmp->XOffset, tmp->BytesPerRow);
+    for (row = 0; row < h; row++) {
+       mem = tmp->Memory + row * tmp->BytesPerRow;
+       for (col = 0; col < width; col++) {
+           write_log ("%s ", BuildBinaryString (*mem++));
+       }
+       write_log ("\n");
+    }
+}
+
+static void DumpLine( struct Line *line )
+{
+    if(line) {
+       write_log("Line->X = %d\n", line->X);
+       write_log("Line->Y = %d\n", line->Y);
+       write_log("Line->Length = %d\n", line->Length);
+       write_log("Line->dX = %d\n", line->dX);
+       write_log("Line->dY = %d\n", line->dY);
+       write_log("Line->sDelta = %d\n", line->sDelta);
+       write_log("Line->lDelta = %d\n", line->lDelta);
+       write_log("Line->twoSDminusLD = %d\n", line->twoSDminusLD);
+       write_log("Line->LinePtrn = %d\n", line->LinePtrn);
+       write_log("Line->PatternShift = %d\n", line->PatternShift);
+       write_log("Line->FgPen = 0x%x\n", line->FgPen);
+       write_log("Line->BgPen = 0x%x\n", line->BgPen);
+       write_log("Line->Horizontal = %d\n", line->Horizontal);
+       write_log("Line->DrawMode = %d\n", line->DrawMode);
+       write_log("Line->Xorigin = %d\n", line->Xorigin);
+       write_log("Line->Yorigin = %d\n", line->Yorigin);
+    }
+}
+#endif
+
+static void ShowSupportedResolutions (void)
+{
+    int i = 0;
+    
+    write_log ("-----------------\n");
+    while (DisplayModes[i].depth >= 0) {
+       write_log ("%s\n", DisplayModes[i].name);
+       i++;
+    }
+    write_log ("-----------------\n");
+}
+
+static uae_u8 GetBytesPerPixel2(uae_u32 RGBfmt, char *file, int line)
+{
+    static BOOL bFailure = FALSE;
+
+    switch (RGBfmt) {
+    case RGBFB_CLUT:
+       return 1;
+       
+    case RGBFB_A8R8G8B8:
+    case RGBFB_A8B8G8R8:
+    case RGBFB_R8G8B8A8:
+    case RGBFB_B8G8R8A8:
+       return 4;
+       
+    case RGBFB_B8G8R8:
+    case RGBFB_R8G8B8:
+       return 3;
+       
+    case RGBFB_R5G5B5:
+    case RGBFB_R5G6B5:
+    case RGBFB_R5G6B5PC:
+    case RGBFB_R5G5B5PC:
+    case RGBFB_B5G6R5PC:
+    case RGBFB_B5G5R5PC:
+       return 2;
+    default:
+       write_log ("ERROR - GetBytesPerPixel() from %s@%d was unsuccessful with 0x%x?!\n", file, line, RGBfmt);
+       if(!bFailure) {
+           bFailure = TRUE;
+           return GetBytesPerPixel(picasso_vidinfo.rgbformat);
+       } else {
+           abort();
+       }
+    }
+    return 0;
+}
+
+/*
+* Amiga <-> native structure conversion functions
+*/
+
+static int CopyRenderInfoStructureA2U (uaecptr amigamemptr, struct RenderInfo *ri)
+{
+    uaecptr memp = get_long (amigamemptr + PSSO_RenderInfo_Memory);
+    
+    if (valid_address (memp, PSSO_RenderInfo_sizeof)) {
+       ri->Memory = get_real_address (memp);
+       ri->BytesPerRow = get_word (amigamemptr + PSSO_RenderInfo_BytesPerRow);
+       ri->RGBFormat = get_long (amigamemptr + PSSO_RenderInfo_RGBFormat);
+       return 1;
+    }
+    write_log ("ERROR - Invalid RenderInfo memory area...\n");
+    return 0;
+}
+
+static int CopyPatternStructureA2U (uaecptr amigamemptr, struct Pattern *pattern)
+{
+    uaecptr memp = get_long (amigamemptr + PSSO_Pattern_Memory);
+    if (valid_address (memp, PSSO_Pattern_sizeof)) {
+       pattern->Memory = get_real_address (memp);
+       pattern->XOffset = get_word (amigamemptr + PSSO_Pattern_XOffset);
+       pattern->YOffset = get_word (amigamemptr + PSSO_Pattern_YOffset);
+       pattern->FgPen = get_long (amigamemptr + PSSO_Pattern_FgPen);
+       pattern->BgPen = get_long (amigamemptr + PSSO_Pattern_BgPen);
+       pattern->Size = get_byte (amigamemptr + PSSO_Pattern_Size);
+       pattern->DrawMode = get_byte (amigamemptr + PSSO_Pattern_DrawMode);
+       return 1;
+    }
+    write_log ("ERROR - Invalid Pattern memory area...\n");
+    return 0;
+}
+
+static void CopyColorIndexMappingA2U (uaecptr amigamemptr, struct ColorIndexMapping *cim)
+{
+    int i;
+    cim->ColorMask = get_long (amigamemptr);
+    for (i = 0; i < 256; i++, amigamemptr += 4)
+       cim->Colors[i] = get_long (amigamemptr + 4);
+}
+
+static int CopyBitMapStructureA2U (uaecptr amigamemptr, struct BitMap *bm)
+{
+    int i;
+    
+    bm->BytesPerRow = get_word (amigamemptr + PSSO_BitMap_BytesPerRow);
+    bm->Rows = get_word (amigamemptr + PSSO_BitMap_Rows);
+    bm->Flags = get_byte (amigamemptr + PSSO_BitMap_Flags);
+    bm->Depth = get_byte (amigamemptr + PSSO_BitMap_Depth);
+    
+    /* ARGH - why is THIS happening? */
+    if(bm->Depth > 8)
+       bm->Depth = 8;
+    
+    for (i = 0; i < bm->Depth; i++) {
+       uaecptr plane = get_long (amigamemptr + PSSO_BitMap_Planes + i * 4);
+       switch (plane) {
+       case 0:
+           bm->Planes[i] = &all_zeros_bitmap;
+           break;
+       case 0xFFFFFFFF:
+           bm->Planes[i] = &all_ones_bitmap;
+           break;
+       default:
+           if (valid_address (plane, bm->BytesPerRow * bm->Rows))
+               bm->Planes[i] = get_real_address (plane);
+           else
+               return 0;
+           break;
+       }
+    }
+    return 1;
+}
+
+static int CopyTemplateStructureA2U (uaecptr amigamemptr, struct Template *tmpl)
+{
+    uaecptr memp = get_long (amigamemptr + PSSO_Template_Memory);
+    
+    if (valid_address (memp, sizeof(struct Template))) {
+       tmpl->Memory = get_real_address (memp);
+       tmpl->BytesPerRow = get_word (amigamemptr + PSSO_Template_BytesPerRow);
+       tmpl->XOffset = get_byte (amigamemptr + PSSO_Template_XOffset);
+       tmpl->DrawMode = get_byte (amigamemptr + PSSO_Template_DrawMode);
+       tmpl->FgPen = get_long (amigamemptr + PSSO_Template_FgPen);
+       tmpl->BgPen = get_long (amigamemptr + PSSO_Template_BgPen);
+       return 1;
+    }
+    write_log ("ERROR - Invalid Template memory area...\n");
+    return 0;
+}
+
+static int CopyLineStructureA2U(uaecptr amigamemptr, struct Line *line)
+{
+    if(valid_address(amigamemptr, sizeof(struct Line))) {
+       line->X = get_word(amigamemptr + PSSO_Line_X);
+       line->Y = get_word(amigamemptr + PSSO_Line_Y);
+       line->Length = get_word(amigamemptr + PSSO_Line_Length);
+       line->dX = get_word(amigamemptr + PSSO_Line_dX);
+       line->dY = get_word(amigamemptr + PSSO_Line_dY);
+       line->lDelta = get_word(amigamemptr + PSSO_Line_lDelta);
+       line->sDelta = get_word(amigamemptr + PSSO_Line_sDelta);
+       line->twoSDminusLD = get_word(amigamemptr + PSSO_Line_twoSDminusLD);
+       line->LinePtrn = get_word(amigamemptr + PSSO_Line_LinePtrn);
+       line->PatternShift = get_word(amigamemptr + PSSO_Line_PatternShift);
+       line->FgPen = get_long(amigamemptr + PSSO_Line_FgPen);
+       line->BgPen = get_long(amigamemptr + PSSO_Line_BgPen);
+       line->Horizontal = get_word(amigamemptr + PSSO_Line_Horizontal);
+       line->DrawMode = get_byte(amigamemptr + PSSO_Line_DrawMode);
+       line->Xorigin = get_word(amigamemptr + PSSO_Line_Xorigin);
+       line->Yorigin = get_word(amigamemptr + PSSO_Line_Yorigin);
+       return 1;
+    }
+    write_log("ERROR - Invalid Line structure...\n");
+    return 0;
+}
+
+static void CopyLibResolutionStructureU2A (struct LibResolution *libres, uaecptr amigamemptr)
+{
+    char *uaememptr = 0;
+    int i;
+    
+    uaememptr = gfxmem_xlate (amigamemptr); /* I know that amigamemptr is inside my gfxmem chunk, so I can just do the xlate() */
+    memset (uaememptr, 0, PSSO_LibResolution_sizeof); /* zero out our LibResolution structure */
+    strcpy (uaememptr + PSSO_LibResolution_P96ID, libres->P96ID);
+    put_long (amigamemptr + PSSO_LibResolution_DisplayID, libres->DisplayID);
+    put_word (amigamemptr + PSSO_LibResolution_Width, libres->Width);
+    put_word (amigamemptr + PSSO_LibResolution_Height, libres->Height);
+    put_word (amigamemptr + PSSO_LibResolution_Flags, libres->Flags);
+    for (i = 0; i < MAXMODES; i++)
+       put_long (amigamemptr + PSSO_LibResolution_Modes + i * 4, libres->Modes[i]);
+#if 0
+    put_long (amigamemptr, libres->Node.ln_Succ);
+    put_long (amigamemptr + 4, libres->Node.ln_Pred);
+    put_byte (amigamemptr + 8, libres->Node.ln_Type);
+    put_byte (amigamemptr + 9, libres->Node.ln_Pri);
+#endif
+    put_long (amigamemptr + 10, amigamemptr + PSSO_LibResolution_P96ID);
+    put_long (amigamemptr + PSSO_LibResolution_BoardInfo, libres->BoardInfo);
+}
+
+/* list is Amiga address of list, in correct endian format for UAE
+* node is Amiga address of node, in correct endian format for UAE */
+static void AmigaListAddTail (uaecptr l, uaecptr n)
+{
+    put_long (n + 0, l + 4); // n->ln_Succ = (struct Node *)&l->lh_Tail;
+    put_long (n + 4, get_long (l + 8)); // n->ln_Pred = l->lh_TailPred;
+    put_long (get_long (l + 8) + 0, n); // l->lh_TailPred->ln_Succ = n;
+    put_long (l + 8, n); // l->lh_TailPred = n;
+}
+
+/*
+* Functions to perform an action on the real screen
+*/
+
+/*
+* Fill a rectangle on the screen.  src points to the start of a line of the
+* filled rectangle in the frame buffer; it can be used as a memcpy source if
+* there is no OS specific function to fill the rectangle.
+*/
+static void do_fillrect(uae_u8 *src, unsigned int x, unsigned int y, unsigned int width, unsigned int height, uae_u32 pen, int Bpp, RGBFTYPE rgbtype)
+{
+    uae_u8 *dst;
+    int orig_width = width;
+    int orig_height = height;
+
+    /* Try OS specific fillrect function here; and return if successful.  Make sure we adjust for
+     * the pen values if we're doing 8-bit display-emulation on a 16-bit or higher screen. */
+#ifdef PIXEL_LOCK
+    flushpixels(); 
+#endif
+
+    if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
+       if(DX_Fill(x, y, width, height, pen, rgbtype))
+           return;
+    } else {   
+       if(DX_Fill(x, y, width, height, picasso_vidinfo.clut[src[0]], rgbtype))
+          return;
+    }
+
+    P96TRACE(("P96_WARNING: do_fillrect() using fall-back routine!\n"));
+    
+    if(y + height > picasso_vidinfo.height)
+       height = picasso_vidinfo.height - y;
+    if(x + width > picasso_vidinfo.width)
+       width = picasso_vidinfo.width - x;
+
+    if (! picasso_vidinfo.extra_mem)
+       return;
+    
+#ifdef LOCK_UNLOCK_MADNESS
+    PICASSO96_Lock();
+    dst = picasso96_state.HostAddress;
+#else
+    dst = gfx_lock_picasso ();
+#endif
+    if (!dst)
+       goto out;
+    
+    width *= Bpp;
+    dst += y * picasso_vidinfo.rowbytes + x * picasso_vidinfo.pixbytes;
+    if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) 
+    {
+       if(Bpp == 1)
+       {
+           while (height-- > 0)
+           {
+               memset(dst, pen, width);
+               dst += picasso_vidinfo.rowbytes;
+           } 
+       }
+       else
+       {
+           while (height-- > 0)
+           {
+               memcpy (dst, src, width);
+               dst += picasso_vidinfo.rowbytes;
+           } 
+       }
+    }
+    else
+    {
+       int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
+       if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
+       {
+           write_log ("ERROR - do_fillrect() calling abort 1!\n");
+           abort ();
+       }
+       
+       while (height-- > 0) 
+       {
+           unsigned int i;
+           switch (psiz) 
+           {
+           case 2:
+               for (i = 0; i < width; i++)
+                   *((uae_u16 *)dst + i) = picasso_vidinfo.clut[src[i]];
+               break;
+           case 4:
+               for (i = 0; i < width; i++)
+                   *((uae_u32 *)dst + i) = picasso_vidinfo.clut[src[i]];
+               break;
+           default:
+               write_log ("ERROR - do_fillrect() calling abort 2!\n");
+               abort ();                       
+               break;
+           }
+           dst += picasso_vidinfo.rowbytes;
+       }
+    }
+out:;
+#ifndef        LOCK_UNLOCK_MADNESS
+    gfx_unlock_picasso ();
+#else
+    PICASSO96_Unlock();
+#endif
+    DX_Invalidate (x, y, orig_width, orig_height);
+}
+
+/*
+* This routine modifies the real screen buffer after a blit has been
+* performed in the save area. If can_do_blit is nonzero, the blit can
+* be performed within the real screen buffer; otherwise, this routine
+* must do it by hand using the data in the frame-buffer, calculated using
+* the RenderInfo data and our coordinates.
+*/
+static void do_blit(struct RenderInfo *ri, int Bpp, 
+                   unsigned int srcx, unsigned int srcy,
+                   unsigned int dstx, unsigned int dsty,
+                   unsigned int width, unsigned int height,
+                   BLIT_OPCODE opcode, int can_do_blit)
+{
+    uae_u8 *dstp, *srcp;
+    int orig_width, orig_height;
+
+    if(picasso96_state.BigAssBitmap && can_do_blit) {
+       srcx = dstx;
+       srcy = dsty;
+       can_do_blit = 0;
+    } //hack to use cpu rotines for scrolling in big Screens
+    if (picasso96_state.XOffset < 0)
+       can_do_blit = 0;
+    
+    dstx = dstx - picasso96_state.XOffset;
+    dsty = dsty - picasso96_state.YOffset;
+    if((int)dstx <= 0) {
+       srcx = srcx - dstx;
+       dstx = 0;
+    }
+    if((int)dsty <= 0) {
+       srcy = srcy - dsty;
+       dsty = 0;
+    }
+
+#ifdef LOCK_UNLOCK_MADNESS
+#ifdef PIXEL_LOCK
+    flushpixels();
+#endif
+#endif
+    /* Is our x/y origin on-screen? */
+    if(dsty >= picasso_vidinfo.height)
+       return;
+    if(dstx >= picasso_vidinfo.width)
+       return;
+
+    /* Is our area in-range? */
+    if(dsty + height >= picasso_vidinfo.height)
+       height = picasso_vidinfo.height - dsty;
+    if(dstx + width >= picasso_vidinfo.width)
+       width = picasso_vidinfo.width - dstx;
+
+    orig_height = height;
+    orig_width = width;
+
+    if (can_do_blit)  {
+       //
+       // Call OS blitting function that can do it in video memory.
+       // Should return if it was successful
+       //
+       if(DX_Blit(srcx, srcy, dstx, dsty, width, height, opcode))
+           return;
+       srcx = dstx;
+       srcy = dsty;
+    }
+    if (opcode != BLIT_SRC) {
+       write_log("do_blit() opcode = %d!\n", opcode);
+       return;
+    }
+
+#ifdef LOCK_UNLOCK_MADNESS
+    PICASSO96_Lock();
+#endif
+
+    srcp = ri->Memory + srcx * Bpp + srcy * ri->BytesPerRow;
+
+    if (! picasso_vidinfo.extra_mem)
+    {
+    #ifdef LOCK_UNLOCK_MADNESS
+       goto out;
+    #else 
+       return;
+    #endif
+    }
+
+#ifdef LOCK_UNLOCK_MADNESS
+    dstp = picasso96_state.HostAddress;
+#else
+    dstp = gfx_lock_picasso ();
+#endif
+    if (dstp == 0) {
+       write_log ("WARNING: do_blit() couldn't lock\n");
+       goto out;
+    }
+    
+    /* The areas can't overlap: the source is always in the Picasso frame buffer,
+    * and the destination is a different buffer owned by the graphics code.  */
+    dstp += dsty * picasso_vidinfo.rowbytes + dstx * picasso_vidinfo.pixbytes;
+    P96TRACE(("do_blit with srcp %p, dstp %p, dst_rowbytes %d, srcx %d, srcy %d, dstx %d, dsty %d, w %d, h %d, dst_pixbytes %d\n",
+       srcp, dstp, picasso_vidinfo.rowbytes, srcx, srcy, dstx, dsty, width, height, picasso_vidinfo.pixbytes));
+    P96TRACE(("gfxmem is at %p\n", gfxmemory));
+       
+    if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) 
+    {
+       P96TRACE(("do_blit type-a\n"));
+       width *= Bpp;
+       while (height-- > 0) 
+       {
+           memcpy (dstp, srcp, width);
+           srcp += ri->BytesPerRow;
+           dstp += picasso_vidinfo.rowbytes;
+
+       }
+    }
+    else
+    {
+       int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
+       P96TRACE(("do_blit type-b\n"));
+       if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
+       {
+           write_log ("ERROR: do_blit() calling abort 1!\n");
+           abort ();
+       }
+       while (height-- > 0) 
+       {
+           unsigned int i;
+           switch (psiz) 
+           {
+           case 2:
+               for (i = 0; i < width; i++)
+                   *((uae_u16 *)dstp + i) = picasso_vidinfo.clut[srcp[i]];
+               break;
+           case 4:
+               for (i = 0; i < width; i++)
+                   *((uae_u32 *)dstp + i) = picasso_vidinfo.clut[srcp[i]];
+               break;
+           default:
+               write_log ("ERROR - do_blit() calling abort 2!\n");
+               abort ();
+               break;
+           }
+           srcp += ri->BytesPerRow;
+           dstp += picasso_vidinfo.rowbytes;
+       }
+    }
+    out:;
+#ifndef LOCK_UNLOCK_MADNESS
+    gfx_unlock_picasso ();
+#else
+    PICASSO96_Unlock();
+#endif
+    DX_Invalidate (dstx, dsty, orig_width, orig_height);
+}
+
+/*
+* Invert a rectangle on the screen.  a render-info is given,
+* so that do_blit can be used if
+* there is no OS specific function to invert the rectangle.
+*/
+static void do_invertrect(struct RenderInfo *ri, int Bpp, int x, int y, int width, int height)
+{
+   /* if(DX_InvertRect(x, y, width, height))
+       return;*/  //deactivate in 0.8.20 
+    P96TRACE(("do_invertrect falling back to do_blit!\n"));
+    do_blit (ri, Bpp, x, y, x, y, width, height, BLIT_SRC, 0);
+}
+
+#if 0
+static uaecptr wgfx_linestart;
+static uaecptr wgfx_lineend;
+static uaecptr wgfx_min, wgfx_max;
+static unsigned long wgfx_y;
+
+static void wgfx_do_flushline (void)
+{
+    uae_u8 *src, *dstp;
+
+    /* Mark these lines as "dirty" */
+
+    if (! picasso_vidinfo.extra_mem) /* The "out" will flush the dirty lines directly */
+       goto out;
+    
+#ifdef LOCK_UNLOCK_MADNESS
+    dstp = picasso96_state.HostAddress;
+#else
+    dstp = gfx_lock_picasso ();
+#endif
+     if (dstp == 0)
+       goto out;
+
+#if P96TRACING_LEVEL > 0
+    P96TRACE(("flushing %d\n", wgfx_y));
+#endif
+
+    src = gfxmemory + wgfx_min;
+    
+    if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat)
+    {
+#if P96TRACING_LEVEL > 0
+       P96TRACE(("flushing type-a\n"));
+#endif
+       dstp += wgfx_y * picasso_vidinfo.rowbytes + wgfx_min - wgfx_linestart;
+       memcpy (dstp, src, wgfx_max - wgfx_min);
+    }
+    else
+    {
+       int width = wgfx_max - wgfx_min;
+       int i;
+       int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
+       P96TRACE(("flushing type-b\n"));
+       if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
+       {
+           write_log ("ERROR - wgfx_do_flushline() calling abort 1!\n");
+           abort ();
+       }
+       
+       dstp += wgfx_y * picasso_vidinfo.rowbytes + (wgfx_min - wgfx_linestart) * psiz;
+       switch (psiz) {
+       case 2:
+           for (i = 0; i < width; i++)
+               *((uae_u16 *)dstp + i) = picasso_vidinfo.clut[src[i]];
+           break;
+       case 4:
+           for (i = 0; i < width; i++)
+               *((uae_u32 *)dstp + i) = picasso_vidinfo.clut[src[i]];
+           break;
+       default:
+           write_log ("ERROR - wgfx_do_flushline() calling abort 2!\n");
+           abort ();                   
+           break;
+       }
+    }
+    
+out:
+#ifndef LOCK_UNLOCK_MADNESS
+    gfx_unlock_picasso ();
+#endif
+    DX_Invalidate (0, wgfx_y, -1, 1);
+
+    wgfx_linestart = 0xFFFFFFFF;
+}
+
+STATIC_INLINE void wgfx_flushline (void)
+{
+    if (wgfx_linestart == 0xFFFFFFFF || ! picasso_on)
+       return;
+    wgfx_do_flushline ();
+}
+#endif
+
+static int renderinfo_is_current_screen (struct RenderInfo *ri)
+{
+    if (! picasso_on)
+       return 0;
+    if (ri->Memory != gfxmemory + (picasso96_state.Address - gfxmem_start))
+       return 0;
+    
+    return 1;
+}
+
+/*
+* Fill a rectangle in the screen.
+*/
+static void do_fillrect_frame_buffer(struct RenderInfo *ri, int X, int Y, int Width, int Height, uae_u32 Pen, int Bpp, RGBFTYPE RGBFormat)
+{
+    int cols;
+    uae_u8 *start, *oldstart;
+    uae_u8 *src, *dst;
+    int lines;
+
+    /* Do our virtual frame-buffer memory.  First, we do a single line fill by hand */
+    oldstart = start = src = ri->Memory + X * Bpp + Y * ri->BytesPerRow;
+    
+    switch (Bpp) 
+    {
+    case 1:
+       memset (start, Pen, Width);
+       break;
+    case 2:
+       for (cols = 0; cols < Width; cols++) 
+       {
+           do_put_mem_word ((uae_u16 *)start, (uae_u16)Pen);
+           start += 2;
+       }
+       break;
+    case 3:
+       for (cols = 0; cols < Width; cols++) 
+       {
+           do_put_mem_byte (start, (uae_u8)Pen);
+           start++;
+           *(uae_u16 *)(start) = (Pen & 0x00FFFF00) >> 8;
+           start+=2;
+       }
+       break;
+    case 4:
+       for (cols = 0; cols < Width; cols++) 
+       {
+           /**start = Pen; */
+           do_put_mem_long ((uae_u32 *)start, Pen);
+           start += 4;
+       }
+       break;
+    }
+    src = oldstart;
+    dst = src + ri->BytesPerRow;
+    /* next, we do the remaining line fills via memcpy() for > 1 BPP, otherwise some more memset() calls */
+    if(Bpp > 1)
+    {
+       for (lines = 0; lines < Height - 1; lines++, dst += ri->BytesPerRow)
+           memcpy (dst, src, Width * Bpp);
+    }
+    else
+    {
+       for (lines = 0; lines < Height - 1; lines++, dst += ri->BytesPerRow)
+           memset(dst, Pen, Width);
+    }
+}
+
+void picasso_handle_vsync (void)
+{
+    flushpixels();
+    if (palette_changed) {
+       DX_SetPalette (0,256);
+       palette_changed = 0;
+    }
+
+    if (vsyncgfxwrite == 1) {
+       static long blitcount;
+       vsyncgfxcount++;
+       if (vsyncgfxcount > 1) {
+           if (picasso_on) {
+               if (picasso96_state.RGBFormat == picasso_vidinfo.rgbformat
+                   || picasso96_state.RGBFormat == RGBFB_CHUNKY) { 
+                   static frame_time_t cycles;
+                   blitcount++;
+                   cycles = read_processor_time();
+                   picasso_refresh(1);
+                   vsyncgfxcount = 0;
+                   write_log("%d Blitnum %.3fms\n", blitcount,
+                       (read_processor_time() - cycles) * 1000 / (double)syncbase);
+               }
+           }
+       }
+    }
+    setoverlay(1);
+}
+
+static int set_panning_called = 0;
+
+/* Clear our screen, since we've got a new Picasso screen-mode, and refresh with the proper contents
+* This is called on several occasions:
+* 1. Amiga-->Picasso transition, via SetSwitch()
+* 2. Picasso-->Picasso transition, via SetPanning().
+* 3. whenever the graphics code notifies us that the screen contents have been lost.
+*/
+extern unsigned int new_beamcon0;
+void picasso_refresh (int call_setpalette)
+{
+    struct RenderInfo ri;
+    static int beamcon0_before, p96refresh_was;
+
+    if (! picasso_on)
+       return;
+    {  //for higher P96 mousedraw rate
+       /* HACK */
+       extern uae_u16 vtotal;
+       if (p96hack_vpos2) {
+           vtotal = p96hack_vpos2;
+           beamcon0_before = new_beamcon0;
+           new_beamcon0 |= 0x80;
+           p96refresh_active = 1;
+           p96refresh_was = 1;
+       } else {
+           if (p96refresh_was) {
+               new_beamcon0 = beamcon0_before;
+               p96refresh_was = 0;
+           }
+           new_beamcon0 |= 0x20;
+       }
+               /* HACK until ntsc timing is fixed.. */
+    } //end for higher P96 mousedraw rate
+    have_done_picasso = 1;
+
+    /* Make sure that the first time we show a Picasso video mode, we don't blit any crap.
+     * We can do this by checking if we have an Address yet.  */
+    if (picasso96_state.Address) {
+       unsigned int width, height;
+
+       /* blit the stuff from our static frame-buffer to the gfx-card */
+       ri.Memory = gfxmemory + (picasso96_state.Address - gfxmem_start);
+       ri.BytesPerRow = picasso96_state.BytesPerRow;
+       ri.RGBFormat = picasso96_state.RGBFormat;
+
+       if(set_panning_called)
+       {
+           width = (picasso96_state.VirtualWidth < picasso96_state.Width) ?
+               picasso96_state.VirtualWidth : picasso96_state.Width;
+           height = (picasso96_state.VirtualHeight < picasso96_state.Height) ?
+               picasso96_state.VirtualHeight : picasso96_state.Height;
+           // Let's put a black-border around the case where we've got a sub-screen...
+           if(!picasso96_state.BigAssBitmap)
+           {
+               if (picasso96_state.XOffset || picasso96_state.YOffset)
+                   DX_Fill(0, 0, picasso96_state.Width, picasso96_state.Height, 0,
+                       picasso96_state.RGBFormat);
+           }
+       }
+       else
+       {
+           width = picasso96_state.Width;
+           height = picasso96_state.Height;
+       }
+       do_blit(&ri, picasso96_state.BytesPerPixel, 0, 0, 0, 0, width, height, BLIT_SRC, 0);
+    } 
+    else
+    {
+       write_log ("ERROR - picasso_refresh() can't refresh!\n");
+    }
+}
+
+
+/*
+* Functions to perform an action on the frame-buffer
+*/
+static void do_blitrect_frame_buffer(struct RenderInfo *ri, struct RenderInfo *dstri,
+                                   unsigned long srcx, unsigned long srcy,
+                                   unsigned long dstx, unsigned long dsty,
+                                   unsigned long width, unsigned long height,
+                                   uae_u8 mask, BLIT_OPCODE opcode)
+{
+    
+    uae_u8 *src, *dst, *tmp, *tmp2, *tmp3;
+    uae_u8 Bpp = GetBytesPerPixel(ri->RGBFormat);
+    unsigned long total_width = width * Bpp;
+    unsigned long linewidth = (total_width + 15) & ~15;
+    unsigned long lines;
+    int can_do_visible_blit = 0;
+
+    src = ri->Memory + srcx * Bpp + srcy * ri->BytesPerRow;
+    dst = dstri->Memory + dstx * Bpp + dsty * dstri->BytesPerRow;
+    if (mask != 0xFF && Bpp > 1)
+    {
+       write_log ("WARNING - BlitRect() has mask 0x%x with Bpp %d.\n", mask, Bpp);
+    }
+    
+    if (mask == 0xFF || Bpp > 1) 
+    {
+       if(opcode == BLIT_SRC)
+       {
+           /* handle normal case efficiently */
+           if (ri->Memory == dstri->Memory && dsty == srcy)
+           {
+               unsigned long i;
+               for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
+                   memmove (dst, src, total_width);
+           }
+           else if (dsty < srcy) 
+           {
+               unsigned long i;
+               for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
+                   memcpy (dst, src, total_width);
+           }
+           else
+           {
+               unsigned long i;
+               src += (height - 1) * ri->BytesPerRow;
+               dst += (height - 1) * dstri->BytesPerRow;
+               for (i = 0; i < height; i++, src -= ri->BytesPerRow, dst -= dstri->BytesPerRow)
+                   memcpy (dst, src, total_width);
+           }
+           return;
+       }
+       else
+       {
+           uae_u8 *src2;
+           uae_u8 *dst2;
+           unsigned int y;
+
+           for(y = 0; y < height; y++) /* Vertical lines */
+           {
+               uae_u8 *bound = src + total_width - 4;
+               uae_u32 *src2_32;
+               uae_u32 *dst2_32;
+               //copy now the longs
+               for(src2_32 = (uae_u32*)src, dst2_32 = (uae_u32*)dst; src2_32 < (uae_u32*)bound; src2_32++, dst2_32++) /* Horizontal bytes */
+               {
+                   switch(opcode)
+                   {
+                   case BLIT_FALSE:
+                   *dst2_32 = 0;
+                   break;
+                   case BLIT_NOR:
+                   *dst2_32 = ~(*src2_32 | *dst2_32);
+                   break;
+                   case BLIT_ONLYDST:
+                   *dst2_32 = *dst2_32 & ~(*src2_32);
+                   break;
+                   case BLIT_NOTSRC:
+                   *dst2_32 = ~(*src2_32);
+                   break;
+                   case BLIT_ONLYSRC:
+                   *dst2_32 = *src2_32 & ~(*dst2_32);
+                   break;
+                   case BLIT_NOTDST:
+                   *dst2_32 = ~(*dst2_32);
+                   break;
+                   case BLIT_EOR:
+                   *dst2_32 = *src2_32 ^ *dst2_32;
+                   break;
+                   case BLIT_NAND:
+                   *dst2_32 = ~(*src2_32 & *dst2_32);
+                   break;
+                   case BLIT_AND:
+                   *dst2_32 = *src2_32 & *dst2_32;
+                   break;
+                   case BLIT_NEOR:
+                   *dst2_32 = ~(*src2_32 ^ *dst2_32);
+                   break;
+                   case BLIT_DST:
+                   write_log( "do_blitrect_frame_buffer shouldn't get BLIT_DST!\n");
+                   break;
+                   case BLIT_NOTONLYSRC:
+                   *dst2_32 = ~(*src2_32) | *dst2_32;
+                   break;
+                   case BLIT_SRC:
+                   write_log( "do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n");
+                   break;
+                   case BLIT_NOTONLYDST:
+                   *dst2_32 = ~(*dst2_32) | *src2_32;
+                   break;
+                   case BLIT_OR:
+                   *dst2_32 = *src2_32 | *dst2_32;
+                   break;
+                   case BLIT_TRUE:
+                   *dst2_32 = 0xFFFFFFFF;
+                   break;
+                   case 30: //code for swap source with dest in byte
+                   {       
+                       uae_u32 temp;
+                       temp = *src2_32;
+                       *src2_32 = *dst2_32;
+                       *dst2_32 = temp;
+                   }
+                   break;
+                   case BLIT_LAST:
+                   write_log( "do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n");
+                   break;
+                   } /* switch opcode */
+               }// for end
+               //now copy the rest few bytes
+               for(src2 = (uae_u8*)src2_32, dst2 = (uae_u8*)dst2_32; src2 < src + total_width; src2++, dst2++) /* Horizontal bytes */
+               {
+                   switch(opcode)
+                   {
+                   case BLIT_FALSE:
+                   *dst2 = 0;
+                   break;
+                   case BLIT_NOR:
+                   *dst2 = ~(*src2 | *dst2);
+                   break;
+                   case BLIT_ONLYDST:
+                   *dst2 = *dst2 & ~(*src2);
+                   break;
+                   case BLIT_NOTSRC:
+                   *dst2 = ~(*src2);
+                   break;
+                   case BLIT_ONLYSRC:
+                   *dst2 = *src2 & ~(*dst2);
+                   break;
+                   case BLIT_NOTDST:
+                   *dst2 = ~(*dst2);
+                   break;
+                   case BLIT_EOR:
+                   *dst2 = *src2 ^ *dst2;
+                   break;
+                   case BLIT_NAND:
+                   *dst2 = ~(*src2 & *dst2);
+                   break;
+                   case BLIT_AND:
+                   *dst2 = *src2 & *dst2;
+                   break;
+                   case BLIT_NEOR:
+                   *dst2 = ~(*src2 ^ *dst2);
+                   break;
+                   case BLIT_DST:
+                   write_log("do_blitrect_frame_buffer shouldn't get BLIT_DST!\n");
+                   break;
+                   case BLIT_NOTONLYSRC:
+                   *dst2 = ~(*src2) | *dst2;
+                   break;
+                   case BLIT_SRC:
+                   write_log("do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n");
+                   break;
+                   case BLIT_NOTONLYDST:
+                   *dst2 = ~(*dst2) | *src2;
+                   break;
+                   case BLIT_OR:
+                   *dst2 = *src2 | *dst2;
+                   break;
+                   case BLIT_TRUE:
+                   *dst2 = 0xFF;
+                   break;
+                   case BLIT_LAST:
+                   write_log("do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n");
+                   break;
+                   case 30: //code for swap source with dest in long
+                   {
+                       uae_u8 temp;
+                       temp = *src2;
+                       *src2 = *dst2;
+                       *dst2 = temp;
+                   }
+                   break;
+                   } /* switch opcode */
+               } /* for width */
+               src += ri->BytesPerRow;
+               dst += dstri->BytesPerRow;
+           } /* for height */
+       }
+       return;
+    }
+
+    tmp3 = tmp2 = tmp = xmalloc (linewidth * height); /* allocate enough memory for the src-rect */
+    if (!tmp)
+        return;
+
+    /* copy the src-rect into our temporary buffer space */
+    for (lines = 0; lines < height; lines++, src += ri->BytesPerRow, tmp2 += linewidth) 
+    {
+       memcpy (tmp2, src, total_width);
+    }
+
+    /* copy the temporary buffer to the destination */
+    for (lines = 0; lines < height; lines++, dst += dstri->BytesPerRow, tmp+= linewidth) 
+    {
+       unsigned long cols;
+       for (cols = 0; cols < width; cols++) 
+       {
+           dst[cols] &= ~mask;
+           dst[cols] |= tmp[cols] & mask;
+       }
+    }
+    /* free the temp-buf */
+    xfree (tmp3);
+} 
+
+/*
+DrawLine: 
+Synopsis: DrawLine(bi, ri, line, Mask, RGBFormat); 
+Inputs: a0: struct BoardInfo *bi 
+a1: struct RenderInfo *ri 
+a2: struct Line *line 
+d0.b: Mask 
+d7.l: RGBFormat 
+
+This function is used to paint a line on the board memory possibly using the blitter. It is called by Draw
+and obeyes the destination RGBFormat as well as ForeGround and BackGround pens and draw modes. 
+*/
+uae_u32 REGPARAM2 picasso_DrawLine (struct regstruct *regs)
+{
+    uae_u32 result = 0;
+#ifdef P96_DRAWLINE
+    struct Line line;
+    struct RenderInfo ri;
+    uae_u8 Mask = m68k_dreg(regs, 0);
+    RGBFTYPE RGBFormat = m68k_dreg(regs, 7);
+
+    CopyRenderInfoStructureA2U(m68k_areg(regs, 1), &ri);
+    CopyLineStructureA2U(m68k_areg(regs, 2), &line);
+#if defined( P96TRACING_ENABLED ) && P96TRACING_LEVEL > 0
+    DumpLine( &line );
+#endif
+#else
+    P96TRACE(("DrawLine() - not implemented!\n" ));
+#endif
+    return result;
+}
+
+#ifdef HARDWARE_SPRITE_EMULATION
+/*
+SetSprite: 
+Synopsis: SetSprite(bi, activate, RGBFormat); 
+Inputs: a0: struct BoardInfo *bi 
+d0: BOOL activate 
+d7: RGBFTYPE RGBFormat 
+
+This function activates or deactivates the hardware sprite. 
+*/
+uae_u32 picasso_SetSprite (void)
+{
+    uae_u32 result = 0;
+    uae_u32 activate = m68k_dreg( regs, 0 );
+    result = DX_ShowCursor( activate );
+    write_log ("SetSprite() - trying to %s cursor, result = %d\n", activate ? "show":"hide", result);
+    return result;
+}
+
+/*
+SetSpritePosition: 
+Synopsis: SetSpritePosition(bi, RGBFormat); 
+Inputs: a0: struct BoardInfo *bi 
+d7: RGBFTYPE RGBFormat 
+
+This function sets the hardware mouse sprite position according to the values in the BoardInfo structure.
+MouseX and MouseY are the coordinates relative to the screen bitmap. XOffset and YOffset must be subtracted
+to account for possible screen panning. 
+*/
+uae_u32 picasso_SetSpritePosition (void)
+{
+    uae_u32 result = 0;
+    uaecptr bi = m68k_areg(regs, 0);
+    uae_u16 MouseX  = get_word(bi + PSSO_BoardInfo_MouseX) - picasso96_state.XOffset;
+    uae_u16 MouseY  = get_word(bi + PSSO_BoardInfo_MouseY) - picasso96_state.YOffset;
+    
+    // Keep these around, because we don't want flickering
+    static uae_u16 OldMouseX = -1;
+    static uae_u16 OldMouseY = -1;
+
+    // Bounds check MouseX and MouseY here, because sometimes they seem to go negative...
+    if((uae_s16)MouseX < 0)
+       MouseX = 0;
+    if((uae_s16)MouseY < 0)
+       MouseY = 0;
+
+    if((MouseX != OldMouseX) || (MouseY != OldMouseY))
+    {
+       result = DX_MoveCursor(MouseX, MouseY);
+       write_log ("SetSpritePosition() - moving cursor to (%d,%d), result = %d\n", MouseX, MouseY, result);
+       if(result)
+       {
+           OldMouseX = MouseX;
+           OldMouseY = MouseY;
+       }
+    }
+    return result;
+}
+
+/*
+SetSpriteImage: 
+Synopsis: SetSpriteImage(bi, RGBFormat); 
+Inputs: a0: struct BoardInfo *bi 
+d7: RGBFTYPE RGBFormat 
+
+This function gets new sprite image data from the MouseImage field of the BoardInfo structure and writes
+it to the board.
+
+There are three possible cases: 
+
+BIB_HIRESSPRITE is set:
+skip the first two long words and the following sprite data is arranged as an array of two longwords. Those form the
+two bit planes for one image line respectively. 
+
+BIB_HIRESSPRITE and BIB_BIGSPRITE are not set:
+skip the first two words and the following sprite data is arranged as an array of two words. Those form the two
+bit planes for one image line respectively. 
+
+BIB_HIRESSPRITE is not set and BIB_BIGSPRITE is set:
+skip the first two words and the following sprite data is arranged as an array of two words. Those form the two bit
+planes for one image line respectively. You have to double each pixel horizontally and vertically. All coordinates
+used in this case already assume a zoomed sprite, only the sprite data is not zoomed yet. You will have to
+compensate for this when accounting for hotspot offsets and sprite dimensions. 
+*/
+uae_u32 picasso_SetSpriteImage (void)
+{
+    uae_u32 result = 0;
+
+    return result;
+}
+
+/*
+SetSpriteColor: 
+Synopsis: SetSpriteColor(bi, index, red, green, blue, RGBFormat); 
+Inputs: a0: struct BoardInfo *bi 
+d0.b: index 
+d1.b: red 
+d2.b: green 
+d3.b: blue 
+d7: RGBFTYPE RGBFormat 
+
+This function changes one of the possible three colors of the hardware sprite. 
+*/
+uae_u32 picasso_SetSpriteColor (void)
+{
+    uae_u32 result = 0;
+
+    return result;
+}
+#endif
+
+/*
+* BOOL FindCard(struct BoardInfo *bi);      and
+*
+* FindCard is called in the first stage of the board initialisation and
+* configuration and is used to look if there is a free and unconfigured
+* board of the type the driver is capable of managing. If it finds one,
+* it immediately reserves it for use by Picasso96, usually by clearing
+* the CDB_CONFIGME bit in the flags field of the ConfigDev struct of
+* this expansion card. But this is only a common example, a driver can
+* do whatever it wants to mark this card as used by the driver. This
+* mechanism is intended to ensure that a board is only configured and
+* used by one driver. FindBoard also usually fills some fields of the
+* BoardInfo struct supplied by the caller, the rtg.library, for example
+* the MemoryBase, MemorySize and RegisterBase fields.
+*/
+uae_u32 REGPARAM2 picasso_FindCard (struct regstruct *regs)
+{
+    uaecptr AmigaBoardInfo = m68k_areg (regs, 0);
+
+    /* NOTES: See BoardInfo struct definition in Picasso96 dev info */
+    
+    if (allocated_gfxmem && !picasso96_state.CardFound) {
+       /* Fill in MemoryBase, MemorySize */
+       put_long (AmigaBoardInfo + PSSO_BoardInfo_MemoryBase, gfxmem_start);
+       /* size of memory, minus a 32K chunk: 16K for pattern bitmaps, 16K for resolution list */
+       put_long (AmigaBoardInfo + PSSO_BoardInfo_MemorySize, allocated_gfxmem - 32768);
+       picasso96_state.CardFound = 1; /* mark our "card" as being found */
+       return -1;
+    } else
+       return 0;
+}
+
+static void FillBoardInfo (uaecptr amigamemptr, struct LibResolution *res, struct PicassoResolution *dm)
+{
+    char *uaememptr;
+    switch (dm->depth) {
+    case 1:
+       res->Modes[CHUNKY] = amigamemptr;
+       break;
+    case 2:
+       res->Modes[HICOLOR] = amigamemptr;
+       break;
+    case 3:
+       res->Modes[TRUECOLOR] = amigamemptr;
+       break;
+    default:
+       res->Modes[TRUEALPHA] = amigamemptr;
+       break;
+    }
+    uaememptr = gfxmem_xlate(amigamemptr); /* I know that amigamemptr is inside my gfxmem chunk, so I can just do the xlate() */
+    memset(uaememptr, 0, PSSO_ModeInfo_sizeof); /* zero out our ModeInfo struct */
+    
+    put_word (amigamemptr + PSSO_ModeInfo_Width, dm->res.width);
+    put_word (amigamemptr + PSSO_ModeInfo_Height, dm->res.height);
+    put_byte (amigamemptr + PSSO_ModeInfo_Depth, dm->depth * 8);
+    put_byte (amigamemptr + PSSO_ModeInfo_Flags, 0);
+    put_word (amigamemptr + PSSO_ModeInfo_HorTotal, dm->res.width);
+    put_word (amigamemptr + PSSO_ModeInfo_HorBlankSize, 0);
+    put_word (amigamemptr + PSSO_ModeInfo_HorSyncStart, 0);
+    put_word (amigamemptr + PSSO_ModeInfo_HorSyncSize, 0);
+    put_byte (amigamemptr + PSSO_ModeInfo_HorSyncSkew, 0);
+    put_byte (amigamemptr + PSSO_ModeInfo_HorEnableSkew, 0);
+    
+    put_word (amigamemptr + PSSO_ModeInfo_VerTotal, dm->res.height);
+    put_word (amigamemptr + PSSO_ModeInfo_VerBlankSize, 0);
+    put_word (amigamemptr + PSSO_ModeInfo_VerSyncStart, 0);
+    put_word (amigamemptr + PSSO_ModeInfo_VerSyncSize, 0);
+    
+    put_byte (amigamemptr + PSSO_ModeInfo_first_union, 98);
+    put_byte (amigamemptr + PSSO_ModeInfo_second_union, 14);
+    
+    put_long (amigamemptr + PSSO_ModeInfo_PixelClock,
+       dm->res.width * dm->res.height * (currprefs.gfx_refreshrate ? abs (currprefs.gfx_refreshrate) : default_freq));
+}
+
+struct modeids {
+    int width, height;
+    int id;
+};
+static struct modeids mi[] =
+{
+/* "original" modes */
+
+    320, 200, 0,
+    320, 240, 1,
+    640, 400, 2,
+    640, 480, 3,
+    800, 600, 4,
+   1024, 768, 5,
+   1152, 864, 6,
+   1280,1024, 7,
+   1600,1280, 8,
+
+/* new modes */
+
+    704, 480, 129,
+    704, 576, 130,
+    720, 480, 131,
+    720, 576, 132,
+    768, 483, 133,
+    768, 576, 134,
+    800, 480, 135,
+    848, 480, 136,
+    854, 480, 137,
+    948, 576, 138,
+   1024, 576, 139,
+   1152, 768, 140,
+   1152, 864, 141,
+   1280, 720, 142,
+   1280, 768, 143,
+   1280, 800, 144,
+   1280, 854, 145,
+   1280, 960, 146,
+   1366, 768, 147,
+   1440, 900, 148,
+   1440, 960, 149,
+   1600,1200, 150,
+   1680,1050, 151,
+   1920,1080, 152,
+   1920,1200, 153,
+   2048,1152, 154,
+   2048,1536, 155,
+   2560,1600, 156,
+   2560,2048, 157,
+    400, 300, 158,
+    512, 384, 159,
+    640, 432, 160,
+   1360, 768, 161,
+   1360,1024, 162,
+   1400,1050, 163,
+   1792,1344, 164,
+   1800,1440, 165,
+   1856,1392, 166,
+   1920,1440, 167,
+
+   -1,-1,0
+};
+
+static int AssignModeID(int dm, int count, int *unkcnt)
+{
+    int i, w, h;
+
+    w = DisplayModes[dm].res.width;
+    h = DisplayModes[dm].res.height;
+    for (i = 0; mi[i].width > 0; i++) {
+       if (w == mi[i].width && h == mi[i].height)
+           return 0x50001000 | (mi[i].id * 0x10000);
+    }
+    (*unkcnt)++;
+    write_log("P96: Non-unique mode %dx%d\n", w, h);
+    return 0x51000000 - (*unkcnt) * 0x10000;
+#if 0
+    int result;
+    if(DisplayModes[i].res.width == 320 && DisplayModes[i].res.height == 200)
+       result = 0x50001000;
+    else  if(DisplayModes[i].res.width == 320 && DisplayModes[i].res.height == 240)
+       result = 0x50011000;
+    else if(DisplayModes[i].res.width == 640 && DisplayModes[i].res.height == 400)
+       result = 0x50021000;
+    else if(DisplayModes[i].res.width == 640 && DisplayModes[i].res.height == 480)
+       result = 0x50031000;
+    else if(DisplayModes[i].res.width == 800 && DisplayModes[i].res.height == 600)
+       result = 0x50041000;
+    else if(DisplayModes[i].res.width == 1024 && DisplayModes[i].res.height == 768)
+       result = 0x50051000;
+    else if(DisplayModes[i].res.width == 1152 && DisplayModes[i].res.height == 864)
+       result = 0x50061000;
+    else if(DisplayModes[i].res.width == 1280 && DisplayModes[i].res.height == 1024)
+       result = 0x50071000;
+    else if(DisplayModes[i].res.width == 1600 && DisplayModes[i].res.height == 1280)
+       result = 0x50081000;
+    else
+       result = 0x50090000 + count * 0x10000;
+    return result;
+#endif
+}
+
+/****************************************
+* InitCard()
+*
+* a2: BoardInfo structure ptr - Amiga-based address in Intel endian-format
+*
+* Job - fill in the following structure members:
+* gbi_RGBFormats: the pixel formats that the host-OS of UAE supports
+*     If UAE is running in a window, it should ONLY report the pixel format of the host-OS desktop
+*     If UAE is running full-screen, it should report ALL pixel formats that the host-OS can handle in full-screen
+*     NOTE: If full-screen, and the user toggles to windowed-mode, all hell will break loose visually. Must inform
+*     user that they're doing something stupid (unless their desktop and full-screen colour modes match).
+* gbi_SoftSpriteFlags: should be the same as above for now, until actual cursor support is added
+* gbi_BitsPerCannon: could be 6 or 8 or ???, depending on the host-OS gfx-card
+* gbi_MaxHorResolution: fill this in for all modes (even if you don't support them)
+* gbi_MaxVerResolution: fill this in for all modes (even if you don't support them)
+*/
+uae_u32 REGPARAM2 picasso_InitCard (struct regstruct *regs)
+{
+    struct LibResolution res;
+    int ModeInfoStructureCount = 1, LibResolutionStructureCount = 0;
+    int i, unkcnt;
+
+    uaecptr amigamemptr = 0;
+    uaecptr AmigaBoardInfo = m68k_areg (regs, 2);
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_BitsPerCannon, DX_BitsPerCannon());
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_RGBFormats, picasso96_pixel_format);
+    put_long (AmigaBoardInfo + PSSO_BoardInfo_BoardType, BT_uaegfx);
+#ifdef HARDWARE_SPRITE_EMULATION
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_SoftSpriteFlags, 0);
+#else
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_SoftSpriteFlags, picasso96_pixel_format);
+#endif
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 0, planar.width);
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 2, chunky.width);
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 4, hicolour.width);
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 6, truecolour.width);
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 8, alphacolour.width);
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 0, planar.height);
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 2, chunky.height);
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 4, hicolour.height);
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 6, truecolour.height);
+    put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 8, alphacolour.height);
+    
+    i = 0;
+    unkcnt = 0;
+    while (DisplayModes[i].depth >= 0) {    
+       int j = i;
+       /* Add a LibResolution structure to the ResolutionsList MinList in our BoardInfo */
+       res.DisplayID = AssignModeID(i, LibResolutionStructureCount, &unkcnt);
+       res.BoardInfo = AmigaBoardInfo;
+       res.Width = DisplayModes[i].res.width;
+       res.Height = DisplayModes[i].res.height;
+       res.Flags = P96F_PUBLIC;
+       memcpy (res.P96ID, "P96-0:", 6);
+       sprintf (res.Name, "uaegfx:%dx%d", res.Width, res.Height);
+       res.Modes[PLANAR] = 0;
+       res.Modes[CHUNKY] = 0;
+       res.Modes[HICOLOR] = 0;
+       res.Modes[TRUECOLOR] = 0;
+       res.Modes[TRUEALPHA] = 0;
+       
+       do {
+           /* Handle this display mode's depth */
+           
+           /* New: Only add the modes when there is enough P96 RTG memory to hold the bitmap */
+           if((allocated_gfxmem - 32768) >
+               (DisplayModes[i].res.width * DisplayModes[i].res.height * DisplayModes[i].depth))
+           {
+               amigamemptr = gfxmem_start + allocated_gfxmem - (PSSO_ModeInfo_sizeof * ModeInfoStructureCount++);
+               FillBoardInfo(amigamemptr, &res, &DisplayModes[i]);
+           }
+           i++;
+       } while (DisplayModes[i].depth >= 0
+           && DisplayModes[i].res.width == DisplayModes[j].res.width
+           && DisplayModes[i].res.height == DisplayModes[j].res.height);
+       
+       amigamemptr = gfxmem_start + allocated_gfxmem - 16384 + (PSSO_LibResolution_sizeof * LibResolutionStructureCount++);
+       CopyLibResolutionStructureU2A (&res, amigamemptr);
+#if defined P96TRACING_ENABLED && P96TRACING_LEVEL > 1
+       DumpLibResolutionStructure(amigamemptr);
+#endif
+       AmigaListAddTail (AmigaBoardInfo + PSSO_BoardInfo_ResolutionsList, amigamemptr);
+    }
+    
+    return -1;
+}
+
+/*
+* SetSwitch:
+* a0: struct BoardInfo
+* d0.w: BOOL state
+* this function should set a board switch to let the Amiga signal pass
+* through when supplied with a 0 in d0 and to show the board signal if
+* a 1 is passed in d0. You should remember the current state of the
+* switch to avoid unneeded switching. If your board has no switch, then
+* simply supply a function that does nothing except a RTS.
+*
+* NOTE: Return the opposite of the switch-state. BDK
+*/
+uae_u32 REGPARAM2 picasso_SetSwitch (struct regstruct *regs)
+{
+    uae_u16 flag = m68k_dreg (regs, 0) & 0xFFFF;
+
+    /* Do not switch immediately.  Tell the custom chip emulation about the
+    * desired state, and wait for custom.c to call picasso_enablescreen
+    * whenever it is ready to change the screen state.  */
+    picasso_requested_on = flag;
+    write_log ("SetSwitch() - trying to show %s screen\n", flag ? "picasso96" : "amiga");
+    
+    /* Put old switch-state in D0 */
+
+    return !flag;
+}
+
+void picasso_enablescreen (int on)
+{  
+#if 0
+    wgfx_linestart = 0xFFFFFFFF;
+#endif
+    picasso_refresh (1);
+    write_log ("SetSwitch() from threadid %d - showing %s screen\n", GetCurrentThreadId(), on ? "picasso96": "amiga");
+    checkrtglibrary();
+}
+
+/*
+* SetColorArray:
+* a0: struct BoardInfo
+* d0.w: startindex
+* d1.w: count
+* when this function is called, your driver has to fetch "count" color
+* values starting at "startindex" from the CLUT field of the BoardInfo
+* structure and write them to the hardware. The color values are always
+* between 0 and 255 for each component regardless of the number of bits
+* per cannon your board has. So you might have to shift the colors
+* before writing them to the hardware.
+*/
+uae_u32 REGPARAM2 picasso_SetColorArray (struct regstruct *regs)
+{
+/* Fill in some static UAE related structure about this new CLUT setting
+    * We need this for CLUT-based displays, and for mapping CLUT to hi/true colour */
+    uae_u16 start = m68k_dreg (regs, 0);
+    uae_u16 count = m68k_dreg (regs, 1);
+    int i;
+    uaecptr boardinfo = m68k_areg (regs, 0);
+    uaecptr clut = boardinfo + PSSO_BoardInfo_CLUT + start * 3;
+    
+    for (i = start; i < start + count; i++) {
+       int r = get_byte (clut);
+       int g = get_byte (clut + 1);
+       int b = get_byte (clut + 2);
+       
+       palette_changed |= (picasso96_state.CLUT[i].Red != r 
+           || picasso96_state.CLUT[i].Green != g
+           || picasso96_state.CLUT[i].Blue != b);
+       
+       picasso96_state.CLUT[i].Red = r; 
+       picasso96_state.CLUT[i].Green = g;
+       picasso96_state.CLUT[i].Blue = b;
+       clut += 3;
+    }
+    P96TRACE(("SetColorArray(%d,%d)\n", start, count));
+    return 1;
+}
+
+/*
+* SetDAC:
+* a0: struct BoardInfo
+* d7: RGBFTYPE RGBFormat
+* This function is called whenever the RGB format of the display changes,
+* e.g. from chunky to TrueColor. Usually, all you have to do is to set
+* the RAMDAC of your board accordingly.
+*/
+uae_u32 REGPARAM2 picasso_SetDAC (struct regstruct *regs)
+{
+/* Fill in some static UAE related structure about this new DAC setting
+    * Lets us keep track of what pixel format the Amiga is thinking about in our frame-buffer */
+    
+    P96TRACE(("SetDAC()\n"));
+    return 1;
+}
+
+
+static void init_picasso_screen(void)
+{
+    if(set_panning_called) {
+       picasso96_state.Extent = picasso96_state.Address + (picasso96_state.BytesPerRow * picasso96_state.VirtualHeight);
+    }
+    if (set_gc_called) {
+       gfx_set_picasso_modeinfo (picasso96_state.Width, picasso96_state.Height,
+           picasso96_state.GC_Depth, picasso96_state.RGBFormat);
+    }
+    if((picasso_vidinfo.width == picasso96_state.Width) &&
+       (picasso_vidinfo.height == picasso96_state.Height) &&
+       (picasso_vidinfo.depth == (picasso96_state.GC_Depth >> 3)) &&
+       (picasso_vidinfo.selected_rgbformat == picasso96_state.RGBFormat)) 
+    {
+       DX_SetPalette (0, 256);
+       picasso_refresh (1); 
+    }
+}
+
+/*
+* SetGC:
+* a0: struct BoardInfo
+* a1: struct ModeInfo
+* d0: BOOL Border
+* This function is called whenever another ModeInfo has to be set. This
+* function simply sets up the CRTC and TS registers to generate the
+* timing used for that screen mode. You should not set the DAC, clocks
+* or linear start adress. They will be set when appropriate by their
+* own functions.
+*/
+uae_u32 REGPARAM2 picasso_SetGC (struct regstruct *regs)
+{
+    /* Fill in some static UAE related structure about this new ModeInfo setting */
+    uae_u32 border   = m68k_dreg (regs, 0);
+    uaecptr modeinfo = m68k_areg (regs, 1);
+    
+    picasso96_state.Width = get_word (modeinfo + PSSO_ModeInfo_Width);
+    picasso96_state.VirtualWidth = picasso96_state.Width; /* in case SetPanning doesn't get called */
+    
+    picasso96_state.Height = get_word (modeinfo + PSSO_ModeInfo_Height);
+    picasso96_state.VirtualHeight = picasso96_state.Height; /* in case SetPanning doesn't get called */
+    
+    picasso96_state.GC_Depth = get_byte (modeinfo + PSSO_ModeInfo_Depth);
+    picasso96_state.GC_Flags = get_byte (modeinfo + PSSO_ModeInfo_Flags);
+    
+    P96TRACE(("SetGC(%d,%d,%d,%d)\n", picasso96_state.Width, picasso96_state.Height, picasso96_state.GC_Depth, border));
+    set_gc_called = 1;
+    picasso96_state.HostAddress = NULL;
+    init_picasso_screen ();
+    init_hz_p96 ();
+    return 1;
+}
+
+/*
+* SetPanning:
+* a0: struct BoardInfo
+* a1: UBYTE *Memory
+* d0: uae_u16 Width
+* d1: WORD XOffset
+* d2: WORD YOffset
+* d7: RGBFTYPE RGBFormat
+* This function sets the view origin of a display which might also be
+* overscanned. In register a1 you get the start address of the screen
+* bitmap on the Amiga side. You will have to subtract the starting
+* address of the board memory from that value to get the memory start
+* offset within the board. Then you get the offset in pixels of the
+* left upper edge of the visible part of an overscanned display. From
+* these values you will have to calculate the LinearStartingAddress
+* fields of the CRTC registers.
+
+  * NOTE: SetPanning() can be used to know when a Picasso96 screen is
+  * being opened.  Better to do the appropriate clearing of the
+  * background here than in SetSwitch() derived functions,
+  * because SetSwitch() is not called for subsequent Picasso screens.
+*/
+
+uae_u32 REGPARAM2 picasso_SetPanning (struct regstruct *regs)
+{   
+    uae_u16 Width = m68k_dreg (regs, 0);
+    uaecptr start_of_screen = m68k_areg (regs, 1);
+    uaecptr bi = m68k_areg(regs, 0);
+    uaecptr bmeptr = get_long(bi + PSSO_BoardInfo_BitMapExtra);  /* Get our BoardInfo ptr's BitMapExtra ptr */
+    uae_u16 bme_width, bme_height;
+
+    if(oldscr == 0) {
+       oldscr = start_of_screen;    
+    }
+    if (oldscr != start_of_screen) {
+       set_gc_called = 0;
+       oldscr = start_of_screen;
+    }
+
+    bme_width = get_word(bmeptr + PSSO_BitMapExtra_Width);
+    bme_height = get_word(bmeptr + PSSO_BitMapExtra_Height);
+    
+    picasso96_state.Address = start_of_screen; /* Amiga-side address */
+    picasso96_state.XOffset = (uae_s16)(m68k_dreg (regs, 1) & 0xFFFF);
+    picasso96_state.YOffset = (uae_s16)(m68k_dreg (regs, 2) & 0xFFFF);
+    picasso96_state.VirtualWidth = bme_width;
+    picasso96_state.VirtualHeight = bme_height;
+    if((bme_width > Width) || (bme_height > picasso96_state.Height)) // NOTE: These were != instead of > before...
+       picasso96_state.BigAssBitmap = 1;
+    else
+       picasso96_state.BigAssBitmap = 0;
+    picasso96_state.RGBFormat = m68k_dreg (regs, 7);
+    picasso96_state.BytesPerPixel = GetBytesPerPixel (picasso96_state.RGBFormat);
+    picasso96_state.BytesPerRow = bme_width * picasso96_state.BytesPerPixel;
+    
+    set_panning_called = 1;
+    P96TRACE(("SetPanning(%d, %d, %d) Start 0x%x, BPR %d Bpp %d RGBF %d\n",
+       Width, picasso96_state.XOffset, picasso96_state.YOffset,
+       start_of_screen, picasso96_state.BytesPerRow, picasso96_state.BytesPerPixel, picasso96_state.RGBFormat));
+    init_picasso_screen ();
+    set_panning_called = 0;
+    
+    return 1;
+}
+
+static void do_xor8 (uae_u8 *ptr, long len, uae_u32 val)
+{
+    int i;
+#if 0 && defined ALIGN_POINTER_TO32
+    int align_adjust = ALIGN_POINTER_TO32(ptr);
+    int len2;
+    
+    len -= align_adjust;
+    while (align_adjust) {
+       *ptr ^= val;
+       ptr++;
+       align_adjust--;
+    }
+    len2 = len >> 2;
+    len -= len2 << 2;
+    for (i = 0; i < len2; i++, ptr += 4) {
+       *(uae_u32 *)ptr ^= val;
+    }
+    while (len) {
+       *ptr ^= val;
+       ptr++;
+       len--;
+    }
+    return;
+#endif
+    for (i = 0; i < len; i++, ptr++) {
+       do_put_mem_byte (ptr, (uae_u8)(do_get_mem_byte (ptr) ^ val));
+    }
+}
+
+/*
+* InvertRect:
+* 
+* Inputs:
+* a0:struct BoardInfo *bi
+* a1:struct RenderInfo *ri
+* d0.w:X
+* d1.w:Y
+* d2.w:Width
+* d3.w:Height
+* d4.l:Mask
+* d7.l:RGBFormat
+* 
+* This function is used to invert a rectangular area on the board. It is called by BltBitMap,
+* BltPattern and BltTemplate.
+*/
+uae_u32 REGPARAM2 picasso_InvertRect (struct regstruct *regs)
+{
+    uaecptr renderinfo = m68k_areg (regs, 1);
+    unsigned long X = (uae_u16)m68k_dreg (regs, 0);
+    unsigned long Y = (uae_u16)m68k_dreg (regs, 1);
+    unsigned long Width = (uae_u16)m68k_dreg (regs, 2);
+    unsigned long Height = (uae_u16)m68k_dreg (regs, 3);
+    uae_u8 mask = (uae_u8)m68k_dreg (regs, 4);
+    int Bpp = GetBytesPerPixel (m68k_dreg (regs, 7));
+    uae_u32 xorval;
+    unsigned int lines;
+    struct RenderInfo ri;
+    uae_u8 *uae_mem, *rectstart;
+    unsigned long width_in_bytes;
+    uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+    flushpixels();
+#endif
+#ifdef NOBLIT
+    return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+    wgfx_flushline ();    
+#endif
+    
+    if (CopyRenderInfoStructureA2U (renderinfo, &ri))
+    {
+       P96TRACE(("InvertRect %dbpp 0x%lx\n", Bpp, (long)mask));
+    
+       if (mask != 0xFF && Bpp > 1) 
+           mask = 0xFF;
+
+       xorval = 0x01010101 * (mask & 0xFF);
+       width_in_bytes = Bpp * Width;
+       rectstart = uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
+    
+       for (lines = 0; lines < Height; lines++, uae_mem += ri.BytesPerRow)
+           do_xor8 (uae_mem, width_in_bytes, xorval);
+    
+       if (vsyncgfxwrite == 0) {
+           if (renderinfo_is_current_screen (&ri)) {
+               if (mask == 0xFF)
+                   do_invertrect(&ri, Bpp, X, Y, Width, Height);
+               else
+                   do_blit(&ri, Bpp, X, Y, X, Y, Width, Height, BLIT_SRC, 0);
+           }
+       }
+       result = 1;
+    }
+
+    return result; /* 1 if supported, 0 otherwise */
+}
+
+/***********************************************************
+FillRect:
+***********************************************************
+* a0: struct BoardInfo *
+* a1: struct RenderInfo *
+* d0: WORD X
+* d1: WORD Y
+* d2: WORD Width
+* d3: WORD Height
+* d4: uae_u32 Pen
+* d5: UBYTE Mask
+* d7: uae_u32 RGBFormat
+***********************************************************/
+uae_u32 REGPARAM2 picasso_FillRect (struct regstruct *regs)
+{
+    uaecptr renderinfo = m68k_areg (regs, 1);
+    uae_u32 X = (uae_u16)m68k_dreg (regs, 0);
+    uae_u32 Y = (uae_u16)m68k_dreg (regs, 1);
+    uae_u32 Width = (uae_u16)m68k_dreg (regs, 2);
+    uae_u32 Height = (uae_u16)m68k_dreg (regs, 3);
+    uae_u32 Pen = m68k_dreg (regs, 4);
+    uae_u8 Mask = (uae_u8)m68k_dreg (regs, 5);
+    RGBFTYPE RGBFormat = m68k_dreg (regs, 7);
+    
+    uae_u8 *src;
+    uae_u8 *oldstart;
+    int Bpp;
+    struct RenderInfo ri;
+    uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+    flushpixels();
+#endif
+#ifdef NOBLIT
+    return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+    wgfx_flushline ();
+#endif
+    
+    if (CopyRenderInfoStructureA2U (renderinfo, &ri) && Y != 0xFFFF)
+    {
+       if (ri.RGBFormat != RGBFormat)
+           write_log ("Weird Stuff!\n");
+    
+       Bpp = GetBytesPerPixel (RGBFormat);
+    
+       P96TRACE(("FillRect(%d, %d, %d, %d) Pen 0x%x BPP %d BPR %d Mask 0x%x\n",
+           X, Y, Width, Height, Pen, Bpp, ri.BytesPerRow, Mask));
+    
+       if(Bpp > 1)
+           Mask = 0xFF;
+    
+       if (Mask == 0xFF) 
+       {
+           if((Width == 1) || (Height == 1))
+           {
+               int i;
+               uaecptr addr;
+               if(renderinfo_is_current_screen(&ri))
+               {
+                   uae_u32 diff = gfxmem_start - (uae_u32)gfxmemory; /* xxx this is sooo wrong.. */
+                   addr = ri.Memory + X * Bpp + Y * ri.BytesPerRow + diff;
+                   if(Width == 1)
+                   {
+                       for(i = 0; i < Height; i++)
+                       {
+                           if(Bpp == 4)
+                               gfxmem_lput(addr + (i * picasso96_state.BytesPerRow), Pen);
+                           else if(Bpp == 2)
+                               gfxmem_wput(addr + (i * picasso96_state.BytesPerRow), Pen);
+                           else
+                               gfxmem_bput(addr + (i * picasso96_state.BytesPerRow), Pen);
+                       }
+                   }
+                   else if(Height == 1)
+                   {
+                       for(i = 0; i < Width; i++)
+                       {
+                           if(Bpp == 4)
+                               gfxmem_lput(addr + (i * Bpp), Pen);
+                           else if(Bpp == 2)
+                               gfxmem_wput(addr + (i * Bpp), Pen);
+                           else
+                               gfxmem_bput(addr + (i * Bpp), Pen);
+                       }
+                   }
+                   return 1;
+               }
+           }
+           /* Do the fill-rect in the frame-buffer */
+           do_fillrect_frame_buffer(&ri, X, Y, Width, Height, Pen, Bpp, RGBFormat);
+           /* Now we do the on-screen display, if renderinfo points to it */
+           if (renderinfo_is_current_screen (&ri))
+           {
+               src = ri.Memory + X * Bpp + Y * ri.BytesPerRow;
+               X = X - picasso96_state.XOffset;
+               Y = Y - picasso96_state.YOffset;            
+               if((int)X < 0) {
+                   Width = Width + X;
+                   X = 0;
+               }
+               if((int)Width < 1)
+                   return 1;
+               if((int)Y < 0) {
+                   Height = Height + Y;
+                   Y = 0;
+               }
+               if((int)Height < 1)
+                   return 1;
+               /* Argh - why does P96Speed do this to me, with FillRect only?! */
+               if((X < picasso96_state.Width) &&
+                   (Y < picasso96_state.Height))
+               {
+                   if(X + Width > picasso96_state.Width)
+                       Width = picasso96_state.Width - X;
+                   if(Y + Height > picasso96_state.Height)
+                       Height = picasso96_state.Height - Y;
+
+                   if (vsyncgfxwrite == 0)
+                       do_fillrect(src, X, Y, Width, Height, Pen, Bpp, RGBFormat);
+               }
+           }
+           result = 1;
+       }
+       else
+       {
+           /* We get here only if Mask != 0xFF */
+           if (Bpp != 1) 
+           {
+               write_log("WARNING - FillRect() has unhandled mask 0x%x with Bpp %d. Using fall-back routine.\n", Mask, Bpp);
+           }
+           else
+           {
+               Pen &= Mask;
+               Mask = ~Mask;
+               oldstart = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
+               {
+                   uae_u8 *start = oldstart;
+                   uae_u8 *end = start + Height * ri.BytesPerRow;
+                   for (; start != end; start += ri.BytesPerRow) 
+                   {
+                       uae_u8 *p = start;
+                       unsigned long cols;
+                       for (cols = 0; cols < Width; cols++) 
+                       {
+                           uae_u32 tmpval = do_get_mem_byte (p + cols) & Mask;
+                           do_put_mem_byte (p + cols, (uae_u8)(Pen | tmpval));
+                       }
+                   }
+               }
+               if (vsyncgfxwrite == 0) {
+                   if (renderinfo_is_current_screen (&ri))
+                       do_blit(&ri, Bpp, X, Y, X, Y, Width, Height, BLIT_SRC, 0);
+               }
+               result = 1;
+           }
+       }
+    }
+    return result;
+}
+
+/*
+* BlitRect() is a generic (any chunky pixel format) rectangle copier
+* NOTE: If dstri is NULL, then we're only dealing with one RenderInfo area, and called from picasso_BlitRect()
+*
+* OpCodes:
+* 0 = FALSE:   dst = 0
+* 1 = NOR:     dst = ~(src | dst)
+* 2 = ONLYDST: dst = dst & ~src
+* 3 = NOTSRC:  dst = ~src
+* 4 = ONLYSRC: dst = src & ~dst
+* 5 = NOTDST:  dst = ~dst
+* 6 = EOR:     dst = src^dst
+* 7 = NAND:    dst = ~(src & dst)
+* 8 = AND:     dst = (src & dst)
+* 9 = NEOR:    dst = ~(src ^ dst)
+*10 = DST:     dst = dst
+*11 = NOTONLYSRC: dst = ~src | dst
+*12 = SRC:     dst = src
+*13 = NOTONLYDST: dst = ~dst | src
+*14 = OR:      dst = src | dst
+*15 = TRUE:    dst = 0xFF
+*/
+struct blitdata
+{
+    struct RenderInfo ri_struct;
+    struct RenderInfo dstri_struct;
+    struct RenderInfo *ri; /* Self-referencing pointers */
+    struct RenderInfo *dstri;
+    unsigned long srcx;
+    unsigned long srcy;
+    unsigned long dstx;
+    unsigned long dsty;
+    unsigned long width;
+    unsigned long height;
+    uae_u8 mask;
+    BLIT_OPCODE opcode;
+} blitrectdata;
+
+static int BlitRectHelper(void)
+{
+    struct RenderInfo *ri = blitrectdata.ri;
+    struct RenderInfo *dstri = blitrectdata.dstri;
+    unsigned long srcx = blitrectdata.srcx;
+    unsigned long srcy = blitrectdata.srcy;
+    unsigned long dstx = blitrectdata.dstx;
+    unsigned long dsty = blitrectdata.dsty;
+    unsigned long width = blitrectdata.width;
+    unsigned long height = blitrectdata.height;
+    uae_u8 mask = blitrectdata.mask;
+    BLIT_OPCODE opcode = blitrectdata.opcode;
+    
+    uae_u8 Bpp = GetBytesPerPixel(ri->RGBFormat);
+    int can_do_visible_blit = 0;
+
+    if(opcode == BLIT_DST)
+    {
+       write_log("WARNING: BlitRect() being called with opcode of BLIT_DST\n");
+       return 1;
+    }
+    
+    /*
+    * If we have no destination RenderInfo, then we're dealing with a single-buffer action, called
+    * from picasso_BlitRect().  The code in do_blitrect_frame_buffer() deals with the frame-buffer,
+    * while the do_blit() code deals with the visible screen.
+    *
+    * If we have a destination RenderInfo, then we've been called from picasso_BlitRectNoMaskComplete()
+    * and we need to put the results on the screen from the frame-buffer.
+    */
+    if (dstri == NULL || dstri->Memory == ri->Memory)
+    {
+       if(mask != 0xFF && Bpp > 1) 
+           mask = 0xFF;
+       dstri = ri;
+       can_do_visible_blit = 1;
+    }
+    
+    /* Do our virtual frame-buffer memory first */
+    do_blitrect_frame_buffer(ri, dstri, srcx, srcy, dstx, dsty, width, height, mask, opcode);
+    /* Now we do the on-screen display, if renderinfo points to it */
+    if (vsyncgfxwrite == 1)
+       return 1;
+    if (renderinfo_is_current_screen (dstri))
+    {
+       if (mask == 0xFF || Bpp > 1) {
+           if(can_do_visible_blit)
+               do_blit(dstri, Bpp, srcx, srcy, dstx, dsty, width, height, opcode, 1);
+           else
+               do_blit(dstri, Bpp, dstx, dsty, dstx, dsty, width, height, opcode, 0);
+       } else {
+           do_blit(dstri, Bpp, dstx, dsty, dstx, dsty, width, height, opcode, 0);
+       }
+       P96TRACE(("Did do_blit 1 in BlitRect()\n"));
+    }
+    else
+    {
+       P96TRACE(("Did not do_blit 1 in BlitRect()\n"));
+    }
+
+    return 1;
+}
+
+static int BlitRect (uaecptr ri, uaecptr dstri,
+               unsigned long srcx, unsigned long srcy, unsigned long dstx, unsigned long dsty,
+               unsigned long width, unsigned long height, uae_u8 mask, BLIT_OPCODE opcode)
+{
+    /* Set up the params */
+    CopyRenderInfoStructureA2U(ri, &blitrectdata.ri_struct);
+    blitrectdata.ri = &blitrectdata.ri_struct;
+    if(dstri) {
+       CopyRenderInfoStructureA2U(dstri, &blitrectdata.dstri_struct);
+       blitrectdata.dstri = &blitrectdata.dstri_struct;
+    } else {
+       blitrectdata.dstri = NULL;
+    }
+    blitrectdata.srcx = srcx;
+    blitrectdata.srcy = srcy;
+    blitrectdata.dstx = dstx;
+    blitrectdata.dsty = dsty;
+    blitrectdata.width = width;
+    blitrectdata.height = height;
+    blitrectdata.mask = mask;
+    blitrectdata.opcode = opcode;
+    
+    return BlitRectHelper();
+}
+
+/***********************************************************
+BlitRect:
+***********************************************************
+* a0:  struct BoardInfo
+* a1:  struct RenderInfo
+* d0:  WORD SrcX
+* d1:  WORD SrcY
+* d2:  WORD DstX
+* d3:  WORD DstY
+* d4:  WORD Width
+* d5:  WORD Height
+* d6:  UBYTE Mask
+* d7:  uae_u32 RGBFormat
+***********************************************************/
+uae_u32 REGPARAM2 picasso_BlitRect (struct regstruct *regs)
+{
+    uaecptr renderinfo = m68k_areg (regs, 1);
+    unsigned long srcx = (uae_u16)m68k_dreg (regs, 0);
+    unsigned long srcy = (uae_u16)m68k_dreg (regs, 1);
+    unsigned long dstx = (uae_u16)m68k_dreg (regs, 2);
+    unsigned long dsty = (uae_u16)m68k_dreg (regs, 3);
+    unsigned long width = (uae_u16)m68k_dreg (regs, 4);
+    unsigned long height = (uae_u16)m68k_dreg (regs, 5);
+    uae_u8 Mask = (uae_u8)m68k_dreg (regs, 6);
+    uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+    flushpixels();
+#endif
+#ifdef NOBLIT
+    return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+    wgfx_flushline ();    
+#endif
+    P96TRACE(("BlitRect(%d, %d, %d, %d, %d, %d, 0x%x)\n", srcx, srcy, dstx, dsty, width, height, Mask));
+    result = BlitRect(renderinfo, 0, srcx, srcy, dstx, dsty, width, height, Mask, BLIT_SRC);
+
+    return result;
+}
+
+/***********************************************************
+BlitRectNoMaskComplete:
+***********************************************************
+* a0:  struct BoardInfo
+* a1:  struct RenderInfo (src)
+* a2:  struct RenderInfo (dst)
+* d0:  WORD SrcX
+* d1:  WORD SrcY
+* d2:  WORD DstX
+* d3:  WORD DstY
+* d4:  WORD Width
+* d5:  WORD Height
+* d6:  UBYTE OpCode
+* d7:  uae_u32 RGBFormat
+* NOTE:        MUST return 0 in D0 if we're not handling this operation
+*      because the RGBFormat or opcode aren't supported.
+*      OTHERWISE return 1
+***********************************************************/
+uae_u32 REGPARAM2 picasso_BlitRectNoMaskComplete (struct regstruct *regs)
+{
+    uaecptr srcri = m68k_areg (regs, 1);
+    uaecptr dstri = m68k_areg (regs, 2);
+    unsigned long srcx = (uae_u16)m68k_dreg (regs, 0);
+    unsigned long srcy = (uae_u16)m68k_dreg (regs, 1);
+    unsigned long dstx = (uae_u16)m68k_dreg (regs, 2);
+    unsigned long dsty = (uae_u16)m68k_dreg (regs, 3);
+    unsigned long width = (uae_u16)m68k_dreg (regs, 4);
+    unsigned long height = (uae_u16)m68k_dreg (regs, 5);
+    uae_u8 OpCode = m68k_dreg (regs, 6);
+    uae_u32 RGBFmt = m68k_dreg (regs, 7);
+    uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+    flushpixels();
+#endif
+#ifdef NOBLIT
+    return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+    wgfx_flushline ();   
+#endif
+
+    P96TRACE(("BlitRectNoMaskComplete() op 0x%2x, xy(%4d,%4d) --> xy(%4d,%4d), wh(%4d,%4d)\n",
+       OpCode, srcx, srcy, dstx, dsty, width, height));
+    
+    result = BlitRect(srcri, dstri, srcx, srcy, dstx, dsty, width, height, 0xFF, OpCode);
+
+    return result;
+}
+
+/* This utility function is used both by BlitTemplate() and BlitPattern() */
+STATIC_INLINE void PixelWrite1(uae_u8 *mem, int bits, uae_u32 fgpen, uae_u32 mask)
+{
+    if (mask != 0xFF)
+       fgpen = (fgpen & mask) | (do_get_mem_byte (mem + bits) & ~mask);
+    do_put_mem_byte (mem + bits, fgpen);
+}
+
+STATIC_INLINE void PixelWrite2(uae_u8 *mem, int bits, uae_u32 fgpen)
+{
+    do_put_mem_word (((uae_u16 *)mem) + bits, fgpen);
+}
+
+STATIC_INLINE void PixelWrite3(uae_u8 *mem, int bits, uae_u32 fgpen)
+{
+    do_put_mem_byte (mem + bits * 3, fgpen & 0x000000FF);
+    *(uae_u16 *)(mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
+}
+
+STATIC_INLINE void PixelWrite4(uae_u8 *mem, int bits, uae_u32 fgpen)
+{
+    do_put_mem_long (((uae_u32 *)mem) + bits, fgpen);
+}
+
+STATIC_INLINE void PixelWrite(uae_u8 *mem, int bits, uae_u32 fgpen, uae_u8 Bpp, uae_u32 mask)
+{
+    switch (Bpp) {
+    case 1:
+       if (mask != 0xFF)
+           fgpen = (fgpen & mask) | (do_get_mem_byte (mem + bits) & ~mask);
+       do_put_mem_byte (mem + bits, (uae_u8)fgpen);
+       break;
+    case 2:
+       do_put_mem_word (((uae_u16 *)mem) + bits, (uae_u16)fgpen);
+       break;
+    case 3:
+       do_put_mem_byte (mem + bits * 3, (uae_u8)fgpen);
+       *(uae_u16 *)(mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
+       break;
+    case 4:
+       do_put_mem_long (((uae_u32 *)mem) + bits, fgpen);
+       break;
+    }
+}
+
+/*
+* BlitPattern:
+* 
+* Synopsis:BlitPattern(bi, ri, pattern, X, Y, Width, Height, Mask, RGBFormat);
+* Inputs:
+* a0:struct BoardInfo *bi
+* a1:struct RenderInfo *ri
+* a2:struct Pattern *pattern
+* d0.w:X
+* d1.w:Y
+* d2.w:Width
+* d3.w:Height
+* d4.w:Mask
+* d7.l:RGBFormat
+* 
+* This function is used to paint a pattern on the board memory using the blitter. It is called by
+* BltPattern, if a AreaPtrn is used with positive AreaPtSz. The pattern consists of a b/w image
+* using a single plane of image data which will be expanded repeatedly to the destination RGBFormat
+* using ForeGround and BackGround pens as well as draw modes. The width of the pattern data is
+* always 16 pixels (one word) and the height is calculated as 2^Size. The data must be shifted up
+* and to the left by XOffset and YOffset pixels at the beginning.
+*/
+uae_u32 REGPARAM2 picasso_BlitPattern (struct regstruct *regs)
+{
+    uaecptr rinf = m68k_areg (regs, 1);
+    uaecptr pinf = m68k_areg (regs, 2);
+    unsigned long X = (uae_u16)m68k_dreg (regs, 0);
+    unsigned long Y = (uae_u16)m68k_dreg (regs, 1);
+    unsigned long W = (uae_u16)m68k_dreg (regs, 2);
+    unsigned long H = (uae_u16)m68k_dreg (regs, 3);
+    uae_u8 Mask = (uae_u8)m68k_dreg (regs, 4);
+    uae_u32 RGBFmt = m68k_dreg (regs, 7);
+    uae_u8 Bpp = GetBytesPerPixel (RGBFmt);
+    int inversion = 0;
+    struct RenderInfo ri;
+    struct Pattern pattern;
+    unsigned long rows;
+    uae_u32 fgpen;
+    uae_u8 *uae_mem;
+    int xshift;
+    unsigned long ysize_mask;
+    uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+    flushpixels();
+#endif
+#ifdef NOBLIT
+    return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+    wgfx_flushline ();
+#endif
+    
+    if(CopyRenderInfoStructureA2U (rinf, &ri) && CopyPatternStructureA2U (pinf, &pattern))
+    {
+       Bpp = GetBytesPerPixel(ri.RGBFormat);
+       uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp; /* offset with address */
+    
+       if (pattern.DrawMode & INVERS)
+           inversion = 1;
+    
+       pattern.DrawMode &= 0x03;
+       if (Mask != 0xFF) 
+       {
+           if(Bpp > 1)
+               Mask = 0xFF;
+
+           if(pattern.DrawMode == COMP)
+           {
+               write_log ("WARNING - BlitPattern() has unhandled mask 0x%x with COMP DrawMode. Using fall-back routine.\n", Mask);
+           }
+           else
+           {
+               result = 1;
+           }
+       }
+       else
+       {
+           result = 1;
+       }
+
+       if(result)
+       {
+           /* write_log ("BlitPattern() xy(%d,%d), wh(%d,%d) draw 0x%x, off(%d,%d), ph %d\n",
+           X, Y, W, H, pattern.DrawMode, pattern.XOffset, pattern.YOffset, 1 << pattern.Size); */
+    #ifdef P96TRACING_ENABLED
+           DumpPattern(&pattern);
+    #endif
+           ysize_mask = (1 << pattern.Size) - 1;
+           xshift = pattern.XOffset & 15;
+    
+           for (rows = 0; rows < H; rows++, uae_mem += ri.BytesPerRow) {
+               unsigned long prow = (rows + pattern.YOffset) & ysize_mask;
+               unsigned int d = do_get_mem_word (((uae_u16 *)pattern.Memory) + prow);
+               uae_u8 *uae_mem2 = uae_mem;
+               unsigned long cols;
+               
+               if (xshift != 0)
+                   d = (d << xshift) | (d >> (16 - xshift));
+               
+               for (cols = 0; cols < W; cols += 16, uae_mem2 += Bpp << 4) 
+               {
+                   long bits;
+                   long max = W - cols;
+                   unsigned int data = d;
+                   
+                   if (max > 16)
+                       max = 16;
+                   
+                   for (bits = 0; bits < max; bits++) 
+                   {
+                       int bit_set = data & 0x8000;
+                       data <<= 1;
+                       switch (pattern.DrawMode) {
+                       case JAM1:
+                           if (inversion)
+                               bit_set = !bit_set;
+                           if (bit_set)
+                               PixelWrite (uae_mem2, bits, pattern.FgPen, Bpp, Mask);
+                           break;
+                       case JAM2:
+                           if (inversion)
+                               bit_set = !bit_set;
+                           if (bit_set)
+                               PixelWrite (uae_mem2, bits, pattern.FgPen, Bpp, Mask);
+                           else
+                               PixelWrite (uae_mem2, bits, pattern.BgPen, Bpp, Mask);
+                           break;
+                       case COMP:
+                           if (bit_set) {
+                               fgpen = pattern.FgPen;
+                               
+                               switch (Bpp) {
+                               case 1:
+                                   {
+                                       uae_u8 *addr = uae_mem2 + bits;
+                                       do_put_mem_byte (addr, (uae_u8)(do_get_mem_byte (addr) ^ fgpen));
+                                   }
+                                   break;
+                               case 2:
+                                   {
+                                       uae_u16 *addr = ((uae_u16 *)uae_mem2) + bits;
+                                       do_put_mem_word (addr, (uae_u16)( do_get_mem_word (addr) ^ fgpen));
+                                   }
+                                   break;
+                               case 3:
+                                   {
+                                       uae_u32 *addr = (uae_u32 *)(uae_mem2 + bits * 3);
+                                       do_put_mem_long (addr, do_get_mem_long (addr) ^ (fgpen & 0x00FFFFFF));
+                                   }
+                                   break;
+                               case 4:
+                                   {
+                                       uae_u32 *addr = ((uae_u32 *)uae_mem2) + bits;
+                                       do_put_mem_long (addr, do_get_mem_long (addr) ^ fgpen);
+                                   }
+                                   break;
+                               }
+                           }
+                           break;
+                       }
+                   }
+               }
+           }
+           #ifdef PIXEL_LOCK
+           flushpixels();
+           #endif
+
+           /* If we need to update a second-buffer (extra_mem is set), then do it only if visible! */
+           if (picasso_vidinfo.extra_mem && renderinfo_is_current_screen (&ri)) {
+               if (vsyncgfxwrite==0)
+                   do_blit(&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0);
+           }
+           result = 1;
+       }
+    }
+
+    return result;
+}
+
+/*************************************************
+BlitTemplate:
+**************************************************
+* Synopsis: BlitTemplate(bi, ri, template, X, Y, Width, Height, Mask, RGBFormat);
+* a0: struct BoardInfo *bi
+* a1: struct RenderInfo *ri
+* a2: struct Template *template
+* d0.w: X
+* d1.w: Y
+* d2.w: Width
+* d3.w: Height
+* d4.w: Mask
+* d7.l: RGBFormat
+*
+* This function is used to paint a template on the board memory using the blitter.
+* It is called by BltPattern and BltTemplate. The template consists of a b/w image
+* using a single plane of image data which will be expanded to the destination RGBFormat
+* using ForeGround and BackGround pens as well as draw modes.
+***********************************************************************************/
+uae_u32 REGPARAM2 picasso_BlitTemplate (struct regstruct *regs)
+{
+    uae_u8 inversion = 0;
+    uaecptr rinf = m68k_areg (regs, 1);
+    uaecptr tmpl = m68k_areg (regs, 2);
+    unsigned long X = (uae_u16)m68k_dreg (regs, 0);
+    unsigned long Y = (uae_u16)m68k_dreg (regs, 1);
+    unsigned long W = (uae_u16)m68k_dreg (regs, 2);
+    unsigned long H = (uae_u16)m68k_dreg (regs, 3);
+    uae_u16 Mask = (uae_u16)m68k_dreg (regs, 4);
+    struct Template tmp;
+    struct RenderInfo ri;
+    unsigned long rows;
+    int bitoffset;
+    uae_u32 fgpen;
+    uae_u8 *uae_mem, Bpp;
+    uae_u8 *tmpl_base;
+    uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+    flushpixels();
+#endif
+#ifdef NOBLIT
+    return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+    wgfx_flushline ();
+#endif
+    
+    if (CopyRenderInfoStructureA2U (rinf, &ri) && CopyTemplateStructureA2U (tmpl, &tmp))
+    {
+       Bpp = GetBytesPerPixel(ri.RGBFormat);
+       uae_mem = ri.Memory + Y*ri.BytesPerRow + X*Bpp; /* offset into address */
+    
+       if (tmp.DrawMode & INVERS)
+           inversion = 1;
+    
+       tmp.DrawMode &= 0x03;
+
+       if (Mask != 0xFF) 
+       {
+           if(Bpp > 1)
+               Mask = 0xFF;
+
+           if(tmp.DrawMode == COMP)
+           {
+               write_log ("WARNING - BlitTemplate() has unhandled mask 0x%x with COMP DrawMode. Using fall-back routine.\n", Mask);
+               flushpixels();  //only need in the windows Version
+               return 0;
+           }
+           else
+           {
+               result = 1;
+           }
+       }
+       else
+       {
+           result = 1;
+       }
+#if 1
+       if (tmp.DrawMode == COMP) {
+           /* workaround, let native blitter handle COMP mode */
+           flushpixels();
+           return 0;
+       }
+#endif
+       if(result)
+       {
+           P96TRACE(("BlitTemplate() xy(%d,%d), wh(%d,%d) draw 0x%x fg 0x%x bg 0x%x \n",
+               X, Y, W, H, tmp.DrawMode, tmp.FgPen, tmp.BgPen));
+    
+           bitoffset = tmp.XOffset % 8;
+    
+#if defined(P96TRACING_ENABLED) && (P96TRACING_LEVEL > 0)
+           DumpTemplate(&tmp, W, H);
+#endif
+    
+           tmpl_base = tmp.Memory + tmp.XOffset / 8;
+           
+           for (rows = 0; rows < H; rows++, uae_mem += ri.BytesPerRow, tmpl_base += tmp.BytesPerRow) {
+               unsigned long cols;
+               uae_u8 *tmpl_mem = tmpl_base;
+               uae_u8 *uae_mem2 = uae_mem;
+               unsigned int data = *tmpl_mem;
+               
+               for (cols = 0; cols < W; cols += 8, uae_mem2 += Bpp << 3) {
+                   unsigned int byte;
+                   long bits;
+                   long max = W - cols;
+                   
+                   if (max > 8)
+                       max = 8;
+                   
+                   data <<= 8;
+                   data |= *++tmpl_mem;
+                   
+                   byte = data >> (8 - bitoffset);
+                   
+                   for (bits = 0; bits < max; bits++) {
+                       int bit_set = (byte & 0x80);
+                       byte <<= 1;
+                       switch (tmp.DrawMode) {
+                       case JAM1:
+                           if (inversion)
+                               bit_set = !bit_set;
+                           if (bit_set) {
+                               fgpen = tmp.FgPen;
+                               PixelWrite(uae_mem2, bits, fgpen, Bpp, Mask);
+                           }
+                           break;
+                       case JAM2:
+                           if (inversion)
+                               bit_set = !bit_set;
+                           fgpen = tmp.BgPen;
+                           if (bit_set)
+                               fgpen = tmp.FgPen;
+                           
+                           PixelWrite(uae_mem2, bits, fgpen, Bpp, Mask);
+                           break;
+                       case COMP:
+                           if (bit_set) {
+                               fgpen = tmp.FgPen;
+                               
+                               switch (Bpp) {
+                               case 1:
+                                   {
+                                       uae_u8 *addr = uae_mem2 + bits;
+                                       do_put_mem_byte (addr, (uae_u8)(do_get_mem_byte (addr) ^ fgpen));
+                                   }
+                                   break;
+                               case 2:
+                                   {
+                                       uae_u16 *addr = ((uae_u16 *)uae_mem2) + bits;
+                                       do_put_mem_word (addr, (uae_u16)(do_get_mem_word (addr) ^ fgpen));
+                                   }
+                                   break;
+                               case 3:
+                                   {
+                                       uae_u32 *addr = (uae_u32 *)(uae_mem2 + bits * 3);
+                                       do_put_mem_long (addr, do_get_mem_long (addr) ^ (fgpen & 0x00FFFFFF));
+                                   }
+                                   break;
+                               case 4:
+                                   {
+                                       uae_u32 *addr = ((uae_u32 *)uae_mem2) + bits;
+                                       do_put_mem_long (addr, do_get_mem_long (addr) ^ fgpen);
+                                   }
+                                   break;
+                               }
+                           }
+                           break;
+                       }
+                   }
+               }
+           }
+           
+           #ifdef PIXEL_LOCK
+           flushpixels();
+           #endif
+           /* If we need to update a second-buffer (extra_mem is set), then do it only if visible! */
+           if(picasso_vidinfo.extra_mem && renderinfo_is_current_screen(&ri)) {
+               if (vsyncgfxwrite == 0)
+                   do_blit(&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0);
+           }
+           result = 1;
+       }
+}    
+    return 1;
+}
+
+/*
+* CalculateBytesPerRow:
+* a0:  struct BoardInfo
+* d0:  uae_u16 Width
+* d7:  RGBFTYPE RGBFormat
+* This function calculates the amount of bytes needed for a line of
+* "Width" pixels in the given RGBFormat.
+*/
+uae_u32 REGPARAM2 picasso_CalculateBytesPerRow (struct regstruct *regs)
+{
+    uae_u16 width = m68k_dreg (regs, 0);
+    uae_u32 type = m68k_dreg (regs, 7);
+    
+    width = GetBytesPerPixel(type) * width;
+    P96TRACE(("CalculateBytesPerRow() = %d\n",width));
+    
+    return width;
+}
+
+/*
+* SetDisplay:
+* a0: struct BoardInfo
+* d0: BOOL state
+* This function enables and disables the video display.
+* 
+* NOTE: return the opposite of the state
+*/
+uae_u32 REGPARAM2 picasso_SetDisplay (struct regstruct *regs)
+{
+    uae_u32 state = m68k_dreg (regs, 0);
+    P96TRACE (("SetDisplay(%d)\n", state));
+    return !state;
+}
+
+void picasso_handle_hsync (void)
+{
+    static int p96hsync;
+    
+    if (currprefs.gfxmem_size == 0)
+       return;
+    if (WIN32GFX_IsPicassoScreen () && currprefs.gfx_pfullscreen && currprefs.gfx_vsync) {
+       if (DirectDraw_GetVerticalBlankStatus ())
+           p96hsync = 0;
+    } else {
+       p96hsync--;
+    }
+    if (p96hsync <= 0) {
+       rtarea[get_long (RTAREA_BASE + 36) + 12 - 1]++;
+       p96hsync = p96syncrate;
+    }
+}
+
+void init_hz_p96 (void)
+{
+    int rate;
+    p96syncrate = maxvpos * vblank_hz;
+    if (isfullscreen ())
+       rate = DirectDraw_CurrentRefreshRate ();
+    else
+       rate = abs (currprefs.gfx_refreshrate);
+    if (rate <= 0)
+       rate = 60;
+    p96syncrate /= rate;
+}
+
+/* NOTE: Watch for those planeptrs of 0x00000000 and 0xFFFFFFFF for all zero / all one bitmaps !!!! */
+static void PlanarToChunky(struct RenderInfo *ri, struct BitMap *bm,
+                          unsigned long srcx, unsigned long srcy,
+                          unsigned long dstx, unsigned long dsty,
+                          unsigned long width, unsigned long height,
+                          uae_u8 mask)
+{
+    int j;
+    
+    uae_u8 *PLANAR[8], *image = ri->Memory + dstx * GetBytesPerPixel (ri->RGBFormat) + dsty * ri->BytesPerRow;
+    int Depth = bm->Depth;
+    unsigned long rows, bitoffset = srcx & 7;
+    long eol_offset;
+    
+    /* if (mask != 0xFF) 
+    write_log ("P2C - pixel-width = %d, bit-offset = %d\n", width, bitoffset); */
+    
+    /* Set up our bm->Planes[] pointers to the right horizontal offset */
+    for (j = 0; j < Depth; j++) {
+       uae_u8 *p = bm->Planes[j];
+       if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
+           p += srcx / 8 + srcy * bm->BytesPerRow;
+       PLANAR[j] = p;
+       if ((mask & (1 << j)) == 0)
+           PLANAR[j] = &all_zeros_bitmap;
+    }
+    eol_offset = (long)bm->BytesPerRow - (long)((width + 7) >> 3);
+    for (rows = 0; rows < height; rows++, image += ri->BytesPerRow) {
+       unsigned long cols;
+       
+       for (cols = 0; cols < width; cols += 8) {
+           int k;
+           uae_u32 a = 0, b = 0;
+           unsigned int msk = 0xFF;
+           long tmp = cols + 8 - width;
+           if (tmp > 0) {
+               msk <<= tmp;
+               b = do_get_mem_long ((uae_u32 *)(image + cols + 4));
+               if (tmp < 4)
+                   b &= 0xFFFFFFFF >> (32 - tmp * 8);
+               else if (tmp > 4) {
+                   a = do_get_mem_long ((uae_u32 *)(image + cols));
+                   a &= 0xFFFFFFFF >> (64 - tmp * 8);
+               }
+           }
+           for (k = 0; k < Depth; k++) {
+               unsigned int data;
+               if (PLANAR[k] == &all_zeros_bitmap)
+                   data = 0;
+               else if (PLANAR[k] == &all_ones_bitmap)
+                   data = 0xFF;
+               else {
+                   data = (uae_u8)(do_get_mem_word ((uae_u16 *)PLANAR[k]) >> (8 - bitoffset));
+                   PLANAR[k]++;
+               }
+               data &= msk;
+               a |= p2ctab[data][0] << k;
+               b |= p2ctab[data][1] << k;
+           }
+           do_put_mem_long ((uae_u32 *)(image + cols), a);
+           do_put_mem_long ((uae_u32 *)(image + cols + 4), b);
+       }
+       for (j = 0; j < Depth; j++) {
+           if (PLANAR[j] != &all_zeros_bitmap && PLANAR[j] != &all_ones_bitmap) {
+               PLANAR[j] += eol_offset;
+           }
+       }
+    }
+}
+
+/*
+* BlitPlanar2Chunky:
+* a0: struct BoardInfo *bi
+* a1: struct BitMap *bm - source containing planar information and assorted details
+* a2: struct RenderInfo *ri - dest area and its details
+* d0.w: SrcX
+* d1.w: SrcY
+* d2.w: DstX
+* d3.w: DstY
+* d4.w: SizeX
+* d5.w: SizeY
+* d6.b: MinTerm - uh oh!
+* d7.b: Mask - uh oh!
+*
+* This function is currently used to blit from planar bitmaps within system memory to chunky bitmaps
+* on the board. Watch out for plane pointers that are 0x00000000 (represents a plane with all bits "0")
+* or 0xffffffff (represents a plane with all bits "1").
+*/
+uae_u32 REGPARAM2 picasso_BlitPlanar2Chunky (struct regstruct *regs)
+{
+    uaecptr bm = m68k_areg (regs, 1);
+    uaecptr ri = m68k_areg (regs, 2);
+    unsigned long srcx = (uae_u16)m68k_dreg (regs, 0);
+    unsigned long srcy = (uae_u16)m68k_dreg (regs, 1);
+    unsigned long dstx = (uae_u16)m68k_dreg (regs, 2);
+    unsigned long dsty = (uae_u16)m68k_dreg (regs, 3);
+    unsigned long width = (uae_u16)m68k_dreg (regs, 4);
+    unsigned long height = (uae_u16)m68k_dreg (regs, 5);
+    uae_u8 minterm = m68k_dreg (regs, 6) & 0xFF;
+    uae_u8 mask = m68k_dreg (regs, 7) & 0xFF;
+    struct RenderInfo local_ri;
+    struct BitMap local_bm;
+    uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+    flushpixels();
+#endif
+#ifdef NOBLIT
+    return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+    wgfx_flushline ();
+#endif
+
+    if (minterm != 0x0C) {
+       write_log ("ERROR - BlitPlanar2Chunky() has minterm 0x%x, which I don't handle. Using fall-back routine.\n",
+           minterm);
+    }
+    else if(CopyRenderInfoStructureA2U (ri, &local_ri) && 
+            CopyBitMapStructureA2U (bm, &local_bm))
+    {
+       P96TRACE(("BlitPlanar2Chunky(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n",
+           srcx, srcy, dstx, dsty, width, height, minterm, mask, local_bm.Depth));
+       P96TRACE(("P2C - BitMap has %d BPR, %d rows\n", local_bm.BytesPerRow, local_bm.Rows));
+       PlanarToChunky (&local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, mask);
+       if (renderinfo_is_current_screen (&local_ri))
+       {
+           if (!vsyncgfxwrite)
+               do_blit(&local_ri, GetBytesPerPixel(local_ri.RGBFormat), dstx, dsty, dstx, dsty, width, height, BLIT_SRC, 0);
+       }
+       result = 1;
+    }
+
+    return result;
+}
+
+/* NOTE: Watch for those planeptrs of 0x00000000 and 0xFFFFFFFF for all zero / all one bitmaps !!!! */
+static void PlanarToDirect(struct RenderInfo *ri, struct BitMap *bm,
+                          unsigned long srcx, unsigned long srcy,
+                          unsigned long dstx, unsigned long dsty,
+                          unsigned long width, unsigned long height, uae_u8 mask,
+                          struct ColorIndexMapping *cim)
+{
+    int j;
+    int bpp = GetBytesPerPixel(ri->RGBFormat);
+    uae_u8 *PLANAR[8];
+    uae_u8 *image = ri->Memory + dstx * bpp + dsty * ri->BytesPerRow;
+    int Depth = bm->Depth;
+    unsigned long rows;
+    long eol_offset;
+    
+    if(!bpp)
+       return;
+    
+    /* Set up our bm->Planes[] pointers to the right horizontal offset */
+    for (j = 0; j < Depth; j++) {
+       uae_u8 *p = bm->Planes[j];
+       if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
+           p += srcx / 8 + srcy * bm->BytesPerRow;
+       PLANAR[j] = p;
+       if ((mask & (1 << j)) == 0)
+           PLANAR[j] = &all_zeros_bitmap;
+    }
+    
+    eol_offset = (long)bm->BytesPerRow - (long)((width + (srcx & 7)) >> 3);
+    for (rows = 0; rows < height; rows++, image += ri->BytesPerRow) {
+       unsigned long cols;
+       uae_u8 *image2 = image;
+       unsigned int bitoffs = 7 - (srcx & 7);
+       int i;
+       
+       for (cols = 0; cols < width; cols ++) {
+           int v = 0, k;
+           for (k = 0; k < Depth; k++) {
+               if (PLANAR[k] == &all_ones_bitmap)
+                   v |= 1 << k;
+               else if (PLANAR[k] != &all_zeros_bitmap) {
+                   v |= ((*PLANAR[k] >> bitoffs) & 1) << k;
+               }
+           }
+           
+           switch (bpp) {
+           case 2:
+               do_put_mem_word ((uae_u16 *)image2, (uae_u16)(cim->Colors[v]));
+               image2 += 2;
+               break;
+           case 3:
+               do_put_mem_byte (image2++, (uae_u8)cim->Colors[v]);
+               do_put_mem_word ((uae_u16 *)image2, (uae_u16)((cim->Colors[v] & 0x00FFFF00) >> 8));
+               image2 += 2;
+               break;
+           case 4:
+               do_put_mem_long ((uae_u32 *)image2, cim->Colors[v]);
+               image2 += 4;
+               break;
+           }
+           bitoffs--;
+           bitoffs &= 7;
+           if (bitoffs == 7) {
+               int k;
+               for (k = 0; k < Depth; k++) {
+                   if (PLANAR[k] != &all_zeros_bitmap && PLANAR[k] != &all_ones_bitmap) {
+                       PLANAR[k]++;
+                   }
+               }
+           }
+       }
+       
+       for (i = 0; i < Depth; i++) {
+           if (PLANAR[i] != &all_zeros_bitmap && PLANAR[i] != &all_ones_bitmap) {
+               PLANAR[i] += eol_offset;
+           }
+       }
+    }
+}
+
+/*
+* BlitPlanar2Direct: 
+* 
+* Synopsis:
+* BlitPlanar2Direct(bi, bm, ri, cim, SrcX, SrcY, DstX, DstY, SizeX, SizeY, MinTerm, Mask);
+* Inputs:
+* a0:struct BoardInfo *bi
+* a1:struct BitMap *bm
+* a2:struct RenderInfo *ri
+* a3:struct ColorIndexMapping *cmi
+* d0.w:SrcX
+* d1.w:SrcY
+* d2.w:DstX
+* d3.w:DstY
+* d4.w:SizeX
+* d5.w:SizeY
+* d6.b:MinTerm
+* d7.b:Mask
+* 
+* This function is currently used to blit from planar bitmaps within system memory to direct color
+* bitmaps (15, 16, 24 or 32 bit) on the board. Watch out for plane pointers that are 0x00000000 (represents
+* a plane with all bits "0") or 0xffffffff (represents a plane with all bits "1"). The ColorIndexMapping is
+* used to map the color index of each pixel formed by the bits in the bitmap's planes to a direct color value
+* which is written to the destination RenderInfo. The color mask and all colors within the mapping are words,
+* triple bytes or longwords respectively similar to the color values used in FillRect(), BlitPattern() or
+* BlitTemplate(). 
+*/
+uae_u32 REGPARAM2 picasso_BlitPlanar2Direct (struct regstruct *regs)
+{
+    uaecptr bm = m68k_areg (regs, 1);
+    uaecptr ri = m68k_areg (regs, 2);
+    uaecptr cim = m68k_areg (regs, 3);
+    unsigned long srcx = (uae_u16)m68k_dreg (regs, 0);
+    unsigned long srcy = (uae_u16)m68k_dreg (regs, 1);
+    unsigned long dstx = (uae_u16)m68k_dreg (regs, 2);
+    unsigned long dsty = (uae_u16)m68k_dreg (regs, 3);
+    unsigned long width = (uae_u16)m68k_dreg (regs, 4);
+    unsigned long height = (uae_u16)m68k_dreg (regs, 5);
+    uae_u8 minterm = m68k_dreg (regs, 6);
+    uae_u8 Mask = m68k_dreg (regs, 7);
+    struct RenderInfo local_ri;
+    struct BitMap local_bm;
+    struct ColorIndexMapping local_cim;
+    uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+    flushpixels();
+#endif
+#ifdef NOBLIT
+    return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+    wgfx_flushline ();
+#endif
+    
+    if (minterm != 0x0C)
+    {
+       write_log ("WARNING - BlitPlanar2Direct() has unhandled op-code 0x%x. Using fall-back routine.\n",
+           minterm);
+    }
+    else if(CopyRenderInfoStructureA2U (ri, &local_ri) &&
+            CopyBitMapStructureA2U (bm, &local_bm))
+    {
+       Mask = 0xFF;
+       CopyColorIndexMappingA2U (cim, &local_cim);
+       P96TRACE(("BlitPlanar2Direct(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n",
+           srcx, srcy, dstx, dsty, width, height, minterm, Mask, local_bm.Depth));
+       PlanarToDirect (&local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, Mask, &local_cim);
+       #ifdef PIXEL_LOCK
+       flushpixels();
+       #endif
+       if (renderinfo_is_current_screen (&local_ri)) {
+           if (!vsyncgfxwrite)
+               do_blit(&local_ri, GetBytesPerPixel(local_ri.RGBFormat), dstx, dsty, dstx, dsty, width, height, BLIT_SRC, 0);
+       }
+       result = 1;
+    }
+
+    return result;
+}
+
+/* @@@ - Work to be done here!
+*
+* The address is the offset into our Picasso96 frame-buffer (pointed to by gfxmem_start)
+* where the value was put.
+*
+* Porting work: on some machines you may not need these functions, ie. if the memory for the
+* Picasso96 frame-buffer is directly viewable or directly blittable.  On Win32 with DirectX,
+* this is not the case.  So I provide some write-through functions (as per Mathias' orders!)
+*/
+#ifdef PIXEL_LOCK
+
+struct frect
+{
+    int top, left, right, bottom;
+    int first;
+};
+
+STATIC_INLINE init_refresh(struct frect *r)
+{
+    r->first = 1;
+    r->left = picasso96_state.Width * picasso96_state.BytesPerPixel;
+    r->top = picasso96_state.Height;
+    r->right = -1;
+    r->bottom = -1;
+}
+
+STATIC_INLINE flush_it(struct frect *r)
+{
+    if (r->right >= 0 && r->bottom >= 0) {
+       DX_Invalidate (r->left / picasso96_state.BytesPerPixel, r->top,
+           (r->right - r->left) / picasso96_state.BytesPerPixel + 1, (r->bottom - r->top) + 1);
+    }
+    init_refresh(r);
+}
+
+#define FLUSH_MIN 30
+STATIC_INLINE void flush_refresh(int x, int y, struct frect *r)
+{
+    if (x < r->left) {
+       if (!r->first && r->left - x > FLUSH_MIN) {
+           flush_it(r);
+           flush_refresh(x, y, r);
+           return;
+       }
+       r->left = x;
+    }
+    if (y < r->top) {
+       if (!r->first && r->top - y > FLUSH_MIN) {
+           flush_it(r);
+           flush_refresh(x, y, r);
+           return;
+       }
+       r->top = y;
+    }
+    if (x > r->right) {
+       if (!r->first && x - r->right > FLUSH_MIN) {
+           flush_it(r);
+           flush_refresh(x, y, r);
+           return;
+       }
+       r->right = x;
+    }
+    if (y > r->bottom) {
+       if (!r->first && y - r->bottom > FLUSH_MIN) {
+           flush_it(r);
+           flush_refresh(x, y, r);
+           return;
+       }
+       r->bottom = y;
+    }
+    r->first = 0;
+}
+
+static void flushpixels_2(void)
+{
+    int i;
+    uae_u8 *dst;
+    int lock = 0;
+    int needrefresh;
+    struct frect r;
+    
+    if (pixelcount == 0)
+       return;
+    if (!picasso_on) {
+       pixelcount = 0;
+       return;
+    }
+    needrefresh = DirectDraw_GetLockableType() == secondary_surface;
+
+    if(DirectDraw_IsLocked() == FALSE) {
+       dst = gfx_lock_picasso ();
+       lock = 1;
+    } else {
+       dst = picasso96_state.HostAddress;
+    }
+    if (!dst)
+       goto out;
+
+    init_refresh(&r);
+
+    if(picasso_vidinfo.rgbformat != picasso96_state.RGBFormat) {
+
+       int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
+       if (picasso96_state.RGBFormat != RGBFB_CHUNKY) {
+           write_log ("ERROR - flushpixels() has non RGBFB_CHUNKY mode!\n");
+           goto out;
+       }
+       for (i = 0; i < pixelcount; i++) { 
+           int i2 = pixelbase[i].size;
+           uaecptr addr = pixelbase[i].addr;
+           uae_u32 value = pixelbase[i].value; 
+           int y = addr / picasso96_state.BytesPerRow;
+           int xbytes = addr % picasso96_state.BytesPerRow;
+
+           if (! picasso_vidinfo.extra_mem)
+               break;
+                  
+           if (xbytes < picasso96_state.Width * picasso96_state.BytesPerPixel && y < picasso96_state.Height) { 
+               if(psiz == 4) {
+                   uae_u8 *addr;
+                          
+                   addr = dst + y * picasso_vidinfo.rowbytes + xbytes * 4;
+                   if (i2 == 4) {
+                       *(uae_u32 *) addr = picasso_vidinfo.clut[value & 0xff];
+                       addr += 4;
+                       *(uae_u32 *) addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+                       addr += 4;
+                       *(uae_u32 *) addr = picasso_vidinfo.clut[(value >> 16) & 0xff];
+                       addr += 4;
+                       *(uae_u32 *) addr = picasso_vidinfo.clut[(value >> 24) & 0xff];
+                       break;
+                   } else if (i2 == 2) {
+                       *(uae_u32 *) addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+                       addr += 4;
+                       *(uae_u32 *) addr = picasso_vidinfo.clut[value & 0xff];
+                       break;
+                   } else if (i2 == 1) {
+                       *(uae_u32 *) addr = picasso_vidinfo.clut[value & 0xff];
+                       break;
+                   }
+               } else {
+                   uae_u8 *addr;
+                          
+                   addr = dst + y * picasso_vidinfo.rowbytes + xbytes * 2;
+                   if (i2 == 4) {
+                       *(uae_u16 *) addr = picasso_vidinfo.clut[value & 0xff];
+                       addr += 2;
+                       *(uae_u16 *) addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+                       addr += 2;
+                       *(uae_u16 *) addr = picasso_vidinfo.clut[(value >> 16) & 0xff];
+                       addr += 2;
+                       *(uae_u16 *) addr = picasso_vidinfo.clut[(value >> 24) & 0xff];
+                       break;
+                   } else if (i2 == 2) {
+                       *(uae_u16 *) addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+                       addr+=2;
+                       *(uae_u16 *) addr = picasso_vidinfo.clut[value & 0xff];
+                       break;
+                   } else if (i2 == 1) {
+                       *(uae_u16 *) addr = picasso_vidinfo.clut[value & 0xff];
+                       break;
+                   }
+               }
+               if (needrefresh)
+                   flush_refresh(xbytes, y, &r);
+           }
+       }
+
+    } else {
+
+       for (i = 0;i < pixelcount; i++) { 
+           uaecptr addr = pixelbase[i].addr;
+           uae_u32 value = pixelbase[i].value;
+           int y = addr / picasso96_state.BytesPerRow;
+           int xbytes = addr % picasso96_state.BytesPerRow;
+           uae_u8 *p = dst + y * picasso_vidinfo.rowbytes + xbytes;
+    
+           if (! picasso_vidinfo.extra_mem)
+               continue;
+
+           if (xbytes < picasso96_state.Width * picasso96_state.BytesPerPixel && y < picasso96_state.Height) {         
+               switch (pixelbase[i].size)
+               {
+                   case 1:
+                   *(uae_u8 *)p = value;
+                   break;
+                   case 2:
+                   *(uae_u16 *)p = value;
+                   break;
+                   case 4:  
+                   *(uae_u32 *)p = value;
+                   break;
+               }
+               if (needrefresh)
+                   flush_refresh(xbytes, y, &r);
+           }
+       }
+    }
+out:;
+    if(lock)
+        gfx_unlock_picasso();
+    pixelcount = 0;
+    flush_it(&r);
+}
+
+
+static int watchbuffersize;
+static void **watchbuffer;
+static uae_u8 *secondarygfx;
+extern uae_u8 *natmem_offset;
+
+static void dowatch(void)
+{
+    uae_u8 *dst;
+    int lock = 0;
+    int needrefresh;
+    struct frect r;
+    ULONG pagesize;
+    ULONG_PTR cnt;
+    int i, j, total;
+
+    if (!secondarygfx) {
+       SYSTEM_INFO si;
+       GetSystemInfo(&si);
+       secondarygfx = xmalloc (allocated_gfxmem);
+       watchbuffersize = allocated_gfxmem / si.dwPageSize + 1;
+       watchbuffer = xmalloc (sizeof(void*) * watchbuffersize);
+    }
+
+    cnt = watchbuffersize;
+    if (GetWriteWatch(WRITE_WATCH_FLAG_RESET, gfxmemory, allocated_gfxmem, watchbuffer, &cnt, &pagesize)) {
+       write_log("GetWriteWatch failed, err=%d\n", GetLastError());
+       return;
+    }
+    if (cnt == 0)
+       return;
+
+    needrefresh = DirectDraw_GetLockableType() == secondary_surface;
+
+    if(DirectDraw_IsLocked() == FALSE) {
+       dst = gfx_lock_picasso ();
+       lock = 1;
+    } else {
+       dst = picasso96_state.HostAddress;
+    }
+    if (!dst)
+       goto out;
+
+    init_refresh(&r);
+
+    total = 0;
+    for (i = 0; i < cnt; i++) {
+       uae_u8 *p1 = watchbuffer[i];
+       uae_u8 *p2 = secondarygfx + (p1 - gfxmemory);
+       uaecptr addr = (uaecptr)(p1 - (p96ram_start + natmem_offset)); /* bleh.. */
+       int y, xbytes;
+       uae_u8 *p;
+       int tonextrow_p, tonextrow_addr;
+
+       if (addr >= picasso96_state.Extent)
+           continue;
+       addr -= (picasso96_state.XOffset * picasso96_state.BytesPerPixel)
+           + (picasso96_state.YOffset * picasso96_state.BytesPerRow);
+        y = addr / picasso96_state.BytesPerRow;
+       if (y >= picasso96_state.Height)
+           continue;
+        xbytes = addr % picasso96_state.BytesPerRow;
+        p = dst + y * picasso_vidinfo.rowbytes + xbytes;
+       tonextrow_p = picasso_vidinfo.rowbytes - xbytes;
+       tonextrow_addr = (picasso96_state.BytesPerRow - xbytes) / 4;
+
+       for (j = 0; j < pagesize / 4; j++) {
+           uae_u32 *pp1 = (uae_u32*)p1;
+           uae_u32 *pp2 = (uae_u32*)p2;
+           if (pp1[j] != pp2[j]) {
+               pp2[j] = pp1[j];
+               *(uae_u32*)p = pp1[j];
+               if (needrefresh)
+                   flush_refresh(xbytes, y, &r);
+               total++;
+           }
+           p += 4;
+           xbytes += 4;
+           if (xbytes >= picasso96_state.Width * picasso96_state.BytesPerPixel) {
+               xbytes -= picasso96_state.Width * picasso96_state.BytesPerPixel;
+               y++;
+               if (y >= picasso96_state.Height)
+                   break;
+               p += tonextrow_p;
+               j += tonextrow_addr;
+           }
+       }
+    }
+    write_log("%d ", total);
+out:;
+    if(lock)
+        gfx_unlock_picasso();
+    flush_it(&r);
+}
+
+
+static void flushpixels(void)
+{
+    flushpixels_2();
+    dowatch();
+}
+#endif
+
+static void write_gfx_x (uaecptr addr, uae_u32 value, int size)
+{
+    uaecptr oldaddr = addr;
+    int y;
+#ifdef LOCK_UNLOCK_MADNESS
+    int x, xbytes;
+    uae_u8 *dst;
+#endif
+
+    if (!picasso_on)
+       return;
+
+#ifdef PIXEL_LOCK
+    addr += gfxmem_start;
+    /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
+    if (addr >= picasso96_state.Address && addr + size < picasso96_state.Extent) {
+       addr -= picasso96_state.Address + (picasso96_state.XOffset * picasso96_state.BytesPerPixel)
+           + (picasso96_state.YOffset * picasso96_state.BytesPerRow);
+       if (pixelcount > MAXFLUSHPIXEL)
+           flushpixels_2();
+       pixelbase[pixelcount].addr = addr;
+       pixelbase[pixelcount].value = value;
+       pixelbase[pixelcount++].size = size;
+    }
+    return;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS   
+    /*
+     * Several writes to successive memory locations are a common access pattern.
+     * Try to optimize it.
+     */
+    if (addr >= wgfx_linestart && addr + size <= wgfx_lineend) {
+       if (addr < wgfx_min)
+           wgfx_min = addr;
+       if (addr + size > wgfx_max)
+           wgfx_max = addr + size;
+       return;
+    } else
+       wgfx_flushline ();
+#endif
+
+    addr += gfxmem_start;
+    /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
+    if (addr < picasso96_state.Address || addr + size >= picasso96_state.Extent)
+       return;
+    addr -= picasso96_state.Address + (picasso96_state.XOffset * picasso96_state.BytesPerPixel)
+       + (picasso96_state.YOffset * picasso96_state.BytesPerRow);
+    
+    y = addr / picasso96_state.BytesPerRow;
+    xbytes = addr % picasso96_state.BytesPerRow;
+    x = xbytes / picasso96_state.BytesPerPixel;
+   
+#ifdef LOCK_UNLOCK_MADNESS
+    if (! picasso_vidinfo.extra_mem) {
+       pixelcount = 0;
+       return;
+    }
+    
+    if (x < picasso96_state.Width && y < picasso96_state.Height) {
+       dst = picasso96_state.HostAddress;
+       //dst = gfx_lock_picasso ();
+       if (dst) {
+           switch (size)
+           {
+               case 1:
+               *(uae_u8 *)(dst + y * picasso_vidinfo.rowbytes + xbytes) = value;
+               break;
+               case 2:
+               do_put_mem_word ((uae_u16 *)(dst + y * picasso_vidinfo.rowbytes + xbytes), value);
+               break;
+               case 4:
+               do_put_mem_long ((uae_u32 *)(dst + y * picasso_vidinfo.rowbytes + xbytes), value);       
+               break;
+           }
+           //gfx_unlock_picasso ();
+       }
+    }
+#else
+    if (y >= picasso96_state.Height)
+       return;
+    wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
+    wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
+    wgfx_y = y;
+    wgfx_min = oldaddr;
+    wgfx_max = oldaddr + size;
+#endif
+}
+
+static uae_u32 REGPARAM2 gfxmem_lget (uaecptr addr)
+{
+    uae_u8 *m;
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+    m = gfxmemory + addr;
+    return do_get_mem_long((uae_u32*)m);
+}
+
+static uae_u32 REGPARAM2 gfxmem_wget (uaecptr addr)
+{
+    uae_u8 *m;
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+    m = gfxmemory + addr;
+    return do_get_mem_word((uae_u16*)m);
+}
+
+static uae_u32 REGPARAM2 gfxmem_bget (uaecptr addr)
+{
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+    return gfxmemory[addr];
+}
+
+static void REGPARAM2 gfxmem_lput (uaecptr addr, uae_u32 l)
+{
+    uae_u8 *m;
+#ifdef SWAPSPEEDUP
+    __asm {         //byteswap now
+       mov eax,l
+       bswap eax
+       mov l,eax
+    }
+#endif
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+
+    m = gfxmemory + addr;
+#ifdef SWAPSPEEDUP
+    *m = l;
+#else
+    do_put_mem_long((uae_u32*)m, l);
+#endif
+}
+
+static void REGPARAM2 gfxmem_wput (uaecptr addr, uae_u32 w)
+{
+    uae_u8 *m;
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+    m = gfxmemory + addr;
+    do_put_mem_word((uae_u16*)m, w);
+}
+
+static void REGPARAM2 gfxmem_bput (uaecptr addr, uae_u32 b)
+{
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+    gfxmemory[addr] = b;
+}
+
+static int REGPARAM2 gfxmem_check (uaecptr addr, uae_u32 size)
+{
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+    return (addr + size) < allocated_gfxmem;
+}
+
+static uae_u8 *REGPARAM2 gfxmem_xlate (uaecptr addr)
+{
+    addr -= gfxmem_start & gfxmem_mask;
+    addr &= gfxmem_mask;
+    return gfxmemory + addr;
+}
+
+addrbank gfxmem_bank = {
+    gfxmem_lget, gfxmem_wget, gfxmem_bget,
+    gfxmem_lput, gfxmem_wput, gfxmem_bput,
+    gfxmem_xlate, gfxmem_check, NULL, "RTG RAM",
+    dummy_lgeti, dummy_wgeti, ABFLAG_RAM
+};
+
+/* Call this function first, near the beginning of code flow
+* Place in InitGraphics() which seems reasonable...
+* Also put it in reset_drawing() for safe-keeping.  */
+void InitPicasso96 (void)
+{
+    have_done_picasso = 0;
+    pixelcount = 0;
+    palette_changed = 0;
+//fastscreen
+    oldscr = 0;
+//fastscreen
+    memset (&picasso96_state, 0, sizeof(struct picasso96_state_struct));
+    
+    if (1) {
+       int i, count;
+       
+       for (i = 0; i < 256; i++) {
+           p2ctab[i][0] = (((i & 128) ? 0x01000000 : 0)
+               | ((i & 64) ? 0x010000 : 0)
+               | ((i & 32) ? 0x0100 : 0)
+               | ((i & 16) ? 0x01 : 0));
+           p2ctab[i][1] = (((i & 8) ? 0x01000000 : 0)
+               | ((i & 4) ? 0x010000 : 0)
+               | ((i & 2) ? 0x0100 : 0)
+               | ((i & 1) ? 0x01 : 0));
+       }
+       count = 0;
+       while (DisplayModes[count].depth >= 0)
+           count++;
+       for (i = 0; i < count; i++) {
+           switch (DisplayModes[i].depth) {
+           case 1:
+               if (DisplayModes[i].res.width > chunky.width)
+                   chunky.width = DisplayModes[i].res.width;
+               if (DisplayModes[i].res.height > chunky.height)
+                   chunky.height = DisplayModes[i].res.height;
+               break;
+           case 2:
+               if (DisplayModes[i].res.width > hicolour.width)
+                   hicolour.width = DisplayModes[i].res.width;
+               if (DisplayModes[i].res.height > hicolour.height)
+                   hicolour.height = DisplayModes[i].res.height;
+               break;
+           case 3:
+               if (DisplayModes[i].res.width > truecolour.width)
+                   truecolour.width = DisplayModes[i].res.width;
+               if (DisplayModes[i].res.height > truecolour.height)
+                   truecolour.height = DisplayModes[i].res.height;
+               break;
+           case 4:
+               if (DisplayModes[i].res.width > alphacolour.width)
+                   alphacolour.width = DisplayModes[i].res.width;
+               if (DisplayModes[i].res.height > alphacolour.height)
+                   alphacolour.height = DisplayModes[i].res.height;
+               break;
+           }
+       }
+       //ShowSupportedResolutions ();
+    }
+}
+
+uae_u8 *restore_p96 (uae_u8 *src)
+{
+    return src;
+}
+
+uae_u8 *save_p96 (int *len, uae_u8 *dstptr)
+{
+    uae_u8 *dstbak,*dst;
+
+    //dstbak = dst = malloc (16 + 12 + 1 + 1);
+    return 0;
+}
+
+#endif
index 861522648f8ff28fe0c9f097355af0e871baf1a3..1b0b06fcac96ee5dd76068787505fc25e39dc6e9 100755 (executable)
@@ -15,9 +15,9 @@
 #define GETBDM(x) (((x) - ((x / 10000) * 10000)) / 100)
 #define GETBDD(x) ((x) % 100)
 
-#define WINUAEBETA 6
+#define WINUAEBETA 7
 #define WINUAEPUBLICBETA 1
-#define WINUAEDATE MAKEBD(2007, 2, 11)
+#define WINUAEDATE MAKEBD(2007, 2, 17)
 
 #define IHF_WINDOWHIDDEN 6
 #define NORMAL_WINDOW_STYLE (WS_VISIBLE | WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU)
index 98a84056a933875f291cfabc636391b035a40a0a..8daed516dafb5d80ecef2fe0b9f279b5a22b2509 100755 (executable)
@@ -997,11 +997,45 @@ uae_u8 *gfx_lock_picasso (void)
     return p;
 }
 
+#define DX_INV 0
+
+#if DX_INV == 0
+
+/* For the DX_Invalidate() and gfx_unlock_picasso() functions */
+static int p96_double_buffer_first, p96_double_buffer_last, p96_double_buffer_needs_flushing = 0;
+
+void gfx_unlock_picasso (void)
+{
+    DirectDraw_SurfaceUnlock();
+    if (p96_double_buffer_needs_flushing) {
+       /* Here, our flush_block() will deal with a offscreen-plain (back-buffer) to visible-surface (front-buffer) */
+       if (DirectDraw_GetLockableType() == secondary_surface) {
+           BOOL relock = FALSE;
+           if (DirectDraw_IsLocked()) {
+               relock = TRUE;
+               unlockscr();
+           }
+           DX_Blit (0, p96_double_buffer_first, 
+                    0, p96_double_buffer_first, 
+                    currentmode->current_width, p96_double_buffer_last - p96_double_buffer_first + 1, 
+                    BLIT_SRC);
+           if (relock) {
+               lockscr();
+           }
+       }
+       p96_double_buffer_needs_flushing = 0;
+    }
+}
+
+#else
+
 void gfx_unlock_picasso (void)
 {
     DirectDraw_SurfaceUnlock();
 }
 
+#endif
+
 static void close_hwnds( void )
 {
     screen_is_initialized = 0;
@@ -1415,14 +1449,67 @@ void DX_SetPalette (int start, int count)
     }
 }
 
+#if DX_INV == 0
+
+void DX_Invalidate (int x, int y, int width, int height)
+{
+    int last;
+    
+    if (y < 0 || height < 0) {
+       y = 0;
+       height = picasso_vidinfo.height;
+    }
+    last = y + height - 1;
+    p96_double_buffer_first = y;
+    p96_double_buffer_last  = last;
+    p96_double_buffer_needs_flushing = 1;
+}
+
+#else
+
+static void flashbox(int dstx, int dsty, int width, int height)
+{
+    int i;
+    HRESULT hr;
+    RECT dstrect;
+    RECT srcrect;
+    DDBLTFX ddbltfx;
+    memset(&ddbltfx, 0, sizeof(ddbltfx));
+    ddbltfx.dwFillColor = 0x550055;
+    ddbltfx.dwSize = sizeof(ddbltfx);
+
+    /* Set up our source rectangle.  This NEVER needs to be adjusted for windowed display, since the
+     * source is ALWAYS in an offscreen buffer, or we're in full-screen mode. */
+    SetRect(&srcrect, dstx, dsty, dstx+width, dsty+height);
+
+    /* Set up our destination rectangle, and adjust for blit to windowed display (if necessary ) */
+    SetRect(&dstrect, dstx, dsty, dstx+width, dsty+height);
+    if(!(currentmode->flags & (DM_DX_FULLSCREEN | DM_OVERLAY)))
+       OffsetRect(&dstrect, amigawin_rect.left, amigawin_rect.top);
+
+    /* Render our fill to the visible (primary) surface */
+    for (i = 0; i < 5; i++) {
+       hr = DirectDraw_Blt(primary_surface, &dstrect, invalid_surface, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
+       ddbltfx.dwFillColor = (i & 1) ? 0x550055 : 0xfffff00;
+    }
+
+}
+
 void DX_Invalidate (int x, int y, int width, int height)
 {
+    if (x < 0) {
+       x = 0;
+       y = 0;
+       width = currentmode->current_width;
+       height = currentmode->current_height;
+    }
     if (DirectDraw_GetLockableType() == secondary_surface) {
         BOOL relock = FALSE;
         if (DirectDraw_IsLocked()) {
            relock = TRUE;
            unlockscr();
        }
+       flashbox (x, y, width, height);
        DX_Blit (x, y, x, y, width, height, BLIT_SRC);
        if (relock) {
            lockscr();
@@ -1430,6 +1517,7 @@ void DX_Invalidate (int x, int y, int width, int height)
     }
 }
 
+#endif
 #endif
 
 int DX_BitsPerCannon (void)
index 867a0c34c38133277369e2b94f9c2813475157c9..3469c70f3084c647a76d29dbe82298eb622037e0 100755 (executable)
@@ -9736,12 +9736,13 @@ void gui_message (const char *format,...)
        ShowWindow (hAmigaWnd, SW_MINIMIZE);
 
     write_log(msg);
-    if (msg[strlen(msg)-1]!='\n')
+    if (msg[strlen(msg) - 1] != '\n')
        write_log("\n");
 
     WIN32GUI_LoadUIString (IDS_ERRORTITLE, szTitle, MAX_DPATH);
 
-    MessageBox (hwnd, msg, szTitle, flags);
+    if (!MessageBox (hwnd, msg, szTitle, flags))
+       write_log("MessageBox(%s) failed, err=%d\n", msg, GetLastError());
 
     if (flipflop)
        ShowWindow (hAmigaWnd, SW_RESTORE);
index f8f8b778dbbdceaffd55d198d9e9831c2a85ff23..c26c0b282b509afed47ec0a1cfb377b03008c913 100755 (executable)
@@ -1,4 +1,12 @@
 
+Beta 7: (possible bug fixes and small tweaks left)
+
+- Picasso96 graphics problems really fixed
+- adjusting GUI sound settings on the fly does not anymore cause
+  random sound issues after returning back to emulation (like
+  missing channel(s) for few moments etc..)
+- Action Replay 1, ver 1.0 added to ROM scanner identication list
+
 Beta 6:
 
 - FPU emulation floating point to integer conversion fixed, previously