From 0dadf7618fb7335808b69037f1b67abb1211dcaf Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 17 Feb 2007 16:44:07 +0200 Subject: [PATCH] imported winuaesrc1400b7.zip --- ar.c | 337 ++-- audio.c | 7 +- cdtv.c | 2 +- expansion.c | 25 +- fpp.c | 6 + include/filesys.h | 1 + include/memory.h | 3 +- memory.c | 1 + od-win32/dxwrap.c | 2 +- od-win32/hardfile_win32.c | 12 +- od-win32/mman.c | 30 +- od-win32/picasso96_win.c | 1215 ++++++----- od-win32/picasso96_win.h | 1 + od-win32/picasso96_xp_win.c | 3695 ++++++++++++++++++++++++++++++++++ od-win32/win32.h | 4 +- od-win32/win32gfx.c | 88 + od-win32/win32gui.c | 5 +- od-win32/winuaechangelog.txt | 8 + 18 files changed, 4752 insertions(+), 690 deletions(-) create mode 100755 od-win32/picasso96_xp_win.c diff --git a/ar.c b/ar.c index 810c6428..e19cf5a2 100755 --- 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 (®s, 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(®s, 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(®s, 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 9e64f734..d9d0f98d 100755 --- 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 d6d68c34..4f63013a 100755 --- 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" diff --git a/expansion.c b/expansion.c index 028e3c02..a1b59dca 100755 --- a/expansion.c +++ b/expansion.c @@ -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 7f76f937..3aeb8475 100755 --- 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 */ diff --git a/include/filesys.h b/include/filesys.h index 90e300b6..8ab02557 100755 --- a/include/filesys.h +++ b/include/filesys.h @@ -31,6 +31,7 @@ struct hardfiledata { unsigned int heads; uae_u64 size2; uae_u64 offset2; + int warned; }; #define FILESYS_VIRTUAL 0 diff --git a/include/memory.h b/include/memory.h index 9bc3c9ca..d4384b2f 100755 --- a/include/memory.h +++ b/include/memory.h @@ -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; diff --git a/memory.c b/memory.c index c6a6bf6e..ce537efe 100755 --- 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 }, diff --git a/od-win32/dxwrap.c b/od-win32/dxwrap.c index aafc70dd..99691921 100755 --- a/od-win32/dxwrap.c +++ b/od-win32/dxwrap.c @@ -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); diff --git a/od-win32/hardfile_win32.c b/od-win32/hardfile_win32.c index 56d38806..89aa99df 100755 --- a/od-win32/hardfile_win32.c +++ b/od-win32/hardfile_win32.c @@ -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; diff --git a/od-win32/mman.c b/od-win32/mman.c index 3d2c7009..4612032c 100755 --- a/od-win32/mman.c +++ b/od-win32/mman.c @@ -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; diff --git a/od-win32/picasso96_win.c b/od-win32/picasso96_win.c index 7bd2c80d..80c8bb77 100755 --- a/od-win32/picasso96_win.c +++ b/od-win32/picasso96_win.c @@ -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 diff --git a/od-win32/picasso96_win.h b/od-win32/picasso96_win.h index 18d3afd8..35ceadac 100755 --- a/od-win32/picasso96_win.h +++ b/od-win32/picasso96_win.h @@ -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 index 00000000..36b43044 --- /dev/null +++ b/od-win32/picasso96_xp_win.c @@ -0,0 +1,3695 @@ +/* +* UAE - The U*nix Amiga Emulator +* +* Picasso96 Support Module +* +* Copyright 1997-2001 Brian King +* 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 diff --git a/od-win32/win32.h b/od-win32/win32.h index 86152264..1b0b06fc 100755 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -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) diff --git a/od-win32/win32gfx.c b/od-win32/win32gfx.c index 98a84056..8daed516 100755 --- a/od-win32/win32gfx.c +++ b/od-win32/win32gfx.c @@ -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) diff --git a/od-win32/win32gui.c b/od-win32/win32gui.c index 867a0c34..3469c70f 100755 --- a/od-win32/win32gui.c +++ b/od-win32/win32gui.c @@ -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); diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index f8f8b778..c26c0b28 100755 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -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 -- 2.47.3