From 619f86c40c1d28e24fbdaba3cae4e3335f9651da Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Thu, 2 May 2013 21:13:06 +0300 Subject: [PATCH] 2600b19 --- .gitignore | 1 + custom2.cpp | 7410 ----------------- drawing - Copy.cpp | 3119 ------- drawing.cpp | 37 +- include/events_normal.h | 92 - include/xwin.h | 1 + main.cpp | 8 +- od-win32/cloanto/RetroPlatformIPC.h | 36 +- od-win32/mman.cpp | 4 +- od-win32/resources/RCa02620 | Bin 212576 -> 0 bytes od-win32/resources/RCa06412 | Bin 212124 -> 0 bytes od-win32/resources/RCb02620 | Bin 212576 -> 0 bytes od-win32/resources/RCb06412 | Bin 212124 -> 0 bytes od-win32/resources/resource | 1153 --- od-win32/rp.cpp | 8 +- od-win32/srcrelease.cmd | 1 + od-win32/sysconfig.h | 3 - od-win32/win32.cpp | 10 + od-win32/win32.h | 5 +- od-win32/win32_scaler.cpp | 4 +- od-win32/win32gfx.cpp | 22 +- od-win32/win32gui.cpp | 3 +- .../Test/winuae.unsuccessfulbuild | 0 od-win32/winuaechangelog.txt | 6 + 24 files changed, 110 insertions(+), 11813 deletions(-) delete mode 100644 custom2.cpp delete mode 100644 drawing - Copy.cpp delete mode 100644 include/events_normal.h delete mode 100644 od-win32/resources/RCa02620 delete mode 100644 od-win32/resources/RCa06412 delete mode 100644 od-win32/resources/RCb02620 delete mode 100644 od-win32/resources/RCb06412 delete mode 100644 od-win32/resources/resource delete mode 100644 od-win32/winuae_msvc11/Test/winuae.unsuccessfulbuild diff --git a/.gitignore b/.gitignore index 698b34f8..16ab9cf5 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ debug fullrelease Release Debug +Test FullRelease singlefilehelper ipctester diff --git a/custom2.cpp b/custom2.cpp deleted file mode 100644 index 2e5df277..00000000 --- a/custom2.cpp +++ /dev/null @@ -1,7410 +0,0 @@ -/* -* UAE - The Un*x Amiga Emulator -* -* Custom chip emulation -* -* Copyright 1995-2002 Bernd Schmidt -* Copyright 1995 Alessandro Bissacco -* Copyright 2000-2010 Toni Wilen -*/ - -#include "sysconfig.h" -#include "sysdeps.h" - -#include -#include - -#include "options.h" -#include "uae.h" -#include "gensound.h" -#include "audio.h" -#include "sounddep/sound.h" -#include "events.h" -#include "memory.h" -#include "custom.h" -#include "newcpu.h" -#include "cia.h" -#include "disk.h" -#include "blitter.h" -#include "xwin.h" -#include "inputdevice.h" -#include "inputrecord.h" -#include "keybuf.h" -#include "serial.h" -#include "autoconf.h" -#include "traps.h" -#include "gui.h" -#include "picasso96.h" -#include "drawing.h" -#include "savestate.h" -#include "ar.h" -#ifdef AVIOUTPUT -#include "avioutput.h" -#endif -#include "debug.h" -#include "akiko.h" -#include "cdtv.h" -#if defined(ENFORCER) -#include "enforcer.h" -#endif -#include "gayle.h" -#include "gfxfilter.h" -#include "a2091.h" -#include "a2065.h" -#include "ncr_scsi.h" -#include "blkdev.h" -#include "sampler.h" - -#define CUSTOM_DEBUG 0 -#define SPRITE_DEBUG 0 -#define SPRITE_DEBUG_MINY 0x0 -#define SPRITE_DEBUG_MAXY 0x100 -#define SPR0_HPOS 0x15 -#define MAX_SPRITES 8 -#define SPRITE_COLLISIONS -#define SPEEDUP -#define AUTOSCALE_SPRITES 1 - -#define SPRBORDER 0 - -STATIC_INLINE bool nocustom (void) -{ - if (picasso_on && currprefs.picasso96_nocustom) - return 1; - return 0; -} - -void uae_abort (const TCHAR *format,...) -{ - static int nomore; - va_list parms; - TCHAR buffer[1000]; - - va_start (parms, format); - _vsntprintf (buffer, sizeof (buffer) - 1, format, parms ); - va_end (parms); - if (nomore) { - write_log (_T("%s\n"), buffer); - return; - } - gui_message (buffer); - nomore = 1; -} - -#if 0 -void customhack_put (struct customhack *ch, uae_u16 v, int hpos) -{ - ch->v = v; - ch->vpos = vpos; - ch->hpos = hpos; -} - -uae_u16 customhack_get (struct customhack *ch, int hpos) -{ - if (ch->vpos == vpos && ch->hpos == hpos) { - ch->vpos = -1; - return 0xffff; - } - return ch->v; -} -#endif - -uae_u16 last_custom_value1; - -static unsigned int n_consecutive_skipped = 0; -static unsigned int total_skipped = 0; - -STATIC_INLINE void sync_copper (int hpos); - - -/* Events */ - -unsigned long int event_cycles, nextevent, is_lastline, currcycle; -long cycles_to_next_event; -long max_cycles_to_next_event; -long cycles_to_hsync_event; -unsigned long int vsync_cycles; -static int extra_cycle; -unsigned long start_cycles; - -static int rpt_did_reset; -struct ev eventtab[ev_max]; -struct ev2 eventtab2[ev2_max]; - -volatile frame_time_t vsynctime, vsyncmintime; - -int vpos; -static int vpos_count, vpos_count_prev; -static int lof_store; // real bit in custom registers -static int lof_current; // what display device thinks -static int lol; -static int next_lineno, prev_lineno; -static enum nln_how nextline_how; -static int lof_changed = 0; -static int scandoubled_line; - -/* Stupid genlock-detection prevention hack. -* We should stop calling vsync_handler() and -* hstop_handler() completely but it is not -* worth the trouble.. -*/ -static int vpos_previous, hpos_previous; -static int vpos_lpen, hpos_lpen, lightpen_triggered; -int lightpen_x, lightpen_y, lightpen_cx, lightpen_cy; - -static uae_u32 sprtaba[256],sprtabb[256]; -static uae_u32 sprite_ab_merge[256]; -/* Tables for collision detection. */ -static uae_u32 sprclx[16], clxmask[16]; - -/* AGA T genlock bit in color registers */ -static uae_u8 color_regs_aga_genlock[256]; - -/* -* Hardware registers of all sorts. -*/ - -static int REGPARAM3 custom_wput_1 (int, uaecptr, uae_u32, int) REGPARAM; - -static uae_u16 cregs[256]; - -uae_u16 intena, intreq; -uae_u16 dmacon; -uae_u16 adkcon; /* used by audio code */ - -static uae_u32 cop1lc, cop2lc, copcon; - -int maxhpos = MAXHPOS_PAL; -int maxhpos_short = MAXHPOS_PAL; -int maxvpos = MAXVPOS_PAL; -int maxvpos_nom = MAXVPOS_PAL; // nominal value (same as maxvpos but "faked" maxvpos in fake 60hz modes) -int hsyncendpos, hsyncstartpos; -static int maxvpos_total = 511; -int minfirstline = VBLANK_ENDLINE_PAL; -int equ_vblank_endline = EQU_ENDLINE_PAL; -double vblank_hz = VBLANK_HZ_PAL, fake_vblank_hz, vblank_hz_stored; -int vblank_skip, doublescan; -frame_time_t syncbase; -static int fmode; -uae_u16 beamcon0, new_beamcon0; -uae_u16 vtotal = MAXVPOS_PAL, htotal = MAXHPOS_PAL; -static int maxvpos_stored, maxhpos_stored; -static uae_u16 hsstop, hbstrt, hbstop, vsstop, vbstrt, vbstop, hsstrt, vsstrt, hcenter; -static int ciavsyncmode; -static int diw_hstrt, diw_hstop; -static int diw_hcounter; - -#define HSYNCTIME (maxhpos * CYCLE_UNIT); - -/* This is but an educated guess. It seems to be correct, but this stuff -* isn't documented well. */ -struct sprite { - uaecptr pt; - int xpos; - int vstart; - int vstop; - int dblscan; /* AGA SSCAN2 */ - int armed; - int dmastate; - int dmacycle; - int ptxhpos; -}; - -static struct sprite spr[MAX_SPRITES]; -static int plfstrt_sprite; - -uaecptr sprite_0; -int sprite_0_width, sprite_0_height, sprite_0_doubled; -uae_u32 sprite_0_colors[4]; -static uae_u8 magic_sprite_mask = 0xff; - -static int sprite_vblank_endline = VBLANK_SPRITE_PAL; - -static unsigned int sprctl[MAX_SPRITES], sprpos[MAX_SPRITES]; -#ifdef AGA -static uae_u16 sprdata[MAX_SPRITES][4], sprdatb[MAX_SPRITES][4]; -#else -static uae_u16 sprdata[MAX_SPRITES][1], sprdatb[MAX_SPRITES][1]; -#endif -static int sprite_last_drawn_at[MAX_SPRITES]; -static int last_sprite_point, nr_armed; -static int sprite_width, sprres; -int sprite_buffer_res; - -#ifdef CPUEMU_12 -uae_u8 cycle_line[256]; -#endif - -static uae_u16 bplxdat[8]; -static bool bpl1dat_written, bpl1dat_early, bpl1dat_done; -static uae_s16 bpl1mod, bpl2mod; -static uaecptr prevbpl[2][MAXVPOS][8]; -static uaecptr bplpt[8], bplptx[8]; - -/*static int blitcount[256]; blitter debug */ - -static struct color_entry current_colors; -static unsigned int bplcon0, bplcon1, bplcon2, bplcon3, bplcon4; -static unsigned int bplcon0d, bplcon0dd, bplcon0_res, bplcon0_planes, bplcon0_planes_limit; -static unsigned int diwstrt, diwstop, diwhigh; -static int diwhigh_written; -static unsigned int ddfstrt, ddfstop, ddfstrt_old_hpos; -static int ddf_change, badmode, diw_change; -static int bplcon1_hpos; - -/* The display and data fetch windows */ - -enum diw_states -{ - DIW_waiting_start, DIW_waiting_stop -}; - -static int plffirstline, plflastline; -int plffirstline_total, plflastline_total; -static int autoscale_bordercolors; -static int plfstrt_start, plfstrt, plfstop; -static int sprite_minx, sprite_maxx; -static int first_bpl_vpos; -static int last_ddf_pix_hpos; -static int last_decide_line_hpos; -static int last_fetch_hpos, last_sprite_hpos; -static int diwfirstword, diwlastword; -static int plfleft_real; -static int last_hdiw; -static enum diw_states diwstate, hdiwstate, ddfstate; -int first_planes_vpos, last_planes_vpos; -int diwfirstword_total, diwlastword_total; -int ddffirstword_total, ddflastword_total; -int firstword_bplcon1; - -static int last_copper_hpos; -static int copper_access; - -/* Sprite collisions */ -static unsigned int clxdat, clxcon, clxcon2, clxcon_bpl_enable, clxcon_bpl_match; - -enum copper_states { - COP_stop, - COP_read1, - COP_read2, - COP_bltwait, - COP_wait_in2, - COP_skip_in2, - COP_wait1, - COP_wait, - COP_skip1, - COP_strobe_delay1, - COP_strobe_delay2, - COP_strobe_extra, // just to skip current cycle when CPU wrote to COPJMP - COP_start_delay -}; - -struct copper { - /* The current instruction words. */ - unsigned int i1, i2; - unsigned int saved_i1, saved_i2; - enum copper_states state, state_prev; - /* Instruction pointer. */ - uaecptr ip, saved_ip; - int hpos, vpos; - unsigned int ignore_next; - int vcmp, hcmp; - - int strobe; /* COPJMP1 / COPJMP2 accessed */ - int last_write, last_write_hpos; - int moveaddr, movedata, movedelay; -}; - -static struct copper cop_state; -static int copper_enabled_thisline; -static int cop_min_waittime; - -/* -* Statistics -*/ -unsigned long int frametime = 0, lastframetime = 0, timeframes = 0; -unsigned long hsync_counter = 0, vsync_counter = 0; -unsigned long int idletime; -int bogusframe; - -/* Recording of custom chip register changes. */ -static int current_change_set; -static struct sprite_entry sprite_entries[2][MAX_SPR_PIXELS / 16]; -static struct color_change color_changes[2][MAX_REG_CHANGE]; - -struct decision line_decisions[2 * (MAXVPOS + 2) + 1]; -static struct draw_info line_drawinfo[2][2 * (MAXVPOS + 2) + 1]; -#define COLOR_TABLE_SIZE (MAXVPOS + 2) * 2 -static struct color_entry color_tables[2][COLOR_TABLE_SIZE]; - -static int next_sprite_entry = 0; -static int prev_next_sprite_entry; -static int next_sprite_forced = 1; - -struct sprite_entry *curr_sprite_entries, *prev_sprite_entries; -struct color_change *curr_color_changes, *prev_color_changes; -struct draw_info *curr_drawinfo, *prev_drawinfo; -struct color_entry *curr_color_tables, *prev_color_tables; - -static int next_color_change; -static int next_color_entry, remembered_color_entry; -static int color_src_match, color_dest_match, color_compare_result; - -static uae_u32 thisline_changed; - -#ifdef SMART_UPDATE -#define MARK_LINE_CHANGED do { thisline_changed = 1; } while (0) -#else -#define MARK_LINE_CHANGED do { ; } while (0) -#endif - -static struct decision thisline_decision; -static int fetch_cycle, fetch_modulo_cycle; - -enum plfstate -{ - plf_idle, - plf_start, - plf_active, - plf_passed_stop, - plf_passed_stop2, - plf_end -} plf_state; - -enum fetchstate { - fetch_not_started, - fetch_started, - fetch_was_plane0 -} fetch_state; - -/* -* helper functions -*/ - -STATIC_INLINE int ecsshres(void) -{ - return bplcon0_res == RES_SUPERHIRES && (currprefs.chipset_mask & CSMASK_ECS_DENISE) && !(currprefs.chipset_mask & CSMASK_AGA); -} - -STATIC_INLINE int nodraw (void) -{ - return !currprefs.cpu_cycle_exact && framecnt != 0; -} - -static int doflickerfix (void) -{ - return currprefs.gfx_vresolution && doublescan < 0 && vpos < MAXVPOS; -} - -uae_u32 get_copper_address (int copno) -{ - switch (copno) { - case 1: return cop1lc; - case 2: return cop2lc; - case -1: return cop_state.ip; - default: return 0; - } -} - -int rpt_available = 0; - -void reset_frame_rate_hack (void) -{ - if (currprefs.m68k_speed != -1) - return; - - if (! rpt_available) { - currprefs.m68k_speed = 0; - return; - } - - rpt_did_reset = 1; - is_lastline = 0; - vsyncmintime = read_processor_time () + vsynctime; - write_log (_T("Resetting frame rate hack\n")); -} - -STATIC_INLINE void setclr (uae_u16 *p, uae_u16 val) -{ - if (val & 0x8000) - *p |= val & 0x7FFF; - else - *p &= ~val; -} - -STATIC_INLINE void alloc_cycle (int hpos, int type) -{ -#ifdef CPUEMU_12 -#if 0 - if (cycle_line[hpos]) - write_log (_T("hpos=%d, old=%d, new=%d\n"), hpos, cycle_line[hpos], type); - if ((type == CYCLE_CPU || type == CYCLE_COPPER) && (hpos & 1)) - write_log (_T("odd %d cycle %d\n"), hpos); - if (!(hpos & 1) && (type == CYCLE_SPRITE || type == CYCLE_REFRESH || type == CYCLE_MISC)) - write_log (_T("even %d cycle %d\n"), type, hpos); -#endif - cycle_line[hpos] = type; -#endif -} -STATIC_INLINE void alloc_cycle_maybe (int hpos, int type) -{ - if (cycle_line[hpos] == 0) - alloc_cycle (hpos, type); -} - -void alloc_cycle_ext(int hpos, int type) -{ - alloc_cycle (hpos, type); -} - -static void hsyncdelay (void) -{ -#if 0 - static int prevhpos; - while (current_hpos () == prevhpos) - do_cycles(CYCLE_UNIT); - prevhpos = current_hpos(); -#endif -} - -static void update_mirrors (void) -{ - aga_mode = (currprefs.chipset_mask & CSMASK_AGA) ? 1 : 0; - direct_rgb = aga_mode; -} - -STATIC_INLINE uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount) -{ - if (!chipmem_check_indirect (plpt, bytecount)) { - static int count = 0; - if (!count) - count++, write_log (_T("Warning: Bad playfield pointer\n")); - return NULL; - } - return chipmem_xlate_indirect (plpt); -} - -STATIC_INLINE void docols (struct color_entry *colentry) -{ - int i; - -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) { - for (i = 0; i < 256; i++) { - int v = color_reg_get (colentry, i); - if (v < 0 || v > 16777215) - continue; - colentry->acolors[i] = getxcolor (v); - } - } else { -#endif - for (i = 0; i < 32; i++) { - int v = color_reg_get (colentry, i); - if (v < 0 || v > 4095) - continue; - colentry->acolors[i] = getxcolor (v); - } -#ifdef AGA - } -#endif -} - -extern struct color_entry colors_for_drawing; - -void notice_new_xcolors (void) -{ - int i; - - update_mirrors (); - docols (¤t_colors); - docols (&colors_for_drawing); - for (i = 0; i < (MAXVPOS + 1) * 2; i++) { - docols (color_tables[0] + i); - docols (color_tables[1] + i); - } -} - -static void do_sprites (int currhp); - -static void remember_ctable (void) -{ - /* This can happen when program program crashes very badly */ - if (next_color_entry >= COLOR_TABLE_SIZE) - return; - if (remembered_color_entry == -1) { - /* The colors changed since we last recorded a color map. Record a - * new one. */ - color_reg_cpy (curr_color_tables + next_color_entry, ¤t_colors); - remembered_color_entry = next_color_entry++; - } - thisline_decision.ctable = remembered_color_entry; - if (color_src_match == -1 || color_dest_match != remembered_color_entry - || line_decisions[next_lineno].ctable != color_src_match) - { - /* The remembered comparison didn't help us - need to compare again. */ - int oldctable = line_decisions[next_lineno].ctable; - int changed = 0; - - if (oldctable == -1) { - changed = 1; - color_src_match = color_dest_match = -1; - } else { - color_compare_result = color_reg_cmp (&prev_color_tables[oldctable], ¤t_colors) != 0; - if (color_compare_result) - changed = 1; - color_src_match = oldctable; - color_dest_match = remembered_color_entry; - } - thisline_changed |= changed; - } else { - /* We know the result of the comparison */ - if (color_compare_result) - thisline_changed = 1; - } -} - -static void remember_ctable_for_border (void) -{ - remember_ctable (); -} - -/* Called to determine the state of the horizontal display window state -* machine at the current position. It might have changed since we last -* checked. */ -static void decide_diw (int hpos) -{ - /* Last hpos = hpos + 0.5, eg. normal PAL end hpos is 227.5 * 2 = 455 - OCS Denise: 9 bit hdiw counter does not reset during lines 0 to 9 - (PAL) or lines 0 to 10 (NTSC). A1000 PAL: 1 to 9, NTSC: 1 to 10. - ECS Denise and AGA: no above "features" - */ - - int hdiw = hpos >= maxhpos ? maxhpos * 2 + 1 : hpos * 2 + 2; - if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE) && vpos <= equ_vblank_endline) { - hdiw = diw_hcounter; - hdiw &= 511; - } - for (;;) { - int lhdiw = hdiw; - if (last_hdiw > lhdiw) - lhdiw = 512; - - if (lhdiw >= diw_hstrt && last_hdiw < diw_hstrt && hdiwstate == DIW_waiting_start) { - if (thisline_decision.diwfirstword == -1) - thisline_decision.diwfirstword = diwfirstword < 0 ? 0 : diwfirstword; - hdiwstate = DIW_waiting_stop; - } - if (lhdiw >= diw_hstop && last_hdiw < diw_hstop && hdiwstate == DIW_waiting_stop) { - if (thisline_decision.diwlastword == -1) - thisline_decision.diwlastword = diwlastword < 0 ? 0 : diwlastword; - hdiwstate = DIW_waiting_start; - } - if (lhdiw != 512) - break; - last_hdiw = 0 - 1; - } - last_hdiw = hdiw; -} - -static int fetchmode; -static int real_bitplane_number[3][3][9]; - -/* Disable bitplane DMA if planes > available DMA slots. This is needed -e.g. by the Sanity WOC demo (at the "Party Effect"). */ -STATIC_INLINE int GET_PLANES_LIMIT (uae_u16 bc0) -{ - int res = GET_RES_AGNUS (bc0); - int planes = GET_PLANES (bc0); - return real_bitplane_number[fetchmode][res][planes]; -} - -/* The HRM says 0xD8, but that can't work... */ -#define HARD_DDF_STOP 0xd4 -#define HARD_DDF_START 0x18 - -static void add_modulos (void) -{ - int m1, m2; - - if (fmode & 0x4000) { - if (((diwstrt >> 8) ^ vpos) & 1) - m1 = m2 = bpl2mod; - else - m1 = m2 = bpl1mod; - } else { - m1 = bpl1mod; - m2 = bpl2mod; - } - - switch (bplcon0_planes_limit) { -#ifdef AGA - case 8: bplpt[7] += m2; bplptx[7] += m2; - case 7: bplpt[6] += m1; bplptx[6] += m1; -#endif - case 6: bplpt[5] += m2; bplptx[5] += m2; - case 5: bplpt[4] += m1; bplptx[4] += m1; - case 4: bplpt[3] += m2; bplptx[3] += m2; - case 3: bplpt[2] += m1; bplptx[2] += m1; - case 2: bplpt[1] += m2; bplptx[1] += m2; - case 1: bplpt[0] += m1; bplptx[0] += m1; - } -} - -static void finish_playfield_line (void) -{ - /* The latter condition might be able to happen in interlaced frames. */ - if (vpos >= minfirstline && (thisframe_first_drawn_line == -1 || vpos < thisframe_first_drawn_line)) - thisframe_first_drawn_line = vpos; - thisframe_last_drawn_line = vpos; - -#ifdef SMART_UPDATE - if (line_decisions[next_lineno].plflinelen != thisline_decision.plflinelen - || line_decisions[next_lineno].plfleft != thisline_decision.plfleft - || line_decisions[next_lineno].bplcon0 != thisline_decision.bplcon0 - || line_decisions[next_lineno].bplcon2 != thisline_decision.bplcon2 -#ifdef ECS_DENISE - || line_decisions[next_lineno].bplcon3 != thisline_decision.bplcon3 -#endif -#ifdef AGA - || line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4 -#endif - ) -#endif /* SMART_UPDATE */ - thisline_changed = 1; -} - -/* The fetch unit mainly controls ddf stop. It's the number of cycles that -are contained in an indivisible block during which ddf is active. E.g. -if DDF starts at 0x30, and fetchunit is 8, then possible DDF stops are -0x30 + n * 8. */ -static int fetchunit, fetchunit_mask; -/* The delay before fetching the same bitplane again. Can be larger than -the number of bitplanes; in that case there are additional empty cycles -with no data fetch (this happens for high fetchmodes and low -resolutions). */ -static int fetchstart, fetchstart_shift, fetchstart_mask; -/* fm_maxplane holds the maximum number of planes possible with the current -fetch mode. This selects the cycle diagram: -8 planes: 73516240 -4 planes: 3120 -2 planes: 10. */ -static int fm_maxplane, fm_maxplane_shift; - -/* The corresponding values, by fetchmode and display resolution. */ -static const int fetchunits[] = { 8,8,8,0, 16,8,8,0, 32,16,8,0 }; -static const int fetchstarts[] = { 3,2,1,0, 4,3,2,0, 5,4,3,0 }; -static const int fm_maxplanes[] = { 3,2,1,0, 3,3,2,0, 3,3,3,0 }; - -static int cycle_diagram_table[3][3][9][32]; -static int cycle_diagram_free_cycles[3][3][9]; -static int cycle_diagram_total_cycles[3][3][9]; -static int *curr_diagram; -static const int cycle_sequences[3 * 8] = { 2,1,2,1,2,1,2,1, 4,2,3,1,4,2,3,1, 8,4,6,2,7,3,5,1 }; - -static void debug_cycle_diagram (void) -{ - int fm, res, planes, cycle, v; - TCHAR aa; - - for (fm = 0; fm <= 2; fm++) { - write_log (_T("FMODE %d\n=======\n"), fm); - for (res = 0; res <= 2; res++) { - for (planes = 0; planes <= 8; planes++) { - write_log (_T("%d: "),planes); - for (cycle = 0; cycle < 32; cycle++) { - v=cycle_diagram_table[fm][res][planes][cycle]; - if (v==0) aa='-'; else if(v>0) aa='1'; else aa='X'; - write_log (_T("%c"),aa); - } - write_log (_T(" %d:%d\n"), - cycle_diagram_free_cycles[fm][res][planes], cycle_diagram_total_cycles[fm][res][planes]); - } - write_log (_T("\n")); - } - } - fm=0; -} - -static void create_cycle_diagram_table (void) -{ - int fm, res, cycle, planes, rplanes, v; - int fetch_start, max_planes, freecycles; - const int *cycle_sequence; - - for (fm = 0; fm <= 2; fm++) { - for (res = 0; res <= 2; res++) { - max_planes = fm_maxplanes[fm * 4 + res]; - fetch_start = 1 << fetchstarts[fm * 4 + res]; - cycle_sequence = &cycle_sequences[(max_planes - 1) * 8]; - max_planes = 1 << max_planes; - for (planes = 0; planes <= 8; planes++) { - freecycles = 0; - for (cycle = 0; cycle < 32; cycle++) - cycle_diagram_table[fm][res][planes][cycle] = -1; - if (planes <= max_planes) { - for (cycle = 0; cycle < fetch_start; cycle++) { - if (cycle < max_planes && planes >= cycle_sequence[cycle & 7]) { - v = cycle_sequence[cycle & 7]; - } else { - v = 0; - freecycles++; - } - cycle_diagram_table[fm][res][planes][cycle] = v; - } - } - cycle_diagram_free_cycles[fm][res][planes] = freecycles; - cycle_diagram_total_cycles[fm][res][planes] = fetch_start; - rplanes = planes; - if (rplanes > max_planes) - rplanes = 0; - if (rplanes == 7 && fm == 0 && res == 0 && !(currprefs.chipset_mask & CSMASK_AGA)) - rplanes = 4; - real_bitplane_number[fm][res][planes] = rplanes; - } - } - } -#if 0 - debug_cycle_diagram (); -#endif -} - - -/* Used by the copper. */ -static int estimated_last_fetch_cycle; -static int cycle_diagram_shift; - -static void estimate_last_fetch_cycle (int hpos) -{ - int fetchunit = fetchunits[fetchmode * 4 + bplcon0_res]; - - if (plf_state < plf_passed_stop) { - int stop = plfstop < hpos || plfstop > HARD_DDF_STOP ? HARD_DDF_STOP : plfstop; - /* We know that fetching is up-to-date up until hpos, so we can use fetch_cycle. */ - int fetch_cycle_at_stop = fetch_cycle + (stop - hpos); - int starting_last_block_at = (fetch_cycle_at_stop + fetchunit - 1) & ~(fetchunit - 1); - - estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit; - } else { - int starting_last_block_at = (fetch_cycle + fetchunit - 1) & ~(fetchunit - 1); - if (plf_state == plf_passed_stop2) - starting_last_block_at -= fetchunit; - - estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit; - } -} - -static uae_u32 outword[MAX_PLANES]; -static int out_nbits, out_offs; -static uae_u32 todisplay[MAX_PLANES][4]; -static uae_u32 fetched[MAX_PLANES]; -#ifdef AGA -static uae_u32 fetched_aga0[MAX_PLANES]; -static uae_u32 fetched_aga1[MAX_PLANES]; -#endif - -/* Expansions from bplcon0/bplcon1. */ -static int toscr_res, toscr_nr_planes, toscr_nr_planes2, fetchwidth; -static int toscr_delay1, toscr_delay2; - -/* The number of bits left from the last fetched words. -This is an optimization - conceptually, we have to make sure the result is -the same as if toscr is called in each clock cycle. However, to speed this -up, we accumulate display data; this variable keeps track of how much. -Thus, once we do call toscr_nbits (which happens at least every 16 bits), -we can do more work at once. */ -static int toscr_nbits; - -/* undocumented bitplane delay hardware feature */ -static int delayoffset; - -STATIC_INLINE void compute_delay_offset (void) -{ - delayoffset = (16 << fetchmode) - (((plfstrt - HARD_DDF_START) & fetchstart_mask) << 1); -#if 0 - /* maybe we can finally get rid of this stupid table.. */ - if (tmp == 4) - delayoffset = 4; // Loons Docs - else if (tmp == 8) - delayoffset = 8; - else if (tmp == 12) // Loons Docs - delayoffset = 4; - else if (tmp == 16) /* Overkill AGA */ - delayoffset = 48; - else if (tmp == 24) /* AB 2 */ - delayoffset = 8; - else if (tmp == 32) - delayoffset = 32; - else if (tmp == 48) /* Pinball Illusions AGA, ingame */ - delayoffset = 16; - else /* what about 40 and 56? */ - delayoffset = 0; - //write_log (_T("%d:%d "), vpos, delayoffset); -#endif -} - -static void record_color_change2 (int hpos, int regno, unsigned long value) -{ - int pos = hpos * 2; - if (regno == 0x1000 + 0x10c) - pos++; // BPLCON4 change needs 1 lores pixel delay - curr_color_changes[next_color_change].linepos = pos; - curr_color_changes[next_color_change].regno = regno; - curr_color_changes[next_color_change++].value = value; - curr_color_changes[next_color_change].regno = -1; -} - -static int isehb (uae_u16 bplcon0, uae_u16 bplcon2) -{ - int bplehb; - if (currprefs.chipset_mask & CSMASK_AGA) - bplehb = (bplcon0 & 0x7010) == 0x6000; - else if (currprefs.chipset_mask & CSMASK_ECS_DENISE) - bplehb = ((bplcon0 & 0xFC00) == 0x6000 || (bplcon0 & 0xFC00) == 0x7000); - else - bplehb = ((bplcon0 & 0xFC00) == 0x6000 || (bplcon0 & 0xFC00) == 0x7000) && !currprefs.cs_denisenoehb; - return bplehb; -} - -// OCS/ECS, lores, 7 planes = 4 "real" planes + BPL5DAT and BPL6DAT as static 5th and 6th plane -STATIC_INLINE int isocs7planes (void) -{ - return !(currprefs.chipset_mask & CSMASK_AGA) && bplcon0_res == 0 && bplcon0_planes == 7; -} - -int is_bitplane_dma (int hpos) -{ - if (fetch_state == fetch_not_started || hpos < plfstrt) - return 0; - if ((plf_state == plf_end && hpos >= thisline_decision.plfright) - || hpos >= estimated_last_fetch_cycle) - return 0; - return curr_diagram[(hpos - cycle_diagram_shift) & fetchstart_mask]; -} - -STATIC_INLINE int is_bitplane_dma_inline (int hpos) -{ - if (fetch_state == fetch_not_started || hpos < plfstrt) - return 0; - if ((plf_state == plf_end && hpos >= thisline_decision.plfright) - || hpos >= estimated_last_fetch_cycle) - return 0; - return curr_diagram[(hpos - cycle_diagram_shift) & fetchstart_mask]; -} - -static void update_denise (int hpos) -{ - toscr_res = GET_RES_DENISE (bplcon0d); - if (bplcon0dd != bplcon0d) { - record_color_change2 (hpos, 0x100 + 0x1000, bplcon0d); - bplcon0dd = bplcon0d; - } - toscr_nr_planes = GET_PLANES (bplcon0d); - if (isocs7planes ()) { - if (toscr_nr_planes2 < 6) - toscr_nr_planes2 = 6; - } else { - toscr_nr_planes2 = toscr_nr_planes; - } -} - -static int bpldmasetuphpos; -static int bpldmasetupphase; - -/* set currently active Agnus bitplane DMA sequence */ -static void setup_fmodes (int hpos) -{ - switch (fmode & 3) - { - case 0: - fetchmode = 0; - break; - case 1: - case 2: - fetchmode = 1; - break; - case 3: - fetchmode = 2; - break; - } - badmode = GET_RES_AGNUS (bplcon0) != GET_RES_DENISE (bplcon0); - bplcon0_res = GET_RES_AGNUS (bplcon0); - bplcon0_planes = GET_PLANES (bplcon0); - bplcon0_planes_limit = GET_PLANES_LIMIT (bplcon0); - fetchunit = fetchunits[fetchmode * 4 + bplcon0_res]; - fetchunit_mask = fetchunit - 1; - fetchstart_shift = fetchstarts[fetchmode * 4 + bplcon0_res]; - fetchstart = 1 << fetchstart_shift; - fetchstart_mask = fetchstart - 1; - fm_maxplane_shift = fm_maxplanes[fetchmode * 4 + bplcon0_res]; - fm_maxplane = 1 << fm_maxplane_shift; - fetch_modulo_cycle = fetchunit - fetchstart; - if (is_bitplane_dma (hpos - 1)) - cycle_line[hpos - 1] = 1; - curr_diagram = cycle_diagram_table[fetchmode][bplcon0_res][bplcon0_planes_limit]; - estimate_last_fetch_cycle (hpos); - if (bpldmasetuphpos >= 0 && debug_dma) - record_dma_event (DMA_EVENT_BPLFETCHUPDATE, hpos, vpos); - bpldmasetuphpos = -1; - bpldmasetupphase = 0; - ddf_change = vpos; -} - -static void BPLCON0_Denise (int hpos, uae_u16 v); - -// writing to BPLCON0 adds 4 cycle delay before Agnus bitplane DMA sequence changes -// (Note that Denise sees the change after 1 cycle) -// AGA needs extra cycle in some specific situations (Brian The Lion "dialog") but not -// in all situations (Superstardust weapon panel) -#define BPLCON_AGNUS_DELAY (4 + (bplcon0_planes == 8 ? 1 : 0)) -#define BPLCON_DENISE_DELAY 1 - -static void maybe_setup_fmodes (int hpos) -{ - switch (bpldmasetupphase) - { - case 0: - BPLCON0_Denise (hpos, bplcon0); - bpldmasetupphase++; - bpldmasetuphpos += BPLCON_AGNUS_DELAY - BPLCON_DENISE_DELAY; - break; - case 1: - setup_fmodes (hpos); - break; - } -} - -STATIC_INLINE void maybe_check (int hpos) -{ - if (bpldmasetuphpos > 0 && hpos >= bpldmasetuphpos) - maybe_setup_fmodes (hpos); -} - -static void bpldmainitdelay (int hpos) -{ - int hposa; - - hposa = hpos + BPLCON_AGNUS_DELAY; - ddf_change = vpos; - if (hposa < 0x14) { - BPLCON0_Denise (hpos, bplcon0); - setup_fmodes (hpos); - return; - } - if (bpldmasetuphpos < 0) { - bpldmasetupphase = 0; - bpldmasetuphpos = hpos + BPLCON_DENISE_DELAY; - } -} - -/* Expand bplcon0/bplcon1 into the toscr_xxx variables. */ -static void compute_toscr_delay_1 (int bplcon1) -{ - int delay1 = (bplcon1 & 0x0f) | ((bplcon1 & 0x0c00) >> 6); - int delay2 = ((bplcon1 >> 4) & 0x0f) | (((bplcon1 >> 4) & 0x0c00) >> 6); - int shdelay1 = (bplcon1 >> 12) & 3; - int shdelay2 = (bplcon1 >> 8) & 3; - int delaymask; - int fetchwidth = 16 << fetchmode; - - delay1 += delayoffset; - delay2 += delayoffset; - delaymask = (fetchwidth - 1) >> toscr_res; - toscr_delay1 = (delay1 & delaymask) << toscr_res; - toscr_delay1 |= shdelay1 >> (RES_MAX - toscr_res); - toscr_delay2 = (delay2 & delaymask) << toscr_res; - toscr_delay2 |= shdelay2 >> (RES_MAX - toscr_res); -} - -static void compute_toscr_delay (int hpos, int bplcon1) -{ - update_denise (hpos); - compute_toscr_delay_1 (bplcon1); -} - -STATIC_INLINE void clear_fetchbuffer (uae_u32 *ptr, int nwords) -{ - int i; - - if (! thisline_changed) { - for (i = 0; i < nwords; i++) { - if (ptr[i]) { - thisline_changed = 1; - break; - } - } - } - memset (ptr, 0, nwords * 4); -} - -static void update_toscr_planes (void) -{ - if (toscr_nr_planes2 > thisline_decision.nr_planes) { - int j; - for (j = thisline_decision.nr_planes; j < toscr_nr_planes2; j++) - clear_fetchbuffer ((uae_u32 *)(line_data[next_lineno] + 2 * MAX_WORDS_PER_LINE * j), out_offs); - thisline_decision.nr_planes = toscr_nr_planes2; - } -} - -STATIC_INLINE void maybe_first_bpl1dat (int hpos) -{ - if (thisline_decision.plfleft != -1) { - // early bpl1dat crap fix (Sequential engine animation) - if (plfleft_real == -1) { - int i; - for (i = 0; i < thisline_decision.nr_planes; i++) { - todisplay[i][0] = 0; -#ifdef AGA - todisplay[i][1] = 0; - todisplay[i][2] = 0; - todisplay[i][3] = 0; -#endif - } - plfleft_real = hpos; - bpl1dat_early = 1; - } - } else { - plfleft_real = thisline_decision.plfleft = hpos; - compute_delay_offset (); - } -} - -STATIC_INLINE void fetch (int nr, int fm, int hpos) -{ - if (nr < bplcon0_planes_limit) { - uaecptr p = bplpt[nr]; - bplpt[nr] += 2 << fm; - bplptx[nr] += 2 << fm; - if (nr == 0) - bpl1dat_written = 1; -#ifdef DEBUGGER - if (debug_dma) - record_dma (0x110 + nr * 2, chipmem_wget_indirect (p), p, hpos, vpos, DMARECORD_BITPLANE); -#endif - switch (fm) - { - case 0: - fetched[nr] = bplxdat[nr] = last_custom_value1 = chipmem_wget_indirect (p); - break; -#ifdef AGA - case 1: - fetched_aga0[nr] = chipmem_lget_indirect (p); - last_custom_value1 = (uae_u16)fetched_aga0[nr]; - break; - case 2: - fetched_aga1[nr] = chipmem_lget_indirect (p); - fetched_aga0[nr] = chipmem_lget_indirect (p + 4); - last_custom_value1 = (uae_u16)fetched_aga0[nr]; - break; -#endif - } - if (plf_state == plf_passed_stop2 && fetch_cycle >= (fetch_cycle & ~fetchunit_mask) + fetch_modulo_cycle) { - int mod; - if (fmode & 0x4000) { - if (((diwstrt >> 8) ^ vpos) & 1) - mod = bpl2mod; - else - mod = bpl1mod; - } else if (nr & 1) - mod = bpl2mod; - else - mod = bpl1mod; - bplpt[nr] += mod; - bplptx[nr] += mod; - } - } else { - // use whatever left in BPLxDAT if no DMA - // normally useless but "7-planes" feature won't work without this - fetched[nr] = bplxdat[nr]; - } -} - -STATIC_INLINE void toscr_3_ecs (int nbits) -{ - int delay1 = toscr_delay1; - int delay2 = toscr_delay2; - int i; - uae_u32 mask = 0xFFFF >> (16 - nbits); - - for (i = 0; i < toscr_nr_planes2; i += 2) { - outword[i] <<= nbits; - outword[i] |= (todisplay[i][0] >> (16 - nbits + delay1)) & mask; - todisplay[i][0] <<= nbits; - } - for (i = 1; i < toscr_nr_planes2; i += 2) { - outword[i] <<= nbits; - outword[i] |= (todisplay[i][0] >> (16 - nbits + delay2)) & mask; - todisplay[i][0] <<= nbits; - } -} - -STATIC_INLINE void shift32plus (uae_u32 *p, int n) -{ - uae_u32 t = p[1]; - t <<= n; - t |= p[0] >> (32 - n); - p[1] = t; -} - -#ifdef AGA -STATIC_INLINE void aga_shift (uae_u32 *p, int n, int fm) -{ - if (fm == 2) { - shift32plus (p + 2, n); - shift32plus (p + 1, n); - } - shift32plus (p + 0, n); - p[0] <<= n; -} - -STATIC_INLINE void toscr_3_aga (int nbits, int fm) -{ - int delay1 = toscr_delay1; - int delay2 = toscr_delay2; - int i; - uae_u32 mask = 0xFFFF >> (16 - nbits); - - { - int offs = (16 << fm) - nbits + delay1; - int off1 = offs >> 5; - if (off1 == 3) - off1 = 2; - offs -= off1 * 32; - for (i = 0; i < toscr_nr_planes2; i += 2) { - uae_u32 t0 = todisplay[i][off1]; - uae_u32 t1 = todisplay[i][off1 + 1]; - uae_u64 t = (((uae_u64)t1) << 32) | t0; - outword[i] <<= nbits; - outword[i] |= (t >> offs) & mask; - aga_shift (todisplay[i], nbits, fm); - } - } - { - int offs = (16 << fm) - nbits + delay2; - int off1 = offs >> 5; - if (off1 == 3) - off1 = 2; - offs -= off1 * 32; - for (i = 1; i < toscr_nr_planes2; i += 2) { - uae_u32 t0 = todisplay[i][off1]; - uae_u32 t1 = todisplay[i][off1 + 1]; - uae_u64 t = (((uae_u64)t1) << 32) | t0; - outword[i] <<= nbits; - outword[i] |= (t >> offs) & mask; - aga_shift (todisplay[i], nbits, fm); - } - } -} - -#endif - -static void toscr_2_0 (int nbits) { toscr_3_ecs (nbits); } -#ifdef AGA -static void toscr_2_1 (int nbits) { toscr_3_aga (nbits, 1); } -static void toscr_2_2 (int nbits) { toscr_3_aga (nbits, 2); } -#endif - -STATIC_INLINE void toscr_1 (int nbits, int fm) -{ - switch (fm) { - case 0: - toscr_2_0 (nbits); - break; -#ifdef AGA - case 1: - toscr_2_1 (nbits); - break; - case 2: - toscr_2_2 (nbits); - break; -#endif - } - out_nbits += nbits; - if (out_nbits == 32) { - int i; - uae_u8 *dataptr = line_data[next_lineno] + out_offs * 4; - for (i = 0; i < thisline_decision.nr_planes; i++) { - uae_u32 *dataptr32 = (uae_u32 *)dataptr; - if (*dataptr32 != outword[i]) { - thisline_changed = 1; - *dataptr32 = outword[i]; - } - outword[i] = 0; - dataptr += MAX_WORDS_PER_LINE * 2; - } - out_offs++; - out_nbits = 0; - } -} - -static void toscr_fm0 (int); -static void toscr_fm1 (int); -static void toscr_fm2 (int); - -STATIC_INLINE void toscr (int nbits, int fm) -{ - switch (fm) { - case 0: toscr_fm0 (nbits); break; -#ifdef AGA - case 1: toscr_fm1 (nbits); break; - case 2: toscr_fm2 (nbits); break; -#endif - } -} - -STATIC_INLINE void toscr_0 (int nbits, int fm) -{ - int t; - - if (nbits > 16) { - toscr (16, fm); - nbits -= 16; - } - - t = 32 - out_nbits; - if (t < nbits) { - toscr_1 (t, fm); - nbits -= t; - } - toscr_1 (nbits, fm); -} - -static void toscr_fm0 (int nbits) { toscr_0 (nbits, 0); } -static void toscr_fm1 (int nbits) { toscr_0 (nbits, 1); } -static void toscr_fm2 (int nbits) { toscr_0 (nbits, 2); } - -static int flush_plane_data (int fm) -{ - int i = 0; - - if (out_nbits <= 16) { - i += 16; - toscr_1 (16, fm); - } - if (out_nbits != 0) { - i += 32 - out_nbits; - toscr_1 (32 - out_nbits, fm); - } - i += 32; - - toscr_1 (16, fm); - toscr_1 (16, fm); - - if (fm == 2) { - /* flush AGA full 64-bit shift register */ - i += 32; - toscr_1 (16, fm); - toscr_1 (16, fm); - } - - if (bpl1dat_early) { - // clear possible crap in right border if - // bpl1dat was written "out of sync" - toscr_1 (16, fm); - toscr_1 (16, fm); - } - - return i >> (1 + toscr_res); -} - -STATIC_INLINE void flush_display (int fm) -{ - if (toscr_nbits > 0 && thisline_decision.plfleft != -1) - toscr (toscr_nbits, fm); - toscr_nbits = 0; -} - -STATIC_INLINE void fetch_start (int hpos) -{ - fetch_state = fetch_started; -} - - -/* Called when all planes have been fetched, i.e. when a new block -of data is available to be displayed. The data in fetched[] is -moved into todisplay[]. */ -STATIC_INLINE void beginning_of_plane_block (int hpos, int fm) -{ - int i; - int oleft = thisline_decision.plfleft; - static uae_u16 bplcon1t, bplcon1t2; - - flush_display (fm); - - if (fm == 0) - for (i = 0; i < MAX_PLANES; i++) { - todisplay[i][0] |= fetched[i]; - } -#ifdef AGA - else - for (i = 0; i < MAX_PLANES; i++) { - if (fm == 2) - todisplay[i][1] = fetched_aga1[i]; - todisplay[i][0] = fetched_aga0[i]; - } -#endif - - update_denise (hpos); - maybe_first_bpl1dat (hpos); - - bplcon1t2 = bplcon1t; - bplcon1t = bplcon1; - // writing to BPLCON1 1 cycle after BPL1DAT access will - // not (except first BPL1DAT write) affect the display - // until next display block - if (bplcon1_hpos != hpos || oleft < 0) - bplcon1t2 = bplcon1t; - compute_toscr_delay (hpos, bplcon1t2); -} - -#ifdef SPEEDUP - -/* The usual inlining tricks - don't touch unless you know what you are doing. */ -STATIC_INLINE void long_fetch_ecs (int plane, int nwords, int weird_number_of_bits, int dma) -{ - uae_u16 *real_pt = (uae_u16 *)pfield_xlateptr (bplpt[plane], nwords * 2); - int delay = (plane & 1) ? toscr_delay2 : toscr_delay1; - int tmp_nbits = out_nbits; - uae_u32 shiftbuffer = todisplay[plane][0]; - uae_u32 outval = outword[plane]; - uae_u32 fetchval = fetched[plane]; - uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs); - - if (dma) { - bplpt[plane] += nwords * 2; - bplptx[plane] += nwords * 2; - } - - if (real_pt == 0) - /* @@@ Don't do this, fall back on chipmem_wget instead. */ - return; - - while (nwords > 0) { - int bits_left = 32 - tmp_nbits; - uae_u32 t; - - shiftbuffer |= fetchval; - - t = (shiftbuffer >> delay) & 0xFFFF; - - if (weird_number_of_bits && bits_left < 16) { - outval <<= bits_left; - outval |= t >> (16 - bits_left); - thisline_changed |= *dataptr ^ outval; - *dataptr++ = outval; - - outval = t; - tmp_nbits = 16 - bits_left; - shiftbuffer <<= 16; - } else { - outval = (outval << 16) | t; - shiftbuffer <<= 16; - tmp_nbits += 16; - if (tmp_nbits == 32) { - thisline_changed |= *dataptr ^ outval; - *dataptr++ = outval; - tmp_nbits = 0; - } - } - nwords--; - if (dma) { - fetchval = do_get_mem_word (real_pt); - real_pt++; - } - } - fetched[plane] = fetchval; - todisplay[plane][0] = shiftbuffer; - outword[plane] = outval; -} - -#ifdef AGA -STATIC_INLINE void long_fetch_aga (int plane, int nwords, int weird_number_of_bits, int fm, int dma) -{ - uae_u32 *real_pt = (uae_u32 *)pfield_xlateptr (bplpt[plane], nwords * 2); - int delay = (plane & 1) ? toscr_delay2 : toscr_delay1; - int tmp_nbits = out_nbits; - uae_u32 *shiftbuffer = todisplay[plane]; - uae_u32 outval = outword[plane]; - uae_u32 fetchval0 = fetched_aga0[plane]; - uae_u32 fetchval1 = fetched_aga1[plane]; - uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs); - int offs = (16 << fm) - 16 + delay; - int off1 = offs >> 5; - if (off1 == 3) - off1 = 2; - offs -= off1 * 32; - - if (dma) { - bplpt[plane] += nwords * 2; - bplptx[plane] += nwords * 2; - } - - if (real_pt == 0) - /* @@@ Don't do this, fall back on chipmem_wget instead. */ - return; - - while (nwords > 0) { - int i; - - shiftbuffer[0] = fetchval0; - if (fm == 2) - shiftbuffer[1] = fetchval1; - - for (i = 0; i < (1 << fm); i++) { - int bits_left = 32 - tmp_nbits; - - uae_u32 t0 = shiftbuffer[off1]; - uae_u32 t1 = shiftbuffer[off1 + 1]; - uae_u64 t = (((uae_u64)t1) << 32) | t0; - - t0 = (uae_u32)((t >> offs) & 0xFFFF); - - if (weird_number_of_bits && bits_left < 16) { - outval <<= bits_left; - outval |= t0 >> (16 - bits_left); - - thisline_changed |= *dataptr ^ outval; - *dataptr++ = outval; - - outval = t0; - tmp_nbits = 16 - bits_left; - aga_shift (shiftbuffer, 16, fm); - } else { - outval = (outval << 16) | t0; - aga_shift (shiftbuffer, 16, fm); - tmp_nbits += 16; - if (tmp_nbits == 32) { - thisline_changed |= *dataptr ^ outval; - *dataptr++ = outval; - tmp_nbits = 0; - } - } - } - - nwords -= 1 << fm; - - if (dma) { - if (fm == 1) - fetchval0 = do_get_mem_long (real_pt); - else { - fetchval1 = do_get_mem_long (real_pt); - fetchval0 = do_get_mem_long (real_pt + 1); - } - real_pt += fm; - } - } - fetched_aga0[plane] = fetchval0; - fetched_aga1[plane] = fetchval1; - outword[plane] = outval; -} -#endif - -static void long_fetch_ecs_0 (int hpos, int nwords, int dma) { long_fetch_ecs (hpos, nwords, 0, dma); } -static void long_fetch_ecs_1 (int hpos, int nwords, int dma) { long_fetch_ecs (hpos, nwords, 1, dma); } -#ifdef AGA -static void long_fetch_aga_1_0 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords, 0, 1, dma); } -static void long_fetch_aga_1_1 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords, 1, 1, dma); } -static void long_fetch_aga_2_0 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords, 0, 2, dma); } -static void long_fetch_aga_2_1 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords, 1, 2, dma); } -#endif - -static void do_long_fetch (int hpos, int nwords, int dma, int fm) -{ - int i; - - flush_display (fm); - switch (fm) { - case 0: - if (out_nbits & 15) { - for (i = 0; i < toscr_nr_planes; i++) - long_fetch_ecs_1 (i, nwords, dma); - } else { - for (i = 0; i < toscr_nr_planes; i++) - long_fetch_ecs_0 (i, nwords, dma); - } - break; -#ifdef AGA - case 1: - if (out_nbits & 15) { - for (i = 0; i < toscr_nr_planes; i++) - long_fetch_aga_1_1 (i, nwords, dma); - } else { - for (i = 0; i < toscr_nr_planes; i++) - long_fetch_aga_1_0 (i, nwords, dma); - } - break; - case 2: - if (out_nbits & 15) { - for (i = 0; i < toscr_nr_planes; i++) - long_fetch_aga_2_1 (i, nwords, dma); - } else { - for (i = 0; i < toscr_nr_planes; i++) - long_fetch_aga_2_0 (i, nwords, dma); - } - break; -#endif - } - - out_nbits += nwords * 16; - out_offs += out_nbits >> 5; - out_nbits &= 31; - - if (dma && toscr_nr_planes > 0) - fetch_state = fetch_was_plane0; -} - -#endif - -/* make sure fetch that goes beyond maxhpos is finished */ -static void finish_final_fetch (int pos, int fm) -{ - if (thisline_decision.plfleft == -1) - return; - if (plf_state == plf_end) - return; - plf_state = plf_end; - ddfstate = DIW_waiting_start; - pos += flush_plane_data (fm); - thisline_decision.plfright = pos; - thisline_decision.plflinelen = out_offs; - finish_playfield_line (); -} - -STATIC_INLINE int one_fetch_cycle_0 (int pos, int ddfstop_to_test, int dma, int fm) -{ - if (plf_state < plf_passed_stop && pos == ddfstop_to_test) - plf_state = plf_passed_stop; - - if ((fetch_cycle & fetchunit_mask) == 0) { - if (plf_state == plf_passed_stop2) { - finish_final_fetch (pos, fm); - return 1; - } - if (plf_state == plf_passed_stop) { - plf_state = plf_passed_stop2; - } else if (plf_state == plf_passed_stop2) { - plf_state = plf_end; - } - - } - - maybe_check (pos); - - if (dma) { - /* fetchstart_mask can be larger than fm_maxplane if FMODE > 0. This means - that the remaining cycles are idle; we'll fall through the whole switch - without doing anything. */ - int cycle_start = fetch_cycle & fetchstart_mask; - switch (fm_maxplane) { - case 8: - switch (cycle_start) { - case 0: fetch (7, fm, pos); break; - case 1: fetch (3, fm, pos); break; - case 2: fetch (5, fm, pos); break; - case 3: fetch (1, fm, pos); break; - case 4: fetch (6, fm, pos); break; - case 5: fetch (2, fm, pos); break; - case 6: fetch (4, fm, pos); break; - case 7: fetch (0, fm, pos); break; - } - break; - case 4: - switch (cycle_start) { - case 0: fetch (3, fm, pos); break; - case 1: fetch (1, fm, pos); break; - case 2: fetch (2, fm, pos); break; - case 3: fetch (0, fm, pos); break; - } - break; - case 2: - switch (cycle_start) { - case 0: fetch (1, fm, pos); break; - case 1: fetch (0, fm, pos); break; - } - break; - } - } - - if (bpl1dat_written) { - // do this here because if program plays with BPLCON0 during scanline - // it is possible that one DMA BPL1DAT write is completely missed - // and we must not draw anything at all in next dma block if this happens - // (Disposable Hero titlescreen) - fetch_state = fetch_was_plane0; - bpl1dat_written = 0; - } - - fetch_cycle++; - toscr_nbits += 2 << toscr_res; - - if (toscr_nbits > 16) { - uae_abort (_T("toscr_nbits > 16 (%d)"), toscr_nbits); - toscr_nbits = 0; - } - if (toscr_nbits == 16) - flush_display (fm); - - return 0; -} - -static int one_fetch_cycle_fm0 (int pos, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (pos, ddfstop_to_test, dma, 0); } -static int one_fetch_cycle_fm1 (int pos, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (pos, ddfstop_to_test, dma, 1); } -static int one_fetch_cycle_fm2 (int pos, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (pos, ddfstop_to_test, dma, 2); } - -STATIC_INLINE int one_fetch_cycle (int pos, int ddfstop_to_test, int dma, int fm) -{ - switch (fm) { - case 0: return one_fetch_cycle_fm0 (pos, ddfstop_to_test, dma); -#ifdef AGA - case 1: return one_fetch_cycle_fm1 (pos, ddfstop_to_test, dma); - case 2: return one_fetch_cycle_fm2 (pos, ddfstop_to_test, dma); -#endif - default: uae_abort (_T("fm corrupt")); return 0; - } -} - -static void update_fetch_x (int hpos, int fm) -{ - int pos; - - if (nodraw ()) - return; - - if (hpos < 0x18) - return; - pos = last_fetch_hpos; - if (pos < 0x18) - pos = 0x18; - update_toscr_planes (); - for (int i = 0; i < 8; i++) { - fetched[i] = bplxdat[i]; - bplxdat[i] = 0; - } - beginning_of_plane_block (hpos, fm); - for (; pos < hpos; pos++) { - - toscr_nbits += 2 << toscr_res; - - if (toscr_nbits > 16) { - uae_abort (_T("toscr_nbits > 16 (%d)"), toscr_nbits); - toscr_nbits = 0; - } - if (toscr_nbits == 16) - flush_display (fm); - - } - flush_display (fm); - bpl1dat_written = 0; -} - -STATIC_INLINE void update_fetch (int until, int fm) -{ - int pos; - int dma = dmaen (DMA_BITPLANE); - - int ddfstop_to_test; - - if (nodraw () || plf_state == plf_end) - return; - - /* We need an explicit test against HARD_DDF_STOP here to guard against - programs that move the DDFSTOP before our current position before we - reach it. */ - ddfstop_to_test = HARD_DDF_STOP; - if (ddfstop >= last_fetch_hpos && plfstop < ddfstop_to_test) - ddfstop_to_test = plfstop; - - update_toscr_planes (); - - pos = last_fetch_hpos; - cycle_diagram_shift = last_fetch_hpos - fetch_cycle; - - /* First, a loop that prepares us for the speedup code. We want to enter - the SPEEDUP case with fetch_state == fetch_was_plane0, and then unroll - whole blocks, so that we end on the same fetch_state again. */ - for (; ; pos++) { - if (pos == until) { - if (until >= maxhpos) { - finish_final_fetch (pos, fm); - return; - } - flush_display (fm); - return; - } - - if (fetch_state == fetch_was_plane0) - break; - - fetch_start (pos); - if (one_fetch_cycle (pos, ddfstop_to_test, dma, fm)) - return; - } - -#ifdef SPEEDUP - /* Unrolled version of the for loop below. */ - if (plf_state < plf_passed_stop && ddf_change != vpos && ddf_change + 1 != vpos - && dma - && (fetch_cycle & fetchstart_mask) == (fm_maxplane & fetchstart_mask) - && !badmode && !debug_dma -# if 0 - /* @@@ We handle this case, but the code would be simpler if we - * disallowed it - it may even be possible to guarantee that - * this condition never is false. Later. */ - && (out_nbits & 15) == 0 -# endif - && toscr_nr_planes == thisline_decision.nr_planes) - { - int offs = (pos - fetch_cycle) & fetchunit_mask; - int ddf2 = ((ddfstop_to_test - offs + fetchunit - 1) & ~fetchunit_mask) + offs; - int ddf3 = ddf2 + fetchunit; - int stop = until < ddf2 ? until : until < ddf3 ? ddf2 : ddf3; - int count; - - count = stop - pos; - - if (count >= fetchstart) { - count &= ~fetchstart_mask; - - if (thisline_decision.plfleft == -1) { - compute_delay_offset (); - compute_toscr_delay_1 (bplcon1); - } - - do_long_fetch (pos, count >> (3 - toscr_res), dma, fm); - - /* This must come _after_ do_long_fetch so as not to confuse flush_display - into thinking the first fetch has produced any output worth emitting to - the screen. But the calculation of delay_offset must happen _before_. */ - maybe_first_bpl1dat (pos); - - if (pos <= ddfstop_to_test && pos + count > ddfstop_to_test) - plf_state = plf_passed_stop; - if (pos <= ddfstop_to_test && pos + count > ddf2) - plf_state = plf_passed_stop2; - if (pos <= ddf2 && pos + count >= ddf2 + fm_maxplane) - add_modulos (); - pos += count; - fetch_cycle += count; - } - } else { -#endif -#ifdef SPEEDUP - } -#endif - for (; pos < until; pos++) { - if (fetch_state == fetch_was_plane0) { - beginning_of_plane_block (pos, fm); - estimate_last_fetch_cycle (pos); - } - fetch_start (pos); - - if (one_fetch_cycle (pos, ddfstop_to_test, dma, fm)) - return; - } - if (until >= maxhpos) { - finish_final_fetch (pos, fm); - return; - } - flush_display (fm); -} - -static void update_fetch_0 (int hpos) { update_fetch (hpos, 0); } -static void update_fetch_1 (int hpos) { update_fetch (hpos, 1); } -static void update_fetch_2 (int hpos) { update_fetch (hpos, 2); } - -STATIC_INLINE void decide_fetch (int hpos) -{ - if (hpos > last_fetch_hpos) { - if (fetch_state != fetch_not_started) { - switch (fetchmode) { - case 0: update_fetch_0 (hpos); break; -#ifdef AGA - case 1: update_fetch_1 (hpos); break; - case 2: update_fetch_2 (hpos); break; -#endif - default: uae_abort (_T("fetchmode corrupt")); - } - } else if (bpl1dat_written) { - // "PIO" mode display -#if 1 - if (!bpl1dat_done) { - bpl1dat_done = true; - //plfleft_real = thisline_decision.plfleft; - } - update_fetch_x (hpos, fetchmode); -#endif - } - maybe_check (hpos); - last_fetch_hpos = hpos; - } -} - -static void start_bpl_processing (int hpos, int hstart, bool dma) -{ - if (first_bpl_vpos < 0) - first_bpl_vpos = vpos; - - if (doflickerfix () && interlace_seen && !scandoubled_line) { - int i; - for (i = 0; i < 8; i++) { - prevbpl[lof_current][vpos][i] = bplptx[i]; - if (!lof_current && (bplcon0 & 4)) - bplpt[i] = prevbpl[1 - lof_current][vpos][i]; - if (!(bplcon0 & 4) || interlace_seen < 0) - prevbpl[1 - lof_current][vpos][i] = prevbpl[lof_current][vpos][i] = 0; - } - } - - plfstrt_sprite = plfstrt; - if (dma) - fetch_start (hpos); - fetch_cycle = 0; - last_fetch_hpos = hstart; - cycle_diagram_shift = last_fetch_hpos; - out_nbits = 0; - out_offs = 0; - toscr_nbits = 0; - thisline_decision.bplres = bplcon0_res; - - ddfstate = DIW_waiting_stop; - compute_toscr_delay (last_fetch_hpos, bplcon1); - - /* If someone already wrote BPL1DAT, clear the area between that point and - the real fetch start. */ - if (!nodraw ()) { - if (thisline_decision.plfleft != -1) { - out_nbits = (plfstrt - thisline_decision.plfleft) << (1 + toscr_res); - out_offs = out_nbits >> 5; - out_nbits &= 31; - } - update_toscr_planes (); - } -} - -/* this may turn on datafetch if program turns dma on during the ddf */ -static void maybe_start_bpl_dma (int hpos) -{ - /* OCS: BPL DMA never restarts if DMA is turned on during DDF - * ECS/AGA: BPL DMA restarts but only if DMA was turned off - outside of DDF or during current line, otherwise display - processing jumps immediately to "DDFSTOP passed"-condition */ - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - return; - if (fetch_state != fetch_not_started) - return; - if (diwstate != DIW_waiting_stop) - return; - if (hpos <= plfstrt) - return; - if (hpos > plfstop - fetchunit) - return; - if (ddfstate != DIW_waiting_start) - plf_state = plf_passed_stop; - start_bpl_processing (hpos, hpos, true); -} - -/* This function is responsible for turning on datafetch if necessary. */ -STATIC_INLINE void decide_line (int hpos) -{ - /* Take care of the vertical DIW. */ - if (vpos == plffirstline) { - diwstate = DIW_waiting_stop; - ddf_change = vpos; - } - if (vpos == plflastline) { - diwstate = DIW_waiting_start; - ddf_change = vpos; - } - - if (hpos <= last_decide_line_hpos) - return; - - if (fetch_state == fetch_not_started && (diwstate == DIW_waiting_stop || (currprefs.chipset_mask & CSMASK_ECS_AGNUS))) { - int ok = 0; - if (last_decide_line_hpos < plfstrt_start && hpos >= plfstrt_start) { - if (plf_state == plf_idle) - plf_state = plf_start; - } - if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) { - if (plf_state == plf_start) - plf_state = plf_active; - if (plf_state == plf_active) - ok = 1; - /* hack warning.. Writing to DDFSTRT when DMA should start must be ignored - * (correct fix would be emulate this delay for every custom register, but why bother..) */ - if (hpos - 2 == ddfstrt_old_hpos) - ok = 0; - } - if (ok && diwstate == DIW_waiting_stop) { - if (dmaen (DMA_BITPLANE)) { - start_bpl_processing (hpos, plfstrt, true); - estimate_last_fetch_cycle (plfstrt); - } - last_decide_line_hpos = hpos; -#ifndef CUSTOM_SIMPLE - do_sprites (hpos); -#endif - return; - } - } - -#ifndef CUSTOM_SIMPLE - if (hpos > last_sprite_hpos && last_sprite_hpos < SPR0_HPOS + 4 * MAX_SPRITES) - do_sprites (hpos); -#endif - - last_decide_line_hpos = hpos; -} - -/* Called when a color is about to be changed (write to a color register), -* but the new color has not been entered into the table yet. */ -static void record_color_change (int hpos, int regno, unsigned long value) -{ - if (regno < 0x1000 && nodraw ()) - return; - /* Early positions don't appear on-screen. */ - if (vpos < minfirstline) - return; - - decide_diw (hpos); - decide_line (hpos); - - if (thisline_decision.ctable == -1) - remember_ctable (); - - if ((regno < 0x1000 || regno == 0x1000 + 0x10c) && hpos < HBLANK_OFFSET && !(beamcon0 & 0x80) && prev_lineno >= 0) { - struct draw_info *pdip = curr_drawinfo + prev_lineno; - int idx = pdip->last_color_change; - int extrahpos = regno == 0x1000 + 0x10c ? 1 : 0; - bool lastsync = false; - /* Move color changes in horizontal cycles 0 to HBLANK_OFFSET to end of previous line. - * Cycles 0 to HBLANK_OFFSET are visible in right border on real Amigas. (because of late hsync) - */ - if (curr_color_changes[idx - 1].regno == 0xffff) { - idx--; - lastsync = true; - } - pdip->last_color_change++; - pdip->nr_color_changes++; - curr_color_changes[idx].linepos = (hpos + maxhpos) * 2 + extrahpos; - curr_color_changes[idx].regno = regno; - curr_color_changes[idx].value = value; - if (lastsync) { - curr_color_changes[idx + 1].linepos = hsyncstartpos * 2; - curr_color_changes[idx + 1].regno = 0xffff; - curr_color_changes[idx + 2].regno = -1; - } else { - curr_color_changes[idx + 1].regno = -1; - } - } - record_color_change2 (hpos, regno, value); - - if (regno == 0 && value != 0 && vpos >= 20) { - // autoscale if COLOR00 changes in top or bottom of screen - if (vpos >= minfirstline) { - int vpos2 = autoscale_bordercolors ? minfirstline : vpos; - if (first_planes_vpos == 0) - first_planes_vpos = vpos2 - 2; - if (plffirstline_total == current_maxvpos ()) - plffirstline_total = vpos2 - 2; - if (vpos2 > last_planes_vpos || vpos2 > plflastline_total) - plflastline_total = last_planes_vpos = vpos2 + 3; - autoscale_bordercolors = 0; - } else { - autoscale_bordercolors++; - } - } -} - -static void record_register_change (int hpos, int regno, unsigned long value) -{ - if (regno == 0x100) { // BPLCON0 - if (value & 0x800) - thisline_decision.ham_seen = 1; - thisline_decision.ehb_seen = !! isehb (value, bplcon2); - } else if (regno == 0x104) { // BPLCON2 - thisline_decision.ehb_seen = !! isehb (value, bplcon2); - } - record_color_change (hpos, regno + 0x1000, value); -} - -typedef int sprbuf_res_t, cclockres_t, hwres_t, bplres_t; - -static int expand_sprres (uae_u16 con0, uae_u16 con3) -{ - int res; - - switch ((con3 >> 6) & 3) - { - default: - res = RES_LORES; - break; -#ifdef ECS_DENISE - case 0: /* ECS defaults (LORES,HIRES=LORES sprite,SHRES=HIRES sprite) */ - if ((currprefs.chipset_mask & CSMASK_ECS_DENISE) && GET_RES_DENISE (con0) == RES_SUPERHIRES) - res = RES_HIRES; - else - res = RES_LORES; - break; -#endif -#ifdef AGA - case 1: - res = RES_LORES; - break; - case 2: - res = RES_HIRES; - break; - case 3: - res = RES_SUPERHIRES; - break; -#endif - } - return res; -} - -/* handle very rarely needed playfield collision (CLXDAT bit 0) */ -/* only known game needing this is Rotor */ -static void do_playfield_collisions (void) -{ - int bplres = bplcon0_res; - hwres_t ddf_left = thisline_decision.plfleft * 2 << bplres; - hwres_t hw_diwlast = coord_window_to_diw_x (thisline_decision.diwlastword); - hwres_t hw_diwfirst = coord_window_to_diw_x (thisline_decision.diwfirstword); - int i, collided, minpos, maxpos; -#ifdef AGA - int planes = (currprefs.chipset_mask & CSMASK_AGA) ? 8 : 6; -#else - int planes = 6; -#endif - - if (clxcon_bpl_enable == 0) { - clxdat |= 1; - return; - } - if (clxdat & 1) - return; - - collided = 0; - minpos = thisline_decision.plfleft * 2; - if (minpos < hw_diwfirst) - minpos = hw_diwfirst; - maxpos = thisline_decision.plfright * 2; - if (maxpos > hw_diwlast) - maxpos = hw_diwlast; - for (i = minpos; i < maxpos && !collided; i+= 32) { - int offs = ((i << bplres) - ddf_left) >> 3; - int j; - uae_u32 total = 0xffffffff; - for (j = 0; j < planes; j++) { - int ena = (clxcon_bpl_enable >> j) & 1; - int match = (clxcon_bpl_match >> j) & 1; - uae_u32 t = 0xffffffff; - if (ena) { - if (j < thisline_decision.nr_planes) { - t = *(uae_u32 *)(line_data[next_lineno] + offs + 2 * j * MAX_WORDS_PER_LINE); - t ^= (match & 1) - 1; - } else { - t = (match & 1) - 1; - } - } - total &= t; - } - if (total) { - collided = 1; -#if 0 - { - int k; - for (k = 0; k < 1; k++) { - uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + offs + 2 * k * MAX_WORDS_PER_LINE); - *ldata ^= 0x5555555555; - } - } -#endif - - } - } - if (collided) - clxdat |= 1; -} - -/* Sprite-to-sprite collisions are taken care of in record_sprite. This one does -playfield/sprite collisions. */ -static void do_sprite_collisions (void) -{ - int nr_sprites = curr_drawinfo[next_lineno].nr_sprites; - int first = curr_drawinfo[next_lineno].first_sprite_entry; - int i; - unsigned int collision_mask = clxmask[clxcon >> 12]; - int bplres = bplcon0_res; - hwres_t ddf_left = thisline_decision.plfleft * 2 << bplres; - hwres_t hw_diwlast = coord_window_to_diw_x (thisline_decision.diwlastword); - hwres_t hw_diwfirst = coord_window_to_diw_x (thisline_decision.diwfirstword); - - if (clxcon_bpl_enable == 0) { - clxdat |= 0x1FE; - return; - } - - for (i = 0; i < nr_sprites; i++) { - struct sprite_entry *e = curr_sprite_entries + first + i; - sprbuf_res_t j; - sprbuf_res_t minpos = e->pos; - sprbuf_res_t maxpos = e->max; - hwres_t minp1 = minpos >> sprite_buffer_res; - hwres_t maxp1 = maxpos >> sprite_buffer_res; - - if (maxp1 > hw_diwlast) - maxpos = hw_diwlast << sprite_buffer_res; - if (maxp1 > thisline_decision.plfright * 2) - maxpos = thisline_decision.plfright * 2 << sprite_buffer_res; - if (minp1 < hw_diwfirst) - minpos = hw_diwfirst << sprite_buffer_res; - if (minp1 < thisline_decision.plfleft * 2) - minpos = thisline_decision.plfleft * 2 << sprite_buffer_res; - - for (j = minpos; j < maxpos; j++) { - int sprpix = spixels[e->first_pixel + j - e->pos] & collision_mask; - int k, offs, match = 1; - - if (sprpix == 0) - continue; - - offs = ((j << bplres) >> sprite_buffer_res) - ddf_left; - sprpix = sprite_ab_merge[sprpix & 255] | (sprite_ab_merge[sprpix >> 8] << 2); - sprpix <<= 1; - - /* Loop over number of playfields. */ - for (k = 1; k >= 0; k--) { - int l; -#ifdef AGA - int planes = (currprefs.chipset_mask & CSMASK_AGA) ? 8 : 6; -#else - int planes = 6; -#endif - if (bplcon0 & 0x400) - match = 1; - for (l = k; match && l < planes; l += 2) { - int t = 0; - if (l < thisline_decision.nr_planes) { - uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE); - uae_u32 word = ldata[offs >> 5]; - t = (word >> (31 - (offs & 31))) & 1; -#if 0 /* debug: draw collision mask */ - if (1) { - int m; - for (m = 0; m < 5; m++) { - ldata = (uae_u32 *)(line_data[next_lineno] + 2 * m * MAX_WORDS_PER_LINE); - ldata[(offs >> 5) + 1] |= 15 << (31 - (offs & 31)); - } - } -#endif - } - if (clxcon_bpl_enable & (1 << l)) { - if (t != ((clxcon_bpl_match >> l) & 1)) - match = 0; - } - } - if (match) { -#if 0 /* debug: mark lines where collisions are detected */ - if (0) { - int l; - for (l = 0; l < 5; l++) { - uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE); - ldata[(offs >> 5) + 1] |= 15 << (31 - (offs & 31)); - } - } -#endif - clxdat |= sprpix << (k * 4); - } - } - } - } -#if 0 - { - static int olx; - if (clxdat != olx) - write_log (_T("%d: %04X\n"), vpos, clxdat); - olx = clxdat; - } -#endif -} - -STATIC_INLINE void record_sprite_1 (int sprxp, uae_u16 *buf, uae_u32 datab, int num, int dbl, - unsigned int mask, int do_collisions, uae_u32 collision_mask) -{ - int j = 0; - while (datab) { - unsigned int col = 0; - unsigned coltmp = 0; - - if ((sprxp >= sprite_minx && sprxp < sprite_maxx) || (bplcon3 & 2)) - col = (datab & 3) << (2 * num); -#if 0 - if (sprxp == sprite_minx || sprxp == sprite_maxx - 1) - col ^= (rand () << 16) | rand (); -#endif - if ((j & mask) == 0) { - unsigned int tmp = (*buf) | col; - *buf++ = tmp; - if (do_collisions) - coltmp |= tmp; - sprxp++; - } - if (dbl > 0) { - unsigned int tmp = (*buf) | col; - *buf++ = tmp; - if (do_collisions) - coltmp |= tmp; - sprxp++; - } - if (dbl > 1) { - unsigned int tmp; - tmp = (*buf) | col; - *buf++ = tmp; - if (do_collisions) - coltmp |= tmp; - tmp = (*buf) | col; - *buf++ = tmp; - if (do_collisions) - coltmp |= tmp; - sprxp++; - sprxp++; - } - j++; - datab >>= 2; - if (do_collisions) { - coltmp &= collision_mask; - if (coltmp) { - unsigned int shrunk_tmp = sprite_ab_merge[coltmp & 255] | (sprite_ab_merge[coltmp >> 8] << 2); - clxdat |= sprclx[shrunk_tmp]; - } - } - } -} - -/* DATAB contains the sprite data; 16 pixels in two-bit packets. Bits 0/1 -determine the color of the leftmost pixel, bits 2/3 the color of the next -etc. -This function assumes that for all sprites in a given line, SPRXP either -stays equal or increases between successive calls. - -The data is recorded either in lores pixels (if OCS/ECS), or in hires or -superhires pixels (if AGA). */ - -static void record_sprite (int line, int num, int sprxp, uae_u16 *data, uae_u16 *datb, unsigned int ctl) -{ - struct sprite_entry *e = curr_sprite_entries + next_sprite_entry; - int i; - int word_offs; - uae_u32 collision_mask; - int width, dbl, half; - unsigned int mask = 0; - int attachment; - - half = 0; - dbl = sprite_buffer_res - sprres; - if (dbl < 0) { - half = -dbl; - dbl = 0; - mask = 1 << half; - } - width = (sprite_width << sprite_buffer_res) >> sprres; - attachment = sprctl[num | 1] & 0x80; - - /* Try to coalesce entries if they aren't too far apart */ - if (!next_sprite_forced && e[-1].max + sprite_width >= sprxp) { - e--; - } else { - next_sprite_entry++; - e->pos = sprxp; - e->has_attached = 0; - } - - if (sprxp < e->pos) - uae_abort (_T("sprxp < e->pos")); - - e->max = sprxp + width; - e[1].first_pixel = e->first_pixel + ((e->max - e->pos + 3) & ~3); - next_sprite_forced = 0; - - collision_mask = clxmask[clxcon >> 12]; - word_offs = e->first_pixel + sprxp - e->pos; - - for (i = 0; i < sprite_width; i += 16) { - unsigned int da = *data; - unsigned int db = *datb; - uae_u32 datab = ((sprtaba[da & 0xFF] << 16) | sprtaba[da >> 8] - | (sprtabb[db & 0xFF] << 16) | sprtabb[db >> 8]); - int off = (i << dbl) >> half; - uae_u16 *buf = spixels + word_offs + off; - if (currprefs.collision_level > 0 && collision_mask) - record_sprite_1 (sprxp + off, buf, datab, num, dbl, mask, 1, collision_mask); - else - record_sprite_1 (sprxp + off, buf, datab, num, dbl, mask, 0, collision_mask); - data++; - datb++; - } - - /* We have 8 bits per pixel in spixstate, two for every sprite pair. The - low order bit records whether the attach bit was set for this pair. */ - if (attachment && !ecsshres ()) { - uae_u32 state = 0x01010101 << (num & ~1); - uae_u8 *stb1 = spixstate.bytes + word_offs; - for (i = 0; i < width; i += 8) { - stb1[0] |= state; - stb1[1] |= state; - stb1[2] |= state; - stb1[3] |= state; - stb1[4] |= state; - stb1[5] |= state; - stb1[6] |= state; - stb1[7] |= state; - stb1 += 8; - } - e->has_attached = 1; - } -} - -static void add_sprite (int *countp, int num, int sprxp, int posns[], int nrs[]) -{ - int count = *countp; - int j, bestp; - - /* Sort the sprites in order of ascending X position before recording them. */ - for (bestp = 0; bestp < count; bestp++) { - if (posns[bestp] > sprxp) - break; - if (posns[bestp] == sprxp && nrs[bestp] < num) - break; - } - for (j = count; j > bestp; j--) { - posns[j] = posns[j - 1]; - nrs[j] = nrs[j - 1]; - } - posns[j] = sprxp; - nrs[j] = num; - count++; - *countp = count; -} - -static int tospritexdiw (int diw) -{ - return coord_window_to_hw_x (diw - (DIW_DDF_OFFSET << lores_shift)) << sprite_buffer_res; -} -static int tospritexddf (int ddf) -{ - return (ddf * 2) << sprite_buffer_res; -} -static int fromspritexdiw (int ddf) -{ - return coord_hw_to_window_x (ddf >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift); -} - -static void calcsprite (void) -{ - sprite_maxx = 0x7fff; - sprite_minx = 0; - if (thisline_decision.diwlastword >= 0) - sprite_maxx = tospritexdiw (thisline_decision.diwlastword); - if (thisline_decision.diwfirstword >= 0) - sprite_minx = tospritexdiw (thisline_decision.diwfirstword); - if (thisline_decision.plfleft >= 0) { - int min, max; - min = tospritexddf (thisline_decision.plfleft); - max = tospritexddf (thisline_decision.plfright); - if (min > sprite_minx && min < max) /* min < max = full line ddf */ - sprite_minx = min; - /* sprites are visible from first BPL1DAT write to end of line - * (undocumented feature) - */ - } -} - -static void decide_sprites (int hpos) -{ - int nrs[MAX_SPRITES * 2], posns[MAX_SPRITES * 2]; - int count, i; - /* apparantly writes to custom registers happen in the 3/4th of cycle - * and sprite xpos comparator sees it immediately */ - int point = hpos * 2 - 3; - int width = sprite_width; - int sscanmask = 0x100 << sprite_buffer_res; - int gotdata = 0; - - if (thisline_decision.plfleft == -1 && !(bplcon3 & 2)) - return; - - if (nodraw () || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point) - return; - - decide_diw (hpos); - decide_line (hpos); - calcsprite (); - - count = 0; - for (i = 0; i < MAX_SPRITES; i++) { - int sprxp = (fmode & 0x8000) ? (spr[i].xpos & ~sscanmask) : spr[i].xpos; - int hw_xp = sprxp >> sprite_buffer_res; - - if (spr[i].xpos < 0) - continue; - - if (!((debug_sprite_mask & magic_sprite_mask) & (1 << i))) - continue; - - if (! spr[i].armed) - continue; - - if (hw_xp > last_sprite_point && hw_xp <= point) - add_sprite (&count, i, sprxp, posns, nrs); - - /* SSCAN2-bit is fun.. */ - if ((fmode & 0x8000) && !(sprxp & sscanmask)) { - sprxp |= sscanmask; - hw_xp = sprxp >> sprite_buffer_res; - if (hw_xp > last_sprite_point && hw_xp <= point) - add_sprite (&count, MAX_SPRITES + i, sprxp, posns, nrs); - } - } - - for (i = 0; i < count; i++) { - int nr = nrs[i] & (MAX_SPRITES - 1); - record_sprite (next_lineno, nr, posns[i], sprdata[nr], sprdatb[nr], sprctl[nr]); - /* get left and right sprite edge if brdsprt enabled */ -#if AUTOSCALE_SPRITES - if (dmaen (DMA_SPRITE) && (bplcon0 & 1) && (bplcon3 & 0x02) && !(bplcon3 & 0x20)) { - int j, jj; - for (j = 0, jj = 0; j < sprite_width; j+= 16, jj++) { - int nx = fromspritexdiw (posns[i] + j); - if (sprdata[nr][jj] || sprdatb[nr][jj]) { - if (diwfirstword_total > nx && nx >= (48 << currprefs.gfx_resolution)) - diwfirstword_total = nx; - if (diwlastword_total < nx + 16 && nx <= (448 << currprefs.gfx_resolution)) - diwlastword_total = nx + 16; - } - } - gotdata = 1; - } -#endif - } - last_sprite_point = point; - -#if AUTOSCALE_SPRITES - /* get upper and lower sprite position if brdsprt enabled */ - if (gotdata) { - if (vpos < first_planes_vpos) - first_planes_vpos = vpos; - if (vpos < plffirstline_total) - plffirstline_total = vpos; - if (vpos > last_planes_vpos) - last_planes_vpos = vpos; - if (vpos > plflastline_total) - plflastline_total = vpos; - } -#endif -} - -STATIC_INLINE int sprites_differ (struct draw_info *dip, struct draw_info *dip_old) -{ - struct sprite_entry *this_first = curr_sprite_entries + dip->first_sprite_entry; - struct sprite_entry *this_last = curr_sprite_entries + dip->last_sprite_entry; - struct sprite_entry *prev_first = prev_sprite_entries + dip_old->first_sprite_entry; - int npixels; - int i; - - if (dip->nr_sprites != dip_old->nr_sprites) - return 1; - - if (dip->nr_sprites == 0) - return 0; - - for (i = 0; i < dip->nr_sprites; i++) - if (this_first[i].pos != prev_first[i].pos - || this_first[i].max != prev_first[i].max - || this_first[i].has_attached != prev_first[i].has_attached) - return 1; - - npixels = this_last->first_pixel + (this_last->max - this_last->pos) - this_first->first_pixel; - if (memcmp (spixels + this_first->first_pixel, spixels + prev_first->first_pixel, - npixels * sizeof (uae_u16)) != 0) - return 1; - if (memcmp (spixstate.bytes + this_first->first_pixel, spixstate.bytes + prev_first->first_pixel, npixels) != 0) - return 1; - return 0; -} - -STATIC_INLINE int color_changes_differ (struct draw_info *dip, struct draw_info *dip_old) -{ - if (dip->nr_color_changes != dip_old->nr_color_changes) - return 1; - - if (dip->nr_color_changes == 0) - return 0; - if (memcmp (curr_color_changes + dip->first_color_change, - prev_color_changes + dip_old->first_color_change, - dip->nr_color_changes * sizeof *curr_color_changes) != 0) - return 1; - return 0; -} - -/* End of a horizontal scan line. Finish off all decisions that were not -* made yet. */ -static void finish_decisions (void) -{ - struct draw_info *dip; - struct draw_info *dip_old; - struct decision *dp; - int changed; - int hpos = maxhpos; - - if (nodraw ()) - return; - - decide_diw (hpos); - decide_line (hpos); - decide_fetch (hpos); - if (bpl1dat_done) { - finish_final_fetch (hpos, fetchmode); - bpl1dat_done = 0; - } - - record_color_change2 (hsyncstartpos, 0xffff, 0); - if (thisline_decision.plfleft != -1 && thisline_decision.plflinelen == -1) { - if (fetch_state != fetch_not_started) { - write_log (_T("fetch_state=%d plfleft=%d,len=%d,vpos=%d,hpos=%d\n"), - fetch_state, thisline_decision.plfleft, thisline_decision.plflinelen, - vpos, hpos); - uae_abort (_T("fetch_state != fetch_not_started")); - } - thisline_decision.plfright = thisline_decision.plfleft; - thisline_decision.plflinelen = 0; - thisline_decision.bplres = RES_LORES; - } - - /* Large DIWSTOP values can cause the stop position never to be - * reached, so the state machine always stays in the same state and - * there's a more-or-less full-screen DIW. */ - if (hdiwstate == DIW_waiting_stop) { - thisline_decision.diwlastword = max_diwlastword; - if (thisline_decision.diwfirstword == -1) - thisline_decision.diwfirstword = 0; - } - - if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword) - MARK_LINE_CHANGED; - if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword) - MARK_LINE_CHANGED; - - dip = curr_drawinfo + next_lineno; - dip_old = prev_drawinfo + next_lineno; - dp = line_decisions + next_lineno; - changed = thisline_changed; - if (thisline_decision.plfleft != -1 && thisline_decision.nr_planes > 0) - record_diw_line (thisline_decision.plfleft, diwfirstword, diwlastword); - - decide_sprites (hpos + 1); - - dip->last_sprite_entry = next_sprite_entry; - dip->last_color_change = next_color_change; - - if (thisline_decision.ctable == -1) { - if (thisline_decision.plfleft == -1) - remember_ctable_for_border (); - else - remember_ctable (); - } - - dip->nr_color_changes = next_color_change - dip->first_color_change; - dip->nr_sprites = next_sprite_entry - dip->first_sprite_entry; - - if (thisline_decision.plfleft != line_decisions[next_lineno].plfleft) - changed = 1; - if (! changed && color_changes_differ (dip, dip_old)) - changed = 1; - if (!changed && thisline_decision.plfleft != -1 && sprites_differ (dip, dip_old)) - changed = 1; - - if (changed) { - thisline_changed = 1; - *dp = thisline_decision; - } else - /* The only one that may differ: */ - dp->ctable = thisline_decision.ctable; - - /* leave free space for possible extra color changes at the end of line */ - next_color_change += (HBLANK_OFFSET + 1) / 2; - - diw_hcounter += maxhpos * 2; - if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE) && vpos == equ_vblank_endline - 1) - diw_hcounter++; - if ((currprefs.chipset_mask & CSMASK_ECS_DENISE) || vpos > equ_vblank_endline || (currprefs.cs_dipagnus && vpos == 0)) { - diw_hcounter = maxhpos * 2; - last_hdiw = 2 - 1; - } - - if (next_color_change >= MAX_REG_CHANGE - 30) { - write_log (_T("color_change buffer overflow!\n")); - next_color_change = 0; - dip->nr_color_changes = 0; - dip->first_color_change = 0; - } -} - -/* Set the state of all decisions to "undecided" for a new scanline. */ -static void reset_decisions (void) -{ - if (nodraw ()) - return; - - toscr_nr_planes = toscr_nr_planes2 = 0; - thisline_decision.bplres = bplcon0_res; - thisline_decision.nr_planes = 0; - bpl1dat_written = 0; - bpl1dat_early = 0; - - plfleft_real = -1; - thisline_decision.plfleft = -1; - thisline_decision.plflinelen = -1; - thisline_decision.ham_seen = !! (bplcon0 & 0x800); - thisline_decision.ehb_seen = !! isehb (bplcon0, bplcon2); - thisline_decision.ham_at_start = !! (bplcon0 & 0x800); - - /* decided_res shouldn't be touched before it's initialized by decide_line(). */ - thisline_decision.diwfirstword = -1; - thisline_decision.diwlastword = -1; - if (hdiwstate == DIW_waiting_stop) { - thisline_decision.diwfirstword = 0; - if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword) - MARK_LINE_CHANGED; - } - thisline_decision.ctable = -1; - - thisline_changed = 0; - curr_drawinfo[next_lineno].first_color_change = next_color_change; - curr_drawinfo[next_lineno].first_sprite_entry = next_sprite_entry; - next_sprite_forced = 1; - - last_sprite_point = 0; - fetch_state = fetch_not_started; - bplcon1_hpos = -1; - if (bpldmasetuphpos >= 0) { - // this can happen in "too fast" modes - BPLCON0_Denise (0, bplcon0); - setup_fmodes (0); - } - bpldmasetuphpos = -1; - bpldmasetupphase = 0; - ddfstrt_old_hpos = -1; - - if (plf_state > plf_active) - plf_state = plf_idle; - if (plf_state == plf_active && !(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - plf_state = plf_idle; - - memset (todisplay, 0, sizeof todisplay); - memset (fetched, 0, sizeof fetched); -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) { - memset (fetched_aga0, 0, sizeof fetched_aga0); - memset (fetched_aga1, 0, sizeof fetched_aga1); - } -#endif - memset (outword, 0, sizeof outword); - - last_decide_line_hpos = -1; - last_ddf_pix_hpos = -1; - last_sprite_hpos = -1; - last_fetch_hpos = -1; - - /* These are for comparison. */ - thisline_decision.bplcon0 = bplcon0; - thisline_decision.bplcon2 = bplcon2; -#ifdef ECS_DENISE - thisline_decision.bplcon3 = bplcon3; -#endif -#ifdef AGA - thisline_decision.bplcon4 = bplcon4; -#endif -} - -static int islinetoggle (void) -{ - int linetoggle = 0; - if (!(beamcon0 & 0x0800) && !(beamcon0 & 0x0020) && (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) { - linetoggle = 1; // NTSC and !LOLDIS -> LOL toggles every line - } else if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS) && currprefs.ntscmode) { - linetoggle = 1; // hardwired NTSC Agnus - } - return linetoggle; -} - -static int isvsync (void) -{ - if (picasso_on || !currprefs.gfx_avsync || (currprefs.gfx_avsync == 0 && !currprefs.gfx_afullscreen)) - return 0; - return currprefs.gfx_avsyncmode == 0 ? 1 : -1; -} - -int vsynctime_orig; - -void compute_vsynctime (void) -{ - fake_vblank_hz = 0; - if (abs (currprefs.chipset_refreshrate) > 0.1) { - vblank_hz = currprefs.chipset_refreshrate; - if (isvsync ()) { - vblank_skip = 1; - if (!fake_vblank_hz && getvsyncrate (vblank_hz) != vblank_hz) { - vblank_hz = getvsyncrate (vblank_hz); - vblank_skip = -1; - } - } - } - if (!fake_vblank_hz) - fake_vblank_hz = vblank_hz; - if (currprefs.turbo_emulation) - vsynctime = vsynctime_orig = 1; - else - vsynctime = vsynctime_orig = syncbase / fake_vblank_hz; - if (!picasso_on) { - updatedisplayarea (); - } - if (currprefs.produce_sound > 1) - update_sound (fake_vblank_hz, (bplcon0 & 4) ? -1 : lof_store, islinetoggle ()); -} - - -static void dumpsync (void) -{ - static int cnt = 100; - if (cnt < 0) - return; - cnt--; - write_log (_T("BEAMCON0=%04X VTOTAL=%04X HTOTAL=%04X\n"), new_beamcon0, vtotal, htotal); - write_log (_T(" HSSTOP=%04X HBSTRT=%04X HBSTOP=%04X\n"), hsstop, hbstrt, hbstop); - write_log (_T(" VSSTOP=%04X VBSTRT=%04X VBSTOP=%04X\n"), vsstop, vbstrt, vbstop); - write_log (_T(" HSSTRT=%04X VSSTRT=%04X HCENTER=%04X\n"), hsstrt, vsstrt, hcenter); -} - -int current_maxvpos (void) -{ - return maxvpos + (lof_store ? 1 : 0); -} - -/* set PAL/NTSC or custom timing variables */ -void init_hz (bool fullinit) -{ - int isntsc; - int odbl = doublescan, omaxvpos = maxvpos; - double ovblank = vblank_hz; - int hzc = 0; - - if (fullinit) - vpos_count = vpos_count_prev = 0; - - if (vsync_switchmode (-1, 0)) - currprefs.gfx_avsync = changed_prefs.gfx_avsync = vsync_switchmode (-1, 0) ? 2 : 0; - - if (!isvsync () && (DBLEQU (currprefs.chipset_refreshrate, 50) && !currprefs.ntscmode) || - (DBLEQU (currprefs.chipset_refreshrate, 60) && currprefs.ntscmode)) { - currprefs.chipset_refreshrate = changed_prefs.chipset_refreshrate = 0.0; - } - - doublescan = 0; - if ((beamcon0 & 0xA0) != (new_beamcon0 & 0xA0)) - hzc = 1; - if (beamcon0 != new_beamcon0) { - write_log (_T("BEAMCON0 %04x -> %04x PC%=%08x\n"), beamcon0, new_beamcon0, M68K_GETPC); - vpos_count = vpos_count_prev = 0; - } - beamcon0 = new_beamcon0; - isntsc = (beamcon0 & 0x20) ? 0 : 1; - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - isntsc = currprefs.ntscmode ? 1 : 0; - if (!isntsc) { - maxvpos = MAXVPOS_PAL; - maxhpos = MAXHPOS_PAL; - minfirstline = VBLANK_ENDLINE_PAL; - vblank_hz = VBLANK_HZ_PAL; - sprite_vblank_endline = VBLANK_SPRITE_PAL; - equ_vblank_endline = EQU_ENDLINE_PAL; - } else { - maxvpos = MAXVPOS_NTSC; - maxhpos = MAXHPOS_NTSC; - minfirstline = VBLANK_ENDLINE_NTSC; - vblank_hz = VBLANK_HZ_NTSC; - sprite_vblank_endline = VBLANK_SPRITE_NTSC; - equ_vblank_endline = EQU_ENDLINE_NTSC; - } - maxvpos_nom = maxvpos; - if (vpos_count > 0) { - // we come here if vpos_count != maxvpos (someone poked VPOSW) - if (vpos_count < 10) - vpos_count = 10; - vblank_hz = (isntsc ? 15734 : 15625.0) / vpos_count; - maxvpos_nom = vpos_count - (lof_current ? 1 : 0); - reset_drawing (); - } - if (beamcon0 & 0x80) { - // programmable scanrates (ECS Agnus) - if (vtotal >= MAXVPOS) - vtotal = MAXVPOS - 1; - maxvpos = vtotal + 1; - if (htotal >= MAXHPOS) - htotal = MAXHPOS - 1; - maxhpos = htotal + 1; - vblank_hz = 227.0 * 312.0 * 50.0 / (maxvpos * maxhpos); - minfirstline = vsstop; - if (minfirstline < 2) - minfirstline = 2; - if (minfirstline >= maxvpos) - minfirstline = maxvpos - 1; - sprite_vblank_endline = minfirstline - 2; - maxvpos_nom = maxvpos; - equ_vblank_endline = -1; - doublescan = htotal <= 164 ? 1 : 0; - dumpsync (); - hzc = 1; - } - if (maxvpos_nom >= MAXVPOS) - maxvpos_nom = MAXVPOS; - if (currprefs.gfx_scandoubler && doublescan == 0) - doublescan = -1; - if (doublescan != odbl || maxvpos != omaxvpos) - hzc = 1; - /* limit to sane values */ - if (vblank_hz < 10) - vblank_hz = 10; - if (vblank_hz > 300) - vblank_hz = 300; - maxhpos_short = maxhpos; - if (beamcon0 & 0x80) { - if (hbstrt > maxhpos) - hsyncstartpos = hbstrt; - else - hsyncstartpos = maxhpos + hbstrt; - if (hbstop > maxhpos) - hsyncendpos = hbstop; - else - hsyncendpos = maxhpos + hbstop; - } else { - hsyncstartpos = maxhpos_short + 13; - hsyncendpos = 24; - } - eventtab[ev_hsync].oldcycles = get_cycles (); - eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME; - events_schedule (); - if (hzc) { - interlace_seen = (bplcon0 & 4) ? 1 : 0; - reset_drawing (); - } - if ((DBLEQU (vblank_hz, 50) || DBLEQU (vblank_hz, 60)) && isvsync () && currprefs.gfx_avsync == 2 && currprefs.gfx_afullscreen > 0) { - if (getvsyncrate (currprefs.gfx_refreshrate) != vblank_hz) - vsync_switchmode (vblank_hz, currprefs.gfx_refreshrate); - } - if (isvsync () > 0) { - changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate = abs (currprefs.gfx_refreshrate); - } - maxvpos_total = (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? 2047 : 511; - if (maxvpos_total > MAXVPOS) - maxvpos_total = MAXVPOS; - if (!p96refresh_active) { - maxvpos_stored = maxvpos; - maxhpos_stored = maxhpos; - vblank_hz_stored = vblank_hz; - } - - compute_vsynctime (); -#ifdef PICASSO96 - init_hz_p96 (); -#endif - if (vblank_hz != ovblank) - updatedisplayarea (); - inputdevice_tablet_strobe (); - write_log (_T("%s mode%s%s V=%.4fHz H=%0.4fHz (%dx%d+%d)\n"), - isntsc ? _T("NTSC") : _T("PAL"), - (bplcon0 & 4) ? _T(" interlaced") : _T(""), - doublescan > 0 ? _T(" dblscan") : _T(""), - vblank_hz, vblank_hz * maxvpos_nom, - maxhpos, maxvpos, lof_store ? 1 : 0); - config_changed = 1; -} - -void init_hz (void) -{ - init_hz (false); -} -void init_hz_full (void) -{ - init_hz (true); -} - -static void calcdiw (void) -{ - int hstrt = diwstrt & 0xFF; - int hstop = diwstop & 0xFF; - int vstrt = diwstrt >> 8; - int vstop = diwstop >> 8; - - // vertical in ECS Agnus - if (diwhigh_written && (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) { - vstrt |= (diwhigh & 7) << 8; - vstop |= ((diwhigh >> 8) & 7) << 8; - } else { - if ((vstop & 0x80) == 0) - vstop |= 0x100; - } - // horizontal in ECS Denise - if (diwhigh_written && (currprefs.chipset_mask & CSMASK_ECS_DENISE)) { - hstrt |= ((diwhigh >> 5) & 1) << 8; - hstop |= ((diwhigh >> 13) & 1) << 8; - } else { - hstop += 0x100; - } - - diw_hstrt = hstrt; - diw_hstop = hstop; - - diwfirstword = coord_diw_to_window_x (hstrt); - diwlastword = coord_diw_to_window_x (hstop); - if (diwfirstword >= diwlastword) { - diwfirstword = 0; - diwlastword = max_diwlastword; - } - if (diwfirstword < 0) - diwfirstword = 0; - - plffirstline = vstrt; - plflastline = vstop; - - plfstrt = ddfstrt; - plfstop = ddfstop; - /* probably not the correct place.. should use plf_state instead */ - if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) { - /* ECS/AGA and ddfstop > maxhpos == always-on display */ - if (plfstop > maxhpos) - plfstrt = 0; - if (plfstrt < HARD_DDF_START) - plfstrt = HARD_DDF_START; - plfstrt_start = plfstrt - 4; - } else { - /* OCS and ddfstrt >= ddfstop == ddfstop = max */ - if (plfstrt >= plfstop && plfstrt >= HARD_DDF_START) - plfstop = 0xff; - plfstrt_start = HARD_DDF_START - 2; - } - diw_change = 2; -} - -/* display mode changed (lores, doubling etc..), recalculate everything */ -void init_custom (void) -{ - update_mirrors(); - create_cycle_diagram_table (); - reset_drawing (); - init_hz_full (); - calcdiw (); -} - -static int timehack_alive = 0; - -static uae_u32 REGPARAM2 timehack_helper (TrapContext *context) -{ -#ifdef HAVE_GETTIMEOFDAY - struct timeval tv; - if (m68k_dreg (regs, 0) == 0) - return timehack_alive; - - timehack_alive = 10; - - gettimeofday (&tv, NULL); - x_put_long (m68k_areg (regs, 0), tv.tv_sec - (((365 * 8 + 2) * 24) * 60 * 60)); - x_put_long (m68k_areg (regs, 0) + 4, tv.tv_usec); - return 0; -#else - return 2; -#endif -} - -/* -* register functions -*/ -STATIC_INLINE uae_u16 DENISEID (void) -{ - if (currprefs.cs_deniserev >= 0) - return currprefs.cs_deniserev; -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) { - if (currprefs.cs_ide == IDE_A4000) - return 0xFCF8; - return 0x00F8; - } -#endif - if (currprefs.chipset_mask & CSMASK_ECS_DENISE) - return 0xFFFC; - return 0xFFFF; -} -STATIC_INLINE uae_u16 DMACONR (int hpos) -{ - decide_line (hpos); - decide_fetch (hpos); - decide_blitter (hpos); - dmacon &= ~(0x4000 | 0x2000); - dmacon |= ((blit_interrupt || (!blit_interrupt && currprefs.cs_agnusbltbusybug && !blt_info.got_cycle)) ? 0 : 0x4000) - | (blt_info.blitzero ? 0x2000 : 0); - return dmacon; -} -STATIC_INLINE uae_u16 INTENAR (void) -{ - return intena; -} -uae_u16 INTREQR (void) -{ - return intreq; -} -STATIC_INLINE uae_u16 ADKCONR (void) -{ - return adkcon; -} - -STATIC_INLINE int islightpentriggered (void) -{ - if (beamcon0 & 0x2000) // LPENDIS - return 0; - return lightpen_triggered > 0; -} -STATIC_INLINE int issyncstopped (void) -{ - return (bplcon0 & 2) && !currprefs.genlock; -} - -STATIC_INLINE int GETVPOS (void) -{ - return islightpentriggered () ? vpos_lpen : (issyncstopped () ? vpos_previous : vpos); -} -STATIC_INLINE int GETHPOS (void) -{ - return islightpentriggered () ? hpos_lpen : (issyncstopped () ? hpos_previous : current_hpos ()); -} - - -// DFF006 = 0.W must be valid result but better do this only in 68000 modes (whdload black screen!) - -#define HPOS_OFFSET (currprefs.cpu_model < 68020 ? 3 : 0) - -STATIC_INLINE uae_u16 VPOSR (void) -{ - unsigned int csbit = 0; - uae_u16 vp = GETVPOS (); - uae_u16 hp = GETHPOS (); - - if (hp + HPOS_OFFSET >= maxhpos) { - vp++; - if (vp >= maxvpos + lof_store) - vp = 0; - } - vp = (vp >> 8) & 7; - - if (currprefs.cs_agnusrev >= 0) { - csbit |= currprefs.cs_agnusrev << 8; - } else { -#ifdef AGA - csbit |= (currprefs.chipset_mask & CSMASK_AGA) ? 0x2300 : 0; -#endif - csbit |= (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? 0x2000 : 0; - if (currprefs.chipmem_size > 1024 * 1024 && (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - csbit |= 0x2100; - if (currprefs.ntscmode) - csbit |= 0x1000; - } - - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - vp &= 1; - vp = vp | (lof_store ? 0x8000 : 0) | csbit; - if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) - vp |= lol ? 0x80 : 0; -#if 0 - if (M68K_GETPC < 0x00f00000 || M68K_GETPC >= 0x10000000) - write_log (_T("VPOSR %04x at %08x\n"), vp, M68K_GETPC); -#endif - if (currprefs.cpu_model >= 68020) - hsyncdelay (); - return vp; -} - -static void VPOSW (uae_u16 v) -{ -#if 0 - if (M68K_GETPC < 0xf00000 || 1) - write_log (_T("VPOSW %04X PC=%08x\n"), v, M68K_GETPC); -#endif - if (lof_store != ((v & 0x8000) ? 1 : 0)) { - lof_changed = 1; - lof_store = (v & 0x8000) ? 1 : 0; - } - if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) { - lol = (v & 0x0080) ? 1 : 0; - if (!islinetoggle ()) - lol = 0; - } - if (lof_changed) - return; - vpos &= 0x00ff; - v &= 7; - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - v &= 1; - vpos |= v << 8; -} - -static void VHPOSW (uae_u16 v) -{ -#if 0 - if (M68K_GETPC < 0xf00000 || 1) - write_log (_T("VHPOSW %04X PC=%08x\n"), v, M68K_GETPC); -#endif - v >>= 8; // lets ignore hpos for now - vpos &= 0xff00; - vpos |= v; -} - -STATIC_INLINE uae_u16 VHPOSR (void) -{ - uae_u16 vp = GETVPOS (); - uae_u16 hp = GETHPOS (); - - hp += HPOS_OFFSET; - if (hp >= maxhpos) { - hp -= maxhpos; - vp++; - if (vp >= maxvpos + lof_store) - vp = 0; - } - if (HPOS_OFFSET) { - hp += 1; - if (hp >= maxhpos) - hp -= maxhpos; - } - - vp <<= 8; - vp |= hp; - if (currprefs.cpu_model >= 68020) - hsyncdelay (); -#if 0 - if (M68K_GETPC < 0x00f00000 || M68K_GETPC >= 0x10000000) - write_log (_T("VPOS %04x %04x at %08x\n"), VPOSR (), vp, M68K_GETPC); -#endif - return vp; -} - -static int test_copper_dangerous (unsigned int address) -{ - int addr = address & 0x01fe; - if (addr < ((copcon & 2) ? ((currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? 0 : 0x40) : 0x80)) { - cop_state.state = COP_stop; - copper_enabled_thisline = 0; - unset_special (SPCFLAG_COPPER); - return 1; - } - return 0; -} - -static void immediate_copper (int num) -{ - int pos = 0; - int oldpos = 0; - - cop_state.state = COP_stop; - cop_state.vpos = vpos; - cop_state.hpos = current_hpos () & ~1; - cop_state.ip = num == 1 ? cop1lc : cop2lc; - - while (pos < (maxvpos << 5)) { - if (oldpos > pos) - pos = oldpos; - if (!dmaen(DMA_COPPER)) - break; - if (cop_state.ip >= currprefs.chipmem_size) - break; - pos++; - oldpos = pos; - cop_state.i1 = chipmem_wget_indirect (cop_state.ip); - cop_state.i2 = chipmem_wget_indirect (cop_state.ip + 2); - cop_state.ip += 4; - if (!(cop_state.i1 & 1)) { // move - cop_state.i1 &= 0x1fe; - if (cop_state.i1 == 0x88) { - cop_state.ip = cop1lc; - continue; - } - if (cop_state.i1 == 0x8a) { - cop_state.ip = cop2lc; - continue; - } - if (test_copper_dangerous (cop_state.i1)) - break; - custom_wput_1 (0, cop_state.i1, cop_state.i2, 0); - } else { // wait or skip - if ((cop_state.i1 >> 8) > ((pos >> 5) & 0xff)) - pos = (((pos >> 5) & 0x100) | ((cop_state.i1 >> 8)) << 5) | ((cop_state.i1 & 0xff) >> 3); - if (cop_state.i1 >= 0xffdf && cop_state.i2 == 0xfffe) - break; - } - } - cop_state.state = COP_stop; - unset_special (SPCFLAG_COPPER); -} - -STATIC_INLINE void COP1LCH (uae_u16 v) -{ - cop1lc = (cop1lc & 0xffff) | ((uae_u32)v << 16); -} -STATIC_INLINE void COP1LCL (uae_u16 v) -{ - cop1lc = (cop1lc & ~0xffff) | (v & 0xfffe); -} -STATIC_INLINE void COP2LCH (uae_u16 v) -{ - cop2lc = (cop2lc & 0xffff) | ((uae_u32)v << 16); -} -STATIC_INLINE void COP2LCL (uae_u16 v) -{ - cop2lc = (cop2lc & ~0xffff) | (v & 0xfffe); -} - -static void compute_spcflag_copper (int hpos); - -// vblank = copper starts at hpos=2 -// normal COPJMP write: takes 2 more cycles -static void COPJMP (int num, int vblank) -{ - int oldstrobe = cop_state.strobe; - -#if CUSTOM_DEBUG > 0 - if (dmaen (DMA_COPPER) && (cop_state.saved_i1 != 0xffff || cop_state.saved_i2 != 0xfffe)) - write_log (_T("vblank without copper ending %08x (%08x %08x)\n"), cop_state.ip, cop1lc, cop2lc); -#endif - - unset_special (SPCFLAG_COPPER); - cop_state.ignore_next = 0; - if (!oldstrobe) - cop_state.state_prev = cop_state.state; - cop_state.state = vblank ? COP_start_delay : (copper_access ? COP_strobe_delay1 : COP_strobe_extra); - cop_state.vpos = vpos; - cop_state.hpos = current_hpos () & ~1; - copper_enabled_thisline = 0; - cop_state.strobe = num; - - if (nocustom ()) { - immediate_copper (num); - return; - } - - if (dmaen (DMA_COPPER)) { - compute_spcflag_copper (current_hpos ()); - } else if (oldstrobe > 0 && oldstrobe != num && cop_state.state_prev == COP_wait) { - /* dma disabled, copper idle and accessed both COPxJMPs -> copper stops! */ - cop_state.state = COP_stop; - } -} - -STATIC_INLINE void COPCON (uae_u16 a) -{ - copcon = a; -} - -static void DMACON (int hpos, uae_u16 v) -{ - int oldcop, newcop; - uae_u16 changed; - - uae_u16 oldcon = dmacon; - - decide_line (hpos); - decide_fetch (hpos); - decide_blitter (hpos); - - setclr (&dmacon, v); - dmacon &= 0x1FFF; - - changed = dmacon ^ oldcon; - - oldcop = (oldcon & DMA_COPPER) && (oldcon & DMA_MASTER); - newcop = (dmacon & DMA_COPPER) && (dmacon & DMA_MASTER); - - if (oldcop != newcop) { - if (newcop && !oldcop) { - compute_spcflag_copper (hpos); - } else if (!newcop) { - copper_enabled_thisline = 0; - unset_special (SPCFLAG_COPPER); - } - } - if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) - set_special (SPCFLAG_BLTNASTY); - - if (dmaen (DMA_BLITTER) && bltstate == BLT_init) - bltstate = BLT_work; - - if ((dmacon & (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) != (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) - unset_special (SPCFLAG_BLTNASTY); - - if (changed & (DMA_MASTER | 0x0f)) - audio_state_machine (); - - if (changed & (DMA_MASTER | DMA_BITPLANE)) { - ddf_change = vpos; - if (dmaen (DMA_BITPLANE)) - maybe_start_bpl_dma (hpos); - } - - events_schedule(); -} - - -void MISC_handler (void) -{ - static bool dorecheck; - bool recheck; - int i; - evt mintime; - evt ct = get_cycles (); - static int recursive; - - if (recursive) { - dorecheck = true; - return; - } - recursive++; - eventtab[ev_misc].active = 0; - recheck = true; - while (recheck) { - recheck = false; - mintime = ~0L; - for (i = 0; i < ev2_max; i++) { - if (eventtab2[i].active) { - if (eventtab2[i].evtime == ct) { - eventtab2[i].active = false; - eventtab2[i].handler (eventtab2[i].data); - if (dorecheck || eventtab2[i].active) { - recheck = true; - dorecheck = false; - } - } else { - evt eventtime = eventtab2[i].evtime - ct; - if (eventtime < mintime) - mintime = eventtime; - } - } - } - } - if (mintime != ~0L) { - eventtab[ev_misc].active = true; - eventtab[ev_misc].oldcycles = ct; - eventtab[ev_misc].evtime = ct + mintime; - events_schedule (); - } - recursive--; -} - -static int irq_nmi; - -void NMI_delayed (void) -{ - irq_nmi = 1; -} - -static uae_u16 intreq_internal, intena_internal; - -int intlev (void) -{ - uae_u16 imask = intreq_internal & intena_internal; - if (irq_nmi) { - irq_nmi = 0; - return 7; - } - if (!(imask && (intena_internal & 0x4000))) - return -1; - if (imask & (0x4000 | 0x2000)) // 13 14 - return 6; - if (imask & (0x1000 | 0x0800)) // 11 12 - return 5; - if (imask & (0x0400 | 0x0200 | 0x0100 | 0x0080)) // 7 8 9 10 - return 4; - if (imask & (0x0040 | 0x0020 | 0x0010)) // 4 5 6 - return 3; - if (imask & 0x0008) // 3 - return 2; - if (imask & (0x0001 | 0x0002 | 0x0004)) // 0 1 2 - return 1; - return -1; -} - -#define INT_PROCESSING_DELAY (3 * CYCLE_UNIT) -STATIC_INLINE int use_eventmode (uae_u16 v) -{ - if (!currprefs.cpu_cycle_exact) - return 0; - if (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68020) - return 1; - if (v & 0x8000) - return 1; - return 0; -} - -static void send_interrupt_do (uae_u32 v) -{ - INTREQ_0 (0x8000 | (1 << v)); -} - -void send_interrupt (int num, int delay) -{ - if (use_eventmode (0x8000) && delay > 0) { - if (!(intreq & (1 << num))) - event2_newevent_xx (-1, delay, num, send_interrupt_do); - } else { - send_interrupt_do (num); - } -} - -static void send_intena_do (uae_u32 v) -{ - intena_internal = v; - doint (); -} -static void send_intreq_do (uae_u32 v) -{ - intreq_internal = v; - doint (); -} - -static void INTENA (uae_u16 v) -{ - uae_u16 old = intena; - setclr (&intena, v); - - if (!(v & 0x8000) && old == intena) - return; - if (use_eventmode (v)) { - event2_newevent_xx (-1, INT_PROCESSING_DELAY, intena, send_intena_do); - } else { - intena_internal = intena; - if (v & 0x8000) - doint (); - } -#if 0 - if (v & 0x40) - write_log (_T("INTENA %04X (%04X) %p\n"), intena, v, M68K_GETPC); -#endif -} - -void INTREQ_nodelay (uae_u16 v) -{ - setclr (&intreq, v); - setclr (&intreq_internal, v); - doint (); -} - -void INTREQ_f (uae_u16 v) -{ - if (use_eventmode (v)) { - send_intreq_do (v); - } else { - setclr (&intreq, v); - setclr (&intreq_internal, v); - } -} - -void INTREQ_0 (uae_u16 v) -{ -#if 0 - if (!(v & 0x8000) && (v & (0x80 | 0x100 | 0x200 | 0x400))) - write_log (_T("audirq clear %d\n"), v); -#endif - - uae_u16 old = intreq; - setclr (&intreq, v); - - if (!(v & 0x8000) && old == intreq) - return; - - if (use_eventmode (v)) { - event2_newevent_xx (-1, INT_PROCESSING_DELAY, intreq, send_intreq_do); - } else { - intreq_internal = intreq; - if (v & 0x8000) - doint (); - } -} - -void INTREQ (uae_u16 data) -{ - INTREQ_0 (data); - serial_check_irq (); - rethink_cias (); -#ifdef A2065 - rethink_a2065 (); -#endif -#ifdef A2091 - rethink_a2091 (); -#endif -#ifdef CDTV - rethink_cdtv (); -#endif -#ifdef CD32 - rethink_akiko (); -#endif - rethink_gayle (); -} - -static void ADKCON (int hpos, uae_u16 v) -{ - if (currprefs.produce_sound > 0) - update_audio (); - DISK_update (hpos); - DISK_update_adkcon (hpos, v); - setclr (&adkcon, v); - audio_update_adkmasks (); - if ((v >> 11) & 1) - serial_uartbreak ((adkcon >> 11) & 1); -} - -static void BEAMCON0 (uae_u16 v) -{ - if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) { - if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE)) - v &= 0x20; - if (v != new_beamcon0) { - new_beamcon0 = v; - if (v & ~0x20) - write_log (_T("warning: %04X written to BEAMCON0 PC=%08X\n"), v, M68K_GETPC); - } - } -} - -#ifndef CUSTOM_SIMPLE - -static void varsync (void) -{ - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - return; -#ifdef PICASSO96 - if (picasso_on && p96refresh_active) { - vtotal = p96refresh_active; - return; - } -#endif - if (!(beamcon0 & 0x80)) - return; - vpos_count = 0; - dumpsync (); -} - -#ifdef PICASSO96 -void set_picasso_hack_rate (int hz) -{ - if (!picasso_on) - return; - vpos_count = 0; - p96refresh_active = maxvpos_stored * vblank_hz_stored / hz; - if (!currprefs.cs_ciaatod) - changed_prefs.cs_ciaatod = currprefs.cs_ciaatod = currprefs.ntscmode ? 2 : 1; - if (p96refresh_active > 0) { - new_beamcon0 |= 0x80; - } -} -#endif - -#endif - -static void BPLxPTH (int hpos, uae_u16 v, int num) -{ - decide_line (hpos); - decide_fetch (hpos); - bplpt[num] = (bplpt[num] & 0x0000ffff) | ((uae_u32)v << 16); - bplptx[num] = (bplptx[num] & 0x0000ffff) | ((uae_u32)v << 16); - //write_log (_T("%d:%d:BPL%dPTH %08X COP=%08x\n"), hpos, vpos, num, bplpt[num], cop_state.ip); -} -static void BPLxPTL (int hpos, uae_u16 v, int num) -{ - decide_line (hpos); - decide_fetch (hpos); - /* chipset feature: BPLxPTL write and next cycle doing DMA fetch using same pointer register -> - * this write goes nowhere (same happens with all DMA channels, not just BPL) - * (intro MoreNewStuffy by PlasmaForce) - */ - /* only detect copper accesses to prevent too fast CPU mode glitches */ - if (copper_access && is_bitplane_dma (hpos + 1) == num + 1) - return; - bplpt[num] = (bplpt[num] & 0xffff0000) | (v & 0x0000fffe); - bplptx[num] = (bplptx[num] & 0xffff0000) | (v & 0x0000fffe); - //write_log (_T("%d:%d:BPL%dPTL %08X COP=%08x\n"), hpos, vpos, num, bplpt[num], cop_state.ip); -} - -static void BPLCON0_Denise (int hpos, uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE)) - v &= ~0x00F1; - else if (! (currprefs.chipset_mask & CSMASK_AGA)) - v &= ~0x00B0; - v &= ~(0x0200 | 0x0100 | 0x0080 | 0x0020); -#if SPRBORDER - v |= 1; -#endif - - if (bplcon0d == v) - return; - - bplcon0dd = -1; - // fake unused 0x0080 bit as an EHB bit (see below) - if (isehb (bplcon0d, bplcon2)) - v |= 0x80; - - record_register_change (hpos, 0x100, (bplcon0d & ~(0x800 | 0x400 | 0x80)) | (v & (0x0800 | 0x400 | 0x80))); - - bplcon0d = v & ~0x80; - -#ifdef ECS_DENISE - if (currprefs.chipset_mask & CSMASK_ECS_DENISE) { - decide_sprites (hpos); - sprres = expand_sprres (v, bplcon3); - } -#endif - if (thisline_decision.plfleft == -1) - update_denise (hpos); -} - -static void BPLCON0 (int hpos, uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE)) - v &= ~0x00F1; - else if (! (currprefs.chipset_mask & CSMASK_AGA)) - v &= ~0x00B0; - v &= ~(0x0200 | 0x0100 | 0x0080 | 0x0020); - -#if SPRBORDER - v |= 1; -#endif - if (bplcon0 == v) - return; - - if (!issyncstopped ()) { - vpos_previous = vpos; - hpos_previous = hpos; - } - - bplcon0 = v; - - bpldmainitdelay (hpos); - - if (thisline_decision.plfleft == -1) - BPLCON0_Denise (hpos, v); -} - -STATIC_INLINE void BPLCON1 (int hpos, uae_u16 v) -{ - if (!(currprefs.chipset_mask & CSMASK_AGA)) - v &= 0xff; - if (bplcon1 == v) - return; - ddf_change = vpos; - decide_line (hpos); - decide_fetch (hpos); - bplcon1_hpos = hpos; - bplcon1 = v; -} - -STATIC_INLINE void BPLCON2 (int hpos, uae_u16 v) -{ - if (!(currprefs.chipset_mask & CSMASK_AGA)) - v &= 0x7f; - if (bplcon2 == v) - return; - decide_line (hpos); - bplcon2 = v; - record_register_change (hpos, 0x104, v); -} - -#ifdef ECS_DENISE -STATIC_INLINE void BPLCON3 (int hpos, uae_u16 v) -{ - if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE)) - return; - if (!(currprefs.chipset_mask & CSMASK_AGA)) { - v &= 0x003f; - v |= 0x0c00; - } -#if SPRBORDER - v |= 2; -#endif - if (bplcon3 == v) - return; - decide_line (hpos); - decide_sprites (hpos); - bplcon3 = v; - sprres = expand_sprres (bplcon0, bplcon3); - record_register_change (hpos, 0x106, v); -} -#endif -#ifdef AGA -STATIC_INLINE void BPLCON4 (int hpos, uae_u16 v) -{ - if (!(currprefs.chipset_mask & CSMASK_AGA)) - return; - if (bplcon4 == v) - return; - decide_line (hpos); - bplcon4 = v; - record_register_change (hpos, 0x10c, v); -} -#endif - -static void BPL1MOD (int hpos, uae_u16 v) -{ - v &= ~1; - if ((uae_s16)bpl1mod == (uae_s16)v) - return; - decide_line (hpos); - decide_fetch (hpos); - bpl1mod = v; -} - -static void BPL2MOD (int hpos, uae_u16 v) -{ - v &= ~1; - if ((uae_s16)bpl2mod == (uae_s16)v) - return; - decide_line (hpos); - decide_fetch (hpos); - bpl2mod = v; -} - -/* needed in special OCS/ECS "7-plane" mode. */ -/* (in reality only BPL0DAT, BPL5DAT and BPL6DAT needed) */ -static void BPLxDAT (int hpos, int num, uae_u16 v) -{ - decide_line (hpos); - decide_fetch (hpos); - bplxdat[num] = v; - if (num == 0) { - bpl1dat_written = 1; - if (thisline_decision.plfleft == -1) { - start_bpl_processing (hpos, hpos, false); - thisline_decision.plfleft = hpos; - compute_delay_offset (); - } - } -} - -static void DIWSTRT (int hpos, uae_u16 v) -{ - if (diwstrt == v && ! diwhigh_written) - return; - decide_diw (hpos); - decide_line (hpos); - diwhigh_written = 0; - diwstrt = v; - calcdiw (); -} - -static void DIWSTOP (int hpos, uae_u16 v) -{ - if (diwstop == v && ! diwhigh_written) - return; - decide_diw (hpos); - decide_line (hpos); - diwhigh_written = 0; - diwstop = v; - calcdiw (); -} - -static void DIWHIGH (int hpos, uae_u16 v) -{ - if (!(currprefs.chipset_mask & (CSMASK_ECS_DENISE | CSMASK_ECS_AGNUS))) - return; - if (!(currprefs.chipset_mask & CSMASK_AGA)) - v &= ~(0x0008 | 0x0010 | 0x1000 | 0x0800); - v &= ~(0x8000 | 0x4000 | 0x0080 | 0x0040); - if (diwhigh_written && diwhigh == v) - return; - decide_line (hpos); - diwhigh_written = 1; - diwhigh = v; - calcdiw (); -} - -static void DDFSTRT (int hpos, uae_u16 v) -{ - v &= 0xfe; - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - v &= 0xfc; - if (ddfstrt == v && hpos + 2 != ddfstrt) - return; - ddf_change = vpos; - decide_line (hpos); - ddfstrt_old_hpos = hpos; - ddfstrt = v; - calcdiw (); - if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) { - static int last_warned; - last_warned = (last_warned + 1) & 4095; - if (last_warned == 0) - write_log (_T("WARNING! Very strange DDF values (%x %x).\n"), ddfstrt, ddfstop); - } -} - -static void DDFSTOP (int hpos, uae_u16 v) -{ - v &= 0xfe; - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - v &= 0xfc; - if (ddfstop == v && hpos + 2 != ddfstop) - return; - ddf_change = vpos; - decide_line (hpos); - decide_fetch (hpos); - decide_blitter (hpos); - ddfstop = v; - calcdiw (); - if (fetch_state != fetch_not_started) - estimate_last_fetch_cycle (hpos); - if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) { - static int last_warned; - if (last_warned == 0) - write_log (_T("WARNING! Very strange DDF values (%x).\n"), ddfstop); - last_warned = (last_warned + 1) & 4095; - } -} - -static void FMODE (int hpos, uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_AGA)) - v = 0; - v &= 0xC00F; - if (fmode == v) - return; - ddf_change = vpos; - fmode = v; - sprite_width = GET_SPRITEWIDTH (fmode); - bpldmainitdelay (hpos); -} - -static void FNULL (uae_u16 v) -{ - -} - -static void BLTADAT (int hpos, uae_u16 v) -{ - maybe_blit (hpos, 0); - - blt_info.bltadat = v; -} -/* -* "Loading data shifts it immediately" says the HRM. Well, that may -* be true for BLTBDAT, but not for BLTADAT - it appears the A data must be -* loaded for every word so that AFWM and ALWM can be applied. -*/ -static void BLTBDAT (int hpos, uae_u16 v) -{ - maybe_blit (hpos, 0); - - if (bltcon1 & 2) - blt_info.bltbhold = v << (bltcon1 >> 12); - else - blt_info.bltbhold = v >> (bltcon1 >> 12); - blt_info.bltbdat = v; -} -static void BLTCDAT (int hpos, uae_u16 v) { maybe_blit (hpos, 0); blt_info.bltcdat = v; reset_blit (0); } - -static void BLTAMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltamod = (uae_s16)(v & 0xFFFE); reset_blit (0); } -static void BLTBMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); reset_blit (0); } -static void BLTCMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); reset_blit (0); } -static void BLTDMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); reset_blit (0); } - -static void BLTCON0 (int hpos, uae_u16 v) { maybe_blit (hpos, 2); bltcon0 = v; reset_blit (1); } -/* The next category is "Most useless hardware register". -* And the winner is... */ -static void BLTCON0L (int hpos, uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - return; // ei voittoa. - maybe_blit (hpos, 2); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); - reset_blit (1); -} -static void BLTCON1 (int hpos, uae_u16 v) { maybe_blit (hpos, 2); bltcon1 = v; reset_blit (2); } - -static void BLTAFWM (int hpos, uae_u16 v) { maybe_blit (hpos, 2); blt_info.bltafwm = v; reset_blit (0); } -static void BLTALWM (int hpos, uae_u16 v) { maybe_blit (hpos, 2); blt_info.bltalwm = v; reset_blit (0); } - -static void BLTAPTH (int hpos, uae_u16 v) { maybe_blit (hpos, 0); bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16); } -static void BLTAPTL (int hpos, uae_u16 v) { maybe_blit (hpos, 0); bltapt = (bltapt & ~0xffff) | (v & 0xFFFE); } -static void BLTBPTH (int hpos, uae_u16 v) { maybe_blit (hpos, 0); bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16); } -static void BLTBPTL (int hpos, uae_u16 v) { maybe_blit (hpos, 0); bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE); } -static void BLTCPTH (int hpos, uae_u16 v) { maybe_blit (hpos, 0); bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16); } -static void BLTCPTL (int hpos, uae_u16 v) { maybe_blit (hpos, 0); bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE); } -static void BLTDPTH (int hpos, uae_u16 v) { maybe_blit (hpos, 0); bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16); } -static void BLTDPTL (int hpos, uae_u16 v) { maybe_blit (hpos, 0); bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE); } - -static void BLTSIZE (int hpos, uae_u16 v) -{ - maybe_blit (hpos, 0); - - blt_info.vblitsize = v >> 6; - blt_info.hblitsize = v & 0x3F; - if (!blt_info.vblitsize) - blt_info.vblitsize = 1024; - if (!blt_info.hblitsize) - blt_info.hblitsize = 64; - do_blitter (hpos, copper_access); -} - -static void BLTSIZV (int hpos, uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - return; - maybe_blit (hpos, 0); - blt_info.vblitsize = v & 0x7FFF; -} - -static void BLTSIZH (int hpos, uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - return; - maybe_blit (hpos, 0); - blt_info.hblitsize = v & 0x7FF; - if (!blt_info.vblitsize) - blt_info.vblitsize = 0x8000; - if (!blt_info.hblitsize) - blt_info.hblitsize = 0x0800; - do_blitter (hpos, copper_access); -} - -STATIC_INLINE void spr_arm (int num, int state) -{ - switch (state) { - case 0: - nr_armed -= spr[num].armed; - spr[num].armed = 0; - break; - default: - nr_armed += 1 - spr[num].armed; - spr[num].armed = 1; - break; - } -} - -STATIC_INLINE void sprstartstop (struct sprite *s) -{ - if (vpos == s->vstart) - s->dmastate = 1; - if (vpos == s->vstop) - s->dmastate = 0; -} - -STATIC_INLINE void SPRxCTLPOS (int num) -{ - int sprxp; - struct sprite *s = &spr[num]; - - sprstartstop (s); - sprxp = (sprpos[num] & 0xFF) * 2 + (sprctl[num] & 1); - sprxp <<= sprite_buffer_res; - /* Quite a bit salad in this register... */ - if (0) { - } -#ifdef AGA - else if (currprefs.chipset_mask & CSMASK_AGA) { - sprxp |= ((sprctl[num] >> 3) & 3) >> (RES_MAX - sprite_buffer_res); - s->dblscan = sprpos[num] & 0x80; - } -#endif -#ifdef ECS_DENISE - else if (currprefs.chipset_mask & CSMASK_ECS_DENISE) { - sprxp |= ((sprctl[num] >> 3) & 2) >> (RES_MAX - sprite_buffer_res); - } -#endif - s->xpos = sprxp; - s->vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100); - s->vstop = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100); - if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) { - s->vstart |= (sprctl[num] << 3) & 0x200; - s->vstop |= (sprctl[num] << 4) & 0x200; - } - sprstartstop (s); -} - -STATIC_INLINE void SPRxCTL_1 (uae_u16 v, int num, int hpos) -{ - struct sprite *s = &spr[num]; - sprctl[num] = v; - spr_arm (num, 0); - SPRxCTLPOS (num); -#if SPRITE_DEBUG > 0 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log (_T("%d:%d:SPR%dCTL %04X P=%06X VSTRT=%d VSTOP=%d HSTRT=%d D=%d A=%d CP=%x PC=%x\n"), - vpos, hpos, num, v, s->pt, s->vstart, s->vstop, s->xpos, spr[num].dmastate, spr[num].armed, cop_state.ip, M68K_GETPC); - } -#endif - -} -STATIC_INLINE void SPRxPOS_1 (uae_u16 v, int num, int hpos) -{ - struct sprite *s = &spr[num]; - sprpos[num] = v; - SPRxCTLPOS (num); -#if SPRITE_DEBUG > 0 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log (_T("%d:%d:SPR%dPOS %04X P=%06X VSTRT=%d VSTOP=%d HSTRT=%d D=%d A=%d CP=%x PC=%x\n"), - vpos, hpos, num, v, s->pt, s->vstart, s->vstop, s->xpos, spr[num].dmastate, spr[num].armed, cop_state.ip, M68K_GETPC); - } -#endif -} -STATIC_INLINE void SPRxDATA_1 (uae_u16 v, int num, int hpos) -{ - sprdata[num][0] = v; -#ifdef AGA - sprdata[num][1] = v; - sprdata[num][2] = v; - sprdata[num][3] = v; -#endif - spr_arm (num, 1); -#if SPRITE_DEBUG > 1 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log (_T("%d:%d:SPR%dDATA %04X P=%06X D=%d A=%d PC=%x\n"), - vpos, hpos, num, v, spr[num].pt, spr[num].dmastate, spr[num].armed, M68K_GETPC); - } -#endif -} -STATIC_INLINE void SPRxDATB_1 (uae_u16 v, int num, int hpos) -{ - sprdatb[num][0] = v; -#ifdef AGA - sprdatb[num][1] = v; - sprdatb[num][2] = v; - sprdatb[num][3] = v; -#endif -#if SPRITE_DEBUG > 1 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log (_T("%d:%d:SPR%dDATB %04X P=%06X D=%d A=%d PC=%x\n"), - vpos, hpos, num, v, spr[num].pt, spr[num].dmastate, spr[num].armed, M68K_GETPC); - } -#endif -} -static void SPRxDATA (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATA_1 (v, num, hpos); } -static void SPRxDATB (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATB_1 (v, num, hpos); } -static void SPRxCTL (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxCTL_1 (v, num, hpos); } -static void SPRxPOS (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxPOS_1 (v, num, hpos); } -static void SPRxPTH (int hpos, uae_u16 v, int num) -{ - decide_sprites (hpos); - if (hpos - 1 != spr[num].ptxhpos) { - spr[num].pt &= 0xffff; - spr[num].pt |= (uae_u32)v << 16; - } -#if SPRITE_DEBUG > 0 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log (_T("%d:%d:SPR%dPTH %06X\n"), vpos, hpos, num, spr[num].pt); - } -#endif -} -static void SPRxPTL (int hpos, uae_u16 v, int num) -{ - decide_sprites (hpos); - if (hpos - 1 != spr[num].ptxhpos) { - spr[num].pt &= ~0xffff; - spr[num].pt |= v & ~1; - } -#if SPRITE_DEBUG > 0 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log (_T("%d:%d:SPR%dPTL %06X\n"), vpos, hpos, num, spr[num].pt); - } -#endif -} - -static void CLXCON (uae_u16 v) -{ - clxcon = v; - clxcon_bpl_enable = (v >> 6) & 63; - clxcon_bpl_match = v & 63; -} - -static void CLXCON2 (uae_u16 v) -{ - if (!(currprefs.chipset_mask & CSMASK_AGA)) - return; - clxcon2 = v; - clxcon_bpl_enable |= v & (0x40 | 0x80); - clxcon_bpl_match |= (v & (0x01 | 0x02)) << 6; -} - -static uae_u16 CLXDAT (void) -{ - uae_u16 v = clxdat | 0x8000; - clxdat = 0; - return v; -} - -#ifdef AGA - -void dump_aga_custom (void) -{ - int c1, c2, c3, c4; - uae_u32 rgb1, rgb2, rgb3, rgb4; - - for (c1 = 0; c1 < 64; c1++) { - c2 = c1 + 64; - c3 = c2 + 64; - c4 = c3 + 64; - rgb1 = current_colors.color_regs_aga[c1] | (color_regs_aga_genlock[c1] << 31); - rgb2 = current_colors.color_regs_aga[c2] | (color_regs_aga_genlock[c2] << 31); - rgb3 = current_colors.color_regs_aga[c3] | (color_regs_aga_genlock[c3] << 31); - rgb4 = current_colors.color_regs_aga[c4] | (color_regs_aga_genlock[c4] << 31); - console_out_f (_T("%3d %08X %3d %08X %3d %08X %3d %08X\n"), - c1, rgb1, c2, rgb2, c3, rgb3, c4, rgb4); - } -} - -static uae_u16 COLOR_READ (int num) -{ - int cr, cg, cb, colreg; - uae_u16 cval; - - if (!(currprefs.chipset_mask & CSMASK_AGA) || !(bplcon2 & 0x0100)) - return 0xffff; - - colreg = ((bplcon3 >> 13) & 7) * 32 + num; - cr = current_colors.color_regs_aga[colreg] >> 16; - cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF; - cb = current_colors.color_regs_aga[colreg] & 0xFF; - if (bplcon3 & 0x200) { - cval = ((cr & 15) << 8) | ((cg & 15) << 4) | ((cb & 15) << 0); - } else { - cval = ((cr >> 4) << 8) | ((cg >> 4) << 4) | ((cb >> 4) << 0); - if (color_regs_aga_genlock[num]) - cval |= 0x8000; - } - return cval; -} -#endif - -static void COLOR_WRITE (int hpos, uae_u16 v, int num) -{ - v &= 0xFFF; -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) { - int r,g,b; - int cr,cg,cb; - int colreg; - uae_u32 cval; - - /* writing is disabled when RDRAM=1 */ - if (bplcon2 & 0x0100) - return; - - colreg = ((bplcon3 >> 13) & 7) * 32 + num; - r = (v & 0xF00) >> 8; - g = (v & 0xF0) >> 4; - b = (v & 0xF) >> 0; - cr = current_colors.color_regs_aga[colreg] >> 16; - cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF; - cb = current_colors.color_regs_aga[colreg] & 0xFF; - - if (bplcon3 & 0x200) { - cr &= 0xF0; cr |= r; - cg &= 0xF0; cg |= g; - cb &= 0xF0; cb |= b; - } else { - cr = r + (r << 4); - cg = g + (g << 4); - cb = b + (b << 4); - color_regs_aga_genlock[colreg] = v >> 15; - } - cval = (cr << 16) | (cg << 8) | cb; - if (cval == current_colors.color_regs_aga[colreg]) - return; - - /* Call this with the old table still intact. */ - record_color_change (hpos, colreg, cval); - remembered_color_entry = -1; - current_colors.color_regs_aga[colreg] = cval; - current_colors.acolors[colreg] = getxcolor (cval); - } else { -#endif - if (current_colors.color_regs_ecs[num] == v) - return; - /* Call this with the old table still intact. */ - record_color_change (hpos, num, v); - remembered_color_entry = -1; - current_colors.color_regs_ecs[num] = v; - current_colors.acolors[num] = getxcolor (v); -#ifdef AGA - } -#endif -} - -/* The copper code. The biggest nightmare in the whole emulator. - -Alright. The current theory: -1. Copper moves happen 2 cycles after state READ2 is reached. -It can't happen immediately when we reach READ2, because the -data needs time to get back from the bus. An additional 2 -cycles are needed for non-Agnus registers, to take into account -the delay for moving data from chip to chip. -2. As stated in the HRM, a WAIT really does need an extra cycle -to wake up. This is implemented by _not_ falling through from -a successful wait to READ1, but by starting the next cycle. -(Note: the extra cycle for the WAIT apparently really needs a -free cycle; i.e. contention with the bitplane fetch can slow -it down). -3. Apparently, to compensate for the extra wake up cycle, a WAIT -will use the _incremented_ horizontal position, so the WAIT -cycle normally finishes two clocks earlier than the position -it was waiting for. The extra cycle then takes us to the -position that was waited for. -If the earlier cycle is busy with a bitplane, things change a bit. -E.g., waiting for position 0x50 in a 6 plane display: In cycle -0x4e, we fetch BPL5, so the wait wakes up in 0x50, the extra cycle -takes us to 0x54 (since 0x52 is busy), then we have READ1/READ2, -and the next register write is at 0x5c. -4. The last cycle in a line is not usable for the copper. -5. A 4 cycle delay also applies to the WAIT instruction. This means -that the second of two back-to-back WAITs (or a WAIT whose -condition is immediately true) takes 8 cycles. -6. This also applies to a SKIP instruction. The copper does not -fetch the next instruction while waiting for the second word of -a WAIT or a SKIP to arrive. -7. A SKIP also seems to need an unexplained additional two cycles -after its second word arrives; this is _not_ a memory cycle (I -think, the documentation is pretty clear on this). -8. Two additional cycles are inserted when writing to COPJMP1/2. */ - -/* Determine which cycles are available for the copper in a display -* with a agiven number of planes. */ - -STATIC_INLINE int copper_cant_read (int hpos, int alloc) -{ - if (hpos + 1 >= maxhpos) // first refresh slot - return 1; - if ((hpos == maxhpos - 3) && (maxhpos & 1)) { - if (alloc) - alloc_cycle (hpos, CYCLE_COPPER); - return -1; - } - return is_bitplane_dma_inline (hpos); -} - -static int custom_wput_copper (int hpos, uaecptr addr, uae_u32 value, int noget) -{ - int v; - - value = debug_wputpeekdma (0xdff000 + addr, value); - copper_access = 1; - v = custom_wput_1 (hpos, addr, value, noget); - copper_access = 0; - return v; -} - -static void dump_copper (TCHAR *error, int until_hpos) -{ - write_log (_T("%s: vpos=%d until_hpos=%d\n"), - error, vpos, until_hpos); - write_log (_T("cvcmp=%d chcmp=%d chpos=%d cvpos=%d ci1=%04X ci2=%04X\n"), - cop_state.vcmp,cop_state.hcmp,cop_state.hpos,cop_state.vpos,cop_state.saved_i1,cop_state.saved_i2); - write_log (_T("cstate=%d ip=%x SPCFLAGS=%x\n"), - cop_state.state, cop_state.ip, regs.spcflags); -} - -// "emulate" chip internal delays, not the right place but fast and 99.9% programs -// use only copper to write BPLCON1 etc.. (exception is HulkaMania/TSP..) -// this table should be filled with zeros and done somewhere else.. -static int customdelay[]= { - 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* 32 0x00 - 0x3e */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x40 - 0x5e */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x60 - 0x7e */ - 0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, /* 0x80 - 0x9e */ - 1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0, /* 32 0xa0 - 0xde */ - /* BPLxPTH/BPLxPTL */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16 */ - /* BPLCON0-3,BPLMOD1-2 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16 */ - /* SPRxPTH/SPRxPTL */ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 16 */ - /* SPRxPOS/SPRxCTL/SPRxDATA/SPRxDATB */ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - /* COLORxx */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - /* RESERVED */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -}; - -static void copper_write (uae_u32 v) -{ - custom_wput_copper (current_hpos (), v >> 16, v & 0xffff, 0); -} - -static void update_copper (int until_hpos) -{ - int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); - int c_hpos = cop_state.hpos; - - if (nocustom ()) - return; - - if (cop_state.state == COP_wait && vp < cop_state.vcmp) { - dump_copper (_T("error2"), until_hpos); - copper_enabled_thisline = 0; - cop_state.state = COP_stop; - unset_special (SPCFLAG_COPPER); - return; - } - - if (until_hpos <= last_copper_hpos) - return; - - if (until_hpos > (maxhpos & ~1)) - until_hpos = maxhpos & ~1; - - for (;;) { - int old_hpos = c_hpos; - int hp; - - if (c_hpos >= until_hpos) - break; - - - /* So we know about the fetch state. */ - decide_line (c_hpos); - decide_fetch (c_hpos); - - if (cop_state.movedelay > 0) { - cop_state.movedelay--; - if (cop_state.movedelay == 0) { - custom_wput_copper (c_hpos, cop_state.moveaddr, cop_state.movedata, 0); - } - } - - if ((c_hpos == maxhpos - 3) && (maxhpos & 1)) - c_hpos += 1; - else - c_hpos += 2; - - switch (cop_state.state) - { - case COP_wait_in2: - if (copper_cant_read (old_hpos, 0)) - continue; - cop_state.state = COP_wait1; - break; - case COP_skip_in2: - if (copper_cant_read (old_hpos, 0)) - continue; - cop_state.state = COP_skip1; - break; - case COP_strobe_extra: - // wait 1 copper cycle doing nothing - cop_state.state = COP_strobe_delay1; - break; - case COP_strobe_delay1: - // first cycle after COPJMP is just like normal first read cycle - if (copper_cant_read (old_hpos, 1)) - continue; - cop_state.state = COP_strobe_delay2; - alloc_cycle (old_hpos, CYCLE_COPPER); -#ifdef DEBUGGER - if (debug_dma) - record_dma (0x8c, chipmem_wget_indirect (cop_state.ip), cop_state.ip, old_hpos, vpos, DMARECORD_COPPER); -#endif - cop_state.ip += 2; - break; - case COP_strobe_delay2: - // second cycle after COPJMP is like second read cycle except - // there is 0x1FE as a target register - // (following word is still read normally and tossed away) - if (copper_cant_read (old_hpos, 1)) - continue; - cop_state.state = COP_read1; - alloc_cycle (old_hpos, CYCLE_COPPER); - if (debug_dma) - record_dma (0x1fe, chipmem_wget_indirect (cop_state.ip), cop_state.ip, old_hpos, vpos, DMARECORD_COPPER); - // next cycle finally reads from new pointer - if (cop_state.strobe == 1) - cop_state.ip = cop1lc; - else - cop_state.ip = cop2lc; - cop_state.strobe = 0; - break; - case COP_start_delay: - if (copper_cant_read (old_hpos, 1)) - continue; - cop_state.state = COP_read1; - alloc_cycle (old_hpos, CYCLE_COPPER); - if (debug_dma) - record_dma (0x1fe, 0, 0xffffffff, old_hpos, vpos, DMARECORD_COPPER); - cop_state.ip = cop1lc; - break; - - case COP_read1: - if (copper_cant_read (old_hpos, 1)) - continue; - cop_state.i1 = last_custom_value1 = chipmem_wget_indirect (cop_state.ip); - alloc_cycle (old_hpos, CYCLE_COPPER); -#ifdef DEBUGGER - if (debug_dma) - record_dma (0x8c, cop_state.i1, cop_state.ip, old_hpos, vpos, DMARECORD_COPPER); -#endif - cop_state.ip += 2; - cop_state.state = COP_read2; - break; - - case COP_read2: - if (copper_cant_read (old_hpos, 1)) - continue; - cop_state.i2 = last_custom_value1 = chipmem_wget_indirect (cop_state.ip); - alloc_cycle (old_hpos, CYCLE_COPPER); - cop_state.ip += 2; - cop_state.saved_i1 = cop_state.i1; - cop_state.saved_i2 = cop_state.i2; - cop_state.saved_ip = cop_state.ip; - - if (cop_state.i1 & 1) { // WAIT or SKIP - cop_state.ignore_next = 0; - if (cop_state.i2 & 1) - cop_state.state = COP_skip_in2; - else - cop_state.state = COP_wait_in2; -#ifdef DEBUGGER - if (debug_dma) - record_dma (0x8c, cop_state.i2, cop_state.ip - 2, old_hpos, vpos, DMARECORD_COPPER); -#endif - } else { // MOVE -#ifdef DEBUGGER - uaecptr debugip = cop_state.ip; -#endif - unsigned int reg = cop_state.i1 & 0x1FE; - uae_u16 data = cop_state.i2; - cop_state.state = COP_read1; -#ifdef DEBUGGER - if (debug_dma) - record_dma (reg, data, cop_state.ip - 2, old_hpos, vpos, DMARECORD_COPPER); -#endif - test_copper_dangerous (reg); - if (! copper_enabled_thisline) - goto out; // was "dangerous" register -> copper stopped - if (cop_state.ignore_next) { - reg = 0x1fe; - cop_state.ignore_next = 0; - } - - cop_state.last_write = reg; - cop_state.last_write_hpos = old_hpos; - if (reg == 0x88) { - cop_state.strobe = 1; - cop_state.state = COP_strobe_delay1; - } else if (reg == 0x8a) { - cop_state.strobe = 2; - cop_state.state = COP_strobe_delay1; - } else { -#if 0 - event2_newevent2 (1, (reg << 16) | data, copper_write); -#else - // FIX: all copper writes happen 1 cycle later than CPU writes - if (customdelay[reg / 2]) { - cop_state.moveaddr = reg; - cop_state.movedata = data; - cop_state.movedelay = customdelay[cop_state.moveaddr / 2]; - } else { - int hpos2 = old_hpos; - custom_wput_copper (hpos2, reg, data, 0); - hpos2++; - if (!nocustom () && reg >= 0x140 && reg < 0x180 && hpos2 >= SPR0_HPOS && hpos2 < SPR0_HPOS + 4 * MAX_SPRITES) { - do_sprites (hpos2); - } - } -#endif - } -#ifdef DEBUGGER - if (debug_copper) - record_copper (debugip - 4, old_hpos, vpos); -#endif - } - break; - - case COP_wait1: - /* There's a nasty case here. As stated in the "Theory" comment above, we - test against the incremented copper position. I believe this means that - we have to increment the _vertical_ position at the last cycle in the line, - and set the horizontal position to 0. - Normally, this isn't going to make a difference, since we consider these - last cycles unavailable for the copper, so waking up in the last cycle has - the same effect as waking up at the start of the line. However, there is - one possible problem: If we're at 0xFFE0, any wait for an earlier position - must _not_ complete (since, in effect, the current position will be back - at 0/0). This can be seen in the Superfrog copper list. - Things get monstrously complicated if we try to handle this "properly" by - incrementing vpos and setting c_hpos to 0. Especially the various speedup - hacks really assume that vpos remains constant during one line. Hence, - this hack: defer the entire decision until the next line if necessary. */ - if (c_hpos >= (maxhpos & ~1) || (c_hpos & 1)) - break; - - cop_state.state = COP_wait; - - cop_state.vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8; - cop_state.hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xFE); - - vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); - - if (cop_state.saved_i1 == 0xFFFF && cop_state.saved_i2 == 0xFFFE) { - cop_state.state = COP_stop; - copper_enabled_thisline = 0; - unset_special (SPCFLAG_COPPER); - goto out; - } - if (vp < cop_state.vcmp) { - copper_enabled_thisline = 0; - unset_special (SPCFLAG_COPPER); - goto out; - } - - /* fall through */ - case COP_wait: - if (copper_cant_read (old_hpos, 0)) - continue; - - hp = c_hpos & (cop_state.saved_i2 & 0xFE); - if (vp <= cop_state.vcmp && hp < cop_state.hcmp) - break; - - /* Now we know that the comparisons were successful. We might still - have to wait for the blitter though. */ - if ((cop_state.saved_i2 & 0x8000) == 0) { - decide_blitter (old_hpos); - if (bltstate != BLT_done) { - /* We need to wait for the blitter. */ - cop_state.state = COP_bltwait; - copper_enabled_thisline = 0; - unset_special (SPCFLAG_COPPER); - goto out; - } else { - if (debug_dma) - record_dma_event (DMA_EVENT_COPPERWAKE, old_hpos, vp); - } - } - -#ifdef DEBUGGER - if (debug_copper) - record_copper (cop_state.ip - 4, old_hpos, vpos); -#endif - - cop_state.state = COP_read1; - break; - - case COP_skip1: - { - unsigned int vcmp, hcmp, vp1, hp1; - - if (c_hpos >= (maxhpos & ~1) || (c_hpos & 1)) - break; - if (copper_cant_read (old_hpos, 0)) - continue; - - vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8; - hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xFE); - vp1 = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); - hp1 = c_hpos & (cop_state.saved_i2 & 0xFE); - - if ((vp1 > vcmp || (vp1 == vcmp && hp1 >= hcmp)) && ((cop_state.saved_i2 & 0x8000) != 0 || bltstate == BLT_done)) - cop_state.ignore_next = 1; - - cop_state.state = COP_read1; - -#ifdef DEBUGGER - if (debug_copper) - record_copper (cop_state.ip - 4, old_hpos, vpos); -#endif - - break; - } - default: - break; - } - } - -out: - cop_state.hpos = c_hpos; - last_copper_hpos = until_hpos; -} - -static void compute_spcflag_copper (int hpos) -{ - int wasenabled = copper_enabled_thisline; - - copper_enabled_thisline = 0; - unset_special (SPCFLAG_COPPER); - if (!dmaen (DMA_COPPER) || cop_state.state == COP_stop || cop_state.state == COP_bltwait || nocustom ()) - return; - - if (cop_state.state == COP_wait) { - int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); - - if (vp < cop_state.vcmp) - return; - } - // do not use past cycles if starting for the first time in this line - // (write to DMACON for example) hpos+1 for long lines - if (!wasenabled && cop_state.hpos < hpos && hpos < maxhpos) { - hpos = (hpos + 2) & ~1; - if (hpos > (maxhpos_short & ~1)) - hpos = maxhpos_short & ~1; - cop_state.hpos = hpos; - } - copper_enabled_thisline = 1; - set_special (SPCFLAG_COPPER); -} - -/* -Copper writes to BLTSIZE: 3 blitter idle cycles, blitter normal cycle starts -(CPU write to BLTSIZE only have 2 idle cycles at start) - -BFD=0 wait: 1 cycle (or 2 if hpos is not aligned) delay before wait ends -*/ -void blitter_done_notify (int hpos) -{ - int vp = vpos; - - if (cop_state.state != COP_bltwait) - return; - - hpos += 3; - hpos &= ~1; - if (hpos >= maxhpos) { - hpos -= maxhpos; - vp++; - } - cop_state.hpos = hpos; - cop_state.vpos = vp; - cop_state.state = COP_read1; - if (debug_dma) - record_dma_event (DMA_EVENT_COPPERWAKE, hpos, vp); - - if (dmaen (DMA_COPPER) && vp == vpos) { - copper_enabled_thisline = 1; - set_special (SPCFLAG_COPPER); - } -} - -void do_copper (void) -{ - int hpos = current_hpos (); - update_copper (hpos); -} - -/* ADDR is the address that is going to be read/written; this access is -the reason why we want to update the copper. This function is also -used from hsync_handler to finish up the line; for this case, we check -hpos against maxhpos. */ -STATIC_INLINE void sync_copper_with_cpu (int hpos, int do_schedule) -{ - /* Need to let the copper advance to the current position. */ - if (copper_enabled_thisline) - update_copper (hpos); -} - -static void cursorsprite (void) -{ - if (!dmaen (DMA_SPRITE) || first_planes_vpos == 0) - return; - sprite_0 = spr[0].pt; - sprite_0_height = spr[0].vstop - spr[0].vstart; - sprite_0_colors[0] = 0; - sprite_0_doubled = 0; - if (sprres == 0) - sprite_0_doubled = 1; - if (currprefs.chipset_mask & CSMASK_AGA) { - int sbasecol = ((bplcon4 >> 4) & 15) << 4; - sprite_0_colors[1] = current_colors.color_regs_aga[sbasecol + 1]; - sprite_0_colors[2] = current_colors.color_regs_aga[sbasecol + 2]; - sprite_0_colors[3] = current_colors.color_regs_aga[sbasecol + 3]; - } else { - sprite_0_colors[1] = xcolors[current_colors.color_regs_ecs[17]]; - sprite_0_colors[2] = xcolors[current_colors.color_regs_ecs[18]]; - sprite_0_colors[3] = xcolors[current_colors.color_regs_ecs[19]]; - } - sprite_0_width = sprite_width; - if (currprefs.input_tablet && currprefs.input_magic_mouse) { - if (currprefs.input_magic_mouse_cursor == MAGICMOUSE_HOST_ONLY && mousehack_alive ()) - magic_sprite_mask &= ~1; - else - magic_sprite_mask |= 1; - } -} - -STATIC_INLINE uae_u16 sprite_fetch (struct sprite *s, int dma, int hpos, int cycle, int mode) -{ - uae_u16 data = last_custom_value1; - if (dma) { - if (cycle && currprefs.cpu_cycle_exact) - s->ptxhpos = hpos; - data = last_custom_value1 = chipmem_wget_indirect (s->pt); - alloc_cycle (hpos, CYCLE_SPRITE); -#ifdef DEBUGGER - if (debug_dma) - record_dma ((s - &spr[0]) * 8 + 0x140 + mode * 4 + cycle * 2, data, s->pt, hpos, vpos, DMARECORD_SPRITE); -#endif - } - s->pt += 2; - return data; -} -STATIC_INLINE uae_u16 sprite_fetch2 (struct sprite *s, int hpos, int cycle, int mode) -{ - uae_u16 data = last_custom_value1 = chipmem_wget_indirect (s->pt); - s->pt += 2; - return data; -} - -STATIC_INLINE void do_sprites_1 (int num, int cycle, int hpos) -{ - struct sprite *s = &spr[num]; - int dma, posctl = 0; - uae_u16 data; - // fetch both sprite pairs even if DMA was switched off between sprites - int isdma = dmaen (DMA_SPRITE) || ((num & 1) && spr[num & ~1].dmacycle); - - if (isdma && vpos == sprite_vblank_endline) - spr_arm (num, 0); - -#ifdef AGA - if (isdma && s->dblscan && (fmode & 0x8000) && (vpos & 1) != (s->vstart & 1) && s->dmastate) { - spr_arm (num, 1); - return; - } -#endif -#if SPRITE_DEBUG > 3 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) - write_log (_T("%d:%d:slot%d:%d\n"), vpos, hpos, num, cycle); -#endif - if (vpos == s->vstart) { -#if SPRITE_DEBUG > 0 - if (!s->dmastate && vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) - write_log (_T("%d:%d:SPR%d START\n"), vpos, hpos, num); -#endif - s->dmastate = 1; - if (num == 0 && cycle == 0) - cursorsprite (); - } - if (vpos == s->vstop || vpos == sprite_vblank_endline) { -#if SPRITE_DEBUG > 0 - if (s->dmastate && vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) - write_log (_T("%d:%d:SPR%d STOP\n"), vpos, hpos, num); -#endif - s->dmastate = 0; -#if 0 - // roots 2.0 flower zoomer bottom part missing if this enabled - if (vpos == s->vstop) { - spr_arm (num, 0); - //return; - } -#endif - } - - if (!isdma) - return; - if (cycle && !s->dmacycle) - return; /* Superfrog intro flashing bee fix */ - - dma = hpos < plfstrt_sprite || diwstate != DIW_waiting_stop; - if (vpos == s->vstop || vpos == sprite_vblank_endline) { - s->dmastate = 0; - posctl = 1; - if (dma) { - data = sprite_fetch (s, dma, hpos, cycle, 0); - switch (sprite_width) - { - case 64: - sprite_fetch2 (s, hpos, cycle, 0); - sprite_fetch2 (s, hpos, cycle, 0); - case 32: - sprite_fetch2 (s, hpos, cycle, 0); - break; - } - //write_log (_T("%d:%d: %04X=%04X\n"), vpos, hpos, 0x140 + cycle * 2 + num * 8, data); - if (cycle == 0) { - SPRxPOS_1 (data, num, hpos); - s->dmacycle = 1; - } else { - SPRxCTL_1 (data, num, hpos); - s->dmastate = 0; - sprstartstop (s); - } - } -#if SPRITE_DEBUG > 1 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log (_T("%d:%d:dma:P=%06X "), vpos, hpos, s->pt); - } -#endif - } - if (s->dmastate && !posctl && dma) { - uae_u16 data; - - data = sprite_fetch (s, dma, hpos, cycle, 1); -#if SPRITE_DEBUG > 1 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log (_T("%d:%d:dma:P=%06X "), vpos, hpos, s->pt); - } -#endif - if (cycle == 0) { - SPRxDATA_1 (data, num, hpos); - s->dmacycle = 1; - } else { - SPRxDATB_1 (data, num, hpos); - spr_arm (num, 1); - } -#ifdef AGA - switch (sprite_width) - { - case 64: - { - uae_u16 data32 = sprite_fetch2 (s, hpos, cycle, 1); - uae_u16 data641 = sprite_fetch2 (s, hpos, cycle, 1); - uae_u16 data642 = sprite_fetch2 (s, hpos, cycle, 1); - if (dma) { - if (cycle == 0) { - sprdata[num][3] = data642; - sprdata[num][2] = data641; - sprdata[num][1] = data32; - } else { - sprdatb[num][3] = data642; - sprdatb[num][2] = data641; - sprdatb[num][1] = data32; - } - } - } - break; - case 32: - { - uae_u16 data32 = sprite_fetch2 (s, hpos, cycle, 1); - if (dma) { - if (cycle == 0) - sprdata[num][1] = data32; - else - sprdatb[num][1] = data32; - } - } - break; - } -#endif - } -} - -static void do_sprites (int hpos) -{ - int maxspr, minspr; - int i; - - if (vpos < sprite_vblank_endline) - return; - - if (doflickerfix () && interlace_seen && (next_lineno & 1)) - return; - -#ifndef CUSTOM_SIMPLE - maxspr = hpos; - minspr = last_sprite_hpos + 1; - - if (minspr >= maxspr || last_sprite_hpos == hpos) - return; - - if (maxspr >= SPR0_HPOS + MAX_SPRITES * 4) - maxspr = SPR0_HPOS + MAX_SPRITES * 4 - 1; - if (minspr < SPR0_HPOS) - minspr = SPR0_HPOS; - - if (minspr == maxspr) - return; - - for (i = minspr; i <= maxspr; i++) { - int cycle = -1; - int num = (i - SPR0_HPOS) / 4; - switch ((i - SPR0_HPOS) & 3) - { - case 0: - cycle = 0; - spr[num].dmacycle = 0; - break; - case 2: - cycle = 1; - break; - } - if (cycle >= 0) { - spr[num].ptxhpos = MAXHPOS; - do_sprites_1 (num, cycle, i); - } - } - - last_sprite_hpos = hpos; -#else - for (i = 0; i < MAX_SPRITES * 2; i++) { - spr[i / 2].dmacycle = 1; - do_sprites_1 (i / 2, i & 1, 0); - } -#endif -} - -static void init_sprites (void) -{ - memset (sprpos, 0, sizeof sprpos); - memset (sprctl, 0, sizeof sprctl); -} - -static void init_hardware_frame (void) -{ - int i; - - first_bpl_vpos = -1; - next_lineno = 0; - prev_lineno = -1; - nextline_how = nln_normal; - diwstate = DIW_waiting_start; - ddfstate = DIW_waiting_start; - first_planes_vpos = 0; - last_planes_vpos = 0; - diwfirstword_total = max_diwlastword; - diwlastword_total = 0; - ddffirstword_total = max_diwlastword; - ddflastword_total = 0; - plflastline_total = 0; - plffirstline_total = current_maxvpos (); - autoscale_bordercolors = 0; - for (i = 0; i < MAX_SPRITES; i++) - spr[i].ptxhpos = MAXHPOS; -} - -void init_hardware_for_drawing_frame (void) -{ - /* Avoid this code in the first frame after a customreset. */ - if (prev_sprite_entries) { - int first_pixel = prev_sprite_entries[0].first_pixel; - int npixels = prev_sprite_entries[prev_next_sprite_entry].first_pixel - first_pixel; - memset (spixels + first_pixel, 0, npixels * sizeof *spixels); - memset (spixstate.bytes + first_pixel, 0, npixels * sizeof *spixstate.bytes); - } - prev_next_sprite_entry = next_sprite_entry; - - next_color_change = 0; - next_sprite_entry = 0; - next_color_entry = 0; - remembered_color_entry = -1; - - prev_sprite_entries = sprite_entries[current_change_set]; - curr_sprite_entries = sprite_entries[current_change_set ^ 1]; - prev_color_changes = color_changes[current_change_set]; - curr_color_changes = color_changes[current_change_set ^ 1]; - prev_color_tables = color_tables[current_change_set]; - curr_color_tables = color_tables[current_change_set ^ 1]; - - prev_drawinfo = line_drawinfo[current_change_set]; - curr_drawinfo = line_drawinfo[current_change_set ^ 1]; - current_change_set ^= 1; - - color_src_match = color_dest_match = -1; - - /* Use both halves of the array in alternating fashion. */ - curr_sprite_entries[0].first_pixel = current_change_set * MAX_SPR_PIXELS; - next_sprite_forced = 1; -} - -static void do_savestate(void); - -static int rpt_vsync (void) -{ - int v = read_processor_time () - vsyncmintime; - if (v > (int)syncbase || v < -((int)syncbase)) { - vsyncmintime = read_processor_time (); - v = 0; - } - return v; -} - -static void framewait (void) -{ - frame_time_t curr_time; - frame_time_t start; - int vs = isvsync (); - - if (vs > 0) { - vsyncmintime = vsynctime; - update_screen (); - return; - } else if (vs < 0) { - vsyncmintime = vsynctime; - vsync_busywait (); - update_screen (); - return; - } - for (;;) { - double v = rpt_vsync () / (syncbase / 1000.0); - if (v >= -4) - break; - sleep_millis (2); - } - update_screen (); - curr_time = start = read_processor_time (); - while (rpt_vsync () < 0); - curr_time = read_processor_time (); - vsyncmintime = curr_time + vsynctime; - idletime += read_processor_time() - start; -} - -static frame_time_t frametime2; - -void fpscounter_reset (void) -{ - timeframes = 0; - frametime2 = 0; - bogusframe = 2; - lastframetime = read_processor_time (); - idletime = 0; -} - -static void fpscounter (void) -{ - frame_time_t now, last; - int mcnt = 10; - - now = read_processor_time (); - last = now - lastframetime; - lastframetime = now; - - if (bogusframe) - return; - - frametime += last; - frametime2 += last; - timeframes++; - if ((timeframes % mcnt) == 0) { - double idle = 1000 - (idletime == 0 ? 0.0 : (double)idletime * 1000.0 / (vsynctime * mcnt)); - int fps = frametime2 == 0 ? 0 : (syncbase * mcnt) / (frametime2 / 10); - if (fps > 9999) - fps = 9999; - if (idle < 0) - idle = 0; - if (idle > 100 * 10) - idle = 100 * 10; - if (fake_vblank_hz * 10 > fps) { - double mult = (double)fake_vblank_hz * 10.0 / fps; - idle *= mult; - } - if (currprefs.turbo_emulation && idle < 100 * 10) - idle = 100 * 10; - gui_fps (fps, (int)idle); - frametime2 = 0; - idletime = 0; - } -} - -// vsync functions that are not hardware timing related -static void vsync_handler_pre (void) -{ - if (bogusframe > 0) - bogusframe--; - - handle_events (); - -#ifdef PICASSO96 - picasso_handle_vsync (); -#endif - audio_vsync (); - blkdev_vsync (); - CIA_vsync_prehandler (); - - if (quit_program > 0) { - /* prevent possible infinite loop at wait_cycles().. */ - framecnt = 0; - reset_decisions (); - return; - } - - config_check_vsync (); - if (timehack_alive > 0) - timehack_alive--; - - inputdevice_vsync (); - - filesys_vsync (); - - sampler_vsync (); - - vsync_handle_redraw (lof_store, lof_changed); -} - -// emulated hardware vsync -static void vsync_handler_post (void) -{ - fpscounter (); - - if (!isvsync () -#ifdef AVIOUTPUT - && ((avioutput_framelimiter && avioutput_enabled) || !avioutput_enabled) -#endif - ) { -#ifdef JIT - if (!currprefs.cachesize) { -#endif - if (currprefs.m68k_speed == -1) { - frame_time_t curr_time = read_processor_time (); - vsyncmintime += vsynctime; - /* @@@ Mathias? How do you think we should do this? */ - /* If we are too far behind, or we just did a reset, adjust the - * needed time. */ - if ((long int)(curr_time - vsyncmintime) > 0 || rpt_did_reset) - vsyncmintime = curr_time + vsynctime; - rpt_did_reset = 0; - update_screen (); - } else if (rpt_available) { - framewait (); - } -#ifdef JIT - } else { - if (rpt_available && currprefs.m68k_speed == 0) { - framewait (); - } else { - update_screen (); - } - } -#endif - } else if (currprefs.m68k_speed == 0) { - framewait (); - } else { - update_screen (); - } - -#if CUSTOM_DEBUG > 1 - if ((intreq & 0x0020) && (intena & 0x0020)) - write_log (_T("vblank interrupt not cleared\n")); -#endif - DISK_vsync (); - if (bplcon0 & 4) - lof_store = lof_store ? 0 : 1; - lof_current = lof_store; - - if (debug_copper) - record_copper_reset (); - if (debug_dma) - record_dma_reset (); - - if (p96refresh_active) { - vpos_count = p96refresh_active; - vtotal = vpos_count; - } - if ((beamcon0 & (0x20 | 0x80)) != (new_beamcon0 & (0x20 | 0x80)) || (abs (vpos_count - vpos_count_prev) > 1)) - init_hz (); - if (lof_changed) - compute_vsynctime (); - vpos_count_prev = vpos_count; - - lof_changed = 0; - - COPJMP (1, 1); - - init_hardware_frame (); - - vsync_cycles = get_cycles (); -} - -#ifdef JIT - -#define N_LINES 8 - -STATIC_INLINE int trigger_frh (int v) -{ - return (v & (N_LINES - 1)) == 0; -} - -static long int diff32 (frame_time_t x, frame_time_t y) -{ - return (long int)(x - y); -} -static void frh_handler (void) -{ - if (currprefs.m68k_speed == -1) { - frame_time_t curr_time = read_processor_time (); - vsyncmintime += vsynctime * N_LINES / maxvpos_nom; - /* @@@ Mathias? How do you think we should do this? */ - /* If we are too far behind, or we just did a reset, adjust the - * needed time. */ - if (rpt_did_reset) { - vsyncmintime = curr_time + vsynctime; - rpt_did_reset = 0; - } - /* Allow this to be one frame's worth of cycles out */ - while (diff32 (curr_time, vsyncmintime + vsynctime) > 0) { - vsyncmintime += vsynctime * N_LINES / maxvpos_nom; - if (currprefs.turbo_emulation) - break; - } - } -} -#endif - -static void copper_check (int n) -{ - if (cop_state.state == COP_wait) { - int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); - if (vp < cop_state.vcmp) { - if (copper_enabled_thisline) - write_log (_T("COPPER BUG %d: vp=%d vpos=%d vcmp=%d act=%d thisline=%d\n"), n, vp, vpos, cop_state.vcmp, copper_enabled_thisline); - } - } -} - -/* - -0 0 - -1 1 -- -2 2 - -3 3 -- -4 4 - -5 5 -- - -0 x - -1 0 -- -2 1 - -3 2 -- -4 3 - -5 4 -- - -*/ - -static void hsync_scandoubler (void) -{ - int i, idx1; - struct draw_info *dip1; - uaecptr bpltmp[8], bpltmpx[8]; - - next_lineno++; - scandoubled_line = 1; - debug_dma = 0; - - for (i = 0; i < 8; i++) { - int diff; - bpltmp[i] = bplpt[i]; - bpltmpx[i] = bplptx[i]; - if (prevbpl[lof_store][vpos][i] && prevbpl[1 - lof_store][vpos][i]) { - diff = prevbpl[lof_store][vpos][i] - prevbpl[1 - lof_store][vpos][i]; - if (lof_store) { - if (bplcon0 & 4) - bplpt[i] = prevbpl[lof_store][vpos][i] - diff; - } else { - if (bplcon0 & 4) - bplpt[i] = prevbpl[lof_store][vpos][i]; - else - bplpt[i] = bplpt[i] - diff; - - } - } - } - - reset_decisions (); - plf_state = plf_idle; - - // copy color changes - dip1 = curr_drawinfo + next_lineno - 1; - for (idx1 = dip1->first_color_change; idx1 < dip1->last_color_change; idx1++) { - struct color_change *cs2 = &curr_color_changes[idx1]; - int regno = cs2->regno; - int hpos = cs2->linepos; - if (regno < 0x1000 && hpos < HBLANK_OFFSET && !(beamcon0 & 0x80) && prev_lineno >= 0) { - struct draw_info *pdip = curr_drawinfo + next_lineno - 1; - int idx = pdip->last_color_change; - pdip->last_color_change++; - pdip->nr_color_changes++; - curr_color_changes[idx].linepos = hpos + maxhpos + 1; - curr_color_changes[idx].regno = regno; - curr_color_changes[idx].value = cs2->value; - curr_color_changes[idx + 1].regno = -1; - } else { - struct color_change *cs1 = &curr_color_changes[next_color_change]; - memcpy (cs1, cs2, sizeof (struct color_change)); - next_color_change++; - } - } - curr_color_changes[next_color_change].regno = -1; - - finish_decisions (); - hsync_record_line_state (next_lineno, nln_normal, thisline_changed); - hardware_line_completed (next_lineno); - scandoubled_line = 0; - - for (i = 0; i < 8; i++) { - bplpt[i] = bpltmp[i]; - bplptx[i] = bpltmpx[i]; - } -} - -static void events_dmal (int); -static uae_u16 dmal, dmal_hpos; - -static void dmal_emu (uae_u32 v) -{ - // Disk and Audio DMA bits are ignored by Agnus, Agnus only checks DMAL and master bit - if (!(dmacon & DMA_MASTER)) - return; - int hpos = current_hpos (); - if (v >= 6) { - v -= 6; - int nr = v / 2; - uaecptr pt = audio_getpt (nr, (v & 1) != 0); - uae_u16 dat = chipmem_wget_indirect (pt); -#ifdef DEBUGGER - if (debug_dma) - record_dma (0xaa + nr * 16, dat, pt, hpos, vpos, DMARECORD_AUDIO); -#endif - last_custom_value1 = dat; - AUDxDAT (nr, dat, pt); - } else { - uae_u16 dat; - int w = v & 1; - uaecptr pt = disk_getpt (); - // disk_fifostatus() needed in >100% disk speed modes - if (w) { - if (disk_fifostatus () <= 0) { - dat = chipmem_wget_indirect (pt); - last_custom_value1 = dat; - DSKDAT (dat); - } - } else { - if (disk_fifostatus () >= 0) { - dat = DSKDATR (); - chipmem_wput_indirect (pt, dat); - } - } -#ifdef DEBUGGER - if (debug_dma) - record_dma (w ? 0x26 : 0x08, dat, pt, hpos, vpos, DMARECORD_DISK); -#endif - } -} - -static void dmal_func (uae_u32 v) -{ - dmal_emu (v); - events_dmal (0); -} - -static void dmal_func2 (uae_u32 v) -{ - while (dmal) { - if (dmal & 3) - dmal_emu (dmal_hpos + ((dmal & 2) ? 1 : 0)); - dmal_hpos += 2; - dmal >>= 2; - } -} - -static void events_dmal (int hp) -{ - if (!dmal) - return; - if (currprefs.cpu_cycle_exact) { - while (dmal) { - if (dmal & 3) - break; - hp += 2; - dmal >>= 2; - dmal_hpos += 2; - } - event2_newevent2 (hp, dmal_hpos + ((dmal & 2) ? 1 : 0), dmal_func); - dmal &= ~3; - } else if (currprefs.cachesize) { - dmal_func2 (0); - } else { - event2_newevent2 (hp, 13, dmal_func2); - } -} - -static void events_dmal_hsync (void) -{ - if (dmal) - write_log (_T("DMAL error!? %04x\n"), dmal); - dmal = audio_dmal (); - dmal <<= 6; - dmal |= disk_dmal (); - if (!dmal) - return; - dmal_hpos = 0; - if (currprefs.cpu_cycle_exact) { - for (int i = 0; i < 6 + 8; i += 2) { - if (dmal & (3 << i)) { - alloc_cycle_ext (i + 7, CYCLE_MISC); - } - } - } - events_dmal (7); -} - -static bool is_vsync (void) -{ - int vp = vpos + 1; - int vpc = vpos_count + 1; - /* Agnus vpos counter keeps counting until it wraps around if VPOSW writes put it past maxvpos */ - if (vp >= maxvpos_total) - vp = 0; - if (vp == maxvpos + lof_store || vp == maxvpos + lof_store + 1 || vpc >= MAXVPOS) { - // vpos_count >= MAXVPOS just to not crash if VPOSW writes prevent vsync completely - return true; - } - return false; -} - -static void set_hpos (void) -{ - maxhpos = maxhpos_short + lol; - eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME; - eventtab[ev_hsync].oldcycles = get_cycles (); -} - -// this finishes current line -static void hsync_handler_pre (bool isvsync) -{ - int hpos = current_hpos (); - - if (!nocustom ()) { - sync_copper_with_cpu (maxhpos, 0); - finish_decisions (); - if (thisline_decision.plfleft != -1) { - if (currprefs.collision_level > 1) - do_sprite_collisions (); - if (currprefs.collision_level > 2) - do_playfield_collisions (); - } - hsync_record_line_state (next_lineno, nextline_how, thisline_changed); - /* reset light pen latch */ - if (vpos == sprite_vblank_endline) { - lightpen_triggered = 0; - sprite_0 = 0; - } - if (lightpen_cx > 0 && (bplcon0 & 8) && !lightpen_triggered && lightpen_cy == vpos) { - vpos_lpen = vpos; - hpos_lpen = lightpen_cx; - lightpen_triggered = 1; - } - hardware_line_completed (next_lineno); - if (doflickerfix () && interlace_seen) - hsync_scandoubler (); - } - -#ifdef A2065 - a2065_hsync_handler (); -#endif -#ifdef CD32 - AKIKO_hsync_handler (); -#endif -#ifdef CDTV - CDTV_hsync_handler (); -#endif - decide_blitter (-1); - -#ifdef PICASSO96 - picasso_handle_hsync (); -#endif - { - void ahi_hsync (void); - ahi_hsync (); - } - - DISK_hsync (); - if (currprefs.produce_sound) - audio_hsync (); - CIA_hsync_prehandler (); - - hsync_counter++; - - if (islinetoggle ()) - lol ^= 1; - else - lol = 0; - - vpos++; - vpos_count++; - if (vpos >= maxvpos_total) - vpos = 0; - if (isvsync) { - vpos = 0; - vsync_counter++; - } - set_hpos (); -#if 0 - static int ppp = 2; - if (input_record && hsync_counter == 100 * 313 + 1) { - ppp--; - if (ppp == 0) - activate_debugger (); - } -#endif -} - -// this prepares for new line -static void hsync_handler_post (bool isvsync) -{ - last_copper_hpos = 0; -#ifdef CPUEMU_12 - if (currprefs.cpu_cycle_exact || currprefs.blitter_cycle_exact) { - memset (cycle_line, 0, sizeof cycle_line); - } -#endif - - bool ciasyncs = !(bplcon0 & 2) || ((bplcon0 & 2) && currprefs.genlock); - CIA_hsync_posthandler (ciasyncs); - if (currprefs.cs_ciaatod > 0) { - static int cia_hsync; - cia_hsync -= 256; - if (cia_hsync <= 0) { - CIA_vsync_posthandler (1); - cia_hsync += ((MAXVPOS_PAL * MAXHPOS_PAL * 50 * 256) / (maxhpos * (currprefs.cs_ciaatod == 2 ? 60 : 50))); - } - } else if (currprefs.cs_ciaatod == 0 && isvsync) { - CIA_vsync_posthandler (ciasyncs); - } - - if (vpos == equ_vblank_endline + 1 && lof_current != lof_store) { - // argh, line=0 field decision was wrong, someone did - // something stupid and changed LOF - // lof_current = lof_store; - // don't really know what to do here exactly without corrupt display - } - - inputdevice_hsync (); - - last_custom_value1 = 0xffff; // refresh slots should set this to 0xffff - - if (!nocustom ()) { - if (!currprefs.blitter_cycle_exact && bltstate != BLT_done && dmaen (DMA_BITPLANE) && diwstate == DIW_waiting_stop) { - blitter_slowdown (thisline_decision.plfleft, thisline_decision.plfright - (16 << fetchmode), - cycle_diagram_total_cycles[fetchmode][GET_RES_AGNUS (bplcon0)][GET_PLANES_LIMIT (bplcon0)], - cycle_diagram_free_cycles[fetchmode][GET_RES_AGNUS (bplcon0)][GET_PLANES_LIMIT (bplcon0)]); - } - } - - if (isvsync) { - // vpos_count >= MAXVPOS just to not crash if VPOSW writes prevent vsync completely - if ((bplcon0 & 8) && !lightpen_triggered) { - vpos_lpen = vpos - 1; - hpos_lpen = maxhpos; - lightpen_triggered = 1; - } - vpos = 0; - vsync_handler_post (); - vpos_count = 0; - } - // DIP Agnus (8361): vblank interrupt is triggered on line 1! - if (currprefs.cs_dipagnus) { - if (vpos == 1) - send_interrupt (5, 1 * CYCLE_UNIT); - } else { - if (vpos == 0) - send_interrupt (5, 1 * CYCLE_UNIT); - } - -#ifdef CPUEMU_12 - if (currprefs.cpu_cycle_exact || currprefs.blitter_cycle_exact) { - int hp = maxhpos - 1, i; - for (i = 0; i < 4; i++) { - alloc_cycle (hp, i == 0 ? CYCLE_STROBE : CYCLE_REFRESH); /* strobe */ -#ifdef DEBUGGER - if (debug_dma) { - uae_u16 strobe = 0x3c; - if (vpos < equ_vblank_endline) - strobe = 0x38; - else if (vpos < minfirstline) - strobe = 0x3a; - else if (vpos + 1 == maxvpos + lof_store) - strobe = 0x38; - else if ((currprefs.chipset_mask & CSMASK_ECS_AGNUS) && lol) - strobe = 0x3e; - record_dma (i == 0 ? strobe : 0x1fe, 0xffff, 0xffffffff, hp, vpos, DMARECORD_REFRESH); - } -#endif - hp += 2; - if (hp >= maxhpos) - hp -= maxhpos; - } - } -#endif - - - events_dmal_hsync (); - -#ifdef JIT - if (currprefs.cachesize) { - if (currprefs.m68k_speed == -1) { - static int count = 0; - count++; - if (trigger_frh (count)) { - frh_handler (); - } - is_lastline = trigger_frh (count + 1) && ! rpt_did_reset; - } else { - is_lastline = 0; - } - } else { -#endif - is_lastline = vpos + 1 == maxvpos + lof_store && currprefs.m68k_speed == -1; -#ifdef JIT - } -#endif - - if (!nocustom ()) { - int lineno = vpos; - if (lineno >= MAXVPOS) - lineno %= MAXVPOS; - if ((bplcon0 & 4) && currprefs.gfx_vresolution) - notice_interlace_seen (); - nextline_how = nln_normal; - if (doflickerfix () && interlace_seen) { - lineno *= 2; - } else if (currprefs.gfx_vresolution && (doublescan <= 0 || interlace_seen > 0)) { - lineno *= 2; - nextline_how = currprefs.gfx_vresolution > VRES_NONDOUBLE && currprefs.gfx_scanlines == false ? nln_doubled : nln_nblack; - if ((bplcon0 & 4) || (interlace_seen > 0 && !lof_current)) { - if (!lof_current) { - lineno++; - nextline_how = nln_lower; - } else { - nextline_how = nln_upper; - } - } - } - prev_lineno = next_lineno; - next_lineno = lineno; - reset_decisions (); - } - - if (uae_int_requested) { - INTREQ (0x8000 | 0x0008); - } - - { - extern int volatile uaenet_int_requested; - extern int volatile uaenet_vsync_requested; - if (uaenet_int_requested || (uaenet_vsync_requested && vpos == 10)) { - INTREQ (0x8000 | 0x2000); - } - } - - { - extern void bsdsock_fake_int_handler (void); - extern int volatile bsd_int_requested; - if (bsd_int_requested) - bsdsock_fake_int_handler (); - } - - plfstrt_sprite = plfstrt; - /* See if there's a chance of a copper wait ending this line. */ - cop_state.hpos = 0; - cop_state.last_write = 0; - compute_spcflag_copper (maxhpos); - - serial_hsynchandler (); -#ifdef CUSTOM_SIMPLE - do_sprites (0); -#endif - - gayle_hsync (); - scsi_hsync (); - - //copper_check (2); - - if (GET_PLANES (bplcon0) > 0 && dmaen (DMA_BITPLANE)) { - if (vpos > last_planes_vpos) - last_planes_vpos = vpos; - if (vpos >= minfirstline && first_planes_vpos == 0) { - first_planes_vpos = vpos > minfirstline ? vpos - 1 : vpos; - } else if (vpos == current_maxvpos () - 1) { - last_planes_vpos = vpos - 1; - } - } - if (diw_change == 0) { - if (vpos >= first_planes_vpos && vpos <= last_planes_vpos) { - if (diwlastword > diwlastword_total) - diwlastword_total = diwlastword; - if (diwfirstword < diwfirstword_total) { - diwfirstword_total = diwfirstword; - firstword_bplcon1 = bplcon1; - } - } - if (diwstate == DIW_waiting_stop) { - int f = 8 << fetchmode; - if (plfstrt + f < ddffirstword_total + f) - ddffirstword_total = plfstrt + f; - if (plfstop + 2 * f > ddflastword_total + 2 * f) - ddflastword_total = plfstop + 2 * f; - } - if ((plffirstline < plffirstline_total || (plffirstline_total == minfirstline && vpos > minfirstline)) && plffirstline < vpos / 2) { - firstword_bplcon1 = bplcon1; - if (plffirstline < minfirstline) - plffirstline_total = minfirstline; - else - plffirstline_total = plffirstline; - } - if (plflastline > plflastline_total && plflastline > plffirstline_total && plflastline > maxvpos / 2) - plflastline_total = plflastline; - } - if (diw_change > 0) - diw_change--; - - -#if 0 - { - static int skip; - if (M68K_GETPC >= 0x0C0D7A2 && M68K_GETPC < 0x00C0D7B2 && vpos == 0xf3) { - if (!skip) - activate_debugger (); - skip = 1; - } - if (vpos != 0xf3) - skip = 0; - } -#endif -} - -static void hsync_handler (void) -{ - bool vs = is_vsync (); - hsync_handler_pre (vs); - if (vs) { - vsync_handler_pre (); - if (savestate_check ()) { - uae_reset (0); - return; - } - } - hsync_handler_post (vs); -} - -void init_eventtab (void) -{ - int i; - - nextevent = 0; - for (i = 0; i < ev_max; i++) { - eventtab[i].active = 0; - eventtab[i].oldcycles = get_cycles (); - } - for (i = 0; i < ev2_max; i++) { - eventtab2[i].active = 0; - } - - eventtab[ev_cia].handler = CIA_handler; - eventtab[ev_hsync].handler = hsync_handler; - eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME; - eventtab[ev_hsync].active = 1; - eventtab[ev_misc].handler = MISC_handler; - eventtab[ev_audio].handler = audio_evhandler; - - eventtab2[ev2_blitter].handler = blitter_handler; - eventtab2[ev2_disk].handler = DISK_handler; - - events_schedule (); -} - -void custom_prepare (void) -{ - set_hpos (); - hsync_handler_post (true); -} - -void custom_reset (int hardreset) -{ - int i; - int zero = 0; - - target_reset (); - reset_all_systems (); - write_log (_T("Reset at %08X\n"), M68K_GETPC); - memory_map_dump (); - - lightpen_x = lightpen_y = -1; - lightpen_triggered = 0; - lightpen_cx = lightpen_cy = -1; - if (!savestate_state) { - extra_cycle = 0; - hsync_counter = 0; - vsync_counter = 0; - currprefs.chipset_mask = changed_prefs.chipset_mask; - update_mirrors (); - if (!aga_mode) { - for (i = 0; i < 32; i++) { - current_colors.color_regs_ecs[i] = 0; - current_colors.acolors[i] = getxcolor (0); - } -#ifdef AGA - } else { - for (i = 0; i < 256; i++) { - current_colors.color_regs_aga[i] = 0; - current_colors.acolors[i] = getxcolor (0); - } -#endif - } - - clxdat = 0; - - /* Clear the armed flags of all sprites. */ - memset (spr, 0, sizeof spr); - nr_armed = 0; - - dmacon = 0; - intreq_internal = 0; - intena = intena_internal = 0; - - copcon = 0; - DSKLEN (0, 0); - - bplcon0 = 0; - bplcon4 = 0x0011; /* Get AGA chipset into ECS compatibility mode */ - bplcon3 = 0x0C00; - - diwhigh = 0; - diwhigh_written = 0; - hdiwstate = DIW_waiting_start; // this does not reset at vblank - - FMODE (0, 0); - CLXCON (0); - setup_fmodes (0); - sprite_width = GET_SPRITEWIDTH (fmode); - beamcon0 = new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20; - bltstate = BLT_done; - blit_interrupt = 1; - lof_store = lof_current = 1; - } - - gayle_reset (hardreset); -#ifdef AUTOCONFIG - expamem_reset (); -#endif - a1000_reset (); - DISK_reset (); - CIA_reset (); - gayle_reset (0); -#ifdef A2091 - a2091_reset (); -#endif -#ifdef NCR - ncr_reset (); -#endif -#ifdef JIT - compemu_reset (); -#endif - unset_special (~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)); - - vpos = 0; - vpos_count = vpos_count_prev = 0; - - inputdevice_reset (); - timehack_alive = 0; - - curr_sprite_entries = 0; - prev_sprite_entries = 0; - sprite_entries[0][0].first_pixel = 0; - sprite_entries[1][0].first_pixel = MAX_SPR_PIXELS; - sprite_entries[0][1].first_pixel = 0; - sprite_entries[1][1].first_pixel = MAX_SPR_PIXELS; - memset (spixels, 0, 2 * MAX_SPR_PIXELS * sizeof *spixels); - memset (&spixstate, 0, sizeof spixstate); - - cop_state.state = COP_stop; - diwstate = DIW_waiting_start; - - dmal = 0; - init_hz_full (); - vpos_lpen = -1; - - audio_reset (); - if (!isrestore ()) { - /* must be called after audio_reset */ - adkcon = 0; - serial_uartbreak (0); - audio_update_adkmasks (); - } - - init_sprites (); - - init_hardware_frame (); - drawing_init (); - - reset_decisions (); - - bogusframe = 1; - - if (isrestore ()) { - uae_u16 v; - uae_u32 vv; - - audio_update_adkmasks (); - INTENA (0); - INTREQ (0); - COPJMP (1, 1); - v = bplcon0; - BPLCON0 (0, 0); - BPLCON0 (0, v); - FMODE (0, fmode); - if (!(currprefs.chipset_mask & CSMASK_AGA)) { - for(i = 0 ; i < 32 ; i++) { - vv = current_colors.color_regs_ecs[i]; - current_colors.color_regs_ecs[i] = -1; - record_color_change (0, i, vv); - remembered_color_entry = -1; - current_colors.color_regs_ecs[i] = vv; - current_colors.acolors[i] = xcolors[vv]; - } -#ifdef AGA - } else { - for(i = 0 ; i < 256 ; i++) { - vv = current_colors.color_regs_aga[i]; - current_colors.color_regs_aga[i] = -1; - record_color_change (0, i, vv); - remembered_color_entry = -1; - current_colors.color_regs_aga[i] = vv; - current_colors.acolors[i] = CONVERT_RGB (vv); - } -#endif - } - CLXCON (clxcon); - CLXCON2 (clxcon2); - calcdiw (); - write_log (_T("CPU=%d Chipset=%s %s\n"), - currprefs.cpu_model, - (currprefs.chipset_mask & CSMASK_AGA) ? _T("AGA") : - (currprefs.chipset_mask & CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE) == (CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE) ? _T("Full ECS") : - (currprefs.chipset_mask & CSMASK_ECS_DENISE) ? _T("ECS Denise") : - (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? _T("ECS") : - _T("OCS"), currprefs.ntscmode ? _T("NTSC") : _T("PAL")); - write_log (_T("State restored\n")); - for (i = 0; i < 8; i++) - nr_armed += spr[i].armed != 0; - if (! currprefs.produce_sound) { - eventtab[ev_audio].active = 0; - events_schedule (); - } - } - sprres = expand_sprres (bplcon0, bplcon3); - sprite_width = GET_SPRITEWIDTH (fmode); - setup_fmodes (0); - -#ifdef ACTION_REPLAY - /* Doing this here ensures we can use the 'reset' command from within AR */ - action_replay_reset (); -#endif -#if defined(ENFORCER) - enforcer_disable (); -#endif - - if (hardreset) - rtc_hardreset(); - - picasso_reset (); -} - -void dumpcustom (void) -{ - console_out_f (_T("DMACON: %04x INTENA: %04x (%04x) INTREQ: %04x (%04x) VPOS: %x HPOS: %x\n"), DMACONR (current_hpos ()), - intena, intena_internal, intreq, intreq_internal, vpos, current_hpos ()); - console_out_f (_T("COP1LC: %08lx, COP2LC: %08lx COPPTR: %08lx\n"), (unsigned long)cop1lc, (unsigned long)cop2lc, cop_state.ip); - console_out_f (_T("DIWSTRT: %04x DIWSTOP: %04x DDFSTRT: %04x DDFSTOP: %04x\n"), - (unsigned int)diwstrt, (unsigned int)diwstop, (unsigned int)ddfstrt, (unsigned int)ddfstop); - console_out_f (_T("BPLCON 0: %04x 1: %04x 2: %04x 3: %04x 4: %04x LOF=%d/%d HDIW=%d VDIW=%d\n"), - bplcon0, bplcon1, bplcon2, bplcon3, bplcon4, - lof_current, lof_store, - hdiwstate == DIW_waiting_start ? 0 : 1, diwstate == DIW_waiting_start ? 0 : 1); - if (timeframes) { - console_out_f (_T("Average frame time: %.2f ms [frames: %d time: %d]\n"), - (double)frametime / timeframes, timeframes, frametime); - if (total_skipped) - console_out_f (_T("Skipped frames: %d\n"), total_skipped); - } -} - -static void gen_custom_tables (void) -{ - int i; - for (i = 0; i < 256; i++) { - sprtaba[i] = ((((i >> 7) & 1) << 0) - | (((i >> 6) & 1) << 2) - | (((i >> 5) & 1) << 4) - | (((i >> 4) & 1) << 6) - | (((i >> 3) & 1) << 8) - | (((i >> 2) & 1) << 10) - | (((i >> 1) & 1) << 12) - | (((i >> 0) & 1) << 14)); - sprtabb[i] = sprtaba[i] * 2; - sprite_ab_merge[i] = (((i & 15) ? 1 : 0) - | ((i & 240) ? 2 : 0)); - } - for (i = 0; i < 16; i++) { - clxmask[i] = (((i & 1) ? 0xF : 0x3) - | ((i & 2) ? 0xF0 : 0x30) - | ((i & 4) ? 0xF00 : 0x300) - | ((i & 8) ? 0xF000 : 0x3000)); - sprclx[i] = (((i & 0x3) == 0x3 ? 1 : 0) - | ((i & 0x5) == 0x5 ? 2 : 0) - | ((i & 0x9) == 0x9 ? 4 : 0) - | ((i & 0x6) == 0x6 ? 8 : 0) - | ((i & 0xA) == 0xA ? 16 : 0) - | ((i & 0xC) == 0xC ? 32 : 0)) << 9; - } -} - -/* mousehack is now in "filesys boot rom" */ -static uae_u32 REGPARAM2 mousehack_helper_old (struct TrapContext *ctx) -{ - return 0; -} - -int custom_init (void) -{ - -#ifdef AUTOCONFIG - if (uae_boot_rom) { - uaecptr pos; - pos = here (); - - org (rtarea_base + 0xFF70); - calltrap (deftrap (mousehack_helper_old)); - dw (RTS); - - org (rtarea_base + 0xFFA0); - calltrap (deftrap (timehack_helper)); - dw (RTS); - - org (pos); - } -#endif - - gen_custom_tables (); - build_blitfilltable (); - - drawing_init (); - - create_cycle_diagram_table (); - - return 1; -} - -/* Custom chip memory bank */ - -static uae_u32 REGPARAM3 custom_lget (uaecptr) REGPARAM; -static uae_u32 REGPARAM3 custom_wget (uaecptr) REGPARAM; -static uae_u32 REGPARAM3 custom_bget (uaecptr) REGPARAM; -static uae_u32 REGPARAM3 custom_lgeti (uaecptr) REGPARAM; -static uae_u32 REGPARAM3 custom_wgeti (uaecptr) REGPARAM; -static void REGPARAM3 custom_lput (uaecptr, uae_u32) REGPARAM; -static void REGPARAM3 custom_wput (uaecptr, uae_u32) REGPARAM; -static void REGPARAM3 custom_bput (uaecptr, uae_u32) REGPARAM; - -addrbank custom_bank = { - custom_lget, custom_wget, custom_bget, - custom_lput, custom_wput, custom_bput, - default_xlate, default_check, NULL, _T("Custom chipset"), - custom_lgeti, custom_wgeti, ABFLAG_IO -}; - -static uae_u32 REGPARAM2 custom_wgeti (uaecptr addr) -{ - if (currprefs.cpu_model >= 68020) - return dummy_wgeti (addr); - return custom_wget (addr); -} -static uae_u32 REGPARAM2 custom_lgeti (uaecptr addr) -{ - if (currprefs.cpu_model >= 68020) - return dummy_lgeti (addr); - return custom_lget (addr); -} - -STATIC_INLINE uae_u32 REGPARAM2 custom_wget_1 (int hpos, uaecptr addr, int noput) -{ - uae_u16 v; -#ifdef JIT - special_mem |= S_READ; -#endif - addr &= 0xfff; -#if CUSTOM_DEBUG > 2 - write_log (_T("%d:%d:wget: %04X=%04X pc=%p\n"), current_hpos(), vpos, addr, addr & 0x1fe, m68k_getpc ()); -#endif - switch (addr & 0x1fe) { - case 0x002: v = DMACONR (hpos); break; - case 0x004: v = VPOSR (); break; - case 0x006: v = VHPOSR (); break; - - case 0x00A: v = JOY0DAT (); break; - case 0x00C: v = JOY1DAT (); break; - case 0x00E: v = CLXDAT (); break; - case 0x010: v = ADKCONR (); break; - - case 0x012: v = POT0DAT (); break; - case 0x014: v = POT1DAT (); break; - case 0x016: v = POTGOR (); break; - case 0x018: v = SERDATR (); break; - case 0x01A: v = DSKBYTR (hpos); break; - case 0x01C: v = INTENAR (); break; - case 0x01E: v = INTREQR (); break; - case 0x07C: v = DENISEID (); break; - -#ifdef AGA - case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A: - case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196: - case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2: - case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE: - case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA: - case 0x1BC: case 0x1BE: - v = COLOR_READ ((addr & 0x3E) / 2); - break; -#endif - - default: - /* OCS/ECS: - * reading write-only register causes write with last value in chip - * bus (custom registers, chipram, slowram) - * and finally returns either all ones or something weird if DMA happens - * in next (or previous) cycle.. FIXME. - * - * OCS-only special case: DFF000 (BLTDDAT) will always return whatever was left in bus - * - * AGA: - * only writes to custom registers change last value, read returns - * last value which then changes to all ones (following read will return - * all ones) - */ - v = last_custom_value1; - if (!noput) { - int r; - uae_u16 old = last_custom_value1; - uae_u16 l = currprefs.cpu_compatible && currprefs.cpu_model == 68000 ? regs.irc : 0xffff; - decide_line (hpos); - decide_fetch (hpos); - decide_blitter (hpos); - debug_wputpeek (0xdff000 + addr, l); - r = custom_wput_1 (hpos, addr, l, 1); - if (r) { // register don't exist - if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) { - v = l; - } else { - if ((addr & 0x1fe) == 0) { - if (is_cycle_ce ()) - v = last_custom_value1; - else - v = l; - } - } - } else { - v = 0xffff; - } -#if CUSTOM_DEBUG > 0 - write_log (_T("%08X read = %04X. Value written=%04X PC=%08x\n"), 0xdff000 | addr, v, l, M68K_GETPC); -#endif - return v; - } - } - last_custom_value1 = v; - return v; -} - -STATIC_INLINE uae_u32 custom_wget2 (uaecptr addr) -{ - uae_u32 v; - int hpos = current_hpos (); - - sync_copper_with_cpu (hpos, 1); - v = custom_wget_1 (hpos, addr, 0); -#ifdef ACTION_REPLAY -#ifdef ACTION_REPLAY_COMMON - addr &= 0x1ff; - ar_custom[addr + 0] = (uae_u8)(v >> 8); - ar_custom[addr + 1] = (uae_u8)(v); -#endif -#endif - return v; -} - -static uae_u32 REGPARAM2 custom_wget (uaecptr addr) -{ - uae_u32 v; - - if (addr & 1) { - /* think about move.w $dff005,d0.. (68020+ only) */ - addr &= ~1; - v = custom_wget2 (addr) << 8; - v |= custom_wget2 (addr + 2) >> 8; - return v; - } - return custom_wget2 (addr); -} - -static uae_u32 REGPARAM2 custom_bget (uaecptr addr) -{ - uae_u32 v; -#ifdef JIT - special_mem |= S_READ; -#endif - v = custom_wget2 (addr & ~1); - v >>= (addr & 1 ? 0 : 8); - return v; -} - -static uae_u32 REGPARAM2 custom_lget (uaecptr addr) -{ -#ifdef JIT - special_mem |= S_READ; -#endif - return ((uae_u32)custom_wget (addr) << 16) | custom_wget (addr + 2); -} -static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int noget) -{ - if (!noget) - last_custom_value1 = value; - addr &= 0x1FE; - value &= 0xffff; -#ifdef ACTION_REPLAY -#ifdef ACTION_REPLAY_COMMON - ar_custom[addr+0]=(uae_u8)(value>>8); - ar_custom[addr+1]=(uae_u8)(value); -#endif -#endif - switch (addr) { - case 0x00E: CLXDAT (); break; - - case 0x020: DSKPTH (value); break; - case 0x022: DSKPTL (value); break; - case 0x024: DSKLEN (value, hpos); break; - case 0x026: DSKDAT (value); break; - - case 0x02A: VPOSW (value); break; - case 0x02C: VHPOSW (value); break; - case 0x02E: COPCON (value); break; - case 0x030: SERDAT (value); break; - case 0x032: SERPER (value); break; - case 0x034: POTGO (value); break; - - case 0x040: BLTCON0 (hpos, value); break; - case 0x042: BLTCON1 (hpos, value); break; - - case 0x044: BLTAFWM (hpos, value); break; - case 0x046: BLTALWM (hpos, value); break; - - case 0x050: BLTAPTH (hpos, value); break; - case 0x052: BLTAPTL (hpos, value); break; - case 0x04C: BLTBPTH (hpos, value); break; - case 0x04E: BLTBPTL (hpos, value); break; - case 0x048: BLTCPTH (hpos, value); break; - case 0x04A: BLTCPTL (hpos, value); break; - case 0x054: BLTDPTH (hpos, value); break; - case 0x056: BLTDPTL (hpos, value); break; - - case 0x058: BLTSIZE (hpos, value); break; - - case 0x064: BLTAMOD (hpos, value); break; - case 0x062: BLTBMOD (hpos, value); break; - case 0x060: BLTCMOD (hpos, value); break; - case 0x066: BLTDMOD (hpos, value); break; - - case 0x070: BLTCDAT (hpos, value); break; - case 0x072: BLTBDAT (hpos, value); break; - case 0x074: BLTADAT (hpos, value); break; - - case 0x07E: DSKSYNC (hpos, value); break; - - case 0x080: COP1LCH (value); break; - case 0x082: COP1LCL (value); break; - case 0x084: COP2LCH (value); break; - case 0x086: COP2LCL (value); break; - - case 0x088: COPJMP (1, 0); break; - case 0x08A: COPJMP (2, 0); break; - - case 0x08E: DIWSTRT (hpos, value); break; - case 0x090: DIWSTOP (hpos, value); break; - case 0x092: DDFSTRT (hpos, value); break; - case 0x094: DDFSTOP (hpos, value); break; - - case 0x096: DMACON (hpos, value); break; - case 0x098: CLXCON (value); break; - case 0x09A: INTENA (value); break; - case 0x09C: INTREQ (value); break; - case 0x09E: ADKCON (hpos, value); break; - - case 0x0A0: AUDxLCH (0, value); break; - case 0x0A2: AUDxLCL (0, value); break; - case 0x0A4: AUDxLEN (0, value); break; - case 0x0A6: AUDxPER (0, value); break; - case 0x0A8: AUDxVOL (0, value); break; - case 0x0AA: AUDxDAT (0, value); break; - - case 0x0B0: AUDxLCH (1, value); break; - case 0x0B2: AUDxLCL (1, value); break; - case 0x0B4: AUDxLEN (1, value); break; - case 0x0B6: AUDxPER (1, value); break; - case 0x0B8: AUDxVOL (1, value); break; - case 0x0BA: AUDxDAT (1, value); break; - - case 0x0C0: AUDxLCH (2, value); break; - case 0x0C2: AUDxLCL (2, value); break; - case 0x0C4: AUDxLEN (2, value); break; - case 0x0C6: AUDxPER (2, value); break; - case 0x0C8: AUDxVOL (2, value); break; - case 0x0CA: AUDxDAT (2, value); break; - - case 0x0D0: AUDxLCH (3, value); break; - case 0x0D2: AUDxLCL (3, value); break; - case 0x0D4: AUDxLEN (3, value); break; - case 0x0D6: AUDxPER (3, value); break; - case 0x0D8: AUDxVOL (3, value); break; - case 0x0DA: AUDxDAT (3, value); break; - - case 0x0E0: BPLxPTH (hpos, value, 0); break; - case 0x0E2: BPLxPTL (hpos, value, 0); break; - case 0x0E4: BPLxPTH (hpos, value, 1); break; - case 0x0E6: BPLxPTL (hpos, value, 1); break; - case 0x0E8: BPLxPTH (hpos, value, 2); break; - case 0x0EA: BPLxPTL (hpos, value, 2); break; - case 0x0EC: BPLxPTH (hpos, value, 3); break; - case 0x0EE: BPLxPTL (hpos, value, 3); break; - case 0x0F0: BPLxPTH (hpos, value, 4); break; - case 0x0F2: BPLxPTL (hpos, value, 4); break; - case 0x0F4: BPLxPTH (hpos, value, 5); break; - case 0x0F6: BPLxPTL (hpos, value, 5); break; - case 0x0F8: BPLxPTH (hpos, value, 6); break; - case 0x0FA: BPLxPTL (hpos, value, 6); break; - case 0x0FC: BPLxPTH (hpos, value, 7); break; - case 0x0FE: BPLxPTL (hpos, value, 7); break; - - case 0x100: BPLCON0 (hpos, value); break; - case 0x102: BPLCON1 (hpos, value); break; - case 0x104: BPLCON2 (hpos, value); break; -#ifdef ECS_DENISE - case 0x106: BPLCON3 (hpos, value); break; -#endif - - case 0x108: BPL1MOD (hpos, value); break; - case 0x10A: BPL2MOD (hpos, value); break; -#ifdef AGA - case 0x10E: CLXCON2 (value); break; -#endif - - case 0x110: BPLxDAT (hpos, 0, value); break; - case 0x112: BPLxDAT (hpos, 1, value); break; - case 0x114: BPLxDAT (hpos, 2, value); break; - case 0x116: BPLxDAT (hpos, 3, value); break; - case 0x118: BPLxDAT (hpos, 4, value); break; - case 0x11A: BPLxDAT (hpos, 5, value); break; - case 0x11C: BPLxDAT (hpos, 6, value); break; - case 0x11E: BPLxDAT (hpos, 7, value); break; - - case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A: - case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196: - case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2: - case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE: - case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA: - case 0x1BC: case 0x1BE: - COLOR_WRITE (hpos, value & 0xFFF, (addr & 0x3E) / 2); - break; - case 0x120: case 0x124: case 0x128: case 0x12C: - case 0x130: case 0x134: case 0x138: case 0x13C: - SPRxPTH (hpos, value, (addr - 0x120) / 4); - break; - case 0x122: case 0x126: case 0x12A: case 0x12E: - case 0x132: case 0x136: case 0x13A: case 0x13E: - SPRxPTL (hpos, value, (addr - 0x122) / 4); - break; - case 0x140: case 0x148: case 0x150: case 0x158: - case 0x160: case 0x168: case 0x170: case 0x178: - SPRxPOS (hpos, value, (addr - 0x140) / 8); - break; - case 0x142: case 0x14A: case 0x152: case 0x15A: - case 0x162: case 0x16A: case 0x172: case 0x17A: - SPRxCTL (hpos, value, (addr - 0x142) / 8); - break; - case 0x144: case 0x14C: case 0x154: case 0x15C: - case 0x164: case 0x16C: case 0x174: case 0x17C: - SPRxDATA (hpos, value, (addr - 0x144) / 8); - break; - case 0x146: case 0x14E: case 0x156: case 0x15E: - case 0x166: case 0x16E: case 0x176: case 0x17E: - SPRxDATB (hpos, value, (addr - 0x146) / 8); - break; - - case 0x36: JOYTEST (value); break; - case 0x5A: BLTCON0L (hpos, value); break; - case 0x5C: BLTSIZV (hpos, value); break; - case 0x5E: BLTSIZH (hpos, value); break; - case 0x1E4: DIWHIGH (hpos, value); break; -#ifdef AGA - case 0x10C: BPLCON4 (hpos, value); break; -#endif - -#ifndef CUSTOM_SIMPLE - case 0x1DC: BEAMCON0 (value); break; -#ifdef ECS_DENISE - case 0x1C0: if (htotal != value) { htotal = value; varsync (); } break; - case 0x1C2: if (hsstop != value) { hsstop = value; varsync (); } break; - case 0x1C4: if (hbstrt != value) { hbstrt = value; varsync (); } break; - case 0x1C6: if (hbstop != value) { hbstop = value; varsync (); } break; - case 0x1C8: if (vtotal != value) { vtotal = value; varsync (); } break; - case 0x1CA: if (vsstop != value) { vsstop = value; varsync (); } break; - case 0x1CC: if (vbstrt < value || vbstrt > value + 1) { vbstrt = value; varsync (); } break; - case 0x1CE: if (vbstop < value || vbstop > value + 1) { vbstop = value; varsync (); } break; - case 0x1DE: if (hsstrt != value) { hsstrt = value; varsync (); } break; - case 0x1E0: if (vsstrt != value) { vsstrt = value; varsync (); } break; - case 0x1E2: if (hcenter != value) { hcenter = value; varsync (); } break; -#endif -#endif - -#ifdef AGA - case 0x1FC: FMODE (hpos, value); break; -#endif - case 0x1FE: FNULL (value); break; - - /* writing to read-only register causes read access */ - default: - if (!noget) { -#if CUSTOM_DEBUG > 0 - write_log (_T("%04X written %08x\n"), addr, M68K_GETPC); -#endif - custom_wget_1 (hpos, addr, 1); - } - return 1; - } - return 0; -} - -static void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value) -{ - int hpos = current_hpos (); -#ifdef JIT - special_mem |= S_WRITE; -#endif -#if CUSTOM_DEBUG > 2 - write_log (_T("%d:%d:wput: %04X %04X pc=%p\n"), hpos, vpos, addr & 0x01fe, value & 0xffff, m68k_getpc ()); -#endif - sync_copper_with_cpu (hpos, 1); - if (addr & 1) { - addr &= ~1; - custom_wput_1 (hpos, addr, (value >> 8) | (value & 0xff00), 0); - custom_wput_1 (hpos, addr + 2, (value << 8) | (value & 0x00ff), 0); - return; - } - custom_wput_1 (hpos, addr, value, 0); -} - -static void REGPARAM2 custom_bput (uaecptr addr, uae_u32 value) -{ - static int warned; - uae_u16 rval; - - if (currprefs.chipset_mask & CSMASK_AGA) { - if (addr & 1) { - rval = value & 0xff; - } else { - rval = (value << 8) | (value & 0xFF); - } - } else { - rval = (value << 8) | (value & 0xff); - } - -#ifdef JIT - special_mem |= S_WRITE; -#endif - if (currprefs.cpu_model == 68060) { - if (addr & 1) - custom_wput (addr & ~1, rval); - else - custom_wput (addr, value << 8); - } else { - custom_wput (addr & ~1, rval); - } -} - -static void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value) -{ -#ifdef JIT - special_mem |= S_WRITE; -#endif - custom_wput (addr & 0xfffe, value >> 16); - custom_wput ((addr + 2) & 0xfffe, (uae_u16)value); -} - -#ifdef SAVESTATE - -void custom_prepare_savestate (void) -{ - int i; - - for (i = 0; i < ev2_max; i++) { - if (eventtab2[i].active) { - eventtab2[i].active = 0; - eventtab2[i].handler (eventtab2[i].data); - } - } -} - -#define RB restore_u8 () -#define SRB (uae_s8)restore_u8 () -#define RBB restore_u8 () != 0 -#define RW restore_u16 () -#define RL restore_u32 () - -uae_u8 *restore_custom (uae_u8 *src) -{ - uae_u16 dsklen, dskbytr; - int dskpt; - int i; - - audio_reset (); - - changed_prefs.chipset_mask = currprefs.chipset_mask = RL & CSMASK_MASK; - update_mirrors (); - RW; /* 000 BLTDDAT */ - RW; /* 002 DMACONR */ - RW; /* 004 VPOSR */ - RW; /* 006 VHPOSR */ - RW; /* 008 DSKDATR (dummy register) */ - JOYSET(0, RW); /* 00A JOY0DAT */ - JOYSET(1, RW); /* 00C JOY1DAT */ - clxdat = RW; /* 00E CLXDAT */ - RW; /* 010 ADKCONR */ - RW; /* 012 POT0DAT* */ - RW; /* 014 POT1DAT* */ - RW; /* 016 POTINP* */ - RW; /* 018 SERDATR* */ - dskbytr = RW; /* 01A DSKBYTR */ - RW; /* 01C INTENAR */ - RW; /* 01E INTREQR */ - dskpt = RL; /* 020-022 DSKPT */ - dsklen = RW; /* 024 DSKLEN */ - RW; /* 026 DSKDAT */ - RW; /* 028 REFPTR */ - i = RW; lof_store = lof_current = (i & 0x8000) ? 1 : 0; lol = (i & 0x0080) ? 1 : 0; /* 02A VPOSW */ - RW; /* 02C VHPOSW */ - COPCON (RW); /* 02E COPCON */ - RW; /* 030 SERDAT* */ - RW; /* 032 SERPER* */ - POTGO (RW); /* 034 POTGO */ - RW; /* 036 JOYTEST* */ - RW; /* 038 STREQU */ - RW; /* 03A STRVHBL */ - RW; /* 03C STRHOR */ - RW; /* 03E STRLONG */ - BLTCON0 (0, RW); /* 040 BLTCON0 */ - BLTCON1 (0, RW); /* 042 BLTCON1 */ - BLTAFWM (0, RW); /* 044 BLTAFWM */ - BLTALWM (0, RW); /* 046 BLTALWM */ - BLTCPTH (0, RW);BLTCPTL(0, RW); /* 048-04B BLTCPT */ - BLTBPTH (0, RW);BLTBPTL(0, RW); /* 04C-04F BLTBPT */ - BLTAPTH (0, RW);BLTAPTL(0, RW); /* 050-053 BLTAPT */ - BLTDPTH (0, RW);BLTDPTL(0, RW); /* 054-057 BLTDPT */ - RW; /* 058 BLTSIZE */ - RW; /* 05A BLTCON0L */ - blt_info.vblitsize = RW;/* 05C BLTSIZV */ - blt_info.hblitsize = RW;/* 05E BLTSIZH */ - BLTCMOD (0, RW); /* 060 BLTCMOD */ - BLTBMOD (0, RW); /* 062 BLTBMOD */ - BLTAMOD (0, RW); /* 064 BLTAMOD */ - BLTDMOD (0, RW); /* 066 BLTDMOD */ - RW; /* 068 ? */ - RW; /* 06A ? */ - RW; /* 06C ? */ - RW; /* 06E ? */ - BLTCDAT (0, RW); /* 070 BLTCDAT */ - BLTBDAT (0, RW); /* 072 BLTBDAT */ - BLTADAT (0, RW); /* 074 BLTADAT */ - RW; /* 076 ? */ - RW; /* 078 ? */ - RW; /* 07A ? */ - RW; /* 07C LISAID */ - DSKSYNC (-1, RW); /* 07E DSKSYNC */ - cop1lc = RL; /* 080/082 COP1LC */ - cop2lc = RL; /* 084/086 COP2LC */ - RW; /* 088 ? */ - RW; /* 08A ? */ - RW; /* 08C ? */ - diwstrt = RW; /* 08E DIWSTRT */ - diwstop = RW; /* 090 DIWSTOP */ - ddfstrt = RW; /* 092 DDFSTRT */ - ddfstop = RW; /* 094 DDFSTOP */ - dmacon = RW & ~(0x2000|0x4000); /* 096 DMACON */ - CLXCON (RW); /* 098 CLXCON */ - intena = intena_internal = RW; /* 09A INTENA */ - intreq = RW; /* 09C INTREQ */ - intreq_internal = intreq; - adkcon = RW; /* 09E ADKCON */ - for (i = 0; i < 8; i++) - bplptx[i] = bplpt[i] = RL; - bplcon0 = RW; /* 100 BPLCON0 */ - bplcon1 = RW; /* 102 BPLCON1 */ - bplcon2 = RW; /* 104 BPLCON2 */ - bplcon3 = RW; /* 106 BPLCON3 */ - bpl1mod = RW; /* 108 BPL1MOD */ - bpl2mod = RW; /* 10A BPL2MOD */ - bplcon4 = RW; /* 10C BPLCON4 */ - clxcon2 = RW; /* 10E CLXCON2* */ - for(i = 0; i < 8; i++) - bplxdat[i] = RW; /* BPLXDAT */ - for(i = 0; i < 32; i++) - current_colors.color_regs_ecs[i] = RW; /* 180 COLORxx */ - htotal = RW; /* 1C0 HTOTAL */ - hsstop = RW; /* 1C2 HSTOP ? */ - hbstrt = RW; /* 1C4 HBSTRT ? */ - hbstop = RW; /* 1C6 HBSTOP ? */ - vtotal = RW; /* 1C8 VTOTAL */ - vsstop = RW; /* 1CA VSSTOP */ - vbstrt = RW; /* 1CC VBSTRT */ - vbstop = RW; /* 1CE VBSTOP */ - RW; /* 1D0 ? */ - RW; /* 1D2 ? */ - RW; /* 1D4 ? */ - RW; /* 1D6 ? */ - RW; /* 1D8 ? */ - RW; /* 1DA ? */ - new_beamcon0 = RW; /* 1DC BEAMCON0 */ - hsstrt = RW; /* 1DE HSSTRT */ - vsstrt = RW; /* 1E0 VSSTT */ - hcenter = RW; /* 1E2 HCENTER */ - diwhigh = RW; /* 1E4 DIWHIGH */ - diwhigh_written = (diwhigh & 0x8000) ? 1 : 0; - hdiwstate = (diwhigh & 0x4000) ? DIW_waiting_stop : DIW_waiting_start; - diwhigh &= 0x3fff; - RW; /* 1E6 ? */ - RW; /* 1E8 ? */ - RW; /* 1EA ? */ - RW; /* 1EC ? */ - RW; /* 1EE ? */ - RW; /* 1F0 ? */ - RW; /* 1F2 ? */ - RW; /* 1F4 ? */ - RW; /* 1F6 ? */ - RW; /* 1F8 ? */ - i = RW; /* 1FA ? */ - if (i & 0x8000) - currprefs.ntscmode = changed_prefs.ntscmode = i & 1; - fmode = RW; /* 1FC FMODE */ - last_custom_value1 = RW;/* 1FE ? */ - - DISK_restore_custom (dskpt, dsklen, dskbytr); - - return src; -} - -#endif /* SAVESTATE */ - -#if defined SAVESTATE || defined DEBUGGER - -#define SB save_u8 -#define SW save_u16 -#define SL save_u32 - -extern uae_u16 serper; - -uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full) -{ - uae_u8 *dstbak, *dst; - int i; - uae_u32 dskpt; - uae_u16 dsklen, dsksync, dskbytr; - - DISK_save_custom (&dskpt, &dsklen, &dsksync, &dskbytr); - - if (dstptr) - dstbak = dst = dstptr; - else - dstbak = dst = xmalloc (uae_u8, 8 + 256 * 2); - - SL (currprefs.chipset_mask); - SW (0); /* 000 BLTDDAT */ - SW (dmacon); /* 002 DMACONR */ - SW (VPOSR ()); /* 004 VPOSR */ - SW (VHPOSR ()); /* 006 VHPOSR */ - SW (0); /* 008 DSKDATR */ - SW (JOYGET (0)); /* 00A JOY0DAT */ - SW (JOYGET (1)); /* 00C JOY1DAT */ - SW (clxdat | 0x8000); /* 00E CLXDAT */ - SW (ADKCONR ()); /* 010 ADKCONR */ - SW (POT0DAT ()); /* 012 POT0DAT */ - SW (POT1DAT ()); /* 014 POT1DAT */ - SW (0) ; /* 016 POTINP * */ - SW (0); /* 018 SERDATR * */ - SW (dskbytr); /* 01A DSKBYTR */ - SW (INTENAR ()); /* 01C INTENAR */ - SW (INTREQR ()); /* 01E INTREQR */ - SL (dskpt); /* 020-023 DSKPT */ - SW (dsklen); /* 024 DSKLEN */ - SW (0); /* 026 DSKDAT */ - SW (0); /* 028 REFPTR */ - SW ((lof_store ? 0x8001 : 0) | (lol ? 0x0080 : 0));/* 02A VPOSW */ - SW (0); /* 02C VHPOSW */ - SW (copcon); /* 02E COPCON */ - SW (serper); /* 030 SERDAT * */ - SW (serdat); /* 032 SERPER * */ - SW (potgo_value); /* 034 POTGO */ - SW (0); /* 036 JOYTEST * */ - SW (0); /* 038 STREQU */ - SW (0); /* 03A STRVBL */ - SW (0); /* 03C STRHOR */ - SW (0); /* 03E STRLONG */ - SW (bltcon0); /* 040 BLTCON0 */ - SW (bltcon1); /* 042 BLTCON1 */ - SW (blt_info.bltafwm); /* 044 BLTAFWM */ - SW (blt_info.bltalwm); /* 046 BLTALWM */ - SL (bltcpt); /* 048-04B BLTCPT */ - SL (bltbpt); /* 04C-04F BLTCPT */ - SL (bltapt); /* 050-053 BLTCPT */ - SL (bltdpt); /* 054-057 BLTCPT */ - SW (0); /* 058 BLTSIZE */ - SW (0); /* 05A BLTCON0L (use BLTCON0 instead) */ - SW (blt_info.vblitsize);/* 05C BLTSIZV */ - SW (blt_info.hblitsize);/* 05E BLTSIZH */ - SW (blt_info.bltcmod); /* 060 BLTCMOD */ - SW (blt_info.bltbmod); /* 062 BLTBMOD */ - SW (blt_info.bltamod); /* 064 BLTAMOD */ - SW (blt_info.bltdmod); /* 066 BLTDMOD */ - SW (0); /* 068 ? */ - SW (0); /* 06A ? */ - SW (0); /* 06C ? */ - SW (0); /* 06E ? */ - SW (blt_info.bltcdat); /* 070 BLTCDAT */ - SW (blt_info.bltbdat); /* 072 BLTBDAT */ - SW (blt_info.bltadat); /* 074 BLTADAT */ - SW (0); /* 076 ? */ - SW (0); /* 078 ? */ - SW (0); /* 07A ? */ - SW (DENISEID ()); /* 07C DENISEID/LISAID */ - SW (dsksync); /* 07E DSKSYNC */ - SL (cop1lc); /* 080-083 COP1LC */ - SL (cop2lc); /* 084-087 COP2LC */ - SW (0); /* 088 ? */ - SW (0); /* 08A ? */ - SW (0); /* 08C ? */ - SW (diwstrt); /* 08E DIWSTRT */ - SW (diwstop); /* 090 DIWSTOP */ - SW (ddfstrt); /* 092 DDFSTRT */ - SW (ddfstop); /* 094 DDFSTOP */ - SW (dmacon); /* 096 DMACON */ - SW (clxcon); /* 098 CLXCON */ - SW (intena); /* 09A INTENA */ - SW (intreq); /* 09C INTREQ */ - SW (adkcon); /* 09E ADKCON */ - for (i = 0; full && i < 32; i++) - SW (0); - for (i = 0; i < 8; i++) - SL (bplpt[i]); /* 0E0-0FE BPLxPT */ - SW (bplcon0); /* 100 BPLCON0 */ - SW (bplcon1); /* 102 BPLCON1 */ - SW (bplcon2); /* 104 BPLCON2 */ - SW (bplcon3); /* 106 BPLCON3 */ - SW (bpl1mod); /* 108 BPL1MOD */ - SW (bpl2mod); /* 10A BPL2MOD */ - SW (bplcon4); /* 10C BPLCON4 */ - SW (clxcon2); /* 10E CLXCON2 */ - for (i = 0;i < 8; i++) - SW (bplxdat[i]); /* 110 BPLxDAT */ - if (full) { - for (i = 0; i < 8; i++) { - SL (spr[i].pt); /* 120-13E SPRxPT */ - SW (sprpos[i]); /* 1x0 SPRxPOS */ - SW (sprctl[i]); /* 1x2 SPRxPOS */ - SW (sprdata[i][0]); /* 1x4 SPRxDATA */ - SW (sprdatb[i][0]); /* 1x6 SPRxDATB */ - } - } - for ( i = 0; i < 32; i++) { - if (currprefs.chipset_mask & CSMASK_AGA) { - uae_u32 v = current_colors.color_regs_aga[i]; - uae_u16 v2; - v &= 0x00f0f0f0; - v2 = (v >> 4) & 15; - v2 |= ((v >> 12) & 15) << 4; - v2 |= ((v >> 20) & 15) << 8; - SW (v2); - } else { - SW (current_colors.color_regs_ecs[i]); /* 180-1BE COLORxx */ - } - } - SW (htotal); /* 1C0 HTOTAL */ - SW (hsstop); /* 1C2 HSTOP*/ - SW (hbstrt); /* 1C4 HBSTRT */ - SW (hbstop); /* 1C6 HBSTOP */ - SW (vtotal); /* 1C8 VTOTAL */ - SW (vsstop); /* 1CA VSSTOP */ - SW (vbstrt); /* 1CC VBSTRT */ - SW (vbstop); /* 1CE VBSTOP */ - SW (0); /* 1D0 */ - SW (0); /* 1D2 */ - SW (0); /* 1D4 */ - SW (0); /* 1D6 */ - SW (0); /* 1D8 */ - SW (0); /* 1DA */ - SW (beamcon0); /* 1DC BEAMCON0 */ - SW (hsstrt); /* 1DE HSSTRT */ - SW (vsstrt); /* 1E0 VSSTRT */ - SW (hcenter); /* 1E2 HCENTER */ - SW (diwhigh | (diwhigh_written ? 0x8000 : 0) | (hdiwstate == DIW_waiting_stop ? 0x4000 : 0)); /* 1E4 DIWHIGH */ - SW (0); /* 1E6 */ - SW (0); /* 1E8 */ - SW (0); /* 1EA */ - SW (0); /* 1EC */ - SW (0); /* 1EE */ - SW (0); /* 1F0 */ - SW (0); /* 1F2 */ - SW (0); /* 1F4 */ - SW (0); /* 1F6 */ - SW (0); /* 1F8 */ - SW (0x8000 | (currprefs.ntscmode ? 1 : 0)); /* 1FA (re-used for NTSC) */ - SW (fmode); /* 1FC FMODE */ - SW (last_custom_value1); /* 1FE */ - - *len = dst - dstbak; - return dstbak; -} - -#endif /* SAVESTATE || DEBUGGER */ - -#ifdef SAVESTATE - -uae_u8 *restore_custom_agacolors (uae_u8 *src) -{ - int i; - - for (i = 0; i < 256; i++) { -#ifdef AGA - uae_u32 v = RL; - color_regs_aga_genlock[i] = 0; - if (v & 0x80000000) - color_regs_aga_genlock[i] = 1; - v &= 0x00ffffff; - current_colors.color_regs_aga[i] = v; -#else - RL; -#endif - } - return src; -} - -uae_u8 *save_custom_agacolors (int *len, uae_u8 *dstptr) -{ - uae_u8 *dstbak, *dst; - int i; - - if (dstptr) - dstbak = dst = dstptr; - else - dstbak = dst = xmalloc (uae_u8, 256 * 4); - for (i = 0; i < 256; i++) -#ifdef AGA - SL (current_colors.color_regs_aga[i] | (color_regs_aga_genlock[i] ? 0x80000000 : 0)); -#else - SL (0); -#endif - *len = dst - dstbak; - return dstbak; -} - -uae_u8 *restore_custom_sprite (int num, uae_u8 *src) -{ - memset (&spr[num], 0, sizeof (struct sprite)); - spr[num].pt = RL; /* 120-13E SPRxPT */ - sprpos[num] = RW; /* 1x0 SPRxPOS */ - sprctl[num] = RW; /* 1x2 SPRxPOS */ - sprdata[num][0] = RW; /* 1x4 SPRxDATA */ - sprdatb[num][0] = RW; /* 1x6 SPRxDATB */ - sprdata[num][1] = RW; - sprdatb[num][1] = RW; - sprdata[num][2] = RW; - sprdatb[num][2] = RW; - sprdata[num][3] = RW; - sprdatb[num][3] = RW; - spr[num].armed = RB; - return src; -} - -uae_u8 *save_custom_sprite (int num, int *len, uae_u8 *dstptr) -{ - uae_u8 *dstbak, *dst; - - if (dstptr) - dstbak = dst = dstptr; - else - dstbak = dst = xmalloc (uae_u8, 30); - SL (spr[num].pt); /* 120-13E SPRxPT */ - SW (sprpos[num]); /* 1x0 SPRxPOS */ - SW (sprctl[num]); /* 1x2 SPRxPOS */ - SW (sprdata[num][0]); /* 1x4 SPRxDATA */ - SW (sprdatb[num][0]); /* 1x6 SPRxDATB */ - SW (sprdata[num][1]); - SW (sprdatb[num][1]); - SW (sprdata[num][2]); - SW (sprdatb[num][2]); - SW (sprdata[num][3]); - SW (sprdatb[num][3]); - SB (spr[num].armed ? 1 : 0); - *len = dst - dstbak; - return dstbak; -} - -uae_u8 *restore_custom_extra (uae_u8 *src) -{ - uae_u32 v = restore_u32 (); - - if (!(v & 1)) - v = 0; - currprefs.cs_compatible = changed_prefs.cs_compatible = v >> 24; - - currprefs.genlock = changed_prefs.genlock = RBB; - currprefs.cs_rtc = changed_prefs.cs_rtc = RB; - currprefs.cs_rtc_adjust = changed_prefs.cs_rtc_adjust = RL; - - currprefs.cs_a1000ram = changed_prefs.cs_a1000ram = RBB; - currprefs.cs_slowmemisfast = changed_prefs.cs_slowmemisfast = RBB; - - currprefs.cs_a2091 = changed_prefs.cs_a2091 = RBB; - currprefs.cs_a4091 = changed_prefs.cs_a4091 = RBB; - currprefs.cs_cdtvscsi = changed_prefs.cs_cdtvscsi = RBB; - - currprefs.cs_pcmcia = changed_prefs.cs_pcmcia = RBB; - currprefs.cs_ciaatod = changed_prefs.cs_ciaatod = RB; - currprefs.cs_ciaoverlay = changed_prefs.cs_ciaoverlay = RBB; - - currprefs.cs_agnusbltbusybug = changed_prefs.cs_agnusbltbusybug = RBB; - currprefs.cs_denisenoehb = changed_prefs.cs_denisenoehb = RBB; - - currprefs.cs_agnusrev = changed_prefs.cs_agnusrev = SRB; - currprefs.cs_deniserev = changed_prefs.cs_deniserev = SRB; - currprefs.cs_fatgaryrev = changed_prefs.cs_fatgaryrev = SRB; - currprefs.cs_ramseyrev = changed_prefs.cs_ramseyrev = SRB; - - currprefs.cs_cd32c2p = changed_prefs.cs_cd32c2p = RBB; - currprefs.cs_cd32cd = changed_prefs.cs_cd32cd = RBB; - currprefs.cs_cd32nvram = changed_prefs.cs_cd32nvram = RBB; - currprefs.cs_cdtvcd = changed_prefs.cs_cdtvcd = RBB; - currprefs.cs_cdtvram = changed_prefs.cs_cdtvram = RBB; - currprefs.cs_cdtvcard = changed_prefs.cs_cdtvcard = RB; - - currprefs.cs_df0idhw = changed_prefs.cs_df0idhw = RBB; - currprefs.cs_dipagnus = changed_prefs.cs_dipagnus = RBB; - currprefs.cs_ide = changed_prefs.cs_ide = RB; - currprefs.cs_mbdmac = changed_prefs.cs_mbdmac = RB; - currprefs.cs_ksmirror_a8 = changed_prefs.cs_ksmirror_a8 = RBB; - currprefs.cs_ksmirror_e0 = changed_prefs.cs_ksmirror_e0 = RBB; - currprefs.cs_resetwarning = changed_prefs.cs_resetwarning = RBB; - - return src; -} - -uae_u8 *save_custom_extra (int *len, uae_u8 *dstptr) -{ - uae_u8 *dstbak, *dst; - - if (dstptr) - dstbak = dst = dstptr; - else - dstbak = dst = xmalloc (uae_u8, 1000); - - SL ((currprefs.cs_compatible << 24) | 1); - SB (currprefs.genlock ? 1 : 0); - SB (currprefs.cs_rtc); - SL (currprefs.cs_rtc_adjust); - - SB (currprefs.cs_a1000ram ? 1 : 0); - SB (currprefs.cs_slowmemisfast ? 1 : 0); - - SB (currprefs.cs_a2091 ? 1 : 0); - SB (currprefs.cs_a4091 ? 1 : 0); - SB (currprefs.cs_cdtvscsi ? 1 : 0); - - SB (currprefs.cs_pcmcia ? 1 : 0); - SB (currprefs.cs_ciaatod); - SB (currprefs.cs_ciaoverlay ? 1 : 0); - - SB (currprefs.cs_agnusbltbusybug ? 1 : 0); - SB (currprefs.cs_denisenoehb ? 1 : 0); - - SB (currprefs.cs_agnusrev); - SB (currprefs.cs_deniserev); - SB (currprefs.cs_fatgaryrev); - SB (currprefs.cs_ramseyrev); - - SB (currprefs.cs_cd32c2p); - SB (currprefs.cs_cd32cd); - SB (currprefs.cs_cd32nvram); - SB (currprefs.cs_cdtvcd ? 1 : 0); - SB (currprefs.cs_cdtvram ? 1 : 0); - SB (currprefs.cs_cdtvcard); - - SB (currprefs.cs_df0idhw ? 1 : 0); - SB (currprefs.cs_dipagnus ? 1 : 0); - SB (currprefs.cs_ide); - SB (currprefs.cs_mbdmac); - SB (currprefs.cs_ksmirror_a8 ? 1 : 0); - SB (currprefs.cs_ksmirror_e0 ? 1 : 0); - SB (currprefs.cs_resetwarning ? 1 : 0); - - *len = dst - dstbak; - return dstbak; -} - -uae_u8 *restore_custom_event_delay (uae_u8 *src) -{ - if (restore_u32 () != 1) - return src; - int cnt = restore_u8 (); - for (int i = 0; i < cnt; i++) { - uae_u8 type = restore_u8 (); - evt e = restore_u64 (); - uae_u32 data = restore_u32 (); - if (type == 1) - event2_newevent_xx (-1, e, data, send_interrupt_do); - } - return src; -} -uae_u8 *save_custom_event_delay (int *len, uae_u8 *dstptr) -{ - uae_u8 *dstbak, *dst; - int cnt = 0; - - for (int i = ev2_misc; i < ev2_max; i++) { - struct ev2 *e = &eventtab2[i]; - if (e->active && e->handler == send_interrupt_do) { - cnt++; - } - } - if (cnt == 0) - return NULL; - - if (dstptr) - dstbak = dst = dstptr; - else - dstbak = dst = xmalloc (uae_u8, 1000); - - save_u32 (1); - save_u8 (cnt); - for (int i = ev2_misc; i < ev2_max; i++) { - struct ev2 *e = &eventtab2[i]; - if (e->active && e->handler == send_interrupt_do) { - save_u8 (1); - save_u64 (e->evtime - get_cycles ()); - save_u32 (e->data); - - } - } - - *len = dst - dstbak; - return dstbak; -} - - -uae_u8 *save_cycles (int *len, uae_u8 *dstptr) -{ - uae_u8 *dstbak, *dst; - if (dstptr) - dstbak = dst = dstptr; - else - dstbak = dst = xmalloc (uae_u8, 1000); - save_u32 (1); - save_u32 (CYCLE_UNIT); - save_u64 (get_cycles ()); - save_u32 (extra_cycle); - write_log (_T("SAVECYCLES %08X\n"), get_cycles ()); - *len = dst - dstbak; - return dstbak; -} - -uae_u8 *restore_cycles (uae_u8 *src) -{ - if (restore_u32 () != 1) - return src; - restore_u32 (); - start_cycles = restore_u64 (); - extra_cycle = restore_u32 (); - write_log (_T("RESTORECYCLES %08X\n"), start_cycles); - return src; -} - -#endif /* SAVESTATE */ - -void check_prefs_changed_custom (void) -{ - if (!config_changed) - return; - currprefs.gfx_framerate = changed_prefs.gfx_framerate; - if (currprefs.turbo_emulation != changed_prefs.turbo_emulation) - warpmode (changed_prefs.turbo_emulation); - if (inputdevice_config_change_test ()) - inputdevice_copyconfig (&changed_prefs, &currprefs); - currprefs.immediate_blits = changed_prefs.immediate_blits; - currprefs.collision_level = changed_prefs.collision_level; - - currprefs.cs_ciaatod = changed_prefs.cs_ciaatod; - currprefs.cs_rtc = changed_prefs.cs_rtc; - currprefs.cs_cd32cd = changed_prefs.cs_cd32cd; - currprefs.cs_cd32c2p = changed_prefs.cs_cd32c2p; - currprefs.cs_cd32nvram = changed_prefs.cs_cd32nvram; - currprefs.cs_cdtvcd = changed_prefs.cs_cdtvcd; - currprefs.cs_ide = changed_prefs.cs_ide; - currprefs.cs_pcmcia = changed_prefs.cs_pcmcia; - currprefs.cs_fatgaryrev = changed_prefs.cs_fatgaryrev; - currprefs.cs_ramseyrev = changed_prefs.cs_ramseyrev; - currprefs.cs_agnusrev = changed_prefs.cs_agnusrev; - currprefs.cs_deniserev = changed_prefs.cs_deniserev; - currprefs.cs_mbdmac = changed_prefs.cs_mbdmac; - currprefs.cs_df0idhw = changed_prefs.cs_df0idhw; - currprefs.cs_slowmemisfast = changed_prefs.cs_slowmemisfast; - - if (currprefs.chipset_mask != changed_prefs.chipset_mask || - currprefs.picasso96_nocustom != changed_prefs.picasso96_nocustom || - currprefs.ntscmode != changed_prefs.ntscmode) { - currprefs.picasso96_nocustom = changed_prefs.picasso96_nocustom; - currprefs.chipset_mask = changed_prefs.chipset_mask; - if (currprefs.ntscmode != changed_prefs.ntscmode) { - currprefs.ntscmode = changed_prefs.ntscmode; - new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20; - } - init_custom (); - } -#ifdef GFXFILTER - currprefs.gfx_filter_horiz_zoom = changed_prefs.gfx_filter_horiz_zoom; - currprefs.gfx_filter_vert_zoom = changed_prefs.gfx_filter_vert_zoom; - currprefs.gfx_filter_horiz_offset = changed_prefs.gfx_filter_horiz_offset; - currprefs.gfx_filter_vert_offset = changed_prefs.gfx_filter_vert_offset; - currprefs.gfx_filter_scanlines = changed_prefs.gfx_filter_scanlines; -#endif -} - -#ifdef CPUEMU_12 - -STATIC_INLINE void sync_copper (int hpos) -{ - if (copper_enabled_thisline) - update_copper (hpos); -} - -STATIC_INLINE void decide_fetch_ce (int hpos) -{ - if ((ddf_change == vpos || ddf_change + 1 == vpos) && vpos < current_maxvpos ()) - decide_fetch (hpos); -} - -#define BLIT_NASTY 4 - -// blitter not in nasty mode = CPU gets one cycle if it has been waiting -// at least 4 cycles (all DMA cycles count, not just blitter cycles, even -// blitter idle cycles do count!) - -extern int cpu_tracer; -STATIC_INLINE int dma_cycle (void) -{ - int hpos, hpos_old; - - blitter_nasty = 1; - if (cpu_tracer == -1) - return current_hpos (); - for (;;) { - int bpldma; - int blitpri = dmacon & DMA_BLITPRI; - hpos_old = current_hpos (); - hpos = hpos_old + 1; - sync_copper (hpos); - decide_line (hpos); - decide_fetch_ce (hpos); - bpldma = is_bitplane_dma (hpos_old); - if (bltstate != BLT_done) { - if (!blitpri && blitter_nasty >= BLIT_NASTY && cycle_line[hpos_old] == 0 && !bpldma) { - alloc_cycle (hpos_old, CYCLE_CPUNASTY); - break; - } - decide_blitter (hpos); - // copper may have been waiting for the blitter - sync_copper (hpos); - } - if (cycle_line[hpos_old] == 0 && !bpldma) { - alloc_cycle (hpos_old, CYCLE_CPU); - break; - } - regs.ce020memcycles -= CYCLE_UNIT; - do_cycles (1 * CYCLE_UNIT); - /* bus was allocated to dma channel, wait for next cycle.. */ - } - return hpos_old; -} - -STATIC_INLINE void checknasty (int hpos, int vpos) -{ - if (blitter_nasty >= BLIT_NASTY && !(dmacon & DMA_BLITPRI)) - record_dma_event (DMA_EVENT_BLITNASTY, hpos, vpos); -} - -uae_u32 wait_cpu_cycle_read (uaecptr addr, int mode) -{ - uae_u32 v = 0; - int hpos; - struct dma_rec *dr; - - hpos = dma_cycle (); - x_do_cycles_pre (CYCLE_UNIT); - -#ifdef DEBUGGER - if (debug_dma) { - int reg = 0x1000; - if (mode < 0) - reg |= 4; - else if (mode > 0) - reg |= 2; - else - reg |= 1; - dr = record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU); - checknasty (hpos, vpos); - } -#endif - if (mode < 0) - v = get_long (addr); - else if (mode > 0) - v = get_word (addr); - else if (mode == 0) - v = get_byte (addr); - -#ifdef DEBUGGER - if (debug_dma) - dr->dat = v; -#endif - - x_do_cycles_post (CYCLE_UNIT, v); - return v; -} - -uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode) -{ - uae_u32 v = 0; - int hpos; - struct dma_rec *dr; - - hpos = dma_cycle (); - x_do_cycles_pre (CYCLE_UNIT); - -#ifdef DEBUGGER - if (debug_dma) { - int reg = 0x1000; - if (mode < 0) - reg |= 4; - else if (mode > 0) - reg |= 2; - else - reg |= 1; - dr = record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU); - checknasty (hpos, vpos); - } -#endif - if (mode < 0) - v = get_long (addr); - else if (mode > 0) - v = get_word (addr); - else if (mode == 0) - v = get_byte (addr); - -#ifdef DEBUGGER - if (debug_dma) - dr->dat = v; -#endif - - regs.ce020memcycles -= CYCLE_UNIT; - return v; -} - -void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v) -{ - int hpos; - - hpos = dma_cycle (); - x_do_cycles_pre (CYCLE_UNIT); - -#ifdef DEBUGGER - if (debug_dma) { - int reg = 0x1100; - if (mode < 0) - reg |= 4; - else if (mode > 0) - reg |= 2; - else - reg |= 1; - record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU); - checknasty (hpos, vpos); - } -#endif - - if (mode < 0) - put_long (addr, v); - else if (mode > 0) - put_word (addr, v); - else if (mode == 0) - put_byte (addr, v); - x_do_cycles_post (CYCLE_UNIT, v); - -} - -void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v) -{ - int hpos; - - hpos = dma_cycle (); - x_do_cycles_pre (CYCLE_UNIT); - -#ifdef DEBUGGER - if (debug_dma) { - int reg = 0x1100; - if (mode < 0) - reg |= 4; - else if (mode > 0) - reg |= 2; - else - reg |= 1; - record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU); - checknasty (hpos, vpos); - } -#endif - - if (mode < 0) - put_long (addr, v); - else if (mode > 0) - put_word (addr, v); - else if (mode == 0) - put_byte (addr, v); - - regs.ce020memcycles -= CYCLE_UNIT; -} - -void do_cycles_ce (unsigned long cycles) -{ - unsigned long c; - - c = cycles + extra_cycle; - while (c >= CYCLE_UNIT) { - int hpos = current_hpos () + 1; - sync_copper (hpos); - decide_line (hpos); - decide_fetch_ce (hpos); - if (bltstate != BLT_done) - decide_blitter (hpos); - do_cycles (1 * CYCLE_UNIT); - c -= CYCLE_UNIT; - } - extra_cycle = c; -} - -int is_cycle_ce (void) -{ - int hpos = current_hpos (); - return cycle_line[hpos]; -} - -#endif - -bool ispal (void) -{ - if (beamcon0 & 0x80) - return currprefs.ntscmode == 0; - return maxvpos_nom >= MAXVPOS_NTSC + (MAXVPOS_PAL - MAXVPOS_NTSC) / 2; -} \ No newline at end of file diff --git a/drawing - Copy.cpp b/drawing - Copy.cpp deleted file mode 100644 index 4c2def42..00000000 --- a/drawing - Copy.cpp +++ /dev/null @@ -1,3119 +0,0 @@ -//#define XLINECHECK - -/* -* UAE - The Un*x Amiga Emulator -* -* Screen drawing functions -* -* Copyright 1995-2000 Bernd Schmidt -* Copyright 1995 Alessandro Bissacco -* Copyright 2000-2008 Toni Wilen -*/ - -/* There are a couple of concepts of "coordinates" in this file. -- DIW coordinates -- DDF coordinates (essentially cycles, resolution lower than lores by a factor of 2) -- Pixel coordinates -* in the Amiga's resolution as determined by BPLCON0 ("Amiga coordinates") -* in the window resolution as determined by the preferences ("window coordinates"). -* in the window resolution, and with the origin being the topmost left corner of -the window ("native coordinates") -One note about window coordinates. The visible area depends on the width of the -window, and the centering code. The first visible horizontal window coordinate is -often _not_ 0, but the value of VISIBLE_LEFT_BORDER instead. - -One important thing to remember: DIW coordinates are in the lowest possible -resolution. - -To prevent extremely bad things (think pixels cut in half by window borders) from -happening, all ports should restrict window widths to be multiples of 16 pixels. */ - -#include "sysconfig.h" -#include "sysdeps.h" - -#include -#include - -#include "options.h" -#include "threaddep/thread.h" -#include "uae.h" -#include "memory.h" -#include "custom.h" -#include "newcpu.h" -#include "xwin.h" -#include "autoconf.h" -#include "gui.h" -#include "picasso96.h" -#include "drawing.h" -#include "savestate.h" -#include "statusline.h" -#include "inputdevice.h" -#include "debug.h" - -extern bool emulate_specialmonitors (struct vidbuffer*, struct vidbuffer*); - -extern int sprite_buffer_res; -int lores_factor, lores_shift; - -int debug_bpl_mask = 0xff, debug_bpl_mask_one; - -static void lores_reset (void) -{ - lores_factor = currprefs.gfx_resolution ? 2 : 1; - lores_shift = currprefs.gfx_resolution; - if (doublescan > 0) { - if (lores_shift < 2) - lores_shift++; - lores_factor = 2; - } - sprite_buffer_res = currprefs.gfx_resolution; - if (doublescan > 0 && sprite_buffer_res < RES_SUPERHIRES) - sprite_buffer_res++; -} - -bool aga_mode; /* mirror of chipset_mask & CSMASK_AGA */ -bool direct_rgb; - -/* The shift factor to apply when converting between Amiga coordinates and window -coordinates. Zero if the resolution is the same, positive if window coordinates -have a higher resolution (i.e. we're stretching the image), negative if window -coordinates have a lower resolution (i.e. we're shrinking the image). */ -static int res_shift; - -static int linedbl, linedbld; - -int interlace_seen = 0; -#define AUTO_LORES_FRAMES 10 -static int can_use_lores = 0, frame_res, frame_res_lace, last_max_ypos; -static uae_u16 bplcon0_store, bplcon3_store; - -/* Lookup tables for dual playfields. The dblpf_*1 versions are for the case -that playfield 1 has the priority, dbplpf_*2 are used if playfield 2 has -priority. If we need an array for non-dual playfield mode, it has no number. */ -/* The dbplpf_ms? arrays contain a shift value. plf_spritemask is initialized -to contain two 16 bit words, with the appropriate mask if pf1 is in the -foreground being at bit offset 0, the one used if pf2 is in front being at -offset 16. */ - -static int dblpf_ms1[256], dblpf_ms2[256], dblpf_ms[256]; -static int dblpf_ind1[256], dblpf_ind2[256]; - -static int dblpf_2nd1[256], dblpf_2nd2[256]; - -static const int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 }; - -static int sprite_offs[256]; - -static uae_u32 clxtab[256]; - -/* Video buffer description structure. Filled in by the graphics system -* dependent code. */ - -struct vidbuf_description gfxvidinfo; - -/* OCS/ECS color lookup table. */ -xcolnr xcolors[4096]; - -struct spritepixelsbuf { - uae_u8 attach; - uae_u8 stdata; - uae_u16 data; -}; -static struct spritepixelsbuf spritepixels[MAX_PIXELS_PER_LINE]; -static int sprite_first_x, sprite_last_x; - -#ifdef AGA -/* AGA mode color lookup tables */ -unsigned int xredcolors[256], xgreencolors[256], xbluecolors[256]; -static int dblpf_ind1_aga[256], dblpf_ind2_aga[256]; -#else -static uae_u8 spriteagadpfpixels[1]; -static int dblpf_ind1_aga[1], dblpf_ind2_aga[1]; -#endif -int xredcolor_s, xredcolor_b, xredcolor_m; -int xgreencolor_s, xgreencolor_b, xgreencolor_m; -int xbluecolor_s, xbluecolor_b, xbluecolor_m; - -struct color_entry colors_for_drawing; - -/* The size of these arrays is pretty arbitrary; it was chosen to be "more -than enough". The coordinates used for indexing into these arrays are -almost, but not quite, Amiga coordinates (there's a constant offset). */ -union { - /* Let's try to align this thing. */ - double uupzuq; - long int cruxmedo; - uae_u8 apixels[MAX_PIXELS_PER_LINE * 2]; - uae_u16 apixels_w[MAX_PIXELS_PER_LINE * 2 / sizeof (uae_u16)]; - uae_u32 apixels_l[MAX_PIXELS_PER_LINE * 2 / sizeof (uae_u32)]; -} pixdata; - -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT -uae_u16 *spixels; -#else -uae_u16 spixels[2 * MAX_SPR_PIXELS]; -#endif - -/* Eight bits for every pixel. */ -union sps_union spixstate; - -static uae_u32 ham_linebuf[MAX_PIXELS_PER_LINE * 2]; -static uae_u8 *real_bplpt[8]; - -static uae_u8 all_ones[MAX_PIXELS_PER_LINE]; -static uae_u8 all_zeros[MAX_PIXELS_PER_LINE]; - -uae_u8 *xlinebuffer; - -static int *amiga2aspect_line_map, *native2amiga_line_map; -static uae_u8 *row_map[MAX_VIDHEIGHT + 1]; -static uae_u8 row_tmp[MAX_PIXELS_PER_LINE * 32 / 8]; -static int max_drawn_amiga_line; - -/* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham */ -typedef void (*line_draw_func)(int, int, bool); - -#define LINE_UNDECIDED 1 -#define LINE_DECIDED 2 -#define LINE_DECIDED_DOUBLE 3 -#define LINE_AS_PREVIOUS 4 -#define LINE_BLACK 5 -#define LINE_REMEMBERED_AS_BLACK 6 -#define LINE_DONE 7 -#define LINE_DONE_AS_PREVIOUS 8 -#define LINE_REMEMBERED_AS_PREVIOUS 9 - -static uae_u8 linestate[(MAXVPOS + 2) * 2 + 1]; - -uae_u8 line_data[(MAXVPOS + 2) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2]; - -/* Centering variables. */ -static int min_diwstart, max_diwstop; -/* The visible window: VISIBLE_LEFT_BORDER contains the left border of the visible -area, VISIBLE_RIGHT_BORDER the right border. These are in window coordinates. */ -int visible_left_border, visible_right_border; -/* Pixels outside of visible_start and visible_stop are always black */ -static int visible_left_start, visible_right_stop; -static int visible_top_start, visible_bottom_stop; - -static int linetoscr_x_adjust_bytes; -static int thisframe_y_adjust; -static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen; -static int extra_y_adjust; -int thisframe_first_drawn_line, thisframe_last_drawn_line; - -/* A frame counter that forces a redraw after at least one skipped frame in -interlace mode. */ -static int last_redraw_point; - -#define MAX_STOP 30000 -static int first_drawn_line, last_drawn_line; -static int first_block_line, last_block_line; - -#define NO_BLOCK -3 - -/* These are generated by the drawing code from the line_decisions array for -each line that needs to be drawn. These are basically extracted out of -bit fields in the hardware registers. */ -static int bplehb, bplham, bpldualpf, bpldualpfpri, bpldualpf2of, bplplanecnt, ecsshres, issprites; -static int bplres; -static int plf1pri, plf2pri, bplxor; -static uae_u32 plf_sprite_mask; -static int sbasecol[2] = { 16, 16 }; -static bool brdsprt, brdblank, brdblank_changed; -static int hposblank; - -bool picasso_requested_on; -bool picasso_on; - -uae_sem_t gui_sem; -int inhibit_frame; - -int framecnt = 0; -static int frame_redraw_necessary; -static int picasso_redraw_necessary; - -#ifdef XLINECHECK -static void xlinecheck (unsigned int start, unsigned int end) -{ - unsigned int xstart = (unsigned int)xlinebuffer + start * gfxvidinfo.drawbuffer.pixbytes; - unsigned int xend = (unsigned int)xlinebuffer + end * gfxvidinfo.drawbuffer.pixbytes; - unsigned int end1 = (unsigned int)gfxvidinfo.drawbuffer.bufmem + gfxvidinfo.drawbuffer.rowbytes * gfxvidinfo.drawbuffer.height; - int min = linetoscr_x_adjust_bytes / gfxvidinfo.drawbuffer.pixbytes; - int ok = 1; - - if (xstart >= gfxvidinfo.drawbuffer.emergmem && xstart < gfxvidinfo.drawbuffer.emergmem + 4096 * gfxvidinfo.drawbuffer.pixbytes && - xend >= gfxvidinfo.drawbuffer.emergmem && xend < gfxvidinfo.drawbuffer.emergmem + 4096 * gfxvidinfo.drawbuffer.pixbytes) - return; - - if (xstart < (unsigned int)gfxvidinfo.drawbuffer.bufmem || xend < (unsigned int)gfxvidinfo.drawbuffer.bufmem) - ok = 0; - if (xend > end1 || xstart >= end1) - ok = 0; - xstart -= (unsigned int)gfxvidinfo.drawbuffer.bufmem; - xend -= (unsigned int)gfxvidinfo.drawbuffer.bufmem; - if ((xstart % gfxvidinfo.drawbuffer.rowbytes) >= gfxvidinfo.drawbuffer.width * gfxvidinfo.drawbuffer.pixbytes) - ok = 0; - if ((xend % gfxvidinfo.drawbuffer.rowbytes) >= gfxvidinfo.drawbuffer.width * gfxvidinfo.drawbuffer.pixbytes) - ok = 0; - if (xstart >= xend) - ok = 0; - if (xend - xstart > gfxvidinfo.drawbuffer.width * gfxvidinfo.drawbuffer.pixbytes) - ok = 0; - - if (!ok) { - write_log (_T("*** %d-%d (%dx%dx%d %d) %p\n"), - start - min, end - min, gfxvidinfo.drawbuffer.width, gfxvidinfo.drawbuffer.height, - gfxvidinfo.drawbuffer.pixbytes, gfxvidinfo.drawbuffer.rowbytes, - xlinebuffer); - } -} -#else -#define xlinecheck -#endif - - -STATIC_INLINE void count_frame (void) -{ - framecnt++; - if (framecnt >= currprefs.gfx_framerate) - framecnt = 0; - if (inhibit_frame) - framecnt = 1; -} - -STATIC_INLINE int xshift (int x, int shift) -{ - if (shift < 0) - return x >> (-shift); - else - return x << shift; -} - -int coord_native_to_amiga_x (int x) -{ - x += visible_left_border; - x = xshift (x, 1 - lores_shift); - return x + 2 * DISPLAY_LEFT_SHIFT - 2 * DIW_DDF_OFFSET; -} - -int coord_native_to_amiga_y (int y) -{ - return native2amiga_line_map[y] + thisframe_y_adjust - minfirstline; -} - -STATIC_INLINE int res_shift_from_window (int x) -{ - if (res_shift >= 0) - return x >> res_shift; - return x << -res_shift; -} - -STATIC_INLINE int res_shift_from_amiga (int x) -{ - if (res_shift >= 0) - return x >> res_shift; - return x << -res_shift; -} - -void notice_screen_contents_lost (void) -{ - picasso_redraw_necessary = 1; - frame_redraw_necessary = 2; -} - -bool isnativevidbuf (void) -{ - if (gfxvidinfo.outbuffer == &gfxvidinfo.drawbuffer) - return true; - return gfxvidinfo.outbuffer->nativepositioning; -} - -extern int plffirstline_total, plflastline_total; -extern int first_planes_vpos, last_planes_vpos; -extern int diwfirstword_total, diwlastword_total; -extern int ddffirstword_total, ddflastword_total; -extern int firstword_bplcon1; -extern int lof_store; - -#define MIN_DISPLAY_W 256 -#define MIN_DISPLAY_H 192 -#define MAX_DISPLAY_W 362 -#define MAX_DISPLAY_H 283 - -static int gclow, gcloh, gclox, gcloy; - -void get_custom_topedge (int *x, int *y) -{ - if (isnativevidbuf ()) { - *x = visible_left_border + (DISPLAY_LEFT_SHIFT << currprefs.gfx_resolution); - *y = minfirstline << currprefs.gfx_vresolution; - } else { - *x = 0; - *y = 0; - } -} - -static void reset_custom_limits (void) -{ - gclow = gcloh = gclox = gcloy = 0; -} - -void set_custom_limits (int w, int h, int dx, int dy) -{ - int vls = visible_left_start; - int vrs = visible_right_stop; - int vts = visible_top_start; - int vbs = visible_bottom_stop; - - if (w <= 0 || dx < 0) { - visible_left_start = 0; - visible_right_stop = MAX_STOP; - } else { - visible_left_start = visible_left_border + dx; - visible_right_stop = visible_left_start + w; - } - if (h <= 0 || dy < 0) { - visible_top_start = 0; - visible_bottom_stop = MAX_STOP; - } else { - visible_top_start = min_ypos_for_screen + dy; - visible_bottom_stop = visible_top_start + h; - } - if (vls != visible_left_start || vrs != visible_right_stop || - vts != visible_top_start || vbs != visible_bottom_stop) - notice_screen_contents_lost (); -} - -int get_custom_limits (int *pw, int *ph, int *pdx, int *pdy) -{ - int w, h, dx, dy, y1, y2, dbl1, dbl2; - int ret = 0; - - if (!pw || !ph || !pdx || !pdy) { - reset_custom_limits (); - return 0; - } - - if (!isnativevidbuf ()) { - *pw = gfxvidinfo.outbuffer->outwidth; - *ph = gfxvidinfo.outbuffer->outheight; - *pdx = 0; - *pdy = 0; - return 1; - } - - *pw = gclow; - *ph = gcloh; - *pdx = gclox; - *pdy = gcloy; - - if (gclow > 0 && gcloh > 0) - ret = -1; - - if (interlace_seen) { - // interlace = only use long frames - if (!lof_store) - return ret; - /* program may have set last visible line as last possible line (CD32 boot screen) */ - if (last_planes_vpos < maxvpos) - last_planes_vpos++; - if (plflastline_total < maxvpos) - plflastline_total++; - } - - if (plflastline_total < 4) - plflastline_total = last_planes_vpos; - - ddffirstword_total = coord_hw_to_window_x (ddffirstword_total * 2 + DIW_DDF_OFFSET); - ddflastword_total = coord_hw_to_window_x (ddflastword_total * 2 + DIW_DDF_OFFSET); - - if (doublescan <= 0 && !programmedmode) { - int min = coord_diw_to_window_x (92); - int max = coord_diw_to_window_x (460); - if (diwfirstword_total < min) - diwfirstword_total = min; - if (diwlastword_total > max) - diwlastword_total = max; - if (ddffirstword_total < min) - ddffirstword_total = min; - if (ddflastword_total > max) - ddflastword_total = max; - if (0 && !(currprefs.chipset_mask & CSMASK_AGA)) { - if (ddffirstword_total > diwfirstword_total) - diwfirstword_total = ddffirstword_total; - if (ddflastword_total < diwlastword_total) - diwlastword_total = ddflastword_total; - } - } - - w = diwlastword_total - diwfirstword_total; - dx = diwfirstword_total - visible_left_border; - - y2 = plflastline_total; - if (y2 > last_planes_vpos) - y2 = last_planes_vpos; - y1 = plffirstline_total; - if (first_planes_vpos > y1) - y1 = first_planes_vpos; - if (minfirstline > y1) - y1 = minfirstline; - - dbl2 = dbl1 = currprefs.gfx_vresolution; - if (doublescan > 0 && interlace_seen <= 0) { - dbl1--; - dbl2--; - } - - h = y2 - y1; - dy = y1 - minfirstline; - - if (first_planes_vpos == 0) { - // no planes enabled during frame - if (ret < 0) - return 1; - h = currprefs.ntscmode ? 200 : 240; - w = 320 << currprefs.gfx_resolution; - dy = 36 / 2; - dx = 58; - } - - if (dx < 0) - dx = 0; - - dy = xshift (dy, dbl2); - h = xshift (h, dbl1); - - if (w == 0 || h == 0) - return 0; - - if (doublescan <= 0 && !programmedmode) { - if ((w >> currprefs.gfx_resolution) < MIN_DISPLAY_W) { - dx += (w - (MIN_DISPLAY_W << currprefs.gfx_resolution)) / 2; - w = MIN_DISPLAY_W << currprefs.gfx_resolution; - } - if ((h >> dbl1) < MIN_DISPLAY_H) { - dy += (h - (MIN_DISPLAY_H << dbl1)) / 2; - h = MIN_DISPLAY_H << dbl1; - } - if ((w >> currprefs.gfx_resolution) > MAX_DISPLAY_W) { - dx += (w - (MAX_DISPLAY_W << currprefs.gfx_resolution)) / 2; - w = MAX_DISPLAY_W << currprefs.gfx_resolution; - } - if ((h >> dbl1) > MAX_DISPLAY_H) { - dy += (h - (MAX_DISPLAY_H << dbl1)) / 2; - h = MAX_DISPLAY_H << dbl1; - } - } - - if (gclow == w && gcloh == h && gclox == dx && gcloy == dy) - return ret; - - if (w <= 0 || h <= 0 || dx < 0 || dy < 0) - return ret; - if (doublescan <= 0 && !programmedmode) { - if (dx > gfxvidinfo.outbuffer->inwidth / 3) - return ret; - if (dy > gfxvidinfo.outbuffer->inheight / 3) - return ret; - } - - gclow = w; - gcloh = h; - gclox = dx; - gcloy = dy; - *pw = w; - *ph = h; - *pdx = dx; - *pdy = dy; -#if 1 - write_log (_T("Display Size: %dx%d Offset: %dx%d\n"), w, h, dx, dy); - write_log (_T("First: %d Last: %d MinV: %d MaxV: %d Min: %d\n"), - plffirstline_total, plflastline_total, - first_planes_vpos, last_planes_vpos, minfirstline); -#endif - return 1; -} - -void get_custom_mouse_limits (int *pw, int *ph, int *pdx, int *pdy, int dbl) -{ - int delay1, delay2; - int w, h, dx, dy, dbl1, dbl2, y1, y2; - - w = diwlastword_total - diwfirstword_total; - dx = diwfirstword_total - visible_left_border; - - y2 = plflastline_total; - if (y2 > last_planes_vpos) - y2 = last_planes_vpos; - y1 = plffirstline_total; - if (first_planes_vpos > y1) - y1 = first_planes_vpos; - if (minfirstline > y1) - y1 = minfirstline; - - h = y2 - y1; - dy = y1 - minfirstline; - - if (*pw > 0) - w = *pw; - - w = xshift (w, res_shift); - - if (*ph > 0) - h = *ph; - - delay1 = (firstword_bplcon1 & 0x0f) | ((firstword_bplcon1 & 0x0c00) >> 6); - delay2 = ((firstword_bplcon1 >> 4) & 0x0f) | (((firstword_bplcon1 >> 4) & 0x0c00) >> 6); -// if (delay1 == delay2) -// dx += delay1; - - dx = xshift (dx, res_shift); - - dbl2 = dbl1 = currprefs.gfx_vresolution; - if ((doublescan > 0 || interlace_seen > 0) && !dbl) { - dbl1--; - dbl2--; - } - if (interlace_seen > 0) - dbl2++; - if (interlace_seen <= 0 && dbl) - dbl2--; - h = xshift (h, dbl1); - dy = xshift (dy, dbl2); - - if (w < 1) - w = 1; - if (h < 1) - h = 1; - if (dx < 0) - dx = 0; - if (dy < 0) - dy = 0; - *pw = w; *ph = h; - *pdx = dx; *pdy = dy; -} - -static struct decision *dp_for_drawing; -static struct draw_info *dip_for_drawing; - -/* Record DIW of the current line for use by centering code. */ -void record_diw_line (int plfstrt, int first, int last) -{ - if (last > max_diwstop) - max_diwstop = last; - if (first < min_diwstart) { - min_diwstart = first; - /* - if (plfstrt * 2 > min_diwstart) - min_diwstart = plfstrt * 2; - */ - } -} - -/* -* Screen update macros/functions -*/ - -/* The important positions in the line: where do we start drawing the left border, -where do we start drawing the playfield, where do we start drawing the right border. -All of these are forced into the visible window (VISIBLE_LEFT_BORDER .. VISIBLE_RIGHT_BORDER). -PLAYFIELD_START and PLAYFIELD_END are in window coordinates. */ -static int playfield_start, playfield_end; -static int real_playfield_start, real_playfield_end; -static int linetoscr_diw_start, linetoscr_diw_end; -static int native_ddf_left, native_ddf_right; - -static int pixels_offset; -static int src_pixel, ham_src_pixel; -/* How many pixels in window coordinates which are to the left of the left border. */ -static int unpainted; -static int seen_sprites; - -/* Initialize the variables necessary for drawing a line. -* This involves setting up start/stop positions and display window -* borders. */ -static void pfield_init_linetoscr (void) -{ - /* First, get data fetch start/stop in DIW coordinates. */ - int ddf_left = dp_for_drawing->plfleft * 2 + DIW_DDF_OFFSET; - int ddf_right = dp_for_drawing->plfright * 2 + DIW_DDF_OFFSET; - - /* Compute datafetch start/stop in pixels; native display coordinates. */ - native_ddf_left = coord_hw_to_window_x (ddf_left); - native_ddf_right = coord_hw_to_window_x (ddf_right); - - linetoscr_diw_start = dp_for_drawing->diwfirstword; - linetoscr_diw_end = dp_for_drawing->diwlastword; - - res_shift = lores_shift - bplres; - - if (dip_for_drawing->nr_sprites == 0) { - if (linetoscr_diw_start < native_ddf_left) - linetoscr_diw_start = native_ddf_left; - if (linetoscr_diw_end > native_ddf_right) - linetoscr_diw_end = native_ddf_right; - } - - /* Perverse cases happen. */ - if (linetoscr_diw_end < linetoscr_diw_start) - linetoscr_diw_end = linetoscr_diw_start; - - playfield_start = linetoscr_diw_start; - playfield_end = linetoscr_diw_end; - - unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start; - ham_src_pixel = MAX_PIXELS_PER_LINE + res_shift_from_window (playfield_start - native_ddf_left); - unpainted = res_shift_from_window (unpainted); - - if (playfield_start < visible_left_border) - playfield_start = visible_left_border; - if (playfield_start > visible_right_border) - playfield_start = visible_right_border; - if (playfield_end < visible_left_border) - playfield_end = visible_left_border; - if (playfield_end > visible_right_border) - playfield_end = visible_right_border; - - real_playfield_end = playfield_end; - real_playfield_start = playfield_start; -#ifdef AGA - if (brdsprt && dip_for_drawing->nr_sprites) { - int min = visible_right_border, max = visible_left_border, i; - for (i = 0; i < dip_for_drawing->nr_sprites; i++) { - int x; - x = curr_sprite_entries[dip_for_drawing->first_sprite_entry + i].pos; - if (x < min) - min = x; - x = curr_sprite_entries[dip_for_drawing->first_sprite_entry + i].max; - if (x > max) - max = x; - } - min = coord_hw_to_window_x (min >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift); - max = coord_hw_to_window_x (max >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift); - if (min < playfield_start) - playfield_start = min; - if (playfield_start < visible_left_border) - playfield_start = visible_left_border; - if (max > playfield_end) - playfield_end = max; - if (playfield_end > visible_right_border) - playfield_end = visible_right_border; - } -#endif - - if (sprite_first_x < sprite_last_x) { - if (sprite_first_x < 0) - sprite_first_x = 0; - if (sprite_last_x >= MAX_PIXELS_PER_LINE - 1) - sprite_last_x = MAX_PIXELS_PER_LINE - 2; - if (sprite_first_x < sprite_last_x) - memset (spritepixels + sprite_first_x, 0, sizeof (struct spritepixelsbuf) * (sprite_last_x - sprite_first_x + 1)); - } - sprite_last_x = 0; - sprite_first_x = MAX_PIXELS_PER_LINE - 1; - - /* Now, compute some offsets. */ - ddf_left -= DISPLAY_LEFT_SHIFT; - pixels_offset = MAX_PIXELS_PER_LINE - (ddf_left << bplres); - ddf_left <<= bplres; - src_pixel = MAX_PIXELS_PER_LINE + res_shift_from_window (playfield_start - native_ddf_left); - - seen_sprites = 0; - if (dip_for_drawing->nr_sprites == 0) - return; - seen_sprites = 1; - /* Must clear parts of apixels. */ - if (linetoscr_diw_start < native_ddf_left) { - int size = res_shift_from_window (native_ddf_left - linetoscr_diw_start); - linetoscr_diw_start = native_ddf_left; - memset (pixdata.apixels + MAX_PIXELS_PER_LINE - size, 0, size); - } - if (linetoscr_diw_end > native_ddf_right) { - int pos = res_shift_from_window (native_ddf_right - native_ddf_left); - int size = res_shift_from_window (linetoscr_diw_end - native_ddf_right); - linetoscr_diw_start = native_ddf_left; - memset (pixdata.apixels + MAX_PIXELS_PER_LINE + pos, 0, size); - } -} - -STATIC_INLINE uae_u16 merge_2pixel16 (uae_u16 p1, uae_u16 p2) -{ - uae_u16 v = ((((p1 >> xredcolor_s) & xredcolor_m) + ((p2 >> xredcolor_s) & xredcolor_m)) / 2) << xredcolor_s; - v |= ((((p1 >> xbluecolor_s) & xbluecolor_m) + ((p2 >> xbluecolor_s) & xbluecolor_m)) / 2) << xbluecolor_s; - v |= ((((p1 >> xgreencolor_s) & xgreencolor_m) + ((p2 >> xgreencolor_s) & xgreencolor_m)) / 2) << xgreencolor_s; - return v; -} -STATIC_INLINE uae_u32 merge_2pixel32 (uae_u32 p1, uae_u32 p2) -{ - uae_u32 v = ((((p1 >> 16) & 0xff) + ((p2 >> 16) & 0xff)) / 2) << 16; - v |= ((((p1 >> 8) & 0xff) + ((p2 >> 8) & 0xff)) / 2) << 8; - v |= ((((p1 >> 0) & 0xff) + ((p2 >> 0) & 0xff)) / 2) << 0; - return v; -} - -STATIC_INLINE xcolnr getbgc (bool blank) -{ -#if 0 - if (blank) - return xcolors[0x088]; - else if (hposblank == 1) - return xcolors[0xf00]; - else if (hposblank == 2) - return xcolors[0x0f0]; - else if (hposblank == 3) - return xcolors[0x00f]; - else if (brdblank) - return xcolors[0x880]; - return xcolors[0xf0f]; -#endif - return (blank || brdblank || hposblank) ? 0 : colors_for_drawing.acolors[0]; -} - -STATIC_INLINE void fill_line_16 (uae_u8 *buf, int start, int stop, bool blank) -{ - uae_u16 *b = (uae_u16 *)buf; - unsigned int i; - unsigned int rem = 0; - xcolnr col = getbgc (blank); - if (((long)&b[start]) & 1) - b[start++] = (uae_u16) col; - if (start >= stop) - return; - if (((long)&b[stop]) & 1) { - rem++; - stop--; - } - for (i = start; i < stop; i += 2) { - uae_u32 *b2 = (uae_u32 *)&b[i]; - *b2 = col; - } - if (rem) - b[stop] = (uae_u16)col; -} - -STATIC_INLINE void fill_line_32 (uae_u8 *buf, int start, int stop, bool blank) -{ - uae_u32 *b = (uae_u32 *)buf; - unsigned int i; - xcolnr col = getbgc (blank); - for (i = start; i < stop; i++) - b[i] = col; -} -static void pfield_do_fill_line2 (int start, int stop, bool blank) -{ - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: fill_line_16 (xlinebuffer, start, stop, blank); break; - case 4: fill_line_32 (xlinebuffer, start, stop, blank); break; - } -} -static void pfield_do_fill_line (int start, int stop, bool blank) -{ - xlinecheck(start, stop); - if (!blank) { - if (start < visible_left_start) { - pfield_do_fill_line2 (start, visible_left_start, true); - start = visible_left_start; - } - if (stop > visible_right_stop) { - pfield_do_fill_line2 (start, visible_right_stop, false); - blank = true; - start = visible_right_stop; - } - } - pfield_do_fill_line2 (start, stop, blank); -} - - -STATIC_INLINE void fill_line2 (int startpos, int len) -{ - int shift; - int nints, nrem; - int *start; - xcolnr val; - - shift = 0; - if (gfxvidinfo.drawbuffer.pixbytes == 2) - shift = 1; - if (gfxvidinfo.drawbuffer.pixbytes == 4) - shift = 2; - - nints = len >> (2 - shift); - nrem = nints & 7; - nints &= ~7; - start = (int *)(((uae_u8*)xlinebuffer) + (startpos << shift)); - val = getbgc (false); - for (; nints > 0; nints -= 8, start += 8) { - *start = val; - *(start+1) = val; - *(start+2) = val; - *(start+3) = val; - *(start+4) = val; - *(start+5) = val; - *(start+6) = val; - *(start+7) = val; - } - - switch (nrem) { - case 7: - *start++ = val; - case 6: - *start++ = val; - case 5: - *start++ = val; - case 4: - *start++ = val; - case 3: - *start++ = val; - case 2: - *start++ = val; - case 1: - *start = val; - } -} - -static void fill_line (void) -{ - int hs = coord_hw_to_window_x (hsyncstartpos * 2); - if (hs >= gfxvidinfo.drawbuffer.inwidth || hposblank) { - hposblank = 3; - fill_line2 (visible_left_border, gfxvidinfo.drawbuffer.inwidth); - } else { - fill_line2 (visible_left_border, hs); - hposblank = 2; - fill_line2 (visible_left_border + hs, gfxvidinfo.drawbuffer.inwidth); - } -} - -#define SPRITE_DEBUG 0 -STATIC_INLINE uae_u8 render_sprites (int pos, int dualpf, uae_u8 apixel, int aga) -{ - struct spritepixelsbuf *spb = &spritepixels[pos]; - unsigned int v = spb->data; - int *shift_lookup = dualpf ? (bpldualpfpri ? dblpf_ms2 : dblpf_ms1) : dblpf_ms; - int maskshift, plfmask; - - /* The value in the shift lookup table is _half_ the shift count we - need. This is because we can't shift 32 bits at once (undefined - behaviour in C). */ - maskshift = shift_lookup[apixel]; - plfmask = (plf_sprite_mask >> maskshift) >> maskshift; - v &= ~plfmask; - if (v != 0 || SPRITE_DEBUG) { - unsigned int vlo, vhi, col; - unsigned int v1 = v & 255; - /* OFFS determines the sprite pair with the highest priority that has - any bits set. E.g. if we have 0xFF00 in the buffer, we have sprite - pairs 01 and 23 cleared, and pairs 45 and 67 set, so OFFS will - have a value of 4. - 2 * OFFS is the bit number in V of the sprite pair, and it also - happens to be the color offset for that pair. - */ - int offs; - if (v1 == 0) - offs = 4 + sprite_offs[v >> 8]; - else - offs = sprite_offs[v1]; - - /* Shift highest priority sprite pair down to bit zero. */ - v >>= offs * 2; - v &= 15; -#if SPRITE_DEBUG > 0 - v ^= 8; -#endif - if (spb->attach && (spb->stdata & (3 << offs))) { - col = v; - if (aga) - col += sbasecol[1]; - else - col += 16; - } else { - /* This sequence computes the correct color value. We have to select - either the lower-numbered or the higher-numbered sprite in the pair. - We have to select the high one if the low one has all bits zero. - If the lower-numbered sprite has any bits nonzero, (VLO - 1) is in - the range of 0..2, and with the mask and shift, VHI will be zero. - If the lower-numbered sprite is zero, (VLO - 1) is a mask of - 0xFFFFFFFF, and we select the bits of the higher numbered sprite - in VHI. - This is _probably_ more efficient than doing it with branches. */ - vlo = v & 3; - vhi = (v & (vlo - 1)) >> 2; - col = (vlo | vhi); - if (aga) { - if (vhi > 0) - col += sbasecol[1]; - else - col += sbasecol[0]; - } else { - col += 16; - } - col += offs * 2; - } - - return col; - } - - return 0; -} - -#include "linetoscr.cpp" - -#define LTPARMS src_pixel, start, stop - -#ifdef ECS_DENISE -/* ECS SuperHires special cases */ - -#define PUTBPIX(x) buf[dpix] = (x); - -STATIC_INLINE uae_u32 shsprite (int dpix, uae_u32 spix_val, uae_u32 v, int spr) -{ - uae_u8 sprcol; - uae_u16 scol; - if (!spr) - return v; - sprcol = render_sprites (dpix, 0, spix_val, 0); - if (!sprcol) - return v; - /* good enough for now.. */ - scol = colors_for_drawing.color_regs_ecs[sprcol] & 0xccc; - scol |= scol >> 2; - return xcolors[scol]; -} - -static int NOINLINE linetoscr_16_sh (int spix, int dpix, int stoppos, int spr) -{ - uae_u16 *buf = (uae_u16 *) xlinebuffer; - - while (dpix < stoppos) { - uae_u16 spix_val1, spix_val2; - uae_u16 v; - int off; - spix_val1 = pixdata.apixels[spix++]; - spix_val2 = pixdata.apixels[spix++]; - off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); - v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; - v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr)); - dpix++; - v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2; - v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val2, xcolors[v], spr)); - dpix++; - } - return spix; -} -static int NOINLINE linetoscr_32_sh (int spix, int dpix, int stoppos, int spr) -{ - uae_u32 *buf = (uae_u32 *) xlinebuffer; - - while (dpix < stoppos) { - uae_u32 spix_val1, spix_val2; - uae_u16 v; - int off; - spix_val1 = pixdata.apixels[spix++]; - spix_val2 = pixdata.apixels[spix++]; - off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); - v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; - v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr)); - dpix++; - v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2; - v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val2, xcolors[v], spr)); - dpix++; - } - return spix; -} -static int NOINLINE linetoscr_32_shrink1_sh (int spix, int dpix, int stoppos, int spr) -{ - uae_u32 *buf = (uae_u32 *) xlinebuffer; - - while (dpix < stoppos) { - uae_u32 spix_val1, spix_val2; - uae_u16 v; - int off; - spix_val1 = pixdata.apixels[spix++]; - spix_val2 = pixdata.apixels[spix++]; - off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); - v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; - v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr)); - dpix++; - } - return spix; -} -static int NOINLINE linetoscr_32_shrink1f_sh (int spix, int dpix, int stoppos, int spr) -{ - uae_u32 *buf = (uae_u32 *) xlinebuffer; - - while (dpix < stoppos) { - uae_u32 spix_val1, spix_val2, dpix_val1, dpix_val2; - uae_u16 v; - int off; - spix_val1 = pixdata.apixels[spix++]; - spix_val2 = pixdata.apixels[spix++]; - off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); - v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; - v |= v >> 2; - dpix_val1 = xcolors[v]; - v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2; - v |= v >> 2; - dpix_val2 = xcolors[v]; - PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel32 (dpix_val1, dpix_val2), spr)); - dpix++; - } - return spix; -} -static int NOINLINE linetoscr_16_shrink1_sh (int spix, int dpix, int stoppos, int spr) -{ - uae_u16 *buf = (uae_u16 *) xlinebuffer; - - while (dpix < stoppos) { - uae_u16 spix_val1, spix_val2; - uae_u16 v; - int off; - spix_val1 = pixdata.apixels[spix++]; - spix_val2 = pixdata.apixels[spix++]; - off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); - v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; - v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr)); - dpix++; - } - return spix; -} -static int NOINLINE linetoscr_16_shrink1f_sh (int spix, int dpix, int stoppos, int spr) -{ - uae_u16 *buf = (uae_u16 *) xlinebuffer; - - while (dpix < stoppos) { - uae_u16 spix_val1, spix_val2, dpix_val1, dpix_val2; - uae_u16 v; - int off; - spix_val1 = pixdata.apixels[spix++]; - spix_val2 = pixdata.apixels[spix++]; - off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); - v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; - v |= v >> 2; - dpix_val1 = xcolors[v]; - v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2; - v |= v >> 2; - dpix_val2 = xcolors[v]; - PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel16 (dpix_val1, dpix_val2), spr)); - dpix++; - } - return spix; -} - - - -static int NOINLINE linetoscr_32_shrink2_sh (int spix, int dpix, int stoppos, int spr) -{ - uae_u32 *buf = (uae_u32 *) xlinebuffer; - - while (dpix < stoppos) { - uae_u32 spix_val1, spix_val2; - uae_u16 v; - int off; - spix_val1 = pixdata.apixels[spix++]; - spix_val2 = pixdata.apixels[spix++]; - off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); - v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; - v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr)); - spix+=2; - dpix++; - } - return spix; -} -static int NOINLINE linetoscr_32_shrink2f_sh (int spix, int dpix, int stoppos, int spr) -{ - uae_u32 *buf = (uae_u32 *) xlinebuffer; - - while (dpix < stoppos) { - uae_u32 spix_val1, spix_val2, dpix_val1, dpix_val2, dpix_val3, dpix_val4; - uae_u16 v; - int off; - spix_val1 = pixdata.apixels[spix++]; - spix_val2 = pixdata.apixels[spix++]; - off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); - v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; - v |= v >> 2; - dpix_val1 = xcolors[v]; - v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2; - v |= v >> 2; - dpix_val2 = xcolors[v]; - dpix_val3 = merge_2pixel32 (dpix_val1, dpix_val2); - spix_val1 = pixdata.apixels[spix++]; - spix_val2 = pixdata.apixels[spix++]; - off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); - v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; - v |= v >> 2; - dpix_val1 = xcolors[v]; - v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2; - v |= v >> 2; - dpix_val2 = xcolors[v]; - dpix_val4 = merge_2pixel32 (dpix_val1, dpix_val2); - PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel32 (dpix_val3, dpix_val4), spr)); - dpix++; - } - return spix; -} -static int NOINLINE linetoscr_16_shrink2_sh (int spix, int dpix, int stoppos, int spr) -{ - uae_u16 *buf = (uae_u16 *) xlinebuffer; - - while (dpix < stoppos) { - uae_u16 spix_val1, spix_val2; - uae_u16 v; - int off; - spix_val1 = pixdata.apixels[spix++]; - spix_val2 = pixdata.apixels[spix++]; - off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); - v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; - v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr)); - spix+=2; - dpix++; - } - return spix; -} -static int NOINLINE linetoscr_16_shrink2f_sh (int spix, int dpix, int stoppos, int spr) -{ - uae_u16 *buf = (uae_u16 *) xlinebuffer; - - while (dpix < stoppos) { - uae_u16 spix_val1, spix_val2, dpix_val1, dpix_val2, dpix_val3, dpix_val4; - uae_u16 v; - int off; - spix_val1 = pixdata.apixels[spix++]; - spix_val2 = pixdata.apixels[spix++]; - off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); - v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; - v |= v >> 2; - dpix_val1 = xcolors[v]; - v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2; - v |= v >> 2; - dpix_val2 = xcolors[v]; - dpix_val3 = merge_2pixel32 (dpix_val1, dpix_val2); - spix_val1 = pixdata.apixels[spix++]; - spix_val2 = pixdata.apixels[spix++]; - off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); - v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; - v |= v >> 2; - dpix_val1 = xcolors[v]; - v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2; - v |= v >> 2; - dpix_val2 = xcolors[v]; - dpix_val4 = merge_2pixel32 (dpix_val1, dpix_val2); - PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel16 (dpix_val3, dpix_val4), spr)); - dpix++; - } - return spix; -} -#endif - -static void pfield_do_linetoscr (int start, int stop, bool blank) -{ - xlinecheck(start, stop); - if (issprites && (currprefs.chipset_mask & CSMASK_AGA)) { - if (res_shift == 0) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_aga_spr (LTPARMS); break; - case 4: src_pixel = linetoscr_32_aga_spr (LTPARMS); break; - } - } else if (res_shift == 2) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_stretch2_aga_spr (LTPARMS); break; - case 4: src_pixel = linetoscr_32_stretch2_aga_spr (LTPARMS); break; - } - } else if (res_shift == 1) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_stretch1_aga_spr (LTPARMS); break; - case 4: src_pixel = linetoscr_32_stretch1_aga_spr (LTPARMS); break; - } - } else if (res_shift == -1) { - if (currprefs.gfx_lores_mode) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink1f_aga_spr (LTPARMS); break; - case 4: src_pixel = linetoscr_32_shrink1f_aga_spr (LTPARMS); break; - } - } else { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink1_aga_spr (LTPARMS); break; - case 4: src_pixel = linetoscr_32_shrink1_aga_spr (LTPARMS); break; - } - } - } else if (res_shift == -2) { - if (currprefs.gfx_lores_mode) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink2f_aga_spr (LTPARMS); break; - case 4: src_pixel = linetoscr_32_shrink2f_aga_spr (LTPARMS); break; - } - } else { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink2_aga_spr (LTPARMS); break; - case 4: src_pixel = linetoscr_32_shrink2_aga_spr (LTPARMS); break; - } - } - } - } else -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) { - if (res_shift == 0) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_aga (LTPARMS); break; - case 4: src_pixel = linetoscr_32_aga (LTPARMS); break; - } - } else if (res_shift == 2) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_stretch2_aga (LTPARMS); break; - case 4: src_pixel = linetoscr_32_stretch2_aga (LTPARMS); break; - } - } else if (res_shift == 1) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_stretch1_aga (LTPARMS); break; - case 4: src_pixel = linetoscr_32_stretch1_aga (LTPARMS); break; - } - } else if (res_shift == -1) { - if (currprefs.gfx_lores_mode) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink1f_aga (LTPARMS); break; - case 4: src_pixel = linetoscr_32_shrink1f_aga (LTPARMS); break; - } - } else { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink1_aga (LTPARMS); break; - case 4: src_pixel = linetoscr_32_shrink1_aga (LTPARMS); break; - } - } - } else if (res_shift == -2) { - if (currprefs.gfx_lores_mode) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink2f_aga (LTPARMS); break; - case 4: src_pixel = linetoscr_32_shrink2f_aga (LTPARMS); break; - } - } else { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink2_aga (LTPARMS); break; - case 4: src_pixel = linetoscr_32_shrink2_aga (LTPARMS); break; - } - } - } - } else -#endif -#ifdef ECS_DENISE - if (ecsshres) { - if (res_shift == 0) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_sh (LTPARMS, issprites); break; - case 4: src_pixel = linetoscr_32_sh (LTPARMS, issprites); break; - } - } else if (res_shift == -1) { - if (currprefs.gfx_lores_mode) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink1f_sh (LTPARMS, issprites); break; - case 4: src_pixel = linetoscr_32_shrink1f_sh (LTPARMS, issprites); break; - } - } else { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink1_sh (LTPARMS, issprites); break; - case 4: src_pixel = linetoscr_32_shrink1_sh (LTPARMS, issprites); break; - } - } - } else if (res_shift == -2) { - if (currprefs.gfx_lores_mode) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink2f_sh (LTPARMS, issprites); break; - case 4: src_pixel = linetoscr_32_shrink2f_sh (LTPARMS, issprites); break; - } - } else { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink2_sh (LTPARMS, issprites); break; - case 4: src_pixel = linetoscr_32_shrink2_sh (LTPARMS, issprites); break; - } - } - } - } else -#endif - if (issprites) { - if (res_shift == 0) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_spr (LTPARMS); break; - case 4: src_pixel = linetoscr_32_spr (LTPARMS); break; - } - } else if (res_shift == 2) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_stretch2_spr (LTPARMS); break; - case 4: src_pixel = linetoscr_32_stretch2_spr (LTPARMS); break; - } - } else if (res_shift == 1) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_stretch1_spr (LTPARMS); break; - case 4: src_pixel = linetoscr_32_stretch1_spr (LTPARMS); break; - } - } else if (res_shift == -1) { - if (currprefs.gfx_lores_mode) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink1f_spr (LTPARMS); break; - case 4: src_pixel = linetoscr_32_shrink1f_spr (LTPARMS); break; - } - } else { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink1_spr (LTPARMS); break; - case 4: src_pixel = linetoscr_32_shrink1_spr (LTPARMS); break; - } - } - } - } else { - if (res_shift == 0) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16 (LTPARMS); break; - case 4: src_pixel = linetoscr_32 (LTPARMS); break; - } - } else if (res_shift == 2) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_stretch2 (LTPARMS); break; - case 4: src_pixel = linetoscr_32_stretch2 (LTPARMS); break; - } - } else if (res_shift == 1) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_stretch1 (LTPARMS); break; - case 4: src_pixel = linetoscr_32_stretch1 (LTPARMS); break; - } - } else if (res_shift == -1) { - if (currprefs.gfx_lores_mode) { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink1f (LTPARMS); break; - case 4: src_pixel = linetoscr_32_shrink1f (LTPARMS); break; - } - } else { - switch (gfxvidinfo.drawbuffer.pixbytes) { - case 2: src_pixel = linetoscr_16_shrink1 (LTPARMS); break; - case 4: src_pixel = linetoscr_32_shrink1 (LTPARMS); break; - } - } - } - } - -} - -static void dummy_worker (int start, int stop, bool blank) -{ -} - -static int ham_decode_pixel; -static unsigned int ham_lastcolor; - -/* Decode HAM in the invisible portion of the display (left of VISIBLE_LEFT_BORDER), - * but don't draw anything in. This is done to prepare HAM_LASTCOLOR for later, - * when decode_ham runs. - * - */ -static void init_ham_decoding (void) -{ - int unpainted_amiga = unpainted; - - ham_decode_pixel = ham_src_pixel; - ham_lastcolor = color_reg_get (&colors_for_drawing, 0); - - if (!bplham) { - if (unpainted_amiga > 0) { - int pv = pixdata.apixels[ham_decode_pixel + unpainted_amiga - 1]; -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) - ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor]; - else -#endif - ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; - } -#ifdef AGA - } else if (currprefs.chipset_mask & CSMASK_AGA) { - if (bplplanecnt >= 7) { /* AGA mode HAM8 */ - while (unpainted_amiga-- > 0) { - int pv = pixdata.apixels[ham_decode_pixel++] ^ bplxor; - switch (pv & 0x3) - { - case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break; - case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break; - case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break; - case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break; - } - } - } else { /* AGA mode HAM6 */ - while (unpainted_amiga-- > 0) { - int pv = pixdata.apixels[ham_decode_pixel++] ^ bplxor; - switch (pv & 0x30) - { - case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break; - case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break; - case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break; - case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break; - } - } - } -#endif - } else { - /* OCS/ECS mode HAM6 */ - while (unpainted_amiga-- > 0) { - int pv = pixdata.apixels[ham_decode_pixel++]; - switch (pv & 0x30) - { - case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break; - case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; - case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; - case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; - } - } - } -} - -static void decode_ham (int pix, int stoppos, bool blank) -{ - int todraw_amiga = res_shift_from_window (stoppos - pix); - - if (!bplham) { - while (todraw_amiga-- > 0) { - int pv = pixdata.apixels[ham_decode_pixel]; -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) - ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor]; - else -#endif - ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; - - ham_linebuf[ham_decode_pixel++] = ham_lastcolor; - } -#ifdef AGA - } else if (currprefs.chipset_mask & CSMASK_AGA) { - if (bplplanecnt >= 7) { /* AGA mode HAM8 */ - while (todraw_amiga-- > 0) { - int pv = pixdata.apixels[ham_decode_pixel] ^ bplxor; - switch (pv & 0x3) - { - case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break; - case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break; - case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break; - case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break; - } - ham_linebuf[ham_decode_pixel++] = ham_lastcolor; - } - } else { /* AGA mode HAM6 */ - while (todraw_amiga-- > 0) { - int pv = pixdata.apixels[ham_decode_pixel] ^ bplxor; - switch (pv & 0x30) - { - case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break; - case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break; - case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break; - case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break; - } - ham_linebuf[ham_decode_pixel++] = ham_lastcolor; - } - } -#endif - } else { - /* OCS/ECS mode HAM6 */ - while (todraw_amiga-- > 0) { - int pv = pixdata.apixels[ham_decode_pixel]; - switch (pv & 0x30) - { - case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break; - case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; - case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; - case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; - } - ham_linebuf[ham_decode_pixel++] = ham_lastcolor; - } - } -} - -static void gen_pfield_tables (void) -{ - int i; - - for (i = 0; i < 256; i++) { - int plane1 = ((i >> 0) & 1) | ((i >> 1) & 2) | ((i >> 2) & 4) | ((i >> 3) & 8); - int plane2 = ((i >> 1) & 1) | ((i >> 2) & 2) | ((i >> 3) & 4) | ((i >> 4) & 8); - - dblpf_2nd1[i] = plane1 == 0 && plane2 != 0; - dblpf_2nd2[i] = plane2 != 0; - -#ifdef AGA - dblpf_ind1_aga[i] = plane1 == 0 ? plane2 : plane1; - dblpf_ind2_aga[i] = plane2 == 0 ? plane1 : plane2; -#endif - - dblpf_ms1[i] = plane1 == 0 ? (plane2 == 0 ? 16 : 8) : 0; - dblpf_ms2[i] = plane2 == 0 ? (plane1 == 0 ? 16 : 0) : 8; - dblpf_ms[i] = i == 0 ? 16 : 8; - - if (plane2 > 0) - plane2 += 8; - dblpf_ind1[i] = i >= 128 ? i & 0x7F : (plane1 == 0 ? plane2 : plane1); - dblpf_ind2[i] = i >= 128 ? i & 0x7F : (plane2 == 0 ? plane1 : plane2); - - sprite_offs[i] = (i & 15) ? 0 : 2; - - clxtab[i] = ((((i & 3) && (i & 12)) << 9) - | (((i & 3) && (i & 48)) << 10) - | (((i & 3) && (i & 192)) << 11) - | (((i & 12) && (i & 48)) << 12) - | (((i & 12) && (i & 192)) << 13) - | (((i & 48) && (i & 192)) << 14)); - - } - - memset (all_ones, 0xff, MAX_PIXELS_PER_LINE); - -} - -/* When looking at this function and the ones that inline it, bear in mind -what an optimizing compiler will do with this code. All callers of this -function only pass in constant arguments (except for E). This means -that many of the if statements will go away completely after inlining. */ -STATIC_INLINE void draw_sprites_1 (struct sprite_entry *e, int dualpf, int has_attach) -{ - uae_u16 *buf = spixels + e->first_pixel; - uae_u8 *stbuf = spixstate.bytes + e->first_pixel; - int spr_pos, pos; - - buf -= e->pos; - stbuf -= e->pos; - - spr_pos = e->pos + ((DIW_DDF_OFFSET - DISPLAY_LEFT_SHIFT) << sprite_buffer_res); - - if (spr_pos < sprite_first_x) - sprite_first_x = spr_pos; - - for (pos = e->pos; pos < e->max; pos++, spr_pos++) { - if (spr_pos >= 0 && spr_pos < MAX_PIXELS_PER_LINE) { - spritepixels[spr_pos].data = buf[pos]; - spritepixels[spr_pos].stdata = stbuf[pos]; - spritepixels[spr_pos].attach = has_attach; - } - } - - if (spr_pos > sprite_last_x) - sprite_last_x = spr_pos; -} - -/* See comments above. Do not touch if you don't know what's going on. -* (We do _not_ want the following to be inlined themselves). */ -/* lores bitplane, lores sprites */ -static void NOINLINE draw_sprites_normal_sp_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0); } -static void NOINLINE draw_sprites_normal_dp_nat (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0); } -static void NOINLINE draw_sprites_normal_sp_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1); } -static void NOINLINE draw_sprites_normal_dp_at (struct sprite_entry *e) { draw_sprites_1 (e, 1, 1); } - -#ifdef AGA -/* not very optimized */ -STATIC_INLINE void draw_sprites_aga (struct sprite_entry *e, int aga) -{ - draw_sprites_1 (e, bpldualpf, e->has_attached); -} -#endif - -STATIC_INLINE void draw_sprites_ecs (struct sprite_entry *e) -{ - if (e->has_attached) { - if (bpldualpf) - draw_sprites_normal_dp_at (e); - else - draw_sprites_normal_sp_at (e); - } else { - if (bpldualpf) - draw_sprites_normal_dp_nat (e); - else - draw_sprites_normal_sp_nat (e); - } -} - -#ifdef AGA -/* clear possible bitplane data outside DIW area */ -static void clear_bitplane_border_aga (void) -{ - int len, shift = res_shift; - uae_u8 v = 0; - - if (shift < 0) { - shift = -shift; - len = (real_playfield_start - playfield_start) << shift; - memset (pixdata.apixels + pixels_offset + (playfield_start << shift), v, len); - len = (playfield_end - real_playfield_end) << shift; - memset (pixdata.apixels + pixels_offset + (real_playfield_end << shift), v, len); - } else { - len = (real_playfield_start - playfield_start) >> shift; - memset (pixdata.apixels + pixels_offset + (playfield_start >> shift), v, len); - len = (playfield_end - real_playfield_end) >> shift; - memset (pixdata.apixels + pixels_offset + (real_playfield_end >> shift), v, len); - } -} -#endif - -/* emulate OCS/ECS only undocumented "SWIV" hardware feature */ -static void weird_bitplane_fix (void) -{ - int i; - int sh = lores_shift; - uae_u8 *p = pixdata.apixels + pixels_offset; - - for (i = playfield_start >> sh; i < playfield_end >> sh; i++) { - if (p[i] > 16) - p[i] = 16; - } -} - -#define MERGE(a,b,mask,shift) do {\ - uae_u32 tmp = mask & (a ^ (b >> shift)); \ - a ^= tmp; \ - b ^= (tmp << shift); \ -} while (0) - -#define GETLONG(P) (*(uae_u32 *)P) - -/* We use the compiler's inlining ability to ensure that PLANES is in effect a compile time -constant. That will cause some unnecessary code to be optimized away. -Don't touch this if you don't know what you are doing. */ -STATIC_INLINE void pfield_doline_1 (uae_u32 *pixels, int wordcount, int planes) -{ - while (wordcount-- > 0) { - uae_u32 b0, b1, b2, b3, b4, b5, b6, b7; - - b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0, b7 = 0; - switch (planes) { -#ifdef AGA - case 8: b0 = GETLONG (real_bplpt[7]); real_bplpt[7] += 4; - case 7: b1 = GETLONG (real_bplpt[6]); real_bplpt[6] += 4; -#endif - case 6: b2 = GETLONG (real_bplpt[5]); real_bplpt[5] += 4; - case 5: b3 = GETLONG (real_bplpt[4]); real_bplpt[4] += 4; - case 4: b4 = GETLONG (real_bplpt[3]); real_bplpt[3] += 4; - case 3: b5 = GETLONG (real_bplpt[2]); real_bplpt[2] += 4; - case 2: b6 = GETLONG (real_bplpt[1]); real_bplpt[1] += 4; - case 1: b7 = GETLONG (real_bplpt[0]); real_bplpt[0] += 4; - } - - MERGE (b0, b1, 0x55555555, 1); - MERGE (b2, b3, 0x55555555, 1); - MERGE (b4, b5, 0x55555555, 1); - MERGE (b6, b7, 0x55555555, 1); - - MERGE (b0, b2, 0x33333333, 2); - MERGE (b1, b3, 0x33333333, 2); - MERGE (b4, b6, 0x33333333, 2); - MERGE (b5, b7, 0x33333333, 2); - - MERGE (b0, b4, 0x0f0f0f0f, 4); - MERGE (b1, b5, 0x0f0f0f0f, 4); - MERGE (b2, b6, 0x0f0f0f0f, 4); - MERGE (b3, b7, 0x0f0f0f0f, 4); - - MERGE (b0, b1, 0x00ff00ff, 8); - MERGE (b2, b3, 0x00ff00ff, 8); - MERGE (b4, b5, 0x00ff00ff, 8); - MERGE (b6, b7, 0x00ff00ff, 8); - - MERGE (b0, b2, 0x0000ffff, 16); - do_put_mem_long (pixels, b0); - do_put_mem_long (pixels + 4, b2); - MERGE (b1, b3, 0x0000ffff, 16); - do_put_mem_long (pixels + 2, b1); - do_put_mem_long (pixels + 6, b3); - MERGE (b4, b6, 0x0000ffff, 16); - do_put_mem_long (pixels + 1, b4); - do_put_mem_long (pixels + 5, b6); - MERGE (b5, b7, 0x0000ffff, 16); - do_put_mem_long (pixels + 3, b5); - do_put_mem_long (pixels + 7, b7); - pixels += 8; - } -} - -/* See above for comments on inlining. These functions should _not_ -be inlined themselves. */ -static void NOINLINE pfield_doline_n1 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 1); } -static void NOINLINE pfield_doline_n2 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 2); } -static void NOINLINE pfield_doline_n3 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 3); } -static void NOINLINE pfield_doline_n4 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 4); } -static void NOINLINE pfield_doline_n5 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 5); } -static void NOINLINE pfield_doline_n6 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 6); } -#ifdef AGA -static void NOINLINE pfield_doline_n7 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 7); } -static void NOINLINE pfield_doline_n8 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 8); } -#endif - -static void pfield_doline (int lineno) -{ - int wordcount = dp_for_drawing->plflinelen; - uae_u32 *data = pixdata.apixels_l + MAX_PIXELS_PER_LINE / 4; - -#ifdef SMART_UPDATE -#define DATA_POINTER(n) ((debug_bpl_mask & (1 << n)) ? (line_data[lineno] + (n) * MAX_WORDS_PER_LINE * 2) : (debug_bpl_mask_one ? all_ones : all_zeros)) - real_bplpt[0] = DATA_POINTER (0); - real_bplpt[1] = DATA_POINTER (1); - real_bplpt[2] = DATA_POINTER (2); - real_bplpt[3] = DATA_POINTER (3); - real_bplpt[4] = DATA_POINTER (4); - real_bplpt[5] = DATA_POINTER (5); -#ifdef AGA - real_bplpt[6] = DATA_POINTER (6); - real_bplpt[7] = DATA_POINTER (7); -#endif -#endif - - switch (bplplanecnt) { - default: break; - case 0: memset (data, 0, wordcount * 32); break; - case 1: pfield_doline_n1 (data, wordcount); break; - case 2: pfield_doline_n2 (data, wordcount); break; - case 3: pfield_doline_n3 (data, wordcount); break; - case 4: pfield_doline_n4 (data, wordcount); break; - case 5: pfield_doline_n5 (data, wordcount); break; - case 6: pfield_doline_n6 (data, wordcount); break; -#ifdef AGA - case 7: pfield_doline_n7 (data, wordcount); break; - case 8: pfield_doline_n8 (data, wordcount); break; -#endif - } -} - -void init_row_map (void) -{ - static uae_u8 *oldbufmem; - static int oldheight, oldpitch; - - int i, j; - if (gfxvidinfo.drawbuffer.height_allocated > MAX_VIDHEIGHT) { - write_log (_T("Resolution too high, aborting\n")); - abort (); - } - if (oldbufmem && oldbufmem == gfxvidinfo.drawbuffer.bufmem && - oldheight == gfxvidinfo.drawbuffer.height_allocated && - oldpitch == gfxvidinfo.drawbuffer.rowbytes) - return; - oldbufmem = gfxvidinfo.drawbuffer.bufmem; - oldheight = gfxvidinfo.drawbuffer.height_allocated; - oldpitch = gfxvidinfo.drawbuffer.rowbytes; - j = 0; - for (i = gfxvidinfo.drawbuffer.height_allocated; i < MAX_VIDHEIGHT + 1; i++) - row_map[i] = row_tmp; - for (i = 0; i < gfxvidinfo.drawbuffer.height_allocated; i++, j += gfxvidinfo.drawbuffer.rowbytes) - row_map[i] = gfxvidinfo.drawbuffer.bufmem + j; -} - -void init_aspect_maps (void) -{ - int i, maxl, h; - - h = gfxvidinfo.drawbuffer.height_allocated; - - if (h == 0) - /* Do nothing if the gfx driver hasn't initialized the screen yet */ - return; - - linedbld = linedbl = currprefs.gfx_vresolution; - if (doublescan > 0 && interlace_seen <= 0) { - linedbl = 0; - linedbld = 1; - } - - if (native2amiga_line_map) - xfree (native2amiga_line_map); - if (amiga2aspect_line_map) - xfree (amiga2aspect_line_map); - - /* At least for this array the +1 is necessary. */ - amiga2aspect_line_map = xmalloc (int, (MAXVPOS + 1) * 2 + 1); - native2amiga_line_map = xmalloc (int, h); - - maxl = (MAXVPOS + 1) << linedbld; - min_ypos_for_screen = minfirstline << linedbl; - max_drawn_amiga_line = -1; - for (i = 0; i < maxl; i++) { - int v = i - min_ypos_for_screen; - if (v >= h && max_drawn_amiga_line < 0) - max_drawn_amiga_line = i - min_ypos_for_screen; - if (i < min_ypos_for_screen || v >= h) - v = -1; - amiga2aspect_line_map[i] = v; - } - if (max_drawn_amiga_line < 0) - max_drawn_amiga_line = maxl - min_ypos_for_screen; - max_drawn_amiga_line >>= linedbl; - - if (currprefs.gfx_ycenter && !currprefs.gfx_filter_autoscale) { - /* @@@ verify maxvpos vs. MAXVPOS */ - extra_y_adjust = (h - (maxvpos_nom << linedbl)) >> 1; - if (extra_y_adjust < 0) - extra_y_adjust = 0; - } - - for (i = 0; i < h; i++) - native2amiga_line_map[i] = -1; - - for (i = maxl - 1; i >= min_ypos_for_screen; i--) { - int j; - if (amiga2aspect_line_map[i] == -1) - continue; - for (j = amiga2aspect_line_map[i]; j < h && native2amiga_line_map[j] == -1; j++) - native2amiga_line_map[j] = i >> linedbl; - } - - gfxvidinfo.xchange = 1 << (RES_MAX - currprefs.gfx_resolution); - gfxvidinfo.ychange = linedbl ? 1 : 2; - - visible_left_start = 0; - visible_right_stop = MAX_STOP; - visible_top_start = 0; - visible_bottom_stop = MAX_STOP; -} - -/* -* A raster line has been built in the graphics buffer. Tell the graphics code -* to do anything necessary to display it. -*/ -static void do_flush_line_1 (struct vidbuffer *vb, int lineno) -{ - if (lineno < first_drawn_line) - first_drawn_line = lineno; - if (lineno > last_drawn_line) - last_drawn_line = lineno; - - if (gfxvidinfo.maxblocklines == 0) - flush_line (vb, lineno); - else { - if ((last_block_line + 2) < lineno) { - if (first_block_line != NO_BLOCK) - flush_block (vb, first_block_line, last_block_line); - first_block_line = lineno; - } - last_block_line = lineno; - if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) { - flush_block (vb, first_block_line, last_block_line); - first_block_line = last_block_line = NO_BLOCK; - } - } -} - -STATIC_INLINE void do_flush_line (struct vidbuffer *vb, int lineno) -{ - do_flush_line_1 (vb, lineno); -} - -/* -* One drawing frame has been finished. Tell the graphics code about it. -* Note that the actual flush_screen() call is a no-op for all reasonable -* systems. -*/ - -STATIC_INLINE void do_flush_screen (struct vidbuffer *vb, int start, int stop) -{ - /* TODO: this flush operation is executed outside locked state! - Should be corrected. - (sjo 26.9.99) */ - - if (vb != gfxvidinfo.outbuffer) - return; - - xlinecheck (start, stop); - if (gfxvidinfo.maxblocklines != 0 && first_block_line != NO_BLOCK) { - flush_block (vb, first_block_line, last_block_line); - } - unlockscr (vb); - if (start <= stop) - flush_screen (vb, start, stop); - else if (isvsync_chipset ()) - flush_screen (vb, 0, 0); /* vsync mode */ -} - -/* We only save hardware registers during the hardware frame. Now, when -* drawing the frame, we expand the data into a slightly more useful -* form. */ -static void pfield_expand_dp_bplcon (void) -{ - static int b2; - - bplres = dp_for_drawing->bplres; - bplplanecnt = dp_for_drawing->nr_planes; - bplham = dp_for_drawing->ham_seen; - bplehb = dp_for_drawing->ehb_seen; - if ((currprefs.chipset_mask & CSMASK_AGA) && (dp_for_drawing->bplcon2 & 0x0200)) - bplehb = 0; - issprites = dip_for_drawing->nr_sprites; -#ifdef ECS_DENISE - ecsshres = bplres == RES_SUPERHIRES && (currprefs.chipset_mask & CSMASK_ECS_DENISE) && !(currprefs.chipset_mask & CSMASK_AGA); -#endif - - plf1pri = dp_for_drawing->bplcon2 & 7; - plf2pri = (dp_for_drawing->bplcon2 >> 3) & 7; - plf_sprite_mask = 0xFFFF0000 << (4 * plf2pri); - plf_sprite_mask |= (0x0000FFFF << (4 * plf1pri)) & 0xFFFF; - bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400; - bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40; - -#ifdef AGA - bpldualpf2of = (dp_for_drawing->bplcon3 >> 10) & 7; - sbasecol[0] = ((dp_for_drawing->bplcon4 >> 4) & 15) << 4; - sbasecol[1] = ((dp_for_drawing->bplcon4 >> 0) & 15) << 4; - brdsprt = !brdblank && (currprefs.chipset_mask & CSMASK_AGA) && (dp_for_drawing->bplcon0 & 1) && (dp_for_drawing->bplcon3 & 0x02); - bplxor = dp_for_drawing->bplcon4 >> 8; -#endif -} - -static bool isham (uae_u16 bplcon0) -{ - int p = GET_PLANES (bplcon0); - if (!(bplcon0 & 0x800)) - return 0; - if (currprefs.chipset_mask & CSMASK_AGA) { - // AGA only has 6 or 8 plane HAM - if (p == 6 || p == 8) - return 1; - } else { - // OCS/ECS also supports 5 plane HAM - if (GET_RES_DENISE (bplcon0) > 0) - return 0; - if (p >= 5) - return 1; - } - return 0; -} - -static void isbrdblank (void) -{ -#ifdef ECS_DENISE - bool brdblank_2 = (currprefs.chipset_mask & CSMASK_ECS_DENISE) && (bplcon0_store & 1) && (bplcon3_store & 0x20); - if (brdblank_2 != brdblank) - brdblank_changed = true; - brdblank = brdblank_2; -#endif -} - -static void pfield_expand_dp_bplconx (int regno, int v) -{ - if (regno == 0xffff) { - hposblank = 1; - return; - } - regno -= 0x1000; - switch (regno) - { - case 0x100: - dp_for_drawing->bplcon0 = v; - dp_for_drawing->bplres = GET_RES_DENISE (v); - dp_for_drawing->nr_planes = GET_PLANES (v); - dp_for_drawing->ham_seen = isham (v); - bplcon0_store = v; - isbrdblank (); - break; - case 0x104: - dp_for_drawing->bplcon2 = v; - break; -#ifdef ECS_DENISE - case 0x106: - dp_for_drawing->bplcon3 = v; - bplcon3_store = v; - isbrdblank (); - break; -#endif -#ifdef AGA - case 0x10c: - dp_for_drawing->bplcon4 = v; - break; -#endif - } - pfield_expand_dp_bplcon (); - res_shift = lores_shift - bplres; -} - -static int drawing_color_matches; -static enum { color_match_acolors, color_match_full } color_match_type; - -/* Set up colors_for_drawing to the state at the beginning of the currently drawn -line. Try to avoid copying color tables around whenever possible. */ -static void adjust_drawing_colors (int ctable, int need_full) -{ - if (drawing_color_matches != ctable) { - if (need_full) { - color_reg_cpy (&colors_for_drawing, curr_color_tables + ctable); - color_match_type = color_match_full; - } else { - memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors, - sizeof colors_for_drawing.acolors); - color_match_type = color_match_acolors; - } - drawing_color_matches = ctable; - } else if (need_full && color_match_type != color_match_full) { - color_reg_cpy (&colors_for_drawing, &curr_color_tables[ctable]); - color_match_type = color_match_full; - } -} - -static void do_color_changes (line_draw_func worker_border, line_draw_func worker_pfield, int vp) -{ - int i; - int lastpos = visible_left_border; - int endpos = visible_left_border + gfxvidinfo.drawbuffer.inwidth; - - for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++) { - int regno = curr_color_changes[i].regno; - unsigned int value = curr_color_changes[i].value; - int nextpos, nextpos_in_range; - - if (i == dip_for_drawing->last_color_change) - nextpos = endpos; - else - nextpos = coord_hw_to_window_x (curr_color_changes[i].linepos); - - nextpos_in_range = nextpos; - if (nextpos > endpos) - nextpos_in_range = endpos; - - if (nextpos_in_range > lastpos) { - if (lastpos < playfield_start) { - int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start; - (*worker_border) (lastpos, t, false); - lastpos = t; - } - } - if (nextpos_in_range > lastpos) { - if (lastpos >= playfield_start && lastpos < playfield_end) { - int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end; - (*worker_pfield) (lastpos, t, false); - /* blank start and end that shouldn't be visible */ - if (lastpos < visible_left_start) - (*worker_border) (lastpos, visible_left_start, true); - if (t > visible_right_stop) - (*worker_border) (visible_right_stop, endpos, true); - lastpos = t; - } - } - if (nextpos_in_range > lastpos) { - if (lastpos >= playfield_end) - (*worker_border) (lastpos, nextpos_in_range, false); - lastpos = nextpos_in_range; - } - - if (regno >= 0x1000) { - pfield_expand_dp_bplconx (regno, value); - } else if (regno >= 0) { - color_reg_set (&colors_for_drawing, regno, value); - colors_for_drawing.acolors[regno] = getxcolor (value); - } - if (lastpos >= endpos) - break; - } - if (vp < visible_top_start || vp >= visible_bottom_stop) { - // outside of visible area - // Just overwrite with black. Above code needs to run because of custom registers, - // not worth the trouble for separate code path just for max 10 lines or so - (*worker_border) (visible_left_border, visible_left_border + gfxvidinfo.drawbuffer.inwidth, true); - } - -} -enum double_how { - dh_buf, - dh_line, - dh_emerg -}; - -static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, int follow_ypos) -{ - static int warned = 0; - int border = 0; - int do_double = 0; - enum double_how dh; - - dp_for_drawing = line_decisions + lineno; - dip_for_drawing = curr_drawinfo + lineno; - - switch (linestate[lineno]) - { - case LINE_REMEMBERED_AS_PREVIOUS: -// if (!warned) // happens when program messes up with VPOSW -// write_log (_T("Shouldn't get here... this is a bug.\n")), warned++; - return; - - case LINE_BLACK: - linestate[lineno] = LINE_REMEMBERED_AS_BLACK; - border = 2; - break; - - case LINE_REMEMBERED_AS_BLACK: - return; - - case LINE_AS_PREVIOUS: - dp_for_drawing--; - dip_for_drawing--; - linestate[lineno] = LINE_DONE_AS_PREVIOUS; - if (dp_for_drawing->plfleft < 0) - border = 1; - break; - - case LINE_DONE_AS_PREVIOUS: - /* fall through */ - case LINE_DONE: - return; - - case LINE_DECIDED_DOUBLE: - if (follow_ypos >= 0) { - do_double = 1; - linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS; - } - - /* fall through */ - default: - if (dp_for_drawing->plfleft < 0) - border = 1; - linestate[lineno] = LINE_DONE; - break; - } - - dh = dh_line; - xlinebuffer = gfxvidinfo.drawbuffer.linemem; - if (xlinebuffer == 0 && do_double - && (border == 0 || dip_for_drawing->nr_color_changes > 0)) - xlinebuffer = gfxvidinfo.drawbuffer.emergmem, dh = dh_emerg; - if (xlinebuffer == 0) - xlinebuffer = row_map[gfx_ypos], dh = dh_buf; - xlinebuffer -= linetoscr_x_adjust_bytes; - - if (border == 0) { - - pfield_expand_dp_bplcon (); - pfield_init_linetoscr (); - pfield_doline (lineno); - - adjust_drawing_colors (dp_for_drawing->ctable, dp_for_drawing->ham_seen || bplehb || ecsshres); - - /* The problem is that we must call decode_ham() BEFORE we do the - sprites. */ - if (dp_for_drawing->ham_seen) { - init_ham_decoding (); - if (dip_for_drawing->nr_color_changes == 0) { - /* The easy case: need to do HAM decoding only once for the - * full line. */ - decode_ham (visible_left_border, visible_right_border, false); - } else /* Argh. */ { - do_color_changes (dummy_worker, decode_ham, lineno); - adjust_drawing_colors (dp_for_drawing->ctable, dp_for_drawing->ham_seen || bplehb); - } - bplham = dp_for_drawing->ham_at_start; - } - - if (plf2pri > 5 && bplplanecnt == 5 && !(currprefs.chipset_mask & CSMASK_AGA)) - weird_bitplane_fix (); - - if (dip_for_drawing->nr_sprites) { - int i; -#ifdef AGA - if (brdsprt) - clear_bitplane_border_aga (); -#endif - for (i = 0; i < dip_for_drawing->nr_sprites; i++) { -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) - draw_sprites_aga (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i, 1); - else -#endif - draw_sprites_ecs (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i); - } - } - - do_color_changes (pfield_do_fill_line, pfield_do_linetoscr, lineno); - - if (dh == dh_emerg) - memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.drawbuffer.pixbytes * gfxvidinfo.drawbuffer.inwidth); - - do_flush_line (vb, gfx_ypos); - if (do_double) { - if (dh == dh_emerg) - memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.drawbuffer.pixbytes * gfxvidinfo.drawbuffer.inwidth); - else if (dh == dh_buf) - memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.drawbuffer.pixbytes * gfxvidinfo.drawbuffer.inwidth); - do_flush_line (vb, follow_ypos); - } - - } else if (border == 1) { - int dosprites = 0; - - adjust_drawing_colors (dp_for_drawing->ctable, 0); - -#ifdef AGA /* this makes things complex.. */ - if (brdsprt && dip_for_drawing->nr_sprites > 0) { - dosprites = 1; - pfield_expand_dp_bplcon (); - pfield_init_linetoscr (); - memset (pixdata.apixels + MAX_PIXELS_PER_LINE, brdblank ? 0 : colors_for_drawing.acolors[0], MAX_PIXELS_PER_LINE); - } -#endif - - if (!dosprites && dip_for_drawing->nr_color_changes == 0) { - fill_line (); - do_flush_line (vb, gfx_ypos); - - if (do_double) { - if (dh == dh_buf) { - xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes; - fill_line (); - } - /* If dh == dh_line, do_flush_line will re-use the rendered line - * from linemem. */ - do_flush_line (vb, follow_ypos); - } - return; - } - - - if (dosprites) { - - int i; - for (i = 0; i < dip_for_drawing->nr_sprites; i++) - draw_sprites_aga (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i, 1); - uae_u16 oxor = bplxor; - memset (pixdata.apixels, 0, sizeof pixdata); - bplxor = 0; - do_color_changes (pfield_do_fill_line, pfield_do_linetoscr, lineno); - bplxor = oxor; - - } else { - - playfield_start = visible_right_border; - playfield_end = visible_right_border; - do_color_changes (pfield_do_fill_line, pfield_do_fill_line, lineno); - - } - - if (dh == dh_emerg) - memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.drawbuffer.pixbytes * gfxvidinfo.drawbuffer.inwidth); - - do_flush_line (vb, gfx_ypos); - if (do_double) { - if (dh == dh_emerg) - memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.drawbuffer.pixbytes * gfxvidinfo.drawbuffer.inwidth); - else if (dh == dh_buf) - memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.drawbuffer.pixbytes * gfxvidinfo.drawbuffer.inwidth); - do_flush_line (vb, follow_ypos); - } - - } else { - - int tmp = hposblank; - hposblank = brdblank; - fill_line (); - do_flush_line (vb, gfx_ypos); - hposblank = tmp; - - } -} - -static void center_image (void) -{ - int prev_x_adjust = visible_left_border; - int prev_y_adjust = thisframe_y_adjust; - int tmp; - - int w = gfxvidinfo.drawbuffer.inwidth; - if (currprefs.gfx_xcenter && !currprefs.gfx_filter_autoscale && max_diwstop > 0) { - - if (max_diwstop - min_diwstart < w && currprefs.gfx_xcenter == 2) - /* Try to center. */ - visible_left_border = (max_diwstop - min_diwstart - w) / 2 + min_diwstart; - else - visible_left_border = max_diwstop - w - (max_diwstop - min_diwstart - w) / 2; - visible_left_border &= ~((xshift (1, lores_shift)) - 1); - - /* Would the old value be good enough? If so, leave it as it is if we want to - * be clever. */ - if (currprefs.gfx_xcenter == 2) { - if (visible_left_border < prev_x_adjust && prev_x_adjust < min_diwstart && min_diwstart - visible_left_border <= 32) - visible_left_border = prev_x_adjust; - } - } else if (gfxvidinfo.drawbuffer.extrawidth) { - visible_left_border = max_diwlastword - w; - //visible_left_border += gfxvidinfo.drawbuffer.extrawidth << currprefs.gfx_resolution; - } else { - if (gfxvidinfo.drawbuffer.inxoffset < 0) { - visible_left_border = 0; - } else { - visible_left_border = gfxvidinfo.drawbuffer.inxoffset - DISPLAY_LEFT_SHIFT; - } - } - - - if (visible_left_border > max_diwlastword - 32) - visible_left_border = max_diwlastword - 32; - if (visible_left_border < 0) - visible_left_border = 0; - visible_left_border &= ~((xshift (1, lores_shift)) - 1); - - //write_log (_T("%d %d %d %d %d\n"), max_diwlastword, gfxvidinfo.drawbuffer.width, lores_shift, currprefs.gfx_resolution, visible_left_border); - - linetoscr_x_adjust_bytes = visible_left_border * gfxvidinfo.drawbuffer.pixbytes; - - visible_right_border = visible_left_border + w; - if (visible_right_border > max_diwlastword) - visible_right_border = max_diwlastword; - - thisframe_y_adjust = minfirstline; - if (currprefs.gfx_ycenter && thisframe_first_drawn_line >= 0 && !currprefs.gfx_filter_autoscale) { - - if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2) - thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line; - else - thisframe_y_adjust = thisframe_first_drawn_line + ((thisframe_last_drawn_line - thisframe_first_drawn_line) - max_drawn_amiga_line) / 2; - - /* Would the old value be good enough? If so, leave it as it is if we want to - * be clever. */ - if (currprefs.gfx_ycenter == 2) { - if (thisframe_y_adjust != prev_y_adjust - && prev_y_adjust <= thisframe_first_drawn_line - && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line) - thisframe_y_adjust = prev_y_adjust; - } - } - - /* Make sure the value makes sense */ - if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos_nom) - thisframe_y_adjust = maxvpos_nom - max_drawn_amiga_line; - if (thisframe_y_adjust < minfirstline) - thisframe_y_adjust = minfirstline; - - thisframe_y_adjust_real = thisframe_y_adjust << linedbl; - tmp = (maxvpos_nom - thisframe_y_adjust + 1) << linedbl; - if (tmp != max_ypos_thisframe) { - last_max_ypos = tmp; - if (last_max_ypos < 0) - last_max_ypos = 0; - } - max_ypos_thisframe = tmp; - - /* @@@ interlace_seen used to be (bplcon0 & 4), but this is probably - * better. */ - if (prev_x_adjust != visible_left_border || prev_y_adjust != thisframe_y_adjust) - frame_redraw_necessary |= (interlace_seen > 0 && linedbl) ? 2 : 1; - - max_diwstop = 0; - min_diwstart = 10000; - - gfxvidinfo.drawbuffer.xoffset = (DISPLAY_LEFT_SHIFT << RES_MAX) + (visible_left_border << (RES_MAX - currprefs.gfx_resolution)); - gfxvidinfo.drawbuffer.yoffset = thisframe_y_adjust << VRES_MAX; - - visible_left_start = visible_left_border; - visible_right_stop = visible_left_start + gfxvidinfo.drawbuffer.inwidth;; -} - -#define FRAMES_UNTIL_RES_SWITCH 1 -static int frame_res_cnt; -static void init_drawing_frame (void) -{ - int i, maxline; -#if 1 - static int frame_res_old; - - if (currprefs.gfx_autoresolution && frame_res >= 0 && frame_res_lace >= 0) { - if (FRAMES_UNTIL_RES_SWITCH > 0 && frame_res_old == frame_res * 2 + frame_res_lace) { - frame_res_cnt--; - if (frame_res_cnt == 0) { - int m = frame_res * 2 + frame_res_lace; - struct wh *dst = currprefs.gfx_apmode[0].gfx_fullscreen ? &changed_prefs.gfx_size_fs : &changed_prefs.gfx_size_win; - while (m < 3 * 2) { - struct wh *src = currprefs.gfx_apmode[0].gfx_fullscreen ? &currprefs.gfx_size_fs_xtra[m] : &currprefs.gfx_size_win_xtra[m]; - if ((src->width > 0 && src->height > 0) || (currprefs.gfx_api || currprefs.gfx_filter > 0)) { - int nr = m >> 1; - int nl = (m & 1) == 0 ? 0 : 1; - int nr_o = nr; - int nl_o = nl; - - if (currprefs.gfx_autoresolution_minh < 0) { - if (nr < nl) - nr = nl; - } else if (nr < currprefs.gfx_autoresolution_minh) { - nr = currprefs.gfx_autoresolution_minh; - } - if (currprefs.gfx_autoresolution_minv < 0) { - if (nl < nr) - nl = nr; - } else if (nl < currprefs.gfx_autoresolution_minv) { - nl = currprefs.gfx_autoresolution_minv; - } - - if (nr > gfxvidinfo.gfx_resolution_reserved) - nr = gfxvidinfo.gfx_resolution_reserved; - if (nl > gfxvidinfo.gfx_vresolution_reserved) - nl = gfxvidinfo.gfx_vresolution_reserved; - - if (changed_prefs.gfx_resolution != nr || changed_prefs.gfx_vresolution != nl) { - changed_prefs.gfx_resolution = nr; - changed_prefs.gfx_vresolution = nl; - write_log (_T("RES -> %d (%d) LINE -> %d (%d) (%d - %d, %d - %d)\n"), nr, nr_o, nl, nl_o, - currprefs.gfx_autoresolution_minh, currprefs.gfx_autoresolution_minv, - gfxvidinfo.gfx_resolution_reserved, gfxvidinfo.gfx_vresolution_reserved); - config_changed = 1; - //activate_debugger (); - } - if (src->width > 0 && src->height > 0) { - if (memcmp (dst, src, sizeof *dst)) { - *dst = *src; - config_changed = 1; - } - } - break; - } - m++; - } - frame_res_cnt = FRAMES_UNTIL_RES_SWITCH; - } - } else { - frame_res_old = frame_res * 2 + frame_res_lace; - frame_res_cnt = FRAMES_UNTIL_RES_SWITCH; - } - } - frame_res = -1; - frame_res_lace = 0; - - if (can_use_lores > AUTO_LORES_FRAMES && 0) { - lores_factor = 1; - lores_shift = 0; - } else { - can_use_lores++; - lores_reset (); - } -#endif - - init_hardware_for_drawing_frame (); - - if (thisframe_first_drawn_line < 0) - thisframe_first_drawn_line = minfirstline; - if (thisframe_first_drawn_line > thisframe_last_drawn_line) - thisframe_last_drawn_line = thisframe_first_drawn_line; - - maxline = ((maxvpos_nom + 1) << linedbl) + 2; -#ifdef SMART_UPDATE - for (i = 0; i < maxline; i++) { - switch (linestate[i]) { - case LINE_DONE_AS_PREVIOUS: - linestate[i] = LINE_REMEMBERED_AS_PREVIOUS; - break; - case LINE_REMEMBERED_AS_BLACK: - break; - default: - linestate[i] = LINE_UNDECIDED; - break; - } - } -#else - memset (linestate, LINE_UNDECIDED, maxline); -#endif - last_drawn_line = 0; - first_drawn_line = 32767; - - first_block_line = last_block_line = NO_BLOCK; - if (frame_redraw_necessary) - frame_redraw_necessary--; - - center_image (); - - thisframe_first_drawn_line = -1; - thisframe_last_drawn_line = -1; - - drawing_color_matches = -1; - seen_sprites = -1; -} - -void putpixel (uae_u8 *buf, int bpp, int x, xcolnr c8, int opaq) -{ - if (x <= 0) - return; - - switch (bpp) { - case 1: - buf[x] = (uae_u8)c8; - break; - case 2: - { - uae_u16 *p = (uae_u16*)buf + x; - *p = (uae_u16)c8; - break; - } - case 3: - /* no 24 bit yet */ - break; - case 4: - { - int i; - if (1 || opaq || currprefs.gfx_filter == 0) { - uae_u32 *p = (uae_u32*)buf + x; - *p = c8; - } else { - for (i = 0; i < 4; i++) { - int v1 = buf[i + bpp * x]; - int v2 = (c8 >> (i * 8)) & 255; - v1 = (v1 * 2 + v2 * 3) / 5; - if (v1 > 255) - v1 = 255; - buf[i + bpp * x] = v1; - } - } - break; - } - } -} - -static void draw_status_line (int line, int statusy) -{ - int bpp, y; - uae_u8 *buf; - - if (!(currprefs.leds_on_screen & STATUSLINE_CHIPSET) || (currprefs.leds_on_screen & STATUSLINE_TARGET)) - return; - bpp = gfxvidinfo.drawbuffer.pixbytes; - y = line - (gfxvidinfo.drawbuffer.outheight - TD_TOTAL_HEIGHT); - xlinebuffer = gfxvidinfo.drawbuffer.linemem; - if (xlinebuffer == 0) - xlinebuffer = row_map[line]; - buf = xlinebuffer; - draw_status_line_single (buf, bpp, statusy, gfxvidinfo.drawbuffer.outwidth, xredcolors, xgreencolors, xbluecolors, NULL); -} - -static void draw_debug_status_line (int line) -{ - xlinebuffer = gfxvidinfo.drawbuffer.linemem; - if (xlinebuffer == 0) - xlinebuffer = row_map[line]; - debug_draw_cycles (xlinebuffer, gfxvidinfo.drawbuffer.pixbytes, line, gfxvidinfo.drawbuffer.outwidth, gfxvidinfo.drawbuffer.outheight, xredcolors, xgreencolors, xbluecolors); -} - -#define LIGHTPEN_HEIGHT 12 -#define LIGHTPEN_WIDTH 17 - -static const char *lightpen_cursor = { - "------.....------" - "------.xxx.------" - "------.xxx.------" - "------.xxx.------" - ".......xxx......." - ".xxxxxxxxxxxxxxx." - ".xxxxxxxxxxxxxxx." - ".......xxx......." - "------.xxx.------" - "------.xxx.------" - "------.xxx.------" - "------.....------" -}; - -static void draw_lightpen_cursor (int x, int y, int line, int onscreen) -{ - int i; - const char *p; - int color1 = onscreen ? 0xff0 : 0xf00; - int color2 = 0x000; - - xlinebuffer = gfxvidinfo.drawbuffer.linemem; - if (xlinebuffer == 0) - xlinebuffer = row_map[line]; - - p = lightpen_cursor + y * LIGHTPEN_WIDTH; - for (i = 0; i < LIGHTPEN_WIDTH; i++) { - int xx = x + i - LIGHTPEN_WIDTH / 2; - if (*p != '-' && xx >= 0 && xx < gfxvidinfo.drawbuffer.outwidth) - putpixel (xlinebuffer, gfxvidinfo.drawbuffer.pixbytes, xx, *p == 'x' ? xcolors[color1] : xcolors[color2], 1); - p++; - } -} - -static int lightpen_y1, lightpen_y2; - -static void lightpen_update (struct vidbuffer *vb) -{ - int i; - - if (lightpen_x < LIGHTPEN_WIDTH + 1) - lightpen_x = LIGHTPEN_WIDTH + 1; - if (lightpen_x >= gfxvidinfo.drawbuffer.inwidth - LIGHTPEN_WIDTH - 1) - lightpen_x = gfxvidinfo.drawbuffer.inwidth - LIGHTPEN_WIDTH - 2; - if (lightpen_y < LIGHTPEN_HEIGHT + 1) - lightpen_y = LIGHTPEN_HEIGHT + 1; - if (lightpen_y >= gfxvidinfo.drawbuffer.inheight - LIGHTPEN_HEIGHT - 1) - lightpen_y = gfxvidinfo.drawbuffer.inheight - LIGHTPEN_HEIGHT - 2; - if (lightpen_y >= max_ypos_thisframe - LIGHTPEN_HEIGHT - 1) - lightpen_y = max_ypos_thisframe - LIGHTPEN_HEIGHT - 2; - - lightpen_cx = (((lightpen_x + visible_left_border) >> lores_shift) >> 1) + DISPLAY_LEFT_SHIFT - DIW_DDF_OFFSET; - - lightpen_cy = lightpen_y; - lightpen_cy >>= linedbl; - lightpen_cy += minfirstline; - - if (lightpen_cx < 0x18) - lightpen_cx = 0x18; - if (lightpen_cx >= maxhpos) - lightpen_cx -= maxhpos; - if (lightpen_cy < minfirstline) - lightpen_cy = minfirstline; - if (lightpen_cy >= maxvpos) - lightpen_cy = maxvpos - 1; - - for (i = 0; i < LIGHTPEN_HEIGHT; i++) { - int line = lightpen_y + i - LIGHTPEN_HEIGHT / 2; - if (line >= 0 || line < max_ypos_thisframe) { - draw_lightpen_cursor(lightpen_x, i, line, lightpen_cx > 0); - flush_line (vb, line); - } - } - lightpen_y1 = lightpen_y - LIGHTPEN_HEIGHT / 2 - 1 + min_ypos_for_screen; - lightpen_y2 = lightpen_y1 + LIGHTPEN_HEIGHT + 2; -} - -void finish_drawing_frame (void) -{ - int i; - bool didflush = false; - struct vidbuffer *vb = &gfxvidinfo.drawbuffer; - - gfxvidinfo.outbuffer = vb; - - if (! lockscr (vb, false)) { - notice_screen_contents_lost (); - return; - } - -#ifndef SMART_UPDATE - /* @@@ This isn't exactly right yet. FIXME */ - if (!interlace_seen) - do_flush_screen (first_drawn_line, last_drawn_line); - else - unlockscr (); - return; -#endif - - for (i = 0; i < max_ypos_thisframe; i++) { - int i1 = i + min_ypos_for_screen; - int line = i + thisframe_y_adjust_real; - int where2; - - where2 = amiga2aspect_line_map[i1]; - if (where2 >= vb->inheight) - break; - if (where2 < 0) - continue; - hposblank = 0; - pfield_draw_line (vb, line, where2, amiga2aspect_line_map[i1 + 1]); - } - - /* clear possible old garbage at the bottom if emulated area become smaller */ - for (i = last_max_ypos; i < vb->outheight; i++) { - int i1 = i + min_ypos_for_screen; - int line = i + thisframe_y_adjust_real; - int where2 = amiga2aspect_line_map[i1]; - - if (where2 >= gfxvidinfo.drawbuffer.outheight) - break; - if (where2 < 0) - continue; - - hposblank = i > last_max_ypos ;// + AMIGA_HEIGHT_EXTRA; - - xlinebuffer = vb->linemem; - if (xlinebuffer == 0) - xlinebuffer = row_map[where2]; - xlinebuffer -= linetoscr_x_adjust_bytes; - fill_line (); - if (line < max_ypos_thisframe) - linestate[line] = LINE_UNDECIDED; - do_flush_line (vb, where2); - } - - if (currprefs.leds_on_screen) { - int slx, sly; - statusline_getpos (&slx, &sly, vb->outwidth, vb->outheight); - for (i = 0; i < TD_TOTAL_HEIGHT; i++) { - int line = sly + i; - draw_status_line (line, i); - do_flush_line (vb, line); - } - } - if (debug_dma > 1) { - for (i = 0; i < vb->outheight; i++) { - int line = i; - draw_debug_status_line (line); - do_flush_line (vb, line); - } - } - - if (lightpen_x > 0 || lightpen_y > 0) - lightpen_update (vb); - - if (currprefs.monitoremu && gfxvidinfo.tempbuffer.bufmem_allocated) { - static bool specialon; - if (emulate_specialmonitors (vb, &gfxvidinfo.tempbuffer)) { - vb = gfxvidinfo.outbuffer = &gfxvidinfo.tempbuffer; - if (vb->nativepositioning) { - vb->inwidth = gfxvidinfo.drawbuffer.inwidth; - vb->inheight = gfxvidinfo.drawbuffer.inheight; - vb->inwidth2 = gfxvidinfo.drawbuffer.inwidth2; - vb->inheight2 = gfxvidinfo.drawbuffer.inheight2; - vb->outwidth = gfxvidinfo.drawbuffer.outwidth; - vb->outheight = gfxvidinfo.drawbuffer.outheight; - } - gfxvidinfo.drawbuffer.tempbufferinuse = true; - if (!specialon) - compute_framesync (); - specialon = true; - do_flush_screen (vb, 0, vb->outheight); - didflush = true; - } else { - gfxvidinfo.drawbuffer.tempbufferinuse = false; - if (specialon) - compute_framesync (); - specialon = false; - } - } - - if (!didflush) - do_flush_screen (vb, first_drawn_line, last_drawn_line); - - -#ifdef ECS_DENISE - if (brdblank_changed) { - last_max_ypos = max_ypos_thisframe; - for (i = 0; i < sizeof linestate / sizeof *linestate; i++) - linestate[i] = LINE_UNDECIDED; - notice_screen_contents_lost (); - brdblank_changed = false; - } -#endif -} - -void hardware_line_completed (int lineno) -{ -#ifndef SMART_UPDATE - { - int i, where; - /* l is the line that has been finished for drawing. */ - i = lineno - thisframe_y_adjust_real; - if (i >= 0 && i < max_ypos_thisframe) { - where = amiga2aspect_line_map[i+min_ypos_for_screen]; - if (where < gfxvidinfo.drawbuffer.outheight && where >= 0) - pfield_draw_line (lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]); - } - } -#endif -} - -void check_picasso (void) -{ -#ifdef PICASSO96 - if (picasso_on && picasso_redraw_necessary) - picasso_refresh (); - picasso_redraw_necessary = 0; - - if (picasso_requested_on == picasso_on) - return; - - picasso_on = picasso_requested_on; - - if (!picasso_on) - clear_inhibit_frame (IHF_PICASSO); - else - set_inhibit_frame (IHF_PICASSO); - - gfx_set_picasso_state (picasso_on); - picasso_enablescreen (picasso_requested_on); - - notice_screen_contents_lost (); - notice_new_xcolors (); - count_frame (); -#endif -} - -void redraw_frame (void) -{ - last_drawn_line = 0; - first_drawn_line = 32767; - finish_drawing_frame (); - flush_screen (gfxvidinfo.inbuffer, 0, 0); -} - -void vsync_handle_check (void) -{ - check_picasso (); - - int changed = check_prefs_changed_gfx (); - if (changed > 0) { - reset_drawing (); - init_row_map (); - init_aspect_maps (); - notice_screen_contents_lost (); - notice_new_xcolors (); - } else if (changed < 0) { - reset_drawing (); - init_row_map (); - init_aspect_maps (); - notice_screen_contents_lost (); - notice_new_xcolors (); - } - check_prefs_changed_audio (); - check_prefs_changed_custom (); - check_prefs_changed_cpu (); -} - -void vsync_handle_redraw (int long_frame, int lof_changed, uae_u16 bplcon0p, uae_u16 bplcon3p) -{ - last_redraw_point++; - if (lof_changed || interlace_seen <= 0 || last_redraw_point >= 2 || long_frame || doublescan < 0) { - last_redraw_point = 0; - - if (framecnt == 0) - finish_drawing_frame (); -#if 0 - if (interlace_seen > 0) { - interlace_seen = -1; - } else if (interlace_seen == -1) { - interlace_seen = 0; - if (currprefs.gfx_scandoubler && currprefs.gfx_vresolution) - notice_screen_contents_lost (); - } -#endif - - if (quit_program < 0) { -#ifdef SAVESTATE - if (!savestate_state) { - if (currprefs.quitstatefile[0]) { - savestate_initsave (currprefs.quitstatefile, 1, 1, true); - save_state (currprefs.quitstatefile, _T("")); - } - } -#endif - quit_program = -quit_program; - set_inhibit_frame (IHF_QUIT_PROGRAM); - set_special (SPCFLAG_BRK); - return; - } - - count_frame (); - - if (framecnt == 0) - init_drawing_frame (); - else if (currprefs.cpu_cycle_exact) - init_hardware_for_drawing_frame (); - } else { - if (isvsync_chipset ()) - flush_screen (gfxvidinfo.inbuffer, 0, 0); /* vsync mode */ - } - - /* check borderblank here because bplcon0 or especially bplcon3 may only be written once outside of displayable area */ - bplcon0_store = bplcon0p; - bplcon3_store = bplcon3p; - isbrdblank (); - - gui_flicker_led (-1, 0, 0); -#ifdef AVIOUTPUT - frame_drawn (); -#endif -} - -void hsync_record_line_state (int lineno, enum nln_how how, int changed) -{ - uae_u8 *state; - - if (framecnt != 0) - return; - - state = linestate + lineno; - changed += frame_redraw_necessary + ((lineno >= lightpen_y1 && lineno <= lightpen_y2) ? 1 : 0); - - switch (how) { - case nln_normal: - *state = changed ? LINE_DECIDED : LINE_DONE; - break; - case nln_doubled: - *state = changed ? LINE_DECIDED_DOUBLE : LINE_DONE; - changed += state[1] != LINE_REMEMBERED_AS_PREVIOUS; - state[1] = changed ? LINE_AS_PREVIOUS : LINE_DONE_AS_PREVIOUS; - break; - case nln_nblack: - *state = changed ? LINE_DECIDED : LINE_DONE; - if (state[1] != LINE_REMEMBERED_AS_BLACK) - state[1] = LINE_BLACK; - break; - case nln_lower: - if (state[-1] == LINE_UNDECIDED) - state[-1] = LINE_DECIDED; //LINE_BLACK; - *state = changed ? LINE_DECIDED : LINE_DONE; - break; - case nln_upper: - *state = changed ? LINE_DECIDED : LINE_DONE; - if (state[1] == LINE_UNDECIDED - || state[1] == LINE_REMEMBERED_AS_PREVIOUS - || state[1] == LINE_AS_PREVIOUS) - state[1] = LINE_DECIDED; //LINE_BLACK; - break; - } -} - -static void dummy_flush_line (struct vidbuf_description *gfxinfo, struct vidbuffer *vb, int line_no) -{ -} - -static void dummy_flush_block (struct vidbuf_description *gfxinfo, struct vidbuffer *vb, int first_line, int last_line) -{ -} - -static void dummy_flush_screen (struct vidbuf_description *gfxinfo, struct vidbuffer *vb, int first_line, int last_line) -{ -} - -static void dummy_flush_clear_screen (struct vidbuf_description *gfxinfo, struct vidbuffer *vb) -{ -} - -static int dummy_lock (struct vidbuf_description *gfxinfo, struct vidbuffer *vb) -{ - return 1; -} - -static void dummy_unlock (struct vidbuf_description *gfxinfo, struct vidbuffer *vb) -{ -} - -static void gfxbuffer_reset (void) -{ - gfxvidinfo.drawbuffer.flush_line = dummy_flush_line; - gfxvidinfo.drawbuffer.flush_block = dummy_flush_block; - gfxvidinfo.drawbuffer.flush_screen = dummy_flush_screen; - gfxvidinfo.drawbuffer.flush_clear_screen = dummy_flush_clear_screen; - gfxvidinfo.drawbuffer.lockscr = dummy_lock; - gfxvidinfo.drawbuffer.unlockscr = dummy_unlock; -} - -void notice_resolution_seen (int res, bool lace) -{ - if (res > frame_res) - frame_res = res; - if (res > 0) - can_use_lores = 0; - if (!frame_res_lace && lace) - frame_res_lace = lace; -} - -bool notice_interlace_seen (bool lace) -{ - bool changed = false; - // non-lace to lace switch (non-lace active at least one frame)? - if (lace) { - if (interlace_seen == 0) { - changed = true; - //write_log (_T("->lace PC=%x\n"), m68k_getpc ()); - } - interlace_seen = currprefs.gfx_vresolution ? 1 : -1; - } else { - if (interlace_seen) { - changed = true; - //write_log (_T("->non-lace PC=%x\n"), m68k_getpc ()); - } - interlace_seen = 0; - } - return changed; -} - -static void clearbuffer (struct vidbuffer *dst) -{ - if (!dst->bufmem_allocated) - return; - uae_u8 *p = dst->bufmem_allocated; - for (int y = 0; y < dst->height_allocated; y++) { - memset (p, 0, dst->width_allocated * dst->pixbytes); - p += dst->rowbytes; - } -} - -void reset_decision_table (void) -{ - for (int i = 0; i < sizeof linestate / sizeof *linestate; i++) - linestate[i] = LINE_UNDECIDED; -} - -void reset_drawing (void) -{ - unsigned int i; - - max_diwstop = 0; - - lores_reset (); - - for (i = 0; i < sizeof linestate / sizeof *linestate; i++) - linestate[i] = LINE_UNDECIDED; - - init_aspect_maps (); - - init_row_map (); - - last_redraw_point = 0; - - memset (spixels, 0, sizeof spixels); - memset (&spixstate, 0, sizeof spixstate); - - init_drawing_frame (); - - notice_screen_contents_lost (); - frame_res_cnt = FRAMES_UNTIL_RES_SWITCH; - lightpen_y1 = lightpen_y2 = -1; - - reset_custom_limits (); - - clearbuffer (&gfxvidinfo.drawbuffer); - clearbuffer (&gfxvidinfo.tempbuffer); -} - -void drawing_init (void) -{ - gen_pfield_tables (); - - uae_sem_init (&gui_sem, 0, 1); -#ifdef PICASSO96 - if (!isrestore ()) { - picasso_on = 0; - picasso_requested_on = 0; - gfx_set_picasso_state (0); - } -#endif - xlinebuffer = gfxvidinfo.drawbuffer.bufmem; - - inhibit_frame = 0; - - gfxbuffer_reset (); - reset_drawing (); -} - -int isvsync_chipset (void) -{ - if (picasso_on || !currprefs.gfx_apmode[0].gfx_vsync || (currprefs.gfx_apmode[0].gfx_vsync == 0 && !currprefs.gfx_apmode[0].gfx_fullscreen)) - return 0; - if (currprefs.gfx_apmode[0].gfx_vsyncmode == 0) - return 1; - if (currprefs.m68k_speed >= 0) - return -1; - return currprefs.cachesize ? -3 : -2; -} - -int isvsync_rtg (void) -{ - if (!picasso_on || !currprefs.gfx_apmode[1].gfx_vsync || (currprefs.gfx_apmode[1].gfx_vsync == 0 && !currprefs.gfx_apmode[1].gfx_fullscreen)) - return 0; - if (currprefs.gfx_apmode[1].gfx_vsyncmode == 0) - return 1; - if (currprefs.m68k_speed >= 0) - return -1; - return currprefs.cachesize ? -3 : -2; -} - -int isvsync (void) -{ - if (picasso_on) - return isvsync_rtg (); - else - return isvsync_chipset (); -} diff --git a/drawing.cpp b/drawing.cpp index 74376370..43756176 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -166,7 +166,7 @@ static uae_u8 all_zeros[MAX_PIXELS_PER_LINE]; uae_u8 *xlinebuffer; static int *amiga2aspect_line_map, *native2amiga_line_map; -static uae_u8 *row_map[MAX_UAE_HEIGHT + 1]; +static uae_u8 **row_map; static uae_u8 row_tmp[MAX_PIXELS_PER_LINE * 32 / 8]; static int max_drawn_amiga_line; @@ -185,7 +185,7 @@ typedef void (*line_draw_func)(int, int, bool); #define LINESTATE_SIZE ((MAXVPOS + 2) * 2 + 1) -static uae_u8 linestate[LINESTATE_SIZE], linestate2[LINESTATE_SIZE]; +static uae_u8 linestate[LINESTATE_SIZE]; uae_u8 line_data[(MAXVPOS + 2) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2]; @@ -290,8 +290,9 @@ static void clearbuffer (struct vidbuffer *dst) void reset_decision_table (void) { - for (int i = 0; i < sizeof linestate / sizeof *linestate; i++) + for (int i = 0; i < sizeof linestate / sizeof *linestate; i++) { linestate[i] = LINE_UNDECIDED; + } } STATIC_INLINE void count_frame (void) @@ -1888,16 +1889,19 @@ void init_row_map (void) static int oldheight, oldpitch; int i, j; - if (gfxvidinfo.drawbuffer.height_allocated > MAX_UAE_HEIGHT) { + if (gfxvidinfo.drawbuffer.height_allocated > max_uae_height) { write_log (_T("Resolution too high, aborting\n")); abort (); } + if (!row_map) + row_map = xmalloc (uae_u8*, max_uae_height + 1); + if (oldbufmem && oldbufmem == gfxvidinfo.drawbuffer.bufmem && oldheight == gfxvidinfo.drawbuffer.height_allocated && oldpitch == gfxvidinfo.drawbuffer.rowbytes) return; - j = oldheight == 0 ? MAX_UAE_HEIGHT : oldheight; - for (i = gfxvidinfo.drawbuffer.height_allocated; i < MAX_UAE_HEIGHT + 1 && i < j + 1; i++) + j = oldheight == 0 ? max_uae_height : oldheight; + for (i = gfxvidinfo.drawbuffer.height_allocated; i < max_uae_height + 1 && i < j + 1; i++) row_map[i] = row_tmp; for (i = 0, j = 0; i < gfxvidinfo.drawbuffer.height_allocated; i++, j += gfxvidinfo.drawbuffer.rowbytes) row_map[i] = gfxvidinfo.drawbuffer.bufmem + j; @@ -2827,17 +2831,21 @@ bool draw_frame (struct vidbuffer *vb) clearbuffer (vb); init_row_map (); memcpy (oldstate, linestate, LINESTATE_SIZE); - memcpy (linestate, linestate2, LINESTATE_SIZE); for (int i = 0; i < LINESTATE_SIZE; i++) { uae_u8 v = linestate[i]; - if (v == LINE_REMEMBERED_AS_PREVIOUS) + if (v == LINE_REMEMBERED_AS_PREVIOUS) { + linestate[i - 1] = LINE_DECIDED_DOUBLE; v = LINE_AS_PREVIOUS; - else if (v == LINE_DONE_AS_PREVIOUS) + } else if (v == LINE_DONE_AS_PREVIOUS) { + linestate[i - 1] = LINE_DECIDED_DOUBLE; v = LINE_AS_PREVIOUS; - else if (v == LINE_REMEMBERED_AS_BLACK) + } else if (v == LINE_REMEMBERED_AS_BLACK) { v = LINE_BLACK; - else if (v == LINE_DONE) + } else if (v == LINE_DONE) { v = LINE_DECIDED; + } +// if (i < maxvpos) +// write_log (_T("%d: %d -> %d\n"), i, linestate[i], v); linestate[i] = v; } last_drawn_line = 0; @@ -3054,13 +3062,12 @@ void vsync_handle_redraw (int long_frame, int lof_changed, uae_u16 bplcon0p, uae void hsync_record_line_state (int lineno, enum nln_how how, int changed) { - uae_u8 *state, *state2; + uae_u8 *state; if (framecnt != 0) return; state = linestate + lineno; - state2 = linestate2 + lineno; changed += frame_redraw_necessary + ((lineno >= lightpen_y1 && lineno <= lightpen_y2) ? 1 : 0); switch (how) { @@ -3090,7 +3097,6 @@ void hsync_record_line_state (int lineno, enum nln_how how, int changed) state[1] = LINE_DECIDED; //LINE_BLACK; break; } - *state2 = *state; } static void dummy_flush_line (struct vidbuf_description *gfxinfo, struct vidbuffer *vb, int line_no) @@ -3192,8 +3198,9 @@ void reset_drawing (void) lores_reset (); - for (i = 0; i < sizeof linestate / sizeof *linestate; i++) + for (i = 0; i < sizeof linestate / sizeof *linestate; i++) { linestate[i] = LINE_UNDECIDED; + } init_aspect_maps (); diff --git a/include/events_normal.h b/include/events_normal.h deleted file mode 100644 index bc1a8495..00000000 --- a/include/events_normal.h +++ /dev/null @@ -1,92 +0,0 @@ - -STATIC_INLINE void cycles_do_special (void) -{ -} -STATIC_INLINE void set_cycles (int c) -{ -} - -STATIC_INLINE void events_schedule (void) -{ - int i; - - unsigned long int mintime = ~0L; - for (i = 0; i < ev_max; i++) { - if (eventtab[i].active) { - unsigned long int eventtime = eventtab[i].evtime - currcycle; - if (eventtime < mintime) - mintime = eventtime; - } - } - nextevent = currcycle + mintime; -} - -extern volatile bool thread_vblank_found; - -STATIC_INLINE void do_cycles_slow (unsigned long cycles_to_add) -{ - if (is_lastline && eventtab[ev_hsync].evtime - currcycle <= cycles_to_add - && (long int)(read_processor_time () - vsyncmintime) < 0 && !thread_vblank_found) - return; - - while ((nextevent - currcycle) <= cycles_to_add) { - int i; - cycles_to_add -= (nextevent - currcycle); - currcycle = nextevent; - - for (i = 0; i < ev_max; i++) { - if (eventtab[i].active && eventtab[i].evtime == currcycle) { - (*eventtab[i].handler)(); - } - } - events_schedule(); - } - currcycle += cycles_to_add; -} - -STATIC_INLINE void do_cycles_fast (void) -{ - if (is_lastline && eventtab[ev_hsync].evtime - currcycle <= 1 - && (long int)(read_processor_time () - vsyncmintime) < 0) - return; - - currcycle++; - if (nextevent == currcycle) { - int i; - - for (i = 0; i < ev_max; i++) { - if (eventtab[i].active && eventtab[i].evtime == currcycle) { - (*eventtab[i].handler) (); - } - } - events_schedule(); - } - -} - -/* This is a special-case function. Normally, all events should lie in the -future; they should only ever be active at the current cycle during -do_cycles. However, a snapshot is saved during do_cycles, and so when -restoring it, we may have other events pending. */ -STATIC_INLINE void handle_active_events (void) -{ - int i; - for (i = 0; i < ev_max; i++) { - if (eventtab[i].active && eventtab[i].evtime == currcycle) { - (*eventtab[i].handler)(); - } - } -} - -STATIC_INLINE unsigned long get_cycles (void) -{ - return currcycle; -} - -extern void init_eventtab (void); - -#if /* M68K_SPEED == 1 */ 0 -#define do_cycles do_cycles_fast -#else -#define do_cycles do_cycles_slow -#endif diff --git a/include/xwin.h b/include/xwin.h index a5ff47ee..7a6efe32 100644 --- a/include/xwin.h +++ b/include/xwin.h @@ -131,6 +131,7 @@ struct vidbuffer }; extern bool isnativevidbuf (void); +extern int max_uae_width, max_uae_height; struct vidbuf_description { diff --git a/main.cpp b/main.cpp index e20007df..a42cc5f9 100644 --- a/main.cpp +++ b/main.cpp @@ -150,10 +150,10 @@ static void fixup_prefs_dim2 (struct wh *wh) wh->width = 160; if (wh->height < 128) wh->height = 128; - if (wh->width > MAX_UAE_WIDTH) - wh->width = MAX_UAE_WIDTH; - if (wh->height > MAX_UAE_HEIGHT) - wh->height = MAX_UAE_HEIGHT; + if (wh->width > max_uae_width) + wh->width = max_uae_width; + if (wh->height > max_uae_height) + wh->height = max_uae_height; } void fixup_prefs_dimensions (struct uae_prefs *prefs) diff --git a/od-win32/cloanto/RetroPlatformIPC.h b/od-win32/cloanto/RetroPlatformIPC.h index d2179860..31dec8ee 100644 --- a/od-win32/cloanto/RetroPlatformIPC.h +++ b/od-win32/cloanto/RetroPlatformIPC.h @@ -8,7 +8,7 @@ : version 2.0 as published by Mozilla Corporation. Authors : os, mcb Created : 2007-08-27 13:55:49 - Updated : 2013-03-20 17:15:00 + Updated : 2013-03-20 17:30:00 Comment : RetroPlatform Player interprocess communication include file *****************************************************************************/ @@ -395,6 +395,40 @@ typedef struct RPScreenCapture WCHAR szScreenFiltered[260]; // "\0" or full path and name (Unicode) of the BMP file to save - filtered (e.g. scanline effects), scaled (e.g. line-doubled and 2X-multiplied), clipped (overscan cropped) bitmap (i.e. as displayed in host environment) } RPSCREENCAPTURE; +// +// The return value of RP_IPC_TO_GUEST_SCREENCAPTURE serves to both indicate an error (if 0) +// and for the guest to process the raw image (i.e. to scale and present appropriate PAL/NTSC +// options to the user). +// +// If the raw image is not the same as the Amiga bitmap, then out of necessity the flags +// describe the properties of the image that is sent to the host, not the Amiga mode. Otherwise +// the host cannot process the image and align it properly for clipping and non-raw overlay. +// +// I.e. if a PAL/NTSC image is set to RP_GUESTSCREENFLAGS_VERTICAL_NONINTERLACED, the host will +// typically double it vertically. If the image is already "deinterlaced" (doubled), the guest +// should set RP_GUESTSCREENFLAGS_VERTICAL_INTERLACED (even if the Amiga image is not +// interlaced), to avoid an additional doubling. +// +// Similarly, the RP_GUESTSCREENFLAGS_HORIZONTAL_xxx flag would normally describe the "real" +// Amiga mode, but if the guest can't send a bitmap that matches the original type then +// the flags should be adjusted accordingly. E.g. if the Amiga mode is Lores but the guest +// is sending a "raw" image where the pixels are doubled, then RP_GUESTSCREENFLAGS_HORIZONTAL_HIRES +// is expected. This is also the case if Super Hires pixels are halved. +// +// The top-left origin of the Raw bitmap should always be as if clipping values were set to the +// currently-agreed minimum. [this is a "bad" explanation, but functionally effective] +// +// Sample raw bitmap sizes for Amiga modes: +// - 752x484 if the flags indicate NTSC Hires/Interlaced +// - 752x576 if the flags indicate PAL Hires/Interlaced +// - Original RTG size if the flags indicate a digital mode +// +// Different sizes may be possible (e.g. for "72" modes), but the left offset does not change. +// +// The top-left origin of the Filtered bitmap should match the origin as displayed in the playback +// window (i.e. net of clipping). +// + // Return codes for RP_IPC_TO_GUEST_SCREENCAPTURE #define RP_SCREENCAPTURE_ERROR 0x00000000 // non-error is always >= 1 (because of "MODE" flags) diff --git a/od-win32/mman.cpp b/od-win32/mman.cpp index 526c9acd..1608c54e 100644 --- a/od-win32/mman.cpp +++ b/od-win32/mman.cpp @@ -198,14 +198,14 @@ bool preinit_shm (void) } if (!natmem_offset) { for (;;) { - natmem_offset = (uae_u8*)VirtualAlloc (NULL, natmem_size, MEM_RESERVE | (VAMODE == 1 ? MEM_WRITE_WATCH : 0), PAGE_READWRITE); + natmem_offset = (uae_u8*)VirtualAlloc (NULL, natmem_size, MEM_RESERVE | (VAMODE == 1 ? MEM_WRITE_WATCH : 0) | MEM_TOP_DOWN, PAGE_READWRITE); if (natmem_offset) break; natmem_size -= 128 * 1024 * 1024; if (!natmem_size) { write_log (_T("Can't allocate 257M of virtual address space!?\n")); natmem_size = 17 * 1024 * 1024; - natmem_offset = (uae_u8*)VirtualAlloc (NULL, natmem_size, MEM_RESERVE | (VAMODE == 1 ? MEM_WRITE_WATCH : 0), PAGE_READWRITE); + natmem_offset = (uae_u8*)VirtualAlloc (NULL, natmem_size, MEM_RESERVE | (VAMODE == 1 ? MEM_WRITE_WATCH : 0) | MEM_TOP_DOWN, PAGE_READWRITE); if (!natmem_size) { write_log (_T("Can't allocate 17M of virtual address space!? Something is seriously wrong\n")); return false; diff --git a/od-win32/resources/RCa02620 b/od-win32/resources/RCa02620 deleted file mode 100644 index 9bdff419dceee9a4027625663fb81d74c748a213..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 212576 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 hHs)#6Hv)2(KXh-K8c<_HL zetf^umWw47Z-iHj)~i2B;Y3YaPh%cy>4zdw;PTpw-tI9I)8+gGnb!Nwm*d;D9y1Xq z`KaXP;2GA|qQ+;1;=R@;`XzbL+;~acA8koImKr6jg+70fY-i-1EIQZWj4DqwVx2SF zS7eJy+7a9Mc3t0z2Mx~=r)0iuR>;16uvByFOh>8{YHH4(Gouvladzp)g_jOW#{P}X z&)iVUN6+~@M!&%?`8RIH^l#LJ5@X^yem)J%=pCOw(s_nn)$M~(uVXaK$P3mh! z%Z{GDEbw$!0cahs1MRkKjko@H53xG$HsOVhc{A{KJJu<_L5fowt6ONPNyk(9ykyT1 zWm3)W$MIeJx0B*^((}XTmsexe$}DmuhTqBLW#9P2;?E`j!cTC9k>0Ls;XZRSXXAuJ z=OP)u0=jy_-6n{-BKgq+^50~Sa6V4fFX08+cd7 z=7c~J3VBpVIM7zpD%mAiT#Zq$7e32a579(+#)|2yk^4p(=sZStl+G^T)HODU;SRny z+37P&eithNi&NUc28TNj;+-D?!pbgaX(j2%w6dL^n2pQ{OSv8ovMcCOlsch}y;>T8 zu_pl?&clQ?$%2pK`!%qE3l;rRw`2CWYQKT_YXowYgF_LkS3Fv z*eu$IXf8C1UEJb8U3ao~5D_g)vj4=->S+v5D9H;fAYx#D58o3l1sN3`>F2`4ebzcZT$vasiTdl1^%gHNQJ)3uWPw z%ODzL>>SCvnaW_OSNRc-iaul>=P3wk@Q3*UU5!3b=K6oYF^Km|E1pBz=*Qqb z_i=?kks6{L%MasE)FoS)XN<-EEW_t0rjlO+UTlrD9^taJ-g0P;fJY=Ls*}#zWu4GJkKKS(DyWG3pOl}}^M=Yupp(#Z=K4{bf!~YoTg!=Y(%P?S zpq@YJ0g8d^@WKycp6&Bt4JsNytdv}&pEuqp)nVLu(nl-gWwNqMC0lzc-*Ropcy+Wx zr>DP}Ph{;UoiKn4761^!wvczz(sR2m`@Fe|v~>HbXGheWe>95fICj+f{~&UR8SuTbZU)gYPOA~EVTEjlhW_0El;l{=S|M4*O&Y)8Iri-DQFdX zkk{4jd^^S*L#**d9M0d@^3~r#Wsxthb;>^DhK(WLBi*%y`#=tn#}OFr4m z!t*y}HYAU9DDuzJH22+7c~864k>ow#;NPb+@Yti^M)|79Ye_)#bnY1WtKW&T_M>5E zOZK8M)Z+kn%+0AB1;zQqtInNFi(PsP{|N~T?<;mEO`j{nVxVHgwm?50{N@D?I||V(;W0i53tW1NTz5`%*b`L34yW?QSWb$V z%l!T{qWSxE9GGespF-4>g{*oQI3-sW-%ghEbj9-++U_rq^-sS1qoO%9J7+ufDGQKj zzkvhSoV)mB5NHE)WV)&EZP1%6KWQvtQNpD-le}r9zu(k(kFm-Mkkg7%!|%vks?q9v|Mf$D~?VbnABkkL^_8bGVxNbY6v}ka62v0rh+FP5Ssq z=)0S5?cYK#{Fm8q`;I^!8PZ{&_qXrb=Z)>I^Q0aB;XEq<1{#f-&O6%r{hY?S{ehRg zPrkoeI0n9v&a3~b8Rn(kojrSXEmgy*woa>UtKrlSgYF#nW3BD(=SC!dWPU_t#E(Z* zg|W}Q=es}kRpITr`cW8@ycD z`H)ol(lZ=Aa}czO1xk4d^2q)EH9mHH?Gdm_v{XA*-W*RiIM>Ch-~RK!E*T>yWt@}PtM21K zmtgUsH;8-V9q{kc$Y2CK)4Qr2oi*mzU<&IOjoFT$=SoZSxZ^=TM>`8UkzZNwU~UHY zXIHK*J(l4is=A!TirvW!Phwm=c)BAmN?~A)=lL5kdbyKvt!7KJ(uAOBwX!rAS_me&4ZoevWOrh2% zar)b?>L}Mf%bY9t0R^NZ(;LMck}m&epom2s1J*3Nakigns}`2{kNK{pd= zd#y4%&W^0B(JtE_O&;YiFhDMVA`k0uK%O>suHi*DXJQCH#lL-TUf=0~{?=_X)TSfB z{I*wO>p-!*zLV(uIIjZ2^({R~X&y-)THe%S>^UmAG&cLB!dG{=jK^lzL?p59cNx2` z+pv596GSS!_U#x!;-Ks4^!j`QRo#+bZ8LxY`*You>fmS7Ba5T$qJ<@?SS^K88Yn`61d*QTq_qf*#J^HXE zsMkX7K=b5b^%`N#NbL+7@98GTO;O~2)Wid^Mfn0P=4)K}8P;jO(y7H-ns`|x*Iza> z;h)hF4hm!Lyxm>>i-_+*XFe5fskR-9PK;E`1I?5n;6+{Gi8y{=Ns>7k%Y8%p$ynxp zR;1CF8%g#kv*3kZ& z*aY6-lDa8Ddmc_VgB$nJMJ?XYWJEZqQ-&6DWmsm!Zi%HU*1Lp%^+wWa+uH%C+jv)Y z#YjYf+i~2(lh_EWQAG(AhQu@TqpoK7Te`K2esgWtOspm1&3I=-6f+KR927yPFZpfw zAMA)cgMXGMeX8s(bJv1$ZkG8KUsis{+wv?Hnlq=A%YZCnMC1milt|`&E#tRz+9o>0 z%g>WKsLA_S3$I%-Z+@Vv)L`B_`_Y~cgJS70;T{y|5>NIlu6!3ZIq|OQ)?k{yMhA}=*b4Q ziUR@HZKDBhubJKer1=O2R9T5X%oW9xMyMCUX zAiITiJwbon`dfC)2@g>b&Z<F;~p03{&+rRY!iopFXZ|fVfb1E-T8@<7B$) z+hyD<@jlt>zb!fuzW~U*2@jV$fxikHUGX5eK>g;3|8WZvb?N_&kIsTeZ>oDToeQyl zp2QpMgf0n0gz@rpqo=>|bM7sMrB4)!2!-D1PkDq-vL@*~f?bC;keq%M@dTr^NE6|RS@_&T^uT613h5W`~xwB|1J zeH}Bd8UGKP{a~N$GCp*H2kM*0(d3tdw*DHLRNTf6`ELD6w9|P>yN3FDI`-|?^P@^y zpfPuq9~YC#Egh$jkWV6xmc9RLYS*mZppAHaqWtLRwZStt4@hM5(N++dzO*azX--C}npWj3OzDDT-thWGa=` zFLWNOF3)wpz*(RF`04I@-Z226vJ6Hd5V6CDGmlmP93ID*@8Y|_W2^Q3 zPd9#ycbn_|{Nx?J^+SRY-`?KX+c?-b-1vH9cjNZPgN>t&{f+DK?ryxkzj1ftyLjgy z{=c_zE#A2suf1zlbpC$4I{)6>xEcFxLi~q-*{hA8WB+dhR>0vfcKvPqe>--)6Z-@n z*W>-m@vnJ4<0tYcApEzJ@8#1tf6(%Zge&g?PQs2w@uH@W&pr@b*^HBZ8I%c+ISzbi zpZIZ$nl5czJ$dhWob~3$Kb=5MTwG3)E}?$g-IrJ#e)2By4ewqnJhf9d7&P5Jl{ZuAQhgc)orG~%XJDbIVG^{IKHWU z9LL|Rgi%=!-(l1j@q;Y+_2ko^0QVC6+8*ddL9`0v}fj>fcw|I^JNIkpZRgX{9VtiH)Fr| zg8%Hrx$g(u4|-NGf7ZVQjD_W#^iMtWqu-3p&ED5H|NR8_)nnYW{ohM?wi6sXpK#Z! z`TGao(OJ9k-1DMK4gIWs-Up$DBXPeDxcASz$h@x-bsYt+zwX_&XGfQQ7?QVp1#?PDMu_g7;q1_J(BYA~R!;K1~`%_uTsd z@dv#)w#=@v)L!-C81m#^%)B2qYM!P2YW|)dho*-G-o4*H1w}FDoseSE)4SCo$h~Nbu*$ z8o^uAy@DxnoR!R9!Rx@bewa&Bz7gZz4EyeO&>CKX_RsuzrORV0JWKwW7rlEQnzvlZ z{53Fp|Gaoez`6T@aY&ZcNwlZoEdl4SYGnP?r(Rl|pNDpDTkd>WnqG}p=ihi!9>>qq z1Y3Fjz%hT$?{bG@&=UHq1Vje8IIEF;#25*8n5QU$!j4_{&wnGhJ@C)#UTl6W;ylLq{Qb`_ zHa~jPjcOlWL-+ofzrA<9Gk5;2fcjR?-Wjhs|E*Z*-Ck%dGXLJJ`GtSr`(EHh`^@I= ze|y&a+sSwEAh7Ow=XuSYpIF9j(h^FY=gW;N={@UE=kIr^t+Bez*v0eES@APJd%yOk zF8Afem+3RG3Qg-y;8)XX#7_dxcn}-`9eXqMKh9bIU)lI7;t~8!tVK~LIKX!&w#ROq z%u)LGP8#KU%yTJvgxectwny*qUgygviCP78G@=b={k3 zwQvez)xfd-*@{tfEMzl1eJ{=WG^}0XE<^#3(~RZ<><#^zQ~NkcM^?g_puv50g0=8_ z?XsTHf3ZJB1M;l4wf?P|4|v~uKN>SK&!w2><2e5>((g+r_5tu!T)un1-h;-p)yQbb zTSj9iU!+}K4Xf(o*yFW;5%vJz*^A%yT!Ksf)EoiN!_EnY7)SgJUNEeI5_7)kcwYDd zjG0+n4h+F#NeuH^;y%1zTbo<3*6*i1UQK%?hRN)`1P$%Wt+V`Wg=fh*>NG$9&7G#8T%RTTy%IbS%*7ATJWX>P zz6(Y+e?*6`-=E;q@G`v%4qirG|HsDvitp_N_j#J$C(27Sbu)00813JKQ_4U0N!avc zk;q&2eB=9M-*3h{jEjZ;Yx<@}s&N&++1|-IK28#1E5^r{PK5Yn!fVl@sSQY6k9FON z=fvHh$u9c&IAjji&(-ul_%0rDIn6T;ql57L5tDuz6oe0yd?vUtv1H;M_K`?XfD9bIZrFwC`x#$#Dv zkw}td-oniMg~Tw;vGb|&2fYMYV4i56#i)$;TarQEYt6SZ*J972#(7fcM#3CrC*ko! zZ|T+`+9#Re{aKp3d5+c?eezANY5AH*ZlC1miP!ifg)i3wpU5#G_V^$$tJD@2mGOBE z{ScNcoGa(|gG!XEc^Fg!4@U~1-IGy}p9!!p3PPdD$22}yY z(h@mayXfpJoE)jGF%?bydcr?`11a%&PV3`zURX8Q8Ip6-KJ2HN!|xUM_c@}4Gs;fP zm@$KS(BvdfK2P)8c4%53%4f7K;it%+f~v4l@d)0G*Na*kVD+&5b|dMDFOnR0B)r!9 zYhIxJ@&D%uzSFqCREeq+M8}1I-V?+6(Poi$2rpnU0z@9!&yPShFQzZv}n%f(H4wxEKBquE`nOzc_ zTx0wSNU1rp>APYEB#`zaTTR&5KgS$Axsf;-x~gKI>zEI@;A~M>?EBb@6jiAUiLU{0pZQ-_psqtR^C1Ggm%|c*mx>F3ljD?k zKUt;9f*qnd@I;o@XUX1LEvJ^wE4fRa5EPc(?jFV1Xt?*|RsQ7T1^rsJ zE?;WNwdY-!EP9m%C%VO+vjs4`YpiH|pVS^u!9qm}`*%GIo>V+jcol&GRhuOguNc)>{Xl_RkCm645>EFQ5gGsx^0y8>`+=W zr&{iC3U|k2UGH#6SFqf=`W~V{7S227-^lk+Ve>dzIo9OA2%%wHxw;j46>mkUaq7RN^K z-~oKA#)_$Sy|KE4lJNpaff1jb@I`hx=9M3(wGxtfcD%eq@$vPoR+3!~+mDs|+@*0# zijCWzJHZpIg($rc3*867NK3p$fTP_jjkVZb|QY-Q(wbH&(39Aol|5NPrUJXp_{u+x7;F zJOlo2xTWIbygTib@269y4!efZ-IxX29u1H9{@n?50R7gM{5LJ0Tqdgs@Gf`b9 z-1D@xIAvl2NqOv$+ScNx%4_W;YrTA*bMg7uyE`VUMfsBE=u2hK9_V{KgAQB$IR3p2 zUZcJga8K-Va-y1+xz;VKPMN@#mR>oWRQ8uTzx2g@$zo)Mj{DX%oYSMe%*Hs#@c+z) z{VyRe%F3@SBb+Z*=XH<^SLUe=`{>I!6}XT8*70JrapfhC+l4z}4N_HG>-)79#@NaX z%J$4O3wzi%)o&w`&u}{^MwoaOoaKw;MNrI4yPnHeya(j$y?`M3Y2qu=VI})BS1C2o zFY4_s~4o&*OZ7=Q8IyE`zsEynSVL z@@9B%blPMUf^DUC==BQb_6BMu{JA${)vNRZDpszXVB!Pv=t>_P$6I&;vH2mqg}ce` z03|8TES+kK*KbjtgswyO{n_Czu!Lrp;Y!|xv6rkkiQtoy9-5q%QYDlrK%H^=o1yku}s8@zZS#9@sr+* zlO;nPOP)xkDr?Yb;DXlEh9sZQn;dG+`83X(na=XOWo<2c-s}R|DGgkF)qgE^-hCbu z>W@l~iTgKB_mz+faK3yc%V)?-$Dix<5bR1mRC^zwV*X{{Ips|^WJxs?2T;6Bwu`bTr+Uk^1N?gJ9f)TS*DQ|jpy>gZy@AAO*E$bd zQd%osllEH0Z`QF^WezR2R&d5R`^|3qS*tQ^7F#QPy}efO ze?4pcGU=Xk*NWuG_6m6rbhVTmZ^x!N?{t*e_GFy&Bld12q@+e+&;Cl~jiD%dibxxBi!a1hD%g z#YR7gSGf*S{i2B%_)IuM;Cm2HJqwG6j85eakooW;)xLwrsz<|L2yW*a7mniu=_ra_ z!kroU6Kgl+Z0-t($MNZgdSr@Pj2Uo#MnVI|_J0=tEAv+4)n_U=)Hy3)?-+;Zrl#&J zQ^{STWUk1cLnHShy6$rl?jtX}L%jo62E+AiH@wJJz!qp$)zjy(>}fBE)KJpMrvW9& z(HfgGC+dq}8BgJul#a_vSA;%l<2cACpM6e^} z6A?u|4u0@BxWd!mE_C};?spqPnafY(u#3T|sT~<2$}^h}k^aac^~_ZND7*W#^A*?^ zo-lb}*_UkAsnHSB*Hl^ptF9(~r|vB1@nin;sXjlgCFf1xy@9jJhXZev_re*DtBr3O z61PKMfyE`});xtQMfizUr%F}X-s2WyIjUwPN5UDEr;R;uMDXQm+K+P3*&SSB3UBVB zcs%pcC6?vc@GJ1meA|72$9-mA!HuLrqDzn=3WqA;U!N+JB->g3u`dED;2T&shT+m5 zkzw6(%>6aAF1q!SWkZK?B=1h@vkR}bKNhT4M(=RfF7nsdMXBA->A^LRGP~9-ZsY12 zRWG=9LLRMgJR(#4>%o)Z9CRM?*{ByrEhVQ(HgqL&NlQG?{HO1)5$#zcnkt)-pZqjy zAb{ceJT^!cavxIGPJEj+iN8yb=lEy4Zb~1+v~QzYDzD;UFI(3yG`v6eu^&zjH}_Azu(Qd zw>lzzwy@{q(@Bn)i&>(<$KYF2BpUj(ZZgFF_sLI=?uS3U4`kp z#i*xMC(T7Yh26dl*>}*5BJZ-D!K-PKb|*<%>}I0nSkHK$@C7zG2DeQdZu~KJf&X(| zyMX4PemttvcVW&~_eCssAZ}nDw@U9)J^^#Cd22`4p{p5{+0CxE)Uc@28XY-S3v)0= z8NR|CG?qCqr|UAFKdLuNNK=asrXMDqd<@bQ>ekIfOJK!8$bQAGxEZa#cdavWkfGve z!Z)e$$QyYae9c`b@KMqQwd5D9hyFXc4!{nX|-8E8;r*<2;WlC(+!RiZ<9iEmhv zN)!jSfE&Pc95=7Ozoow1$@S1{)ESY{z<248SR&RSr_Rvshb}lVlJeKl7+7<;@~OTl zjg|FX>A1+HD*+Ygbl4Xq$hvoIXn)$bzfX~oU9XgoHPRXv$R4l1ob)zvIN{!EIGn~6 zhts%=YjI$0$>A6Y{p~~1*d|IpJcE)0X)A4@}nE*<`%AyOF(W%6}u`&yJ=> z_}Y8P7(@hKkaJIRWx>n4qJBJca?i$b;C}esehJ@W6Bo#I=VqGQDF?Id-|Rkh&Rg*c z(W^R5VK@2Ar}!~T2xV{P=SgD(KJbJul3uZ1OMjfhlsCDNt*(gUlkf;Deo8z^a8wRN z`8@gR-2CP^W&Reran8nuf~Y##Ot-U<35&mMGeveZw(?{-qdLP{x3Z|OCnqC)5eTA_ zS-wxzPs_EFX{UUC?x@pkrDOY41;l3ZqT@S%5#ReL;;uL1-yh=j(7t$*S^|2;5zoCG z-?%Hh^s6&9riIieJXFFT)SrJ^`X;+KmZoZRhkP~lF! zdVRjA@2@NNgM~syzTz~tR5>xNxi8+^tUY#SiTvH%8ay@TOE&|}b$(*L=!NBK1UcS4 z{rii@;~4Zhg%j4iI_DS6(QU{6&NuO0^a$cuP|e+leo~V{uJK-s02h)6 z)1MIG5Q|U0EVt(-_CnmcHdMeybVqcN5cM_yJvXR;hN4?9gF6l?N0DqcxJv|gp++2 zCyq71rx)ViH}S9D@7VeB&Glfhy!`WbDqTKf?AJm2NX3I#>9u6(ly_{G`$JCFPp@`o z_H39!osT{}AC`{cFE{=rof)<#R9fDE2p59e=4w#7oKsKH+$X%3%BP*AGh9oW$hvkb zx}3jT_r@$Sb&MyuqPqzdvi8N*fCi9*LtE=8N5z8X<{j=5=Z2-9lSPXat2$g&-sd%4 zDEK7jq5gQB6ZZVi@%OX%CO!_WV4P<a)Ac36YO}y{&U3mhm2U>Mr&GPE$^27Ppze$9zqXRpDW%PYfN^&wX{o=VccbZJ zX}i{u*JD+p<9aF;MPL*7E6P_^E4TwcsI^xlA9sw^w=b(&no3M!`@WA+R>9Of8I7F1 zzU&r%0;3XPk`Ml@{l49?daXU@U1BNPTPB#)5&O9?ahyq5AnzA(CakZs%a9z$E!z#` z5o7mXh<{k&(!I*8^jcEO+Le}t_gYq`EF>Z#rPbN(VZt9FieyINEPBrUcs<>>1PL$bTFmt?)PI?n443fbC@YnB+7cLirF?+v!MMKNx7 z@&E@N*BXvx)_Qp}&)u+ulaJYktEw$h#{tvS#lUa&IJL5i#CE8?OzKx0;qqy@@$QyZlcC8CgQtk!kc> zk8FA^edA!oY1bTMOM~I&NA6iNFCQV}Lb)HsaMX`PT*5b)^T|3g5lTKyH_ad7M?KaK z0;j1uuTP;qUuE6sPAkqAZz|EVY3JKtRi2^49co0*h#tU&xd-L!&K&M0{b$)zFZbmR z@?ezcMcpjcfA)AC;aza5rU%>fM#KoaYCpx4hze0(#a-Fpr1TCn?yP%IbqWSdvB!Q4 z-v2Uwl$n5!1D{DV67IF239^#wG5=vi^ssZWOIb&T7E+aeWA@p6y{nv`nZb9W5|ZPh z*kPN%8e16&n^PGz4%34;Q7HInz!Hh{H2EIL$Z)J;3UtxM_TIy|tZ5W<+4=fmtW^MG z_jeGiRi$&*kiH#wD_GMfP<|if?e#&ppO!KIQVy5O4SQ z>Vvd9Ze_TNOURBD7Oe-Wo;mXe`3j`{3`208T;Z4C0I!215bMr7_jrKU68q0Qz*P!@ zpy+Wu5Ijg(2YZRbNZQ)l0@oRa;A!($q!pC^>i`_H%)&Q|)RN@NT-7kej#?K?o2w|f z>Un}Mb`^eo^)kT=DjwTU=~R1bcZRI}mdfI^S9Cp)`7~s?I!^_hgOVLz@Naj$ z%T`SH&aAh>)yODCm(E)3BKF>VjW(~0HQ1`rTGT^qz5I5W6*nUx&^J~nXT@*0>3UZ` zPIwAK#zcw$gkCRu!Fl`kS3WcDJ6w;CE$`EQ5-@bSznAM9ay%@mdRJB{Rl)Wexk13uEoFK4mtjy9x9tmiqOnk3$bRR zD?W|!we&@0@tUBYIVww+H!`!`H*0!q7X9EKCpJ4AWh}7?ZRUP>tI3V0dm;A(Abpg# zf0*R+)5v+O^Y#zp9o;2?T*HDTpOefb` zr*~quoK;eKA^NiP`};gWPiP24x3J;CTR4dG_bv66FXp-ob`9R5Q}4#Ut|v?#r>grw zRYakh)?rE2(yu>DE76U(Q!K%$TE3sl6;tx`pwTPt<@^)$(XooD@g48RZjZx@gI<|) zriS*<36Qq|XH#ClI`&U)iF(%Ej&pa6fEgt}oRhO!XpkNFGIFMe_OJ6-PqXRgKh-iR zX z6Pg%ViZ4#!+Q;35vB zm9dAV3ICH6m|jUlhGyNB7)c3t^9;aO_`28(cRR3xn?i0UxojOxaunVPH=kP%br5*h ztcA*RSpQ>OoylUecqjBVAh-JGsMcv#?3DYFL|S%FXw%#a*qkZv3XMbY>BaVi#3dIO zKXi$0NW8lV8_@EoChLb@pH7b5SnA~1w6=2L_ERfy!SnN0iMxFFWo4Gny$={mi+DHn z6v`{GhoL;Znm@_9%33O3IL$t;kx|!(7SbK3D7m1bS^V!RN-$`K0D)jnF+upL3CgonY~{OwZu&Cxf;p>`NCGyGdanj0&%{i{{44_?lG_s$JB zY4N88w{f{gEJwFP=*CoG9=9#Lifqsl!|6Yu4%;)Qy8xDf@(47dqlo%kn6622qK+u*knjw2us=uKl~=$a))+SI~`7VNzmw(33!m8Ani+W9&B#$SaiK1t$rGm(3{+A=FK3dV%D#Ms@B8V z(Pg+R1#M&hJ#RLLLh^$nr^DIDEy-pES_#9FKh?XUvPqJQ?7rn#Uuzt&D%)kR>~Kd`IxqgQ%j~Nxy46<~-;w!xMV$ zwDyFY631I?S7p>#6|(B=MMW~Vk0Hg&+7e4@@=A^OpM)O3`*bd#@)&u6v{yy4`WkEo z_u5JCz6nWA#;-?G-L$IUyP%2%q}p+GS?FXjZX)VITd8x8*nPVybDMGhYY7r zgBG5K9Zs!CZAohPHC><1F7b;<`)k(0XrJSn#Dk=n)ml7xZk!wb7bG#6CHyu8X058^ z)3sJGl^c34avKf{*(hBpcRp~{vi#5M;*8_)x*fRR4J|`T{%ZLu;OEGrbwCUsR zyy9Y<6LV&Wv7&WBY+S~wZx9+Nb<*-Q;u(RzJWDoy%{NM&RIv|5bsd3{53ucX9AAlX zZFoNJPGw%tr@EN-d{Z$To7`Qy@_8A*Rguo=fj{^y&;!FT)y+dMDcKT6H>6j}q1 zke~Pp@E~l)-Ab>*YlPK`3`O7I^Zpv9CMSTenJUR%o$ldNhSFwyqvqYU7ZE;*-oPyD z@K>p)-^I{1{}}W^Up^ullHb@Z`1DST3ry)LY)>{T-VV=+S1af!L;5s0*4(uky7Upl z%P+o)o-J==*1FfrZO6TVhk^glgS*@0zio?xvvkl^{~+jvzQ6Ly(PiXWP+3_W*7Toc zoP!(7ql{J}T9O?r3q;vP<7?iJHQ>ji8byA?@|}9!?R8>xAo=^(iM624cbu1He|x3l zx>{aK^B$g>?%BUQhl&BMR$ns}UFx8F#SzXc-LvA7?&TdkpLAbBw@vr3rOaG}`hiWG`UMkvTvtu~tiDbC*8jVypLKRo|6(gW2p@>J)a!sD8OnGy#Id?R zgVS19x!mATxvI?)TfLiomzCf*Uf)|*>EK<yF(es|nF+3Bc?p^aV zM?hTV?7Gw`mgqQV{Wkg{ZpZw@aqx<$&)Kg5XZ4!LJJilE5%hl-(x-pj=ylS)^2(*h z=atWo9niW zE}FRkdF@S331wxyziVH^x(NH~;zr#&n~PyrIx);0&rZhd60F1%8lZq;&Y zF}&*D*DzkOuWr2R+SxoyyNv(Nv#sH~qE~fgB(gRw%6czxeOdZ+%A{xJlR-OMGvV`s z(>uo&F2AanJibw|n}`k-R>Z03J%i5xIpVpgGn94ccylurKkhNR7c%f!@@U{Ov)7}P zaF!}Z@i~4m^Z8OD} z)C*oQ>1_9xolk4cFXLAUgVo|y&XScjX8xOF-^2U75!j;+$?TQ;V(|Q_Gwqq?7*$@#L^d!E{@TXeaST~_4$e;2#Gp1w^+4LP}Vl;l04c2u;J-=tof;x##!Gk+p0neWl_ME3=Ce-mkCIixP2 zd6X+L4=Z>OoUF_?1SjFZu5A*8$?&F|>9w@l@_BZU>rRwUQNFVoxS%+z>hIpB3@G(+ zw#~K^Jc&F`t@f3PFkFg(>FyL&Cnz6h+AY|1JJzoI0x& zFXN50Uosk{N6IYCcNp$WPZe1{aW| z;U*X12j4pkoB?~NG^1;$E6H>w{*;?Gum+J-U`qWd-?^Epz0`-`W{hU+^9agEWfY#_ z{w?b3zD;YXN4uBkn7P1Nu$hdE5=Z)~+4?hEr`NgR`$t|~bV1ooD_IYPG-uDXOQw(#o0}L5 z7aYc8)vmEKxY1txaEB4x5KhTnjgeEZb{rR>Br@Q{$;g6I&X%+rv}xod{$x&fx!vP+ zIPbgXgq+{%iX~z8xRu$*w@Zx35Nz@{bT~!LHG~d>3Mm3jkO!*18BHy&v^&mTU-OCM2@-c)?!;9aix=cP%FjO8 zAevtdPqbt_ILU1~?=&wNxC(lgR&Xb9|L_Cgb*A|~Ue{;wHmjXEZ|In)AzB9>f(OYT z@NK+<{p0`1+JnY66Sw*8S-kRs);^(Zu}tyb7?wFhcq?E_?4KSfc!=FG0c!_N>RW;F z&e;PjOV^)p9%J|XvP#`md_T$T`mSG(gjOM6x+Hu3lz2;@cShb?{2S^hMCKV1R=y9# zVw8hxALCx~q<};95578JLHz~3WIT5CNhi;AGe*z-bcTC1s&+`6kIojd4TP2WoVxph z+D`$-<5|eLB6KLrw_$Qq94kDIpP_71_q4#zB&$Su4^!e`oZ6JENUt?#M6qA#IqX}n z*IjKk2GR2FMdieR@4u!P!4wEOBgdH|tAwDe9o5wr5-US@&Qehwl?_SxG{@((wlrl{>sonsdNT-;i_K2#kf=5}kv{~+ z5c974PkG0R7}C*#oYA~*S3K7Ho+|G>I{L|<6K;4%?hdYT*NYkBnlBXtz75#f0GkP? zYijm>&~fvg7OSn5mfF-tO*_~^(g?FY28S5uK?iZdzBBkn$W$^LhV)N3gyQ+chm>ta zW(>1ALfglch&Ap+)YiGaSZa#g>*fh`YH4@&>VVBdoit=I=n0^VW)Cgiecvag_9)iy zn;&P$E7wipbOXUV$n9lRf;sC$^_K4VGOq)ncs;xySgRw1qV`kxhr0Yxo91(E^DST` ze-E)$NgQ!v!(YE06P(Ju-05w6cK1gsXU8(MWd#=0vyWr)oxt2*BXa@>ya^t*8G8gH z$FW&Cd>NZ_1Zs+vawkq-Gf8?PE!7c?J*;1nP35k6op1_wCRAqG`CO-E88AF;hz{q2 zkp+1zFwA*`Wvn;D`6%Qg&#jt6=(KVUGF z@>#&%={_(xlk`uh_k3q_Id=p}gH+m&edg@1vj0QQZPgQ!x69>$l_SZkOl*N1U7ggo ziTfIYno&Kev2j=(Ic2)z2N@@M)yylqb;9p_YrAs5>bhjUX+3c>q&2?G)#Q$i^JQt3 z)J}EX^jOl(r4J~xRh^8^fKp6Im75=NTRF{@>*FXKJuFk>*w^a6}%70J$Qj+ZL=zB{6yv9A(NiY z<;{99`E$@F$uK7)-X0IuqR!&ln|#owim6<8dSO%~xb9{swbS_&b1ksvRqRlGk)Ch-J@#Ag z5-$n0KHT>s|8A3Rq)iC77NeZ@9GP~e?{+Gk3Rm-O46-BSyF~xi-)O1gL#4erKs*twXLb1*>#ou-->3%u>=U#NeWsiB*(ZA_91e8n> zoP%R0f{|~+>z8KZT|0p4(CHIhVP;7e*KzUQSe@&-Sj4$rJ9?F0sMHix;Pe)&k&v5 zF>vWr<2%?52)+y&{yBKXB(&-DBNp+$%y2r&r8t z@JlxhI9_F$GBuvD6A*bB@E~8yBa<6_Ke!s!Klr46rQI`3rw;jHb*qo?Gp~MGNiu%= zH!=J+=YmR~V7CACgQK69-fmS8kjJ7b;#{rS_JcQ{ z-3qG;Yvf(v9sIQIKL+OO@n(eX4kvleAMIHPjz3ftPHb}XAoKELVv z9oH=Jf}jO2HvaXvkxOSf2BGWG%~{?dxVvoWt~t9kD*U+0JFrFt{E_?8WxF&g?38w8 z4c?Of)TPFI%amHy6kTdNyh8Ye+`CjdK7E_II$WMFU8_%e%U|IhPRQC-`6;?&`)5gh zcup)makg>UKF)ooMe;2_WZ~=oshqXVx3G%g(#r9(M|tXa!#k-)=5^TcWObKvp!WW9R^XI@Yu_* zgx9`?5#92;zU`-UvlVww{vlvQ1aCKX_)WYrG|`gOUpd1wf4Uv#Z1_8JK&NSZ_?zi} zvQWrwCoNi8elij$gGwFuDVkvW>pS$%Ll7fBveM40=(g%A()}!GA;0`gq zRi2+t#5nw~0UJ&L9jV0j?cjAfff~m(`g-9hf9PCza@yOm7eNt?;;$73ch%(4T^kJ^ zOvIWXSD=O#T*(|kI4O7$jjSOCj+5b4!%M4LAG~V%FKx)_^j~Ajd=5~5-`LvZ0r!)I zM8uC6{;zRT#3N+M!C`($=kQ~^G6rY9RKrxC%kOkQcqsCB-4Hg7&x0^IK-32tD+L2G zK%qH2hsYv2ykjq#g8vw=fDKvEqF%*JUnkoV$f<6E8-G+q08T=|w<4k~{`f<}Wxi*s&fCA7l@5b+slB{D~sGzwHsHJPBKU9+3P?&Z` zbLvpg0?>5LG3K4lPGI5Vfa%ldv`<%Os>+e?qJYB$CuMy}?gKCGx2)C> zM%+$Zq1|US=ivj%Z{oXe5*1Lxrt!J|QKzSwzz@!t+@6{Ob|S*1+8#2o$-_RJNCDl@ zt#4i{^^G}N2wE-rhda5-V>#~2+6hQM54c*sU4MVWa-Ew|YlQM_sCL;mGfuIx;EPit z`0CxMJ_YPbHi*0q_RKP$Gj)dZd6YNb-$k?5EU+>%$F2ZH;7xjnb-U@gN+@+g>prmrFHtp2dPyP&DVCaHG z$8mPCTA#ABqs31gkrh6V!|P!{iTw~|mshYGT00GXLIw=qgTtfsDo@E{ybgZxDl~Pt z`OgWOaB|KAzKkCHFX=UUay`2^{$}D>C7d~pH}NCg2bqi$;hBJkLy0ihrz+r)n{ENNfcK85PK)4VgAj4&C56y=Zvv) zZsrxl)JMbmCR)v_lr|2 zpkAHYQf09%LmkUX1-#di&UoGNJJ-;6K59E#MHwrS1Mm`C>P`KlX&Vm73#w+Yj}zENZFtajIl@GAq>hN*d0q+50vlUGxD%Blz9!ai)RxS;4 z1lYkDU5kojoJLRRzpC{U)pV_*d8WRySPbR6@Ui;zn?4j) zNT25nK~8=(5Uh0_Ywu`Sj^7H)rpntUtZYX$-#082qx&_a5?0TPke=50_v3G1BYnrZ zxAc}8Ufo!UrXvcfC0!euV8wc%N#3e(&baqw&?{6s6`t7xC0vs)^!EX!Hs0jS-t3<% z<&$rsq<5Gx7zo++QFidNz+*H_NjcqagRI0Z;JsIcrU5n|#Hk@``3C-((r?^`HTv$l zVQt*4Vci!=AbXY-bw?7o@n~wVKV+J??{7VpFwQfPCT;utAh4vaGyXWiogN>u@fi7D z@_1lVs87ObGd<*`KxSGeGBu7%>T8L|%g(|w;BPDgX`f#QWl)Dm_RWiUbr=)_C83F1 zZ!M{#wxQt*swTE9$Ik_3jzinByc}Kd#Nwx8X?-|zMrP-lRv?EK$d^gPJqg_&jZrv7TXOTsBA0F0q(c@b>~V9U_Q65 zvW)Lcg+G?W>i6NCXrDkCL7SQxU1AAQy+5Xy6COENe9I1UCLbpRH$9Y`02fw@Xn)D82p)3ODEl-v4j%g}_--Qo~dGg$PR-Vru{y*Jk zoih%2)xB~u64tkJ=eS->y20)OT~-xNSEX*|sG zf|E0HF)~8hr$MzX-MRM@?a=v#C)a~fSwEb&Cpu=ndCJ?na)tb1WW7^S zhi8zkqU+h0V_@}Jjn^k`$Jrt~E=6wf7g%pIXOBu!6<7Z9a+N z)%(2GvwGQ5^J%`!nakA)SVZ^YWW*7=&Vrfv(UYs*6TL^}`_h>x5;~n5BOlP>k${)O zN6_AZpU~&)TEFGsBI{S?9TkwAMfVPPX1yoi7~I?)WS-RIPs1{Ciq<_(CK{J473c1x zPbzK)ADku?d2(GCX1O?bSNMTG33<((toSXF2g*8ZV;WVodU9R6uoRrTi=6K`#Cy5n zoNSx*tUgPQxvPf=HEj9 zBhKa=?CzaqsX`vr-iqla?=8!gd3z({?q2-E4sY+E{B&KXl4Z%fmE-mGkF#xV#EB@A zuusw-gqMNaqKWEqM+G|ix^|Z3$-JGFdSuQ3CKL6`(8TDza^d9F)lR8N#QmUQvis-~->!72 z^P2=o(K2d>ZgsJ1d5!4{y?>2^>gd4E(^Qs0cEot{xc{EG-EeBFKT)uUfowN%FV z3{)$jPgMt;d;XL?{B`#d9ssIpa+N2#$L)Aew;|;3g3pU|zZW;FZ^;~&b`L_9zYUF^ z|Ec}KWB)q1^_%!xl|jSu4l1;)!@^LVv|-ej=gVo4h0{JQZmR++)K%vS3`uhSM>5%; zHyleBtQBns1IO;(q1J+q-Rk68-gZE}&Fy$!cQovVjJlq%WRd#$p&he3(>;3ynzGxb zMdi1XUPj(sd1hTR(%nWi$cx$l$`CgMfX|(PieRqKZUoej=q1iKb6}jkgPrQmC;4_8 z;BC5TW{Pjk*kd!3c`N8!w+|u9fR!QWo~QP0u&gL}7cXZ?Li>+i}>geZ$|mv6)ybl00{{UG=`P zK9P)h=V)ELH;t1wPy9IOoO)gI)p=!!J;vwZWZWzbH=-MD){543*6u1j_pFC@OsCIg zZdup)*1M(q5S>sL<$B#1?UT*>oOiNXcYTUf6j0|R`hGG&vQhPWJ2YMOt)7yBgRejm zzuk3YI)4X;rHjcjoc-e%k=$NRk^2dituE_fTwgehm5@2!4HGIv zr}Ne>s2#;lPK&#`1G)QgTW6liUBM4$u^>VFFcMGCUdRb#Bc5ftf|H@7s{6B{KP-3Q zM}0H;bo!&`0W?8H5BE?`p~U(IO04c_a?JHsxwio`wxzYHANbPa<0!#>T2|z$IGd?n zH>1>4KTco!0mmAy+T{>$Z|_>WmmNATw^p@tWSY3R_KuH8*2q*_49k;>Z+g5aD_kc| zrdTrrw!LfjT7}l8o%x)&jkpDS6d!lQP&hnCnv_&C1&4i$EL>d>=C`~THH61IWq@C% zSYuY!{Xa@^13pJbJdWsC?O`{}UC9dv!Mh+%!m6a5+7d2r0>MJSlW6O{OD{4vn9^Ot zYss_@9%F&924(ECHhdqdo*u54F8vF0x@;^4b2?l65I=Cu;}Iz9?pni{+{CklGWybu z_yO+O@_`yy*J(h!&xeag4-B#o7yAsloa4L2v;EtvhV1g`B8#TbS%zYH7mfPAV~NTZ zS7(N4ooxKnDsQHmzZ-m6_CMP#AmBo?It**1H>I zYixG=$drQyCdz?AI9bC)*&ygiAF`r3t1*c^A3wOQ4bLTc56nvLf@WVGZm9bfz2_E#M8=TQfy8zN30Itr zQOP(*qrb@Ol$S^B4L?V1UuUXC7VV|{wai6T&FtQo*{3p37JFo(cUS;$LGx+hzh^lA zlItMl_S3)Q(#C(?_;0a~Zf))$X;gc~Ua74`UVE>CW}jsVqT&=-XRnrUEO=ju_CC({+r=`#eV86ygcRU zS??p-sJu(z2$qTW=Zg2UKD%*?<5tiHkw$e>r*azL1*_D@%t!#6EVTg5*mZnnx-i>ozfeI0xj?n)FIKTc_(Td&~vT)bTkS5gk{S#c%j82fhl z#ZMZ)cX`riQD_+JKI@V%ji0nC|IXs1xe@g&X_}~*ydKM+HG8SgTKNLYo%Oh-xgB&& zo}g}K*$;^=nx-F1d3%BA98I9KJk8CNpU7PyNWMk1C2FPdwCSc5>{#TyZan$wJ(SO0 zzaHjLcLI`61D@P9q+A^|BYd2AG^rjptow8->N|*(Sxd@#c?}`pyjTvow6HoxCOs=- z%TVmgXQP{8oIeUJ`0S^{D8s`Z@n&63sikGul(=%1P{76&rYeiJgu-0!OL@MM<%~@C zV6gtY&_KqKzTD${yU?)b%K4?@A^2F?=Q2Fx+wgD@w}5k4-*Rn$a-2S#C~ArKbd}hT zU13RK_pm!KL|I(tV^700Kh2)}HuiZo@?1JJ(p=iBA-lNl#$F`PeP*if_sEOs>EqN# zUc7yU@(N~o4UMrsSCZo2G0&dMt;niZz6Lk&fs=R@9UsGIY%k-G%&vVL)X-ox*YB>< zLpJVdy&GB&5$ZnqT<)7{Wn#zdTU|)eh0zE zoMFn$_>$2Zltl_R0-L&L?~WB=B}h+j79yuhO$Odla{aHz>5~(MFY-akhvjBAaLE6I zy~;@unUN%E%BWw}e1gWJnj)GKSMuBadH zs_GRI3Blvb8tZ7WGoY1?ExAdo?8}5rWiH$l-q*%cMV3xY zH{kKOxAs<|ajatc@sgjwjYULghwx672+9!@w+8c87ja-!Hv&r7+*t>MOQSI=>s*$a z>$rxa4(rFzdZo?trzZ!|PGso83XqwKttofLH-?Hr`e|3Nf`ZBKBd7UAA-A{V{PFps zLzB^rjO-eJYJ5acCg%no@0?U|JJ;ndro}F{0_K9&$#7tY%dP>L4dwqXph(^%GL8y7 zX%yB^$jpVC(4ly$UV;{^D%#cQCH)#jN%y6kKOdcM9tJg#ch5b}_!uRrO%2o_)^ZvN zEmY`r#RQL|36DTXVyYEEvs*OrW3G1h4izZdXzwkEL0)0sO- zJZZqZdCtI9vWWdC*BAO8%i$cCAA7M5ud97mUWt26sG~ukd9PZkuvhCtbMKMq@7d75 z6W2PZBgHy)ljA+od!@zO9@-0;+N9c1@fx zZ*UI==h$jBr^6lk)>U%|t?+btL@j-q+T2#~)~U4Ewa0bQqq+jGmm=HySua&;Ps`IK zcgoOVo-RjZPu0G#nv0|9K>wyp_;>c;uTo;8htUm^-+vAcO&3DTZ9J@^O7kNB9+oDn zk=*?&E2-0K{7|X0dzb5>PjXaiiD{l|jVfEZO^$>8I89=9?P#48>Rn|DEq668Ih7NR zmEwEbb9Z>O>*M%&74r0Xa9ro*)Oo=*?E+ymFK9RW?eSbsgL18XptU^+EgjD-bZ_kw z-QypzLR1{cl_QQmqPGLxaT~vRo}4>*1f|7KE@cz$bO^d1Co2C!j;g|$iQG?{oyY*$ z3MEF(Spgjon9mUc$9BtA^hF4afwsU^A$=$IKh^$TN0$Pug2UtqSq*_7f5{`o z8OrRv?ufvu?fWi2{5YPX#Z#F;CtJM5+=)ybEZx<+Jjx~4@X4B2AmM>CzF2e$JU;ki zOiQ*Ar{OSOMCu6@y;yE#oH?gJe2O*c&XT^hP0fGu{;elLF^nz=;VA9Z9-Lc9!5lK9Kz*}vSf(n@1WL`-Y(*>qyXWh8?s|;Y-J_dtt|#JIueM2PXtgEh%osw(6B&b<+75#klZDvq z#KB!b)L$r{0xAW^3^{+Q{*1sI{38xtciZrD%Cu7b22Uz;Q>Wl((5Aa$aXQVZy*9`r zk=`KxEO`geScwyTy~D?~>TamgADv7x;*MxkbV*V~jr;}tPsk>;8e|hIl4iAv`H%w2 zD`wZs!Cca5K8`aRj$@8XY~-S93Cq2MMbdHVt{vJPmWt}`r|Xb^3Lk84QNtqmR<2r5b~NNPv94T2iF>|!y$P3Vasm_q;yMvuLlTJ`4F4=1NTGvga()p))Z)NbYQ?pU zB^MgErm|(d8TRN{m!48vmUW5uR^3A2%Xm5Xtn|k+Y8N#Ij(f_??E?4dSlIW_g zD(ix~>zd?0gL{9RC?TJ%_}O^%7P;zAVihk2v(oWQLTzMgV~;E1H0B?j%1yg>sESi$ zA<{)2QpsfT*g5rDiiyp+pJiOe6EQ_gbeHk_i7$#%Y{v6_*le~iD;0o2zT z9YNV3zN?7-&iGO2R}PPT61(3Fs9%hzz~AE)8Vy~5@vXp<9^cK7t<0|8sBk7~ z572vblk#T#Ev*EpO$_~`@b+q4zTI3$-%K^nHxyQXqa%@fow~9HgoENC<9OZgpROxj zYCfr`8yfHF;khtPl>Bw*l=#F{oou|f4@6YAUc4XYUO<-n>!j6wAJ|2m7_~&3kyC_p z+z%X7SAB2@-E1et+{hky6}5}P&{A4;a{%!VuvHvR-3QI%(B#k}$8q6W%&40Rpo;Fb zm#e99LLM;rY2CvNtz!!J8_vfq=Ny9oIB_lhk)NQ-r?crV35A$8RKbjm$T^J1jOZcp zOJKudry#$})g*;%_f9#7ag3&ipYWrfYmA>2UFpCa;i`HuWL#BTZ5&toS1`u6;0{=F zKAkDBSx!QG$0Y|d&tf%jZ+I6gIcu)f*12|*WF!l+w#BeOAI#KS z({ChwJ!gR;nU#gf=ocFrnBMzSvRl_>PjNEnb?9`~v4p8pY^iL4kM~CKZvJ!vu{^JN z>QoAOn9dE&`IC@B^c&!{{QxDMYR-otb(~4c?Bo!UsRZ{zZ?>gAm0qUv^gKWFE*2+N z&A$63i~p0KR_689)wNi9`F;ZVc682DPxgA;J0ggd(7e9!$C#ITY2P%*)V7s!M zWh!S8jLP%TidBP#uZF+RbFS|&RbT3$>PrDXtnT$vwQuE+4n6hk58~wQSDQxF>;`-g zH^iT)I#l7tdZ_wRWI48}S{8!4dSuLBt)>RXYW}mLYIk@j>1~`}k5M(}SW>ml(XmdQ z;~c8KRB>HS15H}C+*wogIJBSxDmTzo?cuBQoJ!uWonDXjo*yjLMK0KyWi@-Hf+78WY#;>g_1Md3W7X z-7Bu-O3fOgoFzV`$D%5X=;B44EmGxK%4jC8%f8oBXEd%6j8`4FFT3zCTSu&V9>?g$ z5u{>$dxPxXXJG{kT4Yc|EA*Km+xs9@XHpq+tCEIgjS<$BWER?=tMDBUw`JDManRpe z8-J^0diT1Kjp|V)okMj?RANj2L3#}7=p}B|wl0wEqdR(E@VV&@dLgHYJC)sqXKIZF z67IA+sXF-i*2jE{JgNfgNi~n6=us&*>nuXFnQ-2e`4jQ&_S~*Nt(|gKCX?s-I z%_7xI&XGmy1Cyoap<6TJD)#D7LGEfveFCohE+=Yp8(P4fx$mzuCpj zgoR)tc#hrlMWU&@@f7lg`{?mb(z%*Q=EIQIx8pRRN^x;NscPGjeqC|vC$NFw*2oUD zCG->O@TeHNbpp+~yU$_B5+90?I4B9hSf1_qqdA z90pz~Nco;!gYVD+XI`q@n4!uHaAzQ5OAK=xvpN>4-^S!lb=IEAMzcpt04(H1B zdjT=J(*hgaORxGxjct2YvgNF(V*Z{i-Cg66sX;!d4{Im#u%o5qxGuCU|M-Wpmm9%- ztp#%)?27CsC{cKJwwl*6ycfPJ9n!r=#C;V7?6a9m?rENIet7R(s^feQP9&>OSFu)i z9)o9nDAbm8x%>(%;7-tkZ<@0{mEo-J z7H7e+YHv^76A21Xgsr@Zs7uF&8s|dAd{3C?Q>tx=e=La9`f-5WRgD+BxPv z^}J8|q~DDnqRH#pvpUPn-*dAI1ohOMHYce4Zzjy<+;tzZbFF3gWj4e?kwsW8`` zc{=w(!fc10S$7C?cS`97cxlnq&fXRnx31CTySmN{^(1iRpyJhKw#^j1dk&=|;ehx3 z@P?~@3VdH365#^yFZVhh=3?Ug=5edEx5i;i7x5qBNBW&*!w`hQoX-*ltsll@4s&}M zxt%)!X}Bu$OCHUE@%nAsaaePU9R1zs8sHvE*qKAnCSy#JaQ)D(^;Ps4Ro)A`@eP6B zUeEc0{w3x`HF9&eOv!gHdkMl z&YhV1ZL%M@(~s3`Ca+DGu4(^A*LUs(-?^N=i)Bhjip|hFZpZ&pfxiT$Z}SlO4U_NibA9)|WzpH9iG)!PW_ z2#RH7kC?P+br2fQO?wyc#Cwl7?|Iar-~;$;yaJa>YXJJehl+(yof=y5YApfp#8Sq+ z%CwVl8X#XE+yi5NYOGz6eETDv!6qyRcGAkHV)^$0t0(b~J5Ya0vwj+wj*rA$JdNA! zCpQyq=5^9>vi@clUe_nV?WcDF{)$qs-s;SqdWBPp+_|6aRGfkbQQ1^tl;J{mP%u1fJobU-+psI& zza9`)e?mcvC+Bj^c`(bfuM=jzvKXy(o2$bV^Th8dgE4&vtJ2l!y zuLxC_{??;y<2X^Cd=sM9^*R0Xa@#d=Aa->(ESh`4QOVjP9;}*3;zD;%ZiG~x5}o&{ zpKd-S`l5c07*zgtcRWCvYK|)s6LjAIu~&v2)z-9$fA<4N5sc1|Gniy~I0V?3N%^Kg~N{Po@s7()5KOZp4a zXEWf&t>bl#I4h>VfU6>h`2l<%Pb~d;SIrI1S5F4Tqh1ELS1if*XLNT6J3fU9aVU;_ zZSq}j#d%RbM2z%)oCZHz@w$2MB$+fwQ}zAJ{TZ57Gj(SR@TPwr&xS?zGT9+73T+;Z z4Jk+uYvdGE*_@s6$2}HJE}OA5cUOQDFavx1EM}9pf_H~JZlZQQaS(9Ci-rs>xj;LA zU^Oddg{&CZd?;(i`eMz>GgvpA`?MLjmn=YQGnTdET8yl3tQj&xUyE=kP6Q1f?Na#z$d^@S0HQg&H(7gz z@iph$bxMw8+$-fJcNCCWK#mR>DSf+|r(t%_n_MZ6G^G<3CjuWTvv|h27J3NYUcQI__lKm9WNrnI>+1?K zPXF8CAtT#HYs)>f%?*6RH@#{cb*nRtSEEZwV^BBvdi;Kj=R5G}3+ML7tMl*8utYgU z$3px*ziV3tZBMeC`b&BQV39hHSk@zwjuFdGZ1FH65*l7rKY^Zr){2%!jTld=&)05H z2zuc7^B(y|jK3W`k;*Wl40ld&@k(In-8Ay=62{_%C8JL{dg@wKt}u@yT)y=F+emC; zIYUohES~0`6=i9k2YFqE;*o}FJsW3NLWQw~% z(L5!O>(}wk>nCG&k5Xf*zkNAu!7t+9#q>{Ws=v<;)nN=D`-|Y>k5VSFM;M#`Zmj-U z`X;$muOptuKAwg4rhGW|@c+h6)Rpy%=o*ifMHGb_aX5cP+~u1lYy5sdh}hh_lx;_J z37?RnOz>8`2Oq_AWO;BK4!BeA>A}ewI7{~A)8sF*q`UU^X}tfp^jUj6^+bFUDfPWg63BE5nNvPqZ>{=wI5>Eu=9S4}SH zZnhs1kKc)Ng~t;M;p|yEzngpGzBt~uNAO;77;;pk_cZ;6`ETm~kOg=u^Sk}8wqn$y zbh5;?(f*F({int!td*4>#{aUbkV!Yw`R9A3*mb?ezB>%8ZPxqi zT6OL&&+Uk^nsfevaya_dUamUdGNC+e*4j0n?u}5sPT#nF@0aswoS|8KgG1kFeeXAC zk?z^Im&+%)M}4F9z2BTg)%tz2Tv^d9szJ?MxW*>g2KDI!;W=0&S|W_b}B(IUGmXL4VQzIoL1 zpG>-1S3`b}{gm_QMgaB6%rMNanv%yIz8M1!t?pFzCn=id6PV7g(PF67@}13He7lM7 z(mT7J^!!Z@kDjV*8lq9tPe|}`A1?N~7t)BzeY{QN67-#twPW+=>2q4Hbj`|a`GoST z8bZiG*AjL?sealk?RxSb3!XJx@aRBgbY~-9sIF(93axS!?m@;(yuZ#VCEyItzNu5Uh1xDgZw`Zwr0)h!FtcZr>JBX-RZWXg}%lRPgdG`7?+j)7_5# z$J_BVKEb2-4mO8I_Zg4<-U^Q|9%5>%kAhBpgBcanpN6;VQG6m^*tHg7+Un5IT*tC2 zc^p)UkNKwwtDqtXZNI&SWmiF66dY_E5(hDV?xnEWGr%$O?WJe8-fKf zf_fcIsw7L>*nK|zpkAGSZw9}nvYxIIuivkoPn&zAx{UXshHC-gZ{yUd0aVUxKeef@ z*O}G*&-oMX5<(_X4M9xilb}T~Q8hoGhJ>OHDpMwFxf|=)4K6^xlW&7J64UAWnZK47 zu?|kXoV5)ZX|d*HBw$m8T<89%{|gLQCLBg)Nxs|vC|=V?qCQP`fhDhanNjO=G*&y)W4W>Glk}L1 zGcGeSH|dlRmYrj6zud_6*>SJR?Z7?Fu*}HhQI~73M<(-V@l&LibvZWl4MkEj;BMl} zj9#B3a9(~?IxCcG7Iw(nvkWY(sha;AqjToxGNXUdI7L(8a_2|YV+o7pWePXi)u*Pu zo2t}U92c%OPK{Bi9b1lLHuaXSo3ocWwWjvcya9T-vFo!_<{( zm3hmI+|+TfPQaPv#;i{gt8_7rT3RpU4JkX-HZ4{fF}rc=tG45)R8)kA5zgli9G;c= zHyP|XA9gcN=uwJPD7V*7w)ZK#DY<~E*YHy_c5N*p2g#RiTbhP>{d+5T3w`LaAA)aN zBGu2f|JsTtiM`Oh@i_S!Ux!bF{L`-SY?-#l@jD*xb@&eHm06FHWjh#7u66eh`F`$G zlYOI(U>HKBrPw`=-X*V?9GY<=SlWz{wJ z+13ubN2S7)6}|3QS8eZgf1h`^k{+tgwe;&C zx%>}9-_vKn8y%SV5c5AW9jALUJzIFO}I{|I~ntY3DXR;gPL zjp2-WWvgp1CBMdh@7i+iWXv_;)<>prBA+=uREB=G0;0q*=p^&c@$Y*0Pgxlm>bY}P z38}1&4vh<>_Tt>ghi~Fzm*&|u*4Bn{!iZ+%2upqXO)ax)9Nq)!_G)tliJR;5Z4S2W9Zz#2a>*}Qq=@)hSo7H)m2*~eEt+kQ>e43eP>FVMh{ z)$MPU@4#JlBihg<*TGTw*Z2*@%5Ub^Tk#3;M0(|KZu~y9ZgAGM9wiOpDUnx=+P?mu zt;FjdC%lJ$*3iMGyd7&B9)oW|#m{3c?J=kZqb`84`q#l2)E`lyz*xDx*9~KdsW$ z7Ce|stM>yoV|(KCwqid>pRPTDx6{Uu{OB43_@Y5W&7#+CoPi$8x_i2&{m{?{hqy?2 zD~~nLq4~;HEXS{qBM;(-o#uYB<@kCnZRAzZ1lkB1PTiG#+1-|qzLhv*dkwtP1!?XC z5Upc3%FgKG)m=~?nyXwvZ7mGV(v%40&QwoWj+8+&LM#CEBC>iU_!3wlr@C5Lu1 zG*dY{vvxtMImghh>{%+u_3P%Y;IO*GhP(+^%CZ+~_cmiKl9WRj+I4z#8Y6e#^Y;CQ z%cBWXF;Hq1MBdfUY_u9IpZz3ug8fglpzK0ho=ac+v}wXX&VC%W65}!t5PqKK+l+mq3qk>O1k?I>4}AyUVKA z%yBJNj0TGa@7}bW9GQ4z(lQJ4lV8i+%ylP?@+@8fmGl{4)3e~R;Y02;<56?|I!;gPI8JaF9~YR( zj{a+m0}NlKU2yVm!)Lk|e+dtC>( ze(pKX-YWKSA$;a}OxC}hd!A2*=Gi1;DA zN@F;C2S&&fpvt;yxbn^0@f5gqkoLzNck=vjw)!6DgstQ!>b;a0a~MwwM{1hhjy1Cn zPJKVYvTF|-9}daP`)MqAK)Hw9=a;_d7vi7#qi@GkKn!?UpM&;zH74KRJOJ5fUW&h2&$o9=oGc1=;*i z5E8QHhs@4C;1^Kn^+bJ~aGTQc0_wIRVWH|ppwxaI&|K|qjG((0!4JF;4`c4{W1R=F zP9Q64y&12-H8?vRDuj=3V`to#SK<<9Lsct2WqF>YZSifa9_0@67nsDjZ{E|qcs?+= zkHeuOkm9}j^jP}H*<8$4`!$}v_4G$9#j6{4TIudZ2Tq0 z=Y;e(u>o*{J(0Pq3VTk7RX>Yo!8hqrJhKyjy-J^oBY~}OcJ@b(yJS&Y)*b|8(XiMv zvcwvMzR}BKtrdSPFDwZdY7_#B!^cleDt@Z z{p@Z0e=&~cJly!d@fv^6g(Rb1Z2U*uwa4!Elb&S%=1|h4g!xo5uzx6p9n!Cx zPl!Qs>j2PJhYwD}FzAv=;;oGJB%Qrw6JAbEo%;rPkJChMv-&5o55~2W?87?in9pNH zKgDTo26v%DBXS*_V*S8oH@(N_NTu>l45$HK0=MfrK|%TZpb$7HIuGN6gWw}$|Br-| z;1*cXZR6=v$yabj_>LY9g?$ohhoAovpTM!0=Xm3PHMjt_raIwZZ;%T^2Ac9hYc60K zK?`L?#z0w^f+}>O^@>ilLZD+=iq{tW63*}}J7k^g{IBsDkb^60U*NW$LH42H=nQm5 zHAhnh4>f1JqF3HQjMM%hVs6byTnFgYI`46;i8_Sim{Du9C0EbcKTADt(|^-H{*Y%t zUB>7yT#wFQP0s*(!j|IX;SZ7xU;=U$>i9Kqgui9!0CU9__@3lgmz_GahH_QS9WT3< z8tys9ijNe3z{B8iyCGev{mbhpW2{(mNF}(ReGT^L=JANGP>n!$G5hcP#zPvTAwai% z>+?Oj_#ME@JQlBzuF^PxIoMc_Mjy6;G!o^gU=uc2%ZzxUh0fUdB_}b)V;lT0CW+&h`8_!dyeW{a21K z*YMx(*nRukKx98;>BH9PDL$bb^{(&fJ<+bcNNo;4R1Dt`{Xn~U8sjhu*p1}_hBwC% zf22AayvEPb{bT+Jj{u{Z@$KAkjX2q#TR81e@gbq}!C#;~-2z<0mx?_yK>VG)-&-N4 z(88MZq3WHT*b`ab+*O@Bu9suUYgX!Hl0fxp(24QC?Z#|)1)a?!T^S0#nN~`~rH#?j zZ{edzEhrHRK{MrK<>Tp>h5wZF%X&Sm!o6841o)4v7XT?j3QpHGt}Mc+tta6GZxpd{_=LaYXD2smMfa0Ata z__S>qan}QUrt}&&F@O`;ir52Kz&-QwhSevI20P?;w@gN(v^FI@PMEG!k|)23O+flt zjDGiIFOt;lz0~?0ySO)^-^rS>we>p2m*?#4^}K%Rz#UPG#IkP%S0&qWh>Pi@@eN>8 z)bt7W@ojERnk@eo_wnsp^%&$2!)tUybos6NHQZEj2W45+qm;Rj>a@o>tHU1r+8lN( zaOR^EionAIO^deNH`E$YJt7%1`>}!t@%{Q|E7p$GAs@0{(|0jzzqHDuY=tJ;mR9h- z{7nBVMWE`L1xsqLS+TS@WH7M=c$Pruzxku`{?aql}t(Jl516#iPLy#>XJr zS6Wr~Xo|eRqp;k@$LrS6$~D0werfE8=p5Ndhau6(H@_CIsgL~bJ!~`rrz=_3#oP7G zgW$n!&&h?vH=YHDMJ|>8zmFmxiArYv|3l0t8_W73lBteK@GP8dJKo2}{U!ck+jDBU z6SZwg*7-Q*d>5lj0`X3ka9aV1+DDJHP$cH(SPP$bMfO+$9J`F})i$G~tb7e<#g>=I z0c;LzSJtfEFy8(6%e!epskuAs1G@2IFKe~<*zs5K4puq7Eu=2H$lepd1Iq$SP~TUE zca9s&6Jssh9H5R!LQOYf-1bim&l|B0X4Cp>I%RegETrX~CU4i%5%{0jLfjXwuh%BV4Z54i}KG6I?|DIyjN;_>ZQgD=E2H6Z*vWAI4Af4921V zb;2ZQupj=$q7rKKDp6j+Ze*X;G3PO;eI9gksRgHU^yY{)M(O))$k#BkwT`5~n%Idw zcKu|#9eDwzKW;!<-D11GTffIhXv_6F^7)rNlO+oc}+PcbH#S&q|QooIn>rX?Qc@4{24dF__;8OG2*8Zv9?AM19K z?|6XPE5Q%MNy!83yUgpcpk~#Haq?JyT_drl+d;RgvXFz%?-}$tJCIEw8@L{`+gk5BKkP_- zx1Y0ru^?w>KirW(*9kN{polk|EMT-XGLxnE;adck$*TVX?;Yh+6t3lJK#PtBMh--Y6_B^I=8KHIOrN%+w1WjPP_tG$+e_N({OXN&7( zkZe#ZyY=~;y=_i>2z?B^@7rIw^3unUUmNf2*%I~MctcvVfc^9osTR9OYJe=kf*=8Zf$~ltFeRZwDIga(d zrci_`^v3qz*hX6ymxu-#07aSZ8$^-8+_YOb!-RL~;O z>ztLs{eh)krucy4r~NZ3OBSuc(L;GUYq&r?){!{(p_v`!>Yr14Rb;{=EkCR92swFl zVh52i_%N`!)N2h>`H#Wq8g6LUz)s`b2tDF%{FLu{^~&+V-V-e#+oy~r8%=9#j^(a& zTHVlS+{5)<>~*K&cZ|0c>(!k_kKYYf(GBi!?x&EIDV|2o%*Riw+iD#n0m8a=ZRH2M+);`a?0_YUZfSvDe z`ZtmSUIunISE2g*d`q>z)BNpvdD~w@YpFH-2f<^rKSow0GGDqpek$(SE9tw0Og$EM z4_K>;LZF3yn==N*#XpMA)#udSiat%8lT~+zxqNQ=8joUy{p<8COde;=6qd{%QLiVE1+#+j`&TePW&l&WV*HD-B?*u^J_vxokBP_V*HBbv~vbHIr7r*Y1AWh z+xDe&M#`{bTaJ!+;I+VF@h&;HEVr`_E+5d#jekivuK0z#Xzqd{{>dpwXZaX#+-;$B2&p0iuLb&K!z%alpSN!5D`~b9Q@W;%+%<@he3|vllDdru65AM(|jX z#rh=1E>{iJD0aRKHh%Vg#o6Q0q)uQ+4kIy5BtknTNwl%15UrIH>i6N5Ses9@xtlUx z?weMx1m@CrD@y=)_LcAkac9X^yw9gKzv>%@YUuuP_;h@n&%-PId2p3-q^)@8)AYVp z#HZsUb?LX`x@_$~E_Yh*Oj5F}1oXL)Nd{%~dz9(5hb=~42Jx+<_x=icuk)Ga%2nge z1Fv`8HI6b(%e8Wzw}M8j5i*w2K}I!zt>(-)2HQ~9mEKw z2diFL8S%@$j-!y(_d>JEtJ{h!bfQ>?8~+;ruw|UFM7}z=ZX+GV$<4JC_l9qn|EpSn zOzQecvfLdfL7rd>^9(0juDzMD-nV+Rtui;GYxT&ZRj&sN2fRZ6%~q5>VI?%N7SUG6 zF{Qf?8QNamb*x`zF52q}DB8c5HLlV!GLDHxT}zSalQV=%Vi{-62@Z>;1HYBUOq>ge zNp=bP01+-^CH@C#2y~OV7LpZ@E>PoXdGU}kP5#@|lARZxPrxhRjk(Hff_{svrkhf? z|15bpxak%R|8A@~|7>+e`0KIAJi~HQ6g9{9^C(_z8QrhPC}Sdw)cmghmPgx~Y|ie7 z)^bg{JhEjy%}235az@_9Z`A|f72ly#29!Q$=SqnNzNl)4mc$EL{`v8aSG}nfDQ0C-ci2=Fy~2H>BV>t&dT>ckAFm9 zSu>WMD!az!f%|eI-xF-Qp2+hw&sH1}e&`6n zQS#_vS(25A45l_mez~pq3{RsfsAOp)1DdvR*Qlyj*^Lnx*BIj}7H%i6Z|H#9y2k0c zl?AVFuBafJ4Bi88>mIfA88ROC0ujZMU(HypIs)H2+>~DJuyY|;TuDpyx zBlr3DN|}{c&uv<8Te6RIvjk)FF5D1{wA~w&u4zsGcR4~+#|Ni{;f!7C`1upTw_j>g zvAu|;OGd`MnEz(%5_tq=soNcPZT`vGoX(E7?u+#U)gisXO#JFElXn4~1-@zS+k}@r zIL+*a9Bl+Il({MEP#z3xjLb#`401&oY<)9y^^LMMfJ}mWK~rRCGAbk1YiCcy;;A#u zb%pHO@jKar=;66i$#qIVfRU+&#Rh3=AoVGrjl%ERorC0Gb-pW*hIeB zeOi?0b1bP*I<&fCVE-U}!C^lOO<}XNwcTXjul%55(Pvivy%(SRv6v^ ze%0T{yz;NwB7?56Xsv(1{r~^&&b7yi;|Rn26atF0kp*HGB|yGJ3oHvV2FxY!!4i@o zP9$UJVk~1RKR)&JdtR!$r)SQbvp88tM>e}>XR5oa>t5B>*FqX!jsIS4Y+XgM_zQdV zbx<@?N045YouYG0*5pvpjfLo#Ei#7qG@SMR!k@O#eRlFlis7ePhW8P$5uJ-0{uvmO zwQC7q!&j7<7#R1~I6u?l#M~rW(fiz5WPc5biUllxPW_h6W!C*Q-HOVsuliL!j(q}G zZN)v5h;+vO^?XLFW|fXl|K&oi{%ut2vGX+*@H6$;l71Q4d^VJm@Cde&mnz38vJ%YETh*E-_hx}JX1WiSd^E6okuT!Zsa1q@Q!QZc_ikGmw!k(C{%O|2I$4MN6y}PS=X^K# z$r;PH;d#>&E=M)du_172~{@5cLo!A(y z2@dUZ8a-#W_|z@2c&(00di;^TRzw6@Apbx>+1T+Bl1?o6-8TXR1~q4@pfkcH{arTDNJHNi%c0Vf`vv&ArVc-Dj0x5stxDRDLNt zTr6QA>C1bY|Bhok?5Lttqg^0gPj>R>vXgUhi?w@&pOEJ*iP?T0@TZ^5gG1xwPwb;k zsSI6)W{~zngTp~@;)6evo>u>j)9Fqx=RQ{2z-S z-_Nw=VoAko;T5Cx>Q7QQQPbAb813z{R22N}9y5_7@+Zi&-fzAX->&tTi8#qer8Wo8 zu(lQjADJiKYi)sFlLyUhj>P@Zmc(N@)rqyx*AG(djJ%UY=W{qZv(_tg_9wDM zB`w4@zFnX1#Dj+Ch*L7&vK4Y;?><;MbL&b+PAAmVoIhtpDcs}g($5Mn9hZvzYnz`B zgD3dtIp<^a8}yui<6cJp#+guJOgzWW&tqrwj`NRno}rgD5k2HFers}AYj5)==W9jF zj-I|O_;gnRXdSNu?Y3-#Zq3=7VAsl*pH=3(sH^_Zvl1}VVw9B8ZQDcL1l90b&>h0ik9Lo|_}qR9u1|6>k*K;1H;)#|RlDzUp6He<(*YfS`G;%R2P`BwzxFqqiqz9DgL*|U^ zVD=h4r=6DUU#22aL25&&=K06>y}Rft=LU%znm@rNcV|eysTLqyYAO^TH!?PGzRf$X~knm8~qU6 z=RU6RCsIR{WBK9z6LrZ}<{9r|pUZF_#Z>bDurIboT90tqT5mZtA>a{7iYn7t+bn1# zX!Bj{M6Yk))|BpW4Ejbb$H=-W1Q{dVGSx8K&+Hnq@Oq5D5t}?^Q4bf$jfAA7fZGFRKDfhkn!qh zhfYs_GoQ$_pLD_iFIWIz2-`y5O-s-1yzKMlEYi~LPdz)L=K7;iRL8NamWMxuY<;oW z`88B+ovEmdaHOaNC#a7DJGDkMHQUBg722oNN$L00mZ#^E<0fa-^Gp7g49UIXDQFdX zkk{3&eEW_$hFI?xaX5cp%U6E~l}WnF#+5#U=4uXWtKTF=MU%46WnWk}pdaz@Ecs+J zOL~1>Mnm#Qha&$hO>^BXmG`vEIg-2woc(up1|EA5+$diad9Cv>=;>TB@>jnTW$mG1 zXG`{?G1TJ#e9Voh8U@Aq#H+5IOp9H53;ziT3-2p-CrzI-!(!mX#z{G;d#^l=X8R)e z-|x_cM)x66%W@~6A%($!@9{Z^706$zM-+9@QJM}DlFH=m=OqC15{7Du5 zv7={APo{>Nj#4_O)Mx*}VcV5q9^dTo!&u+ngTjpA)K`K9j#a0`8n6ubhPCUiF=RV? zTl;D79&i8hHbQz3me`hB;skpjy$!*h-HVlsPh}X!AHo8co}$*Bj1FspN?74k-guXj zBIYW;Z-iXhuj9Z}yEqF`Qx>x7e(Wi=viNqgoToFM-=XdP0#*Oi%ReZZL!*=1sk1C# zqWuOAT$6WkW)N(Hb7Z=y?|smlEI(;1Vo};laVB-sNPoYne2;gP86c+>rH0>;xyVt; zJm|TWu!1@A`_P~|r$LO0nL-ySaTT=`&8QX>d4)`a9tBtOF?S~I4Bv|&Yo}d{AtMoF zqvGKr#RLy4aU{?D-o4FxI*$+U+hfvMSaj>Vz{hqfa2~FvKIN;h6f$mm6j;9<-=vR^ zguc1?*8VN@!hcx}w=V?h$dC^EyuW?b&NsHJ&U$tHhqKH890(dCofX>p^*oPx`vWg~ zoqT^#I0n9v&a3~b5$2`c^?W4vhjyo~ecJ*@*sUMk#sEYV8 zM4d2p-h00LQ{VZiomUS9c%0cj`M4imDHe=;*<}cVNL9Zo#d2S{D_iHYkb2*C80u%z z!=WCMlfI9OWd)T`&4B!+o`@Sf*Td#^httqh+)V=Y@F1}&kCGpp%HW+ z2f74{5518m!Ka-%T;oZfId+77rgv2fojE3Kb_(kkjoHG_ywcJN-0`3vqaB5n$giwd zFgJqxv#Zt?T){(}>hcP)I~n0oz{P{d9>7keqNSbf2$tb;R*bGag5^8$(BNR?%^r|- z%DlbV2Y%3Pdo^TY4`}x3{XV+)#a*UpEILCnH~PuMV`cTH zh3lD9JKHv6&K)+}@B`g|q5H++c~PV)JTqQ(3r%$Vy2y0>T<>xIOs`e!ZfJQ7f&Kx@ z5b#O_fjy}sxcwSED|OB1RPGo$@{Myyc%%uvonODJNzZh#saJSbdIsKzqU%m7@}zUr z`lt3>nfz!yKdQ+d)ekN~Z%3Mk+wbq~utn$v%P!F0Lb7yvdxd2*F$mu-Fp|?PJh~3Q z2=8D7k3J+nmh)0*tli+!A%!~|M{voWBOCCZw!JpAxkMClhS?)` zWL=F`+4g7>q-D!{1cg1IP8&Pdv!R_xH^%)tpU7g86OF#MXggd3`6* zc{r~_wqtQ~ml{x$(hNx+THe&--E&lO2{!BGgs<*!8N+7PL?p59cY$4>+pv7#R!|}p zp8IyLK;oe5>Gb+^gH_#s!qyc)r)xE`KlRL{qWhSvD z-bQ~@SLV(6`^vPo)1vFZ5{v#Zi%HU*4wVGg`1aU8UB`T?V{gY+cgtwiFh;K84<;d1Dpm$(CJHl z8~z6?qR!wSW$F!xH)H9gxxw#R`v(6cSH}E7|nWva5&{Rp@Mr~B5!&7T9alOI=66nze zw~7OS*X1tXjODJ!>z=+-aL2sC3^@^5PRi7966t;60##-HwO|ZANDPsj1~QfkfOqkG zTQ5uYM5h7CO{*&5c031Xej86yE2H=**%Uc2ySb(o;t+|Ns z{7FN6BBIOUj$h)Wp(+EYv?9tP9%xS=&P(#c$ej>Pxm+-)GdSjB`kW9;BK8L#!8wZT z5`|*dL>s)%v*+`p)hUJve;h{C;Ba%Z;Q5>}vocQA*Hj((g@5|E!U5t!-MOqNProOZ z%dU}M)T*h^5jIr4{+pr`@e6q7ZFsoc3H&PTK*fXL0`;3C{>LpyoJ;?Ae3T0wy{YcW zbS}jHc@%FjB3%-Q2;=4HMo)j^=iFNiOP?qd5emK2XL+;&swV0BgI$LMwEzGB diff --git a/od-win32/resources/RCb02620 b/od-win32/resources/RCb02620 deleted file mode 100644 index 9bdff419dceee9a4027625663fb81d74c748a213..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 212576 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 hHs)#6Hv)2(KXh-K8c<_HL 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 diff --git a/od-win32/resources/resource b/od-win32/resources/resource deleted file mode 100644 index bbb7dad7..00000000 --- a/od-win32/resources/resource +++ /dev/null @@ -1,1153 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by winuae.rc -// -#define IDS_KICKSTART 1 -#define IDS_DISK 2 -#define IDS_DISPLAY 3 -#define IDC_HARDDRIVE_IMAGE 3 -#define IDC_LISTDIALOG_CLEAR 3 -#define IDS_HARDDISK 4 -#define IDS_FLOPPY 5 -#define IDS_ABOUT 6 -#define IDS_LOADSAVE 7 -#define IDS_AVIOUTPUT 8 -#define IDS_IOPORTS 9 -#define IDS_MISC1 10 -#define IDS_MEMORY 11 -#define IDS_CPU 12 -#define IDS_CHIPSET 13 -#define IDS_INPUT 14 -#define IDS_OPENGL 15 -#define IDS_FILTER 15 -#define IDS_MISC2 16 -#define IDS_PATHS 17 -#define IDS_QUICKSTART 18 -#define IDS_FRONTEND 19 -#define IDS_CHIPSET2 20 -#define IDS_GAMEPORTS 21 -#define IDS_EXPANSION 22 -#define IDS_EXTTEXT 100 -#define IDS_EXTACTUAL 101 -#define IDS_SOUND 102 -#define IDS_CDROM 103 -#define IDS_FRAMERATE 104 -#define IDS_SECOND 105 -#define IDS_THIRD 106 -#define IDD_KICKSTART 107 -#define IDS_FOURTH 107 -#define IDD_DISPLAY 108 -#define IDS_FIFTH 108 -#define IDD_MEMORY 109 -#define IDS_SIXTH 109 -#define IDD_FLOPPY 110 -#define IDS_SEVENTH 110 -#define IDD_CPU 111 -#define IDS_EIGHTH 111 -#define IDD_ABOUT 112 -#define IDS_NINTH 112 -#define IDD_HARDDISK 113 -#define IDS_TENTH 113 -#define IDS_SELECTADF 114 -#define IDS_ADF 115 -#define IDS_CHOOSEBLANK 116 -#define IDS_SELECTHDF 117 -#define IDS_HDF 118 -#define IDS_SELECTUAE 119 -#define IDS_UAE 120 -#define IDS_SELECTROM 121 -#define IDD_SOUND 122 -#define IDS_ROM 122 -#define IDI_APPICON 123 -#define IDS_SELECTKEY 123 -#define IDI_CPU 124 -#define IDS_KEY 124 -#define IDI_ABOUT 125 -#define IDS_SELECTINFO 125 -#define IDS_NONE 126 -#define IDS_VOLUME 127 -#define IDI_HARDDISK 128 -#define IDS_PATH 128 -#define IDS_RW 129 -#define IDI_SOUND 130 -#define IDS_SECTORS 130 -#define IDS_SURFACES 131 -#define IDS_RESERVED 132 -#define IDS_BLOCKSIZE 133 -#define IDI_FLOPPY 134 -#define IDS_NAME 134 -#define IDD_LOADSAVE 135 -#define IDS_DESCRIPTION 135 -#define IDS_ONEINSTANCE 136 -#define IDI_IOPORTS 137 -#define IDS_INSTALLDIRECTX 137 -#define IDD_IOPORTS 138 -#define IDS_REGKEYCREATEFAILED 138 -#define IDS_COULDNOTLOADCONFIG 139 -#define IDD_CONTRIBUTORS 140 -#define IDS_NOHELP 140 -#define IDD_MISC1 141 -#define IDS_MUSTSELECTCONFIG 141 -#define IDD_HARDFILE 142 -#define IDS_NOAGA 142 -#define IDD_FILESYS 143 -#define IDS_INVALIDCOMPORT 143 -#define IDS_WSOCK2NEEDED 144 -#define IDD_MISC2 144 -#define IDS_UNSUPPORTEDPIXELFORMAT 145 -#define IDS_WAVEOUTOPENFAILURE 146 -#define IDS_MUSTENTERNAME 147 -#define IDS_MUSTSELECTCONFIGFORDELETE 148 -#define IDS_DELETECONFIGCONFIRMATION 149 -#define IDI_MISC1 150 -#define IDS_DELETECONFIGTITLE 150 -#define IDC_MYHAND 151 -#define IDS_GFXCARDCHECK 151 -#define IDS_GFXCARDTITLE 152 -#define IDD_DEBUGGER 152 -#define IDD_SETINFO 153 -#define IDS_MUSTSELECTPATH 153 -#define IDI_ICON1 153 -#define IDS_SETTINGSERROR 154 -#define IDD_CHIPSET 154 -#define IDS_MUSTSELECTNAME 155 -#define IDI_MOVE_UP 155 -#define IDD_CHIPSET2 155 -#define IDS_MUSTSELECTFILE 156 -#define IDI_MOVE_DOWN 156 -#define IDS_FAILEDHARDFILECREATION 157 -#define IDD_AVIOUTPUT 157 -#define IDS_CREATIONERROR 158 -#define IDI_AVIOUTPUT 158 -#define IDS_ERRORTITLE 159 -#define IDS_SELECTFILESYSROOT 160 -#define IDD_OPENGL 160 -#define IDD_FILTER 160 -#define IDS_DEFAULTMIDIOUT 161 -#define IDS_DEFAULTMIDIIN 162 -#define IDS_CONTRIBUTORS1 163 -#define IDD_HARDDRIVE 163 -#define IDS_CONTRIBUTORS2 164 -#define IDS_INVALIDPRTPORT 165 -#define IDS_SELECTUSS 166 -#define IDS_RESTOREUSS 166 -#define IDS_USS 167 -#define IDS_WRONGOSVERSION 168 -#define IDR_DRIVE_STARTUP_A500_1 168 -#define IDS_SELECTFLASH 169 -#define IDR_DRIVE_CLICK_A500_1 169 -#define IDS_FLASH 170 -#define IDR_DRIVE_SPIN_A500_1 170 -#define IDD_INPUT 171 -#define IDS_INPUTHOSTWIDGET 171 -#define IDI_INPUT 172 -#define IDS_INPUTAMIGAEVENT 172 -#define IDD_DISK 172 -#define IDS_INPUTAUTOFIRE 173 -#define IDS_SAVEUSS 174 -#define IDS_MIDIOVERFLOW 175 -#define IDS_HFDSIZE 176 -#define IDS_DEVICE 177 -#define IDS_BOOTPRI 178 -#define IDS_WRONGDXVERSION 179 -#define IDI_MISC2 180 -#define IDS_FLOPPY_COMPATIBLE 180 -#define IDR_DRIVE_SNATCH_A500_1 181 -#define IDS_FLOPPY_TURBO 181 -#define IDI_DISK 182 -#define IDR_DRIVE_SPINND_A500_1 182 -#define IDS_YES 182 -#define IDD_PANEL 183 -#define IDS_NO 183 -#define IDD_PATHS 184 -#define IDS_PRI_ABOVENORMAL 184 -#define IDI_CONFIGFILE 185 -#define IDD_QUICKSTART 185 -#define IDS_PRI_NORMAL 185 -#define IDM_SYSTRAY 186 -#define IDS_PRI_BELOWNORMAL 186 -#define IDS_PRI_LOW 187 -#define IDI_FOLDER 188 -#define IDS_OLDRTGLIBRARY 188 -#define IDI_DISPLAY 190 -#define IDS_DEFAULT_AF 190 -#define IDS_DEFAULT_WINUAE 191 -#define IDI_ROOT 192 -#define IDS_INP 192 -#define IDS_RESTOREINP 193 -#define IDI_MEMORY 194 -#define IDS_SAVEINP 194 -#define IDS_SCREEN_WINDOWED 195 -#define IDS_SCREEN_FULLSCREEN 196 -#define IDS_SCREEN_FULLWINDOW 197 -#define IDS_SCREEN_VSYNC 198 -#define IDS_SCREEN_VSYNC_AUTOSWITCH 199 -#define IDS_SOUND_MONO 200 -#define IDS_SOUND_MIXED 201 -#define IDI_QUICKSTART 201 -#define IDS_SOUND_STEREO 202 -#define IDS_SOUND_INTERPOL_DISABLED 203 -#define IDS_DISABLED 203 -#define IDS_SOUND_INTERPOL_RH 204 -#define IDI_PATHS 204 -#define IDS_SOUND_INTERPOL_CRUX 205 -#define IDS_SOUND_FILTER_OFF 206 -#define IDS_SOUND_FILTER_EMULATED 207 -#define IDS_SOUND_FILTER_EMULATED_E 208 -#define IDS_INPUT_COMPATIBILITY 209 -#define IDS_INPUT_GAMEPORTS 209 -#define IDS_INPUT_CUSTOM 210 -#define IDS_INPUT_COPY_DEFAULT 211 -#define IDS_INPUT_COPY_CUSTOM 212 -#define IDS_3D_NO_FILTER 213 -#define IDS_3D_BILINEAR 214 -#define IDS_VSYNC_DEFAULT 215 -#define IDS_DRIVESOUND_NONE 216 -#define IDS_DRIVESOUND_DEFAULT_A500 217 -#define IDS_AVIOUTPUT_NOCODEC 218 -#define IDS_DISK_IMAGENAME 219 -#define IDS_DISK_DRIVENAME 220 -#define IDS_UNSUPPORTEDSCREENMODE 222 -#define IDS_UNSUPPORTEDSCREENMODE_1 223 -#define IDS_UNSUPPORTEDSCREENMODE_2 224 -#define IDS_UNSUPPORTEDSCREENMODE_3 225 -#define IDS_UNSUPPORTEDSCREENMODE_4 226 -#define IDS_FLOPPYTYPE35DD 227 -#define IDS_FLOPPYTYPE35HD 228 -#define IDS_FLOPPYTYPE525SD 229 -#define IDS_FLOPPYTYPEDISABLED 230 -#define IDS_STMENUNOFLOPPY 231 -#define IDS_TREEVIEW_HARDWARE 232 -#define IDS_TREEVIEW_HOST 233 -#define IDS_TREEVIEW_MISC 234 -#define IDS_TREEVIEW_SETTINGS 235 -#define IDS_WINUAETITLE_MMB 236 -#define IDS_WINUAETITLE_NORMAL 237 -#define IDS_STARTEMULATION 238 -#define IDS_TREEVIEW_ABOUT 239 -#define IDS_NOHARDDRIVES 240 -#define IDS_DEFAULT_HOST 241 -#define IDS_SOUND_4CHANNEL 242 -#define IDS_HF_FS_CUSTOM 243 -#define IDS_SELECTFS 244 -#define IDS_KEYJOY 245 -#define IDB_XARCADE 246 -#define IDS_STATEFILE_UNCOMPRESSED 246 -#define IDS_STATEFILE_RAMDUMP 247 -#define IDS_STATEFILE_WAVE 248 -#define IDD_FRONTEND 249 -#define IDS_SOUND_SWAP_PAULA 249 -#define IDS_SOUND_SWAP_AHI 250 -#define IDD_PROGRESSBAR 250 -#define IDS_SOUND_SWAP_BOTH 251 -#define IDD_STRINGBOX 251 -#define IDB_LCD160X43 252 -#define IDS_SOUND_FILTER_ON_AGA 252 -#define IDS_SOUND_FILTER_ON 253 -#define IDS_SOUND_FILTER_ON_A500 253 -#define IDS_DRIVESOUND_PC_FLOPPY 254 -#define IDS_FLOPPYTYPE35DDESCOM 255 -#define IDS_SOUND_STEREO2 256 -#define IDS_INPUT_CUSTOMEVENT 257 -#define IDS_DEFAULT_NEWWINUAE 258 -#define IDS_SOUND_CLONED51 259 -#define IDS_SOUND_51 260 -#define IDS_AUTOMATIC 261 -#define IDI_GAMEPORTS 262 -#define IDS_ALL 262 -#define IDD_GAMEPORTS 263 -#define IDS_INPUTTOGGLE 263 -#define IDS_NETDISCONNECTED 264 -#define IDS_QS_CD 265 -#define IDS_QS_CD_AUTO 266 -#define IDS_QS_CD_IMAGE 267 -#define IDS_REMAPTITLE 268 -#define IDS_FILTER_NOOVERLAYS 269 -#define IDS_STMENUNOCD 270 -#define IDS_ON 271 -#define IDS_INPUTQUALIFIER 272 -#define IDS_GENERIC 273 -#define IDS_AUTODETECT 274 -#define IDS_NUMSG_NEEDEXT2 300 -#define IDS_NUMSG_NOROMKEY 301 -#define IDS_NUMSG_KSROMCRCERROR 302 -#define IDS_NUMSG_KSROMREADERROR 303 -#define IDS_NUMSG_NOEXTROM 304 -#define IDS_NUMSG_MODRIP_NOTFOUND 305 -#define IDS_NUMSG_MODRIP_FINISHED 306 -#define IDS_NUMSG_MODRIP_SAVE 307 -#define IDS_NUMSG_KS68020 308 -#define IDS_NUMSG_ROMNEED 309 -#define IDS_NUMSG_NOZLIB 310 -#define IDS_NUMSG_STATEHD 311 -#define IDS_NUMSG_NOCAPS 312 -#define IDS_NUMSG_OLDCAPS 313 -#define IDS_IMGCHK_BOOTBLOCKCRCERROR 314 -#define IDS_IMGCHK_BOOTBLOCKNO 315 -#define IDS_IMGCHK_DAMAGED 316 -#define IDS_IMGCHK_KS2 317 -#define IDS_IMGCHK_KS3 318 -#define IDS_ROMSCANEND 319 -#define IDS_ROM_AVAILABLE 320 -#define IDS_ROM_UNAVAILABLE 321 -#define IDS_HARDDRIVESAFETYWARNING1 322 -#define IDS_NUMSG_KS68EC020 323 -#define IDS_ROMSCANNOROMS 324 -#define IDS_NUMSG_KICKREP 325 -#define IDS_NUMSG_KICKREPNO 326 -#define IDS_NUMSG_NOROM 327 -#define IDS_HDCLONE_OK 328 -#define IDS_HDCLONE_FAIL 329 -#define IDR_DBGACCEL 330 -#define IDS_NUMSG_KS68030 331 -#define IDS_NUMSG_EXPROMNEED 332 -#define IDS_HARDDRIVESAFETYWARNING2 333 -#define IDM_DBGCONTEXTMENU 334 -#define IDS_SB_FAVORITENAME 334 -#define IDD_DBGMEMINPUT 335 -#define IDS_SB_CUSTOMEVENT 335 -#define IDS_FLOPPYTYPE35DDPC 336 -#define IDS_FLOPPYTYPE35HDPC 337 -#define IDS_JOYMODE_DEFAULT 338 -#define IDS_JOYMODE_MOUSE 339 -#define IDS_JOYMODE_JOYSTICK 340 -#define IDS_JOYMODE_JOYSTICKANALOG 341 -#define IDS_JOYMODE_LIGHTPEN 342 -#define IDS_JOYMODE_MOUSE_CDTV 343 -#define IDS_JOYMODE_JOYSTICK_CD32 344 -#define IDS_TABLET_BOTH_CURSORS 345 -#define IDI_DISKIMAGE 345 -#define IDS_TABLET_NATIVE_CURSOR 346 -#define IDS_TABLET_HOST_CURSOR 347 -#define IDI_PORTS 347 -#define IDS_AUTOSCALE_DISABLED 348 -#define IDS_AUTOSCALE_SCALING 349 -#define IDI_FILE 349 -#define IDS_AUTOSCALE_RESIZE 350 -#define IDS_PRINTER_ASCII 351 -#define IDD_EXPANSION 351 -#define IDS_PRINTER_EPSON 352 -#define IDS_PRINTER_EPSON9 352 -#define IDS_PRINTER_POSTSCRIPT_DETECTION 353 -#define IDI_EXPANSION 353 -#define IDS_PRINTER_POSTSCRIPT_EMULATION 354 -#define IDD_INPUTMAP 354 -#define IDS_PRINTER_PASSTHROUGH 355 -#define IDD_INFOBOX 355 -#define IDS_RES_LORES 356 -#define IDS_RES_HIRES 357 -#define IDS_RES_SUPERHIRES 358 -#define IDS_PRINTER_EPSON48 359 -#define IDS_SELECTCD 360 -#define IDS_CD 361 -#define IDS_BUFFER_SINGLE 362 -#define IDS_BUFFER_DOUBLE 363 -#define IDS_BUFFER_TRIPLE 364 -#define IDS_AUTOSCALE_CENTER 365 -#define IDS_AUTOSCALE_MAX 366 -#define IDS_AUTOSCALE_TV 367 -#define IDS_JOYMODE_GAMEPAD 368 -#define IDS_AUTOSCALE_DEFAULT 369 -#define IDS_AUTOSCALE_MANUAL 370 -#define IDS_PORT_AUTOFIRE 371 -#define IDS_PORT_AUTOFIRE_TOGGLE 372 -#define IDS_PORT_AUTOFIRE_ALWAYS 373 -#define IDS_PORT_AUTOFIRE_NO 374 -#define IDS_AUTOSCALE_INTEGER 375 -#define IDS_SCREEN_VSYNC2_AUTOSWITCH 376 -#define IDS_SCREEN_VSYNC2 377 -#define IDS_SCREEN_VSYNC_NONE 378 -#define IDS_FILTEROVERLAYTYPE_MASKS 379 -#define IDS_FILTEROVERLAYTYPE_OVERLAYS 380 -#define IDS_AUTOSCALE_INTEGER_AUTOSCALE 381 -#define IDS_WSTYLE_BORDERLESS 382 -#define IDS_WSTYLE_MINIMAL 383 -#define IDS_WSTYLE_STANDARD 384 -#define IDS_WSTYLE_EXTENDED 385 -#define IDD_LIST 386 -#define IDS_MISCLISTITEMS1 386 -#define IDS_MISCLISTITEMS2 387 -#define IDS_MISCLISTITEMS3 388 -#define IDS_QS_MODELS 1000 -#define IDS_QS_MODEL_A500 1001 -#define IDS_QS_MODEL_A500P 1002 -#define IDS_QS_MODEL_A600 1003 -#define IDS_QS_MODEL_A1000 1004 -#define IDS_QS_MODEL_A1200 1005 -#define IDS_QS_MODEL_CD32 1006 -#define IDS_QS_MODEL_CDTV 1007 -#define IDS_QS_MODEL_UAE 1008 -#define IDS_QS_MODEL_ARCADIA 1009 -#define IDS_QS_MODEL_A3000 1010 -#define IDS_QS_MODEL_A4000 1011 -#define IDS_QS_MODEL_A4000T 1012 -#define IDC_RESOLUTION 1021 -#define IDC_SERIAL 1022 -#define IDC_REFRESHRATE 1022 -#define IDC_ILLEGAL 1023 -#define IDC_MIDILIST 1023 -#define IDC_MIDIOUTLIST 1023 -#define IDC_DA_MODE 1023 -#define IDC_MIDIINLIST 1024 -#define IDC_RESOLUTION2 1024 -#define IDC_DISPLAYSELECT 1024 -#define IDC_AUTOCONFIG 1025 -#define IDC_PRINTERLIST 1025 -#define IDC_RESOLUTIONDEPTH 1025 -#define IDC_CHIPMEM 1026 -#define IDC_CREATELOGFILE 1026 -#define IDC_PORT0_JOYS 1026 -#define IDC_SCREENMODE_NATIVE 1026 -#define IDC_PRINTERTYPELIST 1026 -#define IDC_FASTMEM 1027 -#define IDC_PORT1_JOYS 1027 -#define IDC_SCREENMODE_RTG 1027 -#define IDC_DONGLELIST 1027 -#define IDC_MBMEM1 1028 -#define IDC_PORT_TABLET_CURSOR 1028 -#define IDC_SAMPLERLIST 1028 -#define IDC_DISPLAY_BUFFERCNT 1028 -#define IDC_PORT0_JOYSMODE 1029 -#define IDC_SCREENMODE_NATIVE2 1029 -#define IDC_SLOWMEM 1030 -#define IDC_PORT1_JOYSMODE 1030 -#define IDC_SCREENMODE_RTG2 1030 -#define IDC_MBMEM2 1031 -#define IDC_PORT2_JOYS 1031 -#define IDC_PORT3_JOYS 1032 -#define IDC_PARALLEL 1033 -#define IDC_PORT0_AF 1033 -#define IDC_PORT1_AF 1034 -#define IDC_FOCUSMINIMIZE 1041 -#define IDC_FASTTEXT 1043 -#define IDC_FASTRAM 1044 -#define IDC_CHIPRAM 1045 -#define IDC_SLOWRAM 1046 -#define IDC_Z3TEXT 1047 -#define IDC_Z3FASTRAM 1048 -#define IDC_Z3FASTMEM 1049 -#define IDC_MBRAM1 1050 -#define IDC_MBRAM2 1051 -#define IDC_Z3CHIPMEM 1052 -#define IDC_Z3CHIPRAM 1053 -#define IDC_MAX32RAM 1054 -#define IDC_UAEHOME 1070 -#define IDC_PICASSOHOME 1071 -#define IDC_AMIGAHOME 1072 -#define IDC_WINUAEHOME 1073 -#define IDC_AIABHOME 1074 -#define IDC_CLOANTOHOME 1075 -#define IDC_THEROOTS 1076 -#define IDC_CAPS 1077 -#define IDC_ABIME 1078 -#define IDC_AMIGASYS 1079 -#define IDC_AMIKIT 1080 -#define IDC_RICHEDIT1 1091 -#define IDC_RICHEDIT2 1092 -#define IDC_CONTRIBUTORS 1124 -#define IDC_BLACKER_THAN_BLACK 1170 -#define IDC_BLITIMM 1174 -#define IDC_BLITWAIT 1175 -#define IDC_LORES 1176 -#define IDC_RATE2BOX 1177 -#define IDC_LORES_SMOOTHED 1179 -#define IDC_FLICKERFIXER 1180 -#define IDC_AUTORESOLUTION 1181 -#define IDC_RATE2ENABLE 1182 -#define IDC_FRAMERATE 1185 -#define IDC_XSIZE 1187 -#define IDC_YSIZE 1188 -#define IDC_INPUTAUTOFIRERATE 1188 -#define IDC_LM_NORMAL 1189 -#define IDC_INPUTSPEEDD 1189 -#define IDC_LM_DOUBLED 1190 -#define IDC_INPUTSPEEDA 1190 -#define IDC_GFXCARDTEXT 1191 -#define IDC_LM_SCANLINES 1191 -#define IDC_INPUTSPEEDM 1191 -#define IDC_P96RAM 1192 -#define IDC_P96MEM 1193 -#define IDC_DA_SLIDER 1193 -#define IDC_FRAMERATE2 1194 -#define IDC_RATE2TEXT 1195 -#define IDC_DA_TEXT 1196 -#define IDC_CPU0 1200 -#define IDC_CPU1 1201 -#define IDC_CPU2 1202 -#define IDC_CPU3 1203 -#define IDC_CPU4 1204 -#define IDC_CPU5 1205 -#define IDC_CS_HOST 1209 -#define IDC_CS_68000 1210 -#define IDC_CS_ADJUSTABLE 1211 -#define IDC_COMPATIBLE 1214 -#define IDC_TRUST0 1215 -#define IDC_TRUST1 1216 -#define IDC_CACHE 1218 -#define IDC_CYCLEEXACT 1219 -#define IDC_CPUIDLE 1220 -#define IDC_GENLOCK 1220 -#define IDC_COMPATIBLE_FPU 1221 -#define IDC_FASTERRTG 1221 -#define IDC_COMPATIBLE24 1222 -#define IDC_SPEED 1223 -#define IDC_FPU0 1224 -#define IDC_FPU1 1225 -#define IDC_FPU2 1226 -#define IDC_FPU3 1227 -#define IDC_SOUNDSETTINGS 1229 -#define IDC_8BIT 1230 -#define IDC_16BIT 1231 -#define IDC_11KHZ 1232 -#define IDC_22KHZ 1233 -#define IDC_44KHZ 1234 -#define IDC_48KHZ 1235 -#define IDC_SOUNDSIZE 1236 -#define IDC_FREQUENCY 1237 -#define IDC_SOUND0 1238 -#define IDC_SOUND1 1239 -#define IDC_SOUND2 1240 -#define IDC_SOUNDSTYLE 1242 -#define IDC_SOUNDSTYLE0 1243 -#define IDC_STEREO 1244 -#define IDC_SOUNDSTYLE1 1245 -#define IDC_SOUNDINTERPOLATION 1248 -#define IDC_INTERPOLATION0 1249 -#define IDC_INTERPOLATION1 1250 -#define IDC_INTERPOLATION2 1251 -#define IDC_STEREOMODE 1252 -#define IDC_SOUNDINTERPOLATION2 1252 -#define IDC_STEREOMODE0 1253 -#define IDC_STEREOMODE1 1254 -#define IDC_STEREOMODE2 1255 -#define IDC_SOUNDINTERPOLATION3 1256 -#define IDC_DF0TEXT 1270 -#define IDC_DF1TEXT 1271 -#define IDC_DF2TEXT 1272 -#define IDC_DF3TEXT 1273 -#define IDC_EJECT0 1274 -#define IDC_EJECT1 1275 -#define IDC_EJECT2 1276 -#define IDC_EJECT3 1277 -#define IDC_DF0 1278 -#define IDC_DF1 1279 -#define IDC_DF2 1280 -#define IDC_DF3 1281 -#define IDC_CREATE 1282 -#define IDC_CREATE_RAW 1283 -#define IDC_SNAPSHOTNAME 1284 -#define IDC_SNAPSHOT 1285 -#define IDC_SAVEIMAGE0 1285 -#define IDC_DOSAVESTATE 1286 -#define IDC_SAVEIMAGE1 1286 -#define IDC_DOLOADSTATE 1287 -#define IDC_SAVEIMAGE2 1287 -#define IDC_PROWIZARD 1288 -#define IDC_SAVEIMAGE3 1288 -#define IDC_GUI_FONT 1288 -#define IDC_GUI_DEFAULT 1289 -#define IDC_GUI_LISTFONT 1290 -#define IDC_PORT0_JOYSC 1302 -#define IDC_PORT0_KBDA 1303 -#define IDC_PORT0_KBDB 1304 -#define IDC_PORT0_KBDC 1305 -#define IDC_PORT0_KBDD 1306 -#define IDC_PORT0_KBDE 1307 -#define IDC_PORT1_JOYSC 1308 -#define IDC_PORT1_KBDA 1309 -#define IDC_PORT1_KBDB 1310 -#define IDC_PORT1_KBDC 1311 -#define IDC_PORT1_KBDD 1312 -#define IDC_PORT1_KBDE 1313 -#define IDC_MIDIFRAME 1314 -#define IDC_SERPARFRAME 1315 -#define IDC_SERIALFRAME 1316 -#define IDC_EDIT 1334 -#define IDC_REMOVE 1335 -#define IDC_VOLUMELIST 1336 -#define IDC_UP 1337 -#define IDC_DOWN 1338 -#define IDC_NEW_FS 1339 -#define IDC_NEW_HF 1340 -#define IDC_NEW_HD 1341 -#define IDC_PORT0 1342 -#define IDC_NEW_FSARCH 1342 -#define IDC_PORT1 1343 -#define IDC_PATH_NAME 1362 -#define IDC_SELECTOR 1363 -#define IDC_VOLUME_NAME 1364 -#define IDC_HARDFILE_DEVICE 1364 -#define IDC_SECTORS 1365 -#define IDC_VOLUME_DEVICE 1365 -#define IDC_HEADS 1366 -#define IDC_RESERVED 1367 -#define IDC_BLOCKSIZE 1368 -#define IDC_HARDFILE_BOOTPRI 1369 -#define IDC_SECTORS_TEXT 1370 -#define IDC_SURFACES_TEXT 1371 -#define IDC_RESERVED_TEXT 1372 -#define IDC_RESERVED_TEXT2 1373 -#define IDC_BLOCKSIZE_TEXT 1374 -#define ID_OK 1375 -#define IDC_HARDFILE_BOOTPRI_TEXT 1375 -#define IDC_PATH_FILESYS 1376 -#define IDC_HARDFILE_DIR_TEXT 1377 -#define IDC_HARDFILE_DEVICE_TEXT 1378 -#define IDC_HFRDB 1380 -#define IDC_RDB 1380 -#define IDC_HARDFILE_FILESYS_TEXT 1380 -#define IDC_FS_AUTOBOOT 1380 -#define IDC_FILESYS_SELECTOR 1381 -#define IDC_HDF_AUTOBOOT 1382 -#define IDC_HDF_DONOTMOUNT 1383 -#define IDC_ROMFILE 1390 -#define IDC_KEYFILE 1391 -#define IDC_KICKCHOOSER 1392 -#define IDC_KEYCHOOSER 1393 -#define IDC_ROMFILE2 1394 -#define IDC_ROMCHOOSER2 1395 -#define IDC_FLASHCHOOSER 1396 -#define IDC_FLASHFILE 1397 -#define IDC_CARTFILE 1398 -#define IDC_CARTCHOOSER 1399 -#define IDC_SAVE 1400 -#define IDC_LOAD 1401 -#define IDC_DELETE 1403 -#define IDC_CONFIGLIST 1404 -#define IDC_EDITNAME 1405 -#define IDC_EDITDESCRIPTION 1406 -#define IDC_QUICKSAVE 1408 -#define IDC_QUICKLOAD 1409 -#define IDC_EXIT 1410 -#define IDC_EDITPATH 1410 -#define IDC_HDF_RDB 1500 -#define IDC_HFSIZE 1501 -#define IDC_HF_SIZE 1501 -#define IDC_LINEMODE 1502 -#define IDC_CREATEHF 1502 -#define IDC_HF_CREATE 1502 -#define IDC_SOCKETS 1503 -#define IDC_HF_DOSTYPE 1503 -#define IDC_HDF_CONTROLLER 1504 -#define IDC_RESETAMIGA 1504 -#define IDC_QUITEMU 1505 -#define IDC_MAPDRIVES 1507 -#define IDC_CPUTEXT 1508 -#define IDC_MAPDRIVES_NET 1508 -#define IDC_RESTARTEMU 1508 -#define IDC_CACHETEXT 1509 -#define IDC_SWAP 1509 -#define IDC_MAPDRIVES_CD 1509 -#define IDC_SELECTRESTEXT 1510 -#define IDC_FLUSHPRINTER 1510 -#define IDC_MAPDRIVES_REMOVABLE 1510 -#define IDC_PORT0_TEST 1510 -#define IDC_SCREENRESTEXT 1511 -#define IDC_MAPDRIVES_AUTO 1511 -#define IDC_PORT0_TEST2 1511 -#define IDC_PORT1_TEST 1511 -#define IDC_WIDTHTEXT 1512 -#define IDC_WINDOWEDTEXT 1512 -#define IDC_PORT2_TEST 1512 -#define IDC_MAPDRIVES_LIMIT 1512 -#define IDC_HEIGHTTEXT 1513 -#define IDC_PORT3_TEST 1513 -#define IDC_SETTINGSTEXT 1514 -#define IDC_REFRESHTEXT 1515 -#define IDC_SETTINGSTEXT2 1515 -#define IDC_DISABLE1 1516 -#define IDC_DF1WP 1516 -#define IDC_QUICKSTART_COMPA 1516 -#define IDC_REFRESH2TEXT 1516 -#define IDC_DISABLE2 1517 -#define IDC_DF2WP 1517 -#define IDC_QUICKSTART_DF 1517 -#define IDC_DISABLE3 1518 -#define IDC_XCENTER 1518 -#define IDC_DF3WP 1518 -#define IDC_DF1WP2 1518 -#define IDC_QUICKSTART_HOST 1518 -#define IDC_YCENTER 1519 -#define IDC_DISABLE0 1519 -#define IDC_DF0WP 1519 -#define IDC_OCS 1520 -#define IDC_HDFLOPPY 1520 -#define IDC_SETTINGSTEXT3 1520 -#define IDC_ECS_AGNUS 1521 -#define IDC_ECS_DENISE 1522 -#define IDC_ECS 1523 -#define IDC_AGA 1524 -#define IDC_NTSC 1525 -#define IDC_NOSPEED 1527 -#define IDC_NOSOUND 1528 -#define IDC_INACTIVE_NOSOUND 1528 -#define IDC_MIDI 1529 -#define IDC_NOSPEEDPAUSE 1529 -#define IDC_INACTIVE_PAUSE 1529 -#define IDC_KICKSHIFTER 1530 -#define IDC_MIDI2 1530 -#define IDC_HIGHPRIORITY 1530 -#define IDC_MINIMIZED_NOSOUND 1530 -#define IDC_MINIMIZED_PAUSE 1531 -#define IDC_STATEREC_RECORD 1532 -#define IDC_KBLED_USB 1533 -#define IDC_ACTIVE_PAUSE 1534 -#define IDC_KBLED_USB2 1534 -#define IDC_ACTIVE_NOSOUND 1535 -#define IDC_STATECLEAR 1536 -#define IDC_SER_SHARED 1553 -#define IDC_GUI_RESIZE 1553 -#define IDC_SER_CTSRTS 1554 -#define IDC_SER_DIRECT 1555 -#define IDC_PSPRINTER 1556 -#define IDC_PSPRINTERDETECT 1557 -#define IDC_UAESERIAL 1558 -#define IDC_VIEWINFO 1568 -#define IDC_SETINFO 1569 -#define IDC_FLOPPYSLIDER 1570 -#define IDC_FLOPPYSLIDERTEXT 1571 -#define IDC_FLOPPYSPEED 1572 -#define IDC_FLOPPYSPD 1572 -#define IDC_GUILANGUAGE_LIST 1573 -#define IDC_SOUNDBUFFERRAM 1574 -#define IDC_SOUNDADJUST 1575 -#define IDC_SOUNDBUFFERTEXT 1576 -#define IDC_SOUNDVOLUME 1576 -#define IDC_SOUNDBUFFERMEM 1577 -#define IDC_HARDFLUSH 1578 -#define IDC_SOUNDADJUSTNUM 1578 -#define IDC_CONSTJUMP 1579 -#define IDC_SOUNDDRIVEVOLUME 1579 -#define IDC_JITFPU 1580 -#define IDC_SOUNDVOLUME2 1580 -#define IDC_NOFLAGS 1581 -#define IDC_SOUNDDRIVEVOLUME2 1581 -#define IDC_CS_CACHE_TEXT 1582 -#define IDC_CS_CACHE_TEXT2 1583 -#define IDC_COLLISIONS 1584 -#define IDC_JITENABLE 1584 -#define IDC_DISASSEMBLY 1585 -#define IDC_MMUENABLE 1585 -#define IDC_COLLISION0 1589 -#define IDC_COLLISION1 1590 -#define IDC_AUDIOSYNC 1590 -#define IDC_COLLISION2 1591 -#define IDC_COLLISION3 1592 -#define IDC_SOUNDLAGSLIDER 1592 -#define IDC_SOUNDLAGCAPTION 1594 -#define IDC_FLOPPYTYPE 1594 -#define IDC_SYNCPARAMS 1595 -#define IDC_DF0TYPE 1595 -#define IDC_SOUNDLAGTEXT 1596 -#define IDC_DF1TYPE 1596 -#define IDC_DF2TYPE 1597 -#define IDC_SOUNDSPEEDSLIDER 1598 -#define IDC_DF3TYPE 1598 -#define IDC_SOUNDSPEEDTEXT 1599 -#define IDC_SOUNDSPEEDCAPTION 1600 -#define IDC_RTGMATCHDEPTH 1601 -#define IDC_ROMFILE2TEXT 1602 -#define IDC_ROMTEXT 1603 -#define IDC_KEYTEXT 1604 -#define IDC_CD32 1605 -#define IDC_AKIKOC2P 1605 -#define IDC_FLASHTEXT 1605 -#define IDC_SCSIDEVICE 1606 -#define IDC_FLASHTEXT2 1606 -#define IDC_INPUTTYPE 1607 -#define IDC_INPUTSELECTTEXT 1608 -#define IDC_NOUAEFSDB 1608 -#define IDC_INPUTDEVICE 1609 -#define IDC_MAPROM 1609 -#define IDC_NORECYCLEBIN 1609 -#define IDC_AVIOUTPUT_FILETEXT 1610 -#define IDC_INPUTDEVICETEXT 1610 -#define IDC_ALWAYSONTOP 1610 -#define IDC_AVIOUTPUT_FILE 1611 -#define IDC_INPUTLIST 1611 -#define IDC_CATWEASEL 1611 -#define IDC_INPUTAMIGA 1612 -#define IDC_AVIOUTPUT_VIDEO 1613 -#define IDC_INPUTAUTOFIRE 1613 -#define IDC_PORT_MOUSETRICK 1613 -#define IDC_AVIOUTPUT_AUDIO 1614 -#define IDC_INPUTCOPYFROM 1614 -#define IDC_SANA2 1614 -#define IDC_AVIOUTPUT_VIDEO_CODEC 1615 -#define IDC_INPUTDEVICEDISABLE 1615 -#define IDC_AVIOUTPUT_ACTIVATED 1615 -#define IDC_A2065 1615 -#define IDC_AVIOUTPUT_AUDIO_CODEC 1616 -#define IDC_INPUTAMIGACNT 1616 -#define IDC_FILTERHZ 1616 -#define IDC_SAMPLERIPPER_ACTIVATED 1616 -#define IDC_AVIOUTPUT_BORDER_TRIM 1617 -#define IDC_FILTERVZ 1617 -#define IDC_AVIOUTPUT_AUDIO_STATIC 1618 -#define IDC_FILTERHO 1618 -#define IDC_AVIOUTPUT_VIDEO_STATIC 1619 -#define IDC_FILTERVO 1619 -#define IDC_AVIOUTPUT_8BIT 1620 -#define IDC_FILTERASPECT 1620 -#define IDC_STATEREC_PLAY 1620 -#define IDC_AVIOUTPUT_24BIT 1621 -#define IDC_FILTERASPECT2 1621 -#define IDC_STATEREC_SAVE 1621 -#define IDC_AVIOUTPUT_WIDTH 1622 -#define IDC_AVIOUTPUT_HEIGHT 1623 -#define IDC_AVIOUTPUT_FRAME 1624 -#define IDC_FILTERXL 1624 -#define IDC_FILTERSLR 1625 -#define IDC_FILTERHZMULT 1626 -#define IDC_FILTERMODE 1627 -#define IDC_FILTERFILTER 1628 -#define IDC_FILTERDEFAULT 1629 -#define IDC_FILTERXTRA 1630 -#define IDC_INPUTDEADZONE 1630 -#define IDC_INPUTCOPY 1631 -#define IDC_FILTERPRESETS 1631 -#define IDC_SCREENSHOT 1632 -#define IDC_INPUTSWAP 1632 -#define IDC_FILTERPRESETLOAD 1632 -#define IDC_FLOPPYSPDTEXT 1633 -#define IDC_FILTERPRESETSAVE 1633 -#define IDC_INPUTREMAP 1633 -#define IDC_FLOPPYSPD_TEXT 1634 -#define IDC_FILTERPRESETDELETE 1634 -#define IDC_INPUTTEST 1634 -#define IDC_HARDDRIVE 1635 -#define IDC_INACTIVE_PRI 1635 -#define IDC_FILTERVZMULT 1635 -#define IDC_INPUTTEST2 1635 -#define IDC_SOUNDPRIMARY 1636 -#define IDC_MINIMIZED_PRI 1636 -#define IDC_FILTERAUTOSCALE 1636 -#define IDC_VOLUME_BOOTPRI_TEXT 1637 -#define IDC_FILTEROVERLAY 1637 -#define IDC_VOLUME_BOOTPRI 1638 -#define IDC_FILTEROVERLAYTYPE 1638 -#define IDC_KBLED1 1639 -#define IDC_KBLED2 1640 -#define IDC_SOUNDFILTER 1640 -#define IDC_KBLED3 1641 -#define IDC_SOUNDCALIBRATE 1641 -#define IDC_ACTIVE_PRIORITY 1642 -#define IDC_SOUNDDRIVE 1642 -#define IDC_KBLED4 1642 -#define IDC_GUI_SIZE 1642 -#define IDC_INACTIVE_PRIORITY 1643 -#define IDC_ACTIVE_PRI 1644 -#define IDC_MINIMIZED_PRIORITY 1645 -#define IDC_AVIOUTPUT_FRAMELIMITER 1645 -#define IDC_STATEREC_RATE 1646 -#define IDC_SOUNDDRIVESELECT 1647 -#define IDC_PANELTREE 1647 -#define IDC_AVIOUTPUT_NOSOUNDOUTPUT 1647 -#define IDC_STATE_BUFFERSIZE_TEXT 1648 -#define IDC_CONFIGTREE 1648 -#define IDC_AVIOUTPUT_NOSOUNDSYNC 1648 -#define IDC_AVIOUTPUT_OPTIONS 1649 -#define IDC_STATE_RATE_TEXT 1649 -#define IDC_DISKLISTREMOVE 1649 -#define IDC_DF0QENABLE 1649 -#define IDC_AVIOUTPUT_ORIGINALSIZE 1649 -#define IDC_SOUNDCARD 1650 -#define IDC_UPBM 1650 -#define IDC_DISKLISTINSERT 1650 -#define IDC_DF1QENABLE 1650 -#define IDC_AVIOUTPUT_ORIGINALSIZE2 1650 -#define IDC_SCREENSHOT_ORIGINALSIZE 1650 -#define IDC_SOUNDCARDLIST 1651 -#define IDC_STATE_BUFFERSIZE2 1651 -#define IDC_STATEREC_BUFFERSIZE 1651 -#define IDC_SOUNDFREQ 1652 -#define IDC_STATEREC_AUTOPLAY 1652 -#define IDC_SOUNDFREQTXT 1653 -#define IDC_PANEL_FRAME 1653 -#define IDC_SOUNDFILTERTXT 1654 -#define IDC_PANEL_FRAME_OUTER 1654 -#define IDC_SOUNDSTEREO 1655 -#define IDC_CONFIGTYPE 1655 -#define IDC_SOUNDDRIVETXT 1656 -#define IDC_PATHS_ROM 1656 -#define IDC_SOUNDSTEREOSEP 1656 -#define IDC_SOUNDSTEREOTXT 1657 -#define IDC_PATHS_CONFIG 1657 -#define IDC_SOUNDINTERPOLATIONTXT 1658 -#define IDC_PATHS_SCREENSHOT 1658 -#define IDC_DISK 1659 -#define IDC_DISKLIST 1659 -#define IDC_PATHS_SAVEIMAGE 1659 -#define IDC_SOUNDSTEREOSEPTXT 1659 -#define IDC_PATHS_SAVESTATE 1660 -#define IDC_SOUNDSTEREOMIXTXT 1660 -#define IDC_PATHS_ROMS 1661 -#define IDC_SOUNDSTEREOMIX 1661 -#define IDC_PATHS_CONFIGS 1662 -#define IDC_SOUNDSWAP 1662 -#define IDC_PATHS_SCREENSHOTS 1663 -#define IDC_PATHS_SAVESTATES 1664 -#define IDC_SOUNDSTEREOSWAPTXT 1664 -#define IDC_SOUNDSWAPTXT 1664 -#define IDC_PATHS_SAVEIMAGES 1665 -#define IDC_PATHS_ROML 1666 -#define IDC_PATHS_CONFIGL 1667 -#define IDC_PATHS_SCREENSHOTL 1668 -#define IDC_PATHS_STATEFILEL 1669 -#define IDC_PATHS_SAVEIMAGEL 1670 -#define IDC_PATHS_DEFAULT 1671 -#define IDC_ROM_RESCAN 1672 -#define IDC_QUICKSTARTMODE 1673 -#define IDC_RESETREGISTRY 1673 -#define IDC_QUICKSTART_MODEL 1674 -#define IDC_PATHS_AVIOUTPUTL 1674 -#define IDC_QUICKSTART_CONFIGURATION 1675 -#define IDC_PATHS_AVIOUTPUT 1675 -#define IDC_QUICKSTART_COMPATIBILITY 1676 -#define IDC_PATHS_AVIOUTPUTS 1676 -#define IDC_QUICKSTART_CONFIG 1677 -#define IDC_RESETDISKHISTORY 1677 -#define IDC_DF0Q 1678 -#define IDC_DF0QQ 1678 -#define IDC_PATHS_RIPSL 1678 -#define IDC_DF1Q 1679 -#define IDC_QUICKSTART_HOSTCONFIG 1679 -#define IDC_PATHS_RIP 1679 -#define IDC_DF1QQ 1680 -#define IDC_PATHS_RIPS 1680 -#define IDC_QUICKSTART_SETCONFIG 1681 -#define IDC_CONFIGAUTO 1682 -#define IDC_CD0Q_TYPE 1682 -#define IDC_DF0TEXTQ 1683 -#define IDC_CONFIGNOLINK 1683 -#define IDC_DF0WPQ 1684 -#define IDC_EJECT0Q 1685 -#define IDC_DF1WPQ 1686 -#define IDC_EJECT1Q 1687 -#define IDC_DF1TEXTQ 1688 -#define IDC_FILTERXLV 1692 -#define IDC_FILTERVOV 1693 -#define IDC_FILTERHOV 1694 -#define IDC_CONFIGLINK 1694 -#define IDC_FILTERVZV 1695 -#define IDC_PS_PARAMS 1695 -#define IDC_FILTERHZV 1696 -#define IDC_HF_TYPE 1696 -#define IDC_PRINTERAUTOFLUSH 1697 -#define IDC_PRINTERAUTOFLUSHTXT 1698 -#define IDC_DISKTEXT 1699 -#define IDC_FE_LIST 1700 -#define IDC_FE_INFO 1701 -#define IDC_FE_INFO2 1702 -#define IDC_FE_SCREENSHOT 1702 -#define IDC_PATHS_DEFAULTTYPE 1704 -#define IDC_SCSIMODE 1705 -#define IDC_PROGRESSBAR 1705 -#define IDC_PROGRESSBAR_TEXT 1706 -#define IDC_LANGUAGE 1706 -#define IDC_CREATE_NAME 1707 -#define IDC_NETDEVICE 1707 -#define IDC_SOUND_AUTO 1709 -#define IDC_FILTERKEEPASPECT 1709 -#define IDC_CS_RTC 1710 -#define IDC_FILTERKEEPAUTOSCALEASPECT 1710 -#define IDC_CS_CIAA_TOD1 1711 -#define IDC_CS_CIAA_TOD2 1712 -#define IDC_CS_EXT 1712 -#define IDC_CS_CIAA_TOD3 1713 -#define IDC_SOUND_DS 1713 -#define IDC_MONITOREMU 1713 -#define IDC_CS_COMPATIBLE 1714 -#define IDC_CS_RAMSEYREV 1715 -#define IDC_SOUND_WASAPI 1715 -#define IDC_CS_KSMIRROR_E0 1716 -#define IDC_STRINGBOXEDIT 1716 -#define IDC_SOUND_OPENAL 1716 -#define IDC_CS_CD32CD 1717 -#define IDC_CS_CD32C2P 1718 -#define IDC_SOUND_PORTAUDIO 1718 -#define IDC_CS_CD32NVRAM 1719 -#define IDC_CS_CDTVCD 1720 -#define IDC_CS_CDTVRAM 1721 -#define IDC_CS_IDE1 1722 -#define IDC_CS_IDE2 1723 -#define IDC_CS_IDE3 1724 -#define IDC_CS_A1000RAM 1724 -#define IDC_CS_RAMSEY 1725 -#define IDC_CS_GARY 1726 -#define IDC_CS_FATGARY 1726 -#define IDC_CS_DMAC 1727 -#define IDC_CS_RTCADJUST 1728 -#define IDC_CS_FATGARYREV 1729 -#define IDC_CS_CDTVRAMEXP 1730 -#define IDC_CS_RTC1 1731 -#define IDC_CS_RTC2 1732 -#define IDC_CS_RTC3 1733 -#define IDC_CS_IDE4 1734 -#define IDC_CS_DF0IDHW 1734 -#define IDC_CS_AGNUS 1735 -#define IDC_CS_AGNUSREV 1736 -#define IDC_CS_DENISE 1737 -#define IDC_CS_DENISEREV 1738 -#define IDC_DBG_OUTPUT1 1739 -#define IDC_CS_PCMCIA 1739 -#define IDC_CS_SLOWISFAST 1740 -#define IDC_DBG_HELP 1740 -#define IDC_DBG_INPUT 1741 -#define IDC_CS_KSMIRROR_A8 1741 -#define IDC_DBG_DREG 1742 -#define IDC_CS_CIAOVERLAY 1742 -#define IDC_DBG_AREG 1743 -#define IDC_CS_RESETWARNING 1743 -#define IDC_DBG_CCR 1744 -#define IDC_CS_NOEHB 1744 -#define IDC_DBG_AMEM 1745 -#define IDC_CS_DIPAGNUS 1745 -#define IDC_DBG_SP_VBR 1746 -#define IDC_DBG_MMISC 1747 -#define IDC_DBG_PC 1748 -#define IDC_DBG_PREFETCH 1749 -#define IDC_DBG_FPREG 1750 -#define IDC_DBG_FPSR 1751 -#define IDC_DBG_OUTPUT2 1752 -#define IDC_DBG_MEMINPUT 1753 -#define IDC_DBG_MEMDOWN 1754 -#define IDC_DBG_MEMUP 1755 -#define IDC_DBG_MEM 1756 -#define IDC_DBG_DASM 1757 -#define IDC_DBG_MEMDOWNFAST 1758 -#define IDC_DBG_MEMTOPC 1759 -#define IDC_DBG_MEMUPFAST 1760 -#define IDC_DA_RESET 1761 -#define IDC_DBG_STATUS 1762 -#define IDC_DBG_BRKPTS 1763 -#define IDC_DBG_MCUSTOM 1764 -#define IDC_DBG_MISC 1765 -#define IDC_DBG_CUSTOM 1766 -#define IDC_DBG_MISCCPU 1767 -#define IDC_CS_A2091 1768 -#define IDC_CS_DMAC2 1769 -#define IDC_CS_A4091 1770 -#define IDC_CS_CDTVSCSI 1771 -#define IDC_CS_SCSIMODE 1772 -#define IDC_DF0ENABLE 1773 -#define IDC_DF1ENABLE 1774 -#define IDC_FS_SELECT_DIR 1774 -#define IDC_FS_SELECT_FILE 1775 -#define IDC_FLOPPY_FFS 1775 -#define IDC_DF2ENABLE 1776 -#define IDC_FS_SELECT_EJECT 1776 -#define IDC_FS_RW 1777 -#define IDC_FLOPPY_BOOTABLE 1777 -#define IDC_DF3ENABLE 1778 -#define IDC_HDF_RW 1778 -#define IDC_HDFINFO 1779 -#define IDC_DBG_AUTOSET 1780 -#define IDC_HF_SPARSE 1780 -#define IDC_DBG_DASM2 1781 -#define IDC_HF_DYNAMIC 1781 -#define IDC_DBG_MEM2 1782 -#define IDC_DBG_MEMINPUT2 1783 -#define IDC_DBG_ADDRINPUTTXT 1784 -#define IDC_RTG_SCALE 1785 -#define IDC_RTG_MATCH_DEPTH 1786 -#define IDC_RTG_8BIT 1787 -#define IDC_RTG_16BIT 1788 -#define IDC_PATHS_CONFIGCACHE 1788 -#define IDC_RTG_24BIT 1789 -#define IDC_ASSOCIATELIST 1789 -#define IDC_PORT_TABLET 1789 -#define IDC_PATHS_RELATIVE 1789 -#define IDC_RTG_32BIT 1790 -#define IDC_ASSOCIATE_OFF 1790 -#define IDC_PORT_TABLET_FULL 1790 -#define IDC_CPU_MULTIPLIER 1790 -#define IDC_CPU_FREQUENCY2 1790 -#define IDC_DD_SURFACETYPE 1791 -#define IDC_RTG_SCALE_ALLOW 1791 -#define IDC_CPU_FREQUENCY 1791 -#define IDC_RTG_SCALE_ASPECTRATIO 1792 -#define IDC_ASSOCIATE_ON 1792 -#define IDC_DD_SURFACETYPE2 1792 -#define IDC_DXMODE 1792 -#define IDC_RTG_VBLANKRATE 1793 -#define IDC_DF0WPTEXTQ 1793 -#define IDC_WINDOWEDMODE 1793 -#define IDC_DF1WPTEXTQ 1794 -#define IDC_RTG_Z2Z3 1794 -#define IDC_RTG_BUFFERCNT 1795 -#define IDC_RTG_VBINTERRUPT 1796 -#define IDC_INPUTMAPLIST 1797 -#define IDC_RTG_HWSPRITE 1797 -#define IDC_PORT1_REMAP 1798 -#define IDC_PORT0_REMAP 1799 -#define IDC_PORT2_REMAP 1800 -#define IDC_PORT3_REMAP 1801 -#define IDC_INPUTMAPOUT 1801 -#define IDC_INFOBOX_TEXT2 1802 -#define IDC_INFOBOX_TEXT1 1803 -#define IDC_INFOBOX_TEXT3 1804 -#define IDC_CD_EJECT 1804 -#define IDC_CD_TEXT 1805 -#define IDC_CD_TYPE 1806 -#define IDC_CD_SELECT 1807 -#define IDC_FASTMEMAUTOCONFIG 1808 -#define IDC_RTG_DISPLAYSELECT 1809 -#define IDC_MISCLIST 1810 -#define IDC_STATENAME 1811 -#define IDC_SAMPLER_STEREO 1812 -#define IDC_LISTDIALOG_LIST 1813 -#define ID__FLOPPYDRIVES 40004 -#define ID_FLOPPYDRIVES_DF0 40005 -#define ID_ST_CONFIGURATION 40010 -#define ID_ST_HELP 40011 -#define ID_ST_QUIT 40012 -#define ID_ST_EJECTALL 40013 -#define ID_ST_DF0 40014 -#define ID_ST_DF1 40015 -#define ID_ST_DF2 40016 -#define ID_ST_DF3 40017 -#define ID_ST_RESET 40019 -#define ID_DBG_PAGE1 40020 -#define ID_DBG_PAGE2 40021 -#define ID_DBG_PAGE3 40022 -#define ID_DBG_PAGE4 40023 -#define ID_DBG_PAGE5 40024 -#define ID_DBG_PAGE6 40025 -#define ID_DBG_PAGE7 40026 -#define ID_DBG_PAGE8 40027 -#define ID_DBG_PAGE9 40028 -#define ID_DBG_STEP_OVER 40029 -#define ID_DBG_STEP_INTO 40030 -#define ID_DBG_SETTOA0 40031 -#define ID_DBG_SETTOA1 40032 -#define ID_DBG_SETTOA2 40033 -#define ID_DBG_SETTOA3 40034 -#define ID_DBG_SETTOA4 40035 -#define ID_DBG_SETTOA5 40036 -#define ID_DBG_SETTOA6 40037 -#define ID_DBG_SETTOA7 40038 -#define ID_DBG_ENTERADDR 40039 -#define ID_DBG_COPYLBLINE 40040 -#define ID_DBG_COPYLB 40041 -#define ID_DBG_TOGGLEBP 40042 -#define ID_DBG_DELETEBPS 40043 -#define ID_DBG_SETTOPC 40044 -#define ID_MENU_CDDRIVES 40045 -#define ID_CDDRIVES_EJECT 40046 -#define ID_ST_CDEJECTALL 40047 -#define ID_CDDRIVES_CD 40048 -#define ID_ST_CD0 40049 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NO_MFC 1 -#define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 387 -#define _APS_NEXT_COMMAND_VALUE 40050 -#define _APS_NEXT_CONTROL_VALUE 1814 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/od-win32/rp.cpp b/od-win32/rp.cpp index ad86ddae..be411e29 100644 --- a/od-win32/rp.cpp +++ b/od-win32/rp.cpp @@ -1030,7 +1030,8 @@ static LRESULT CALLBACK RPHostMsgFunction2 (UINT uMessage, WPARAM wParam, LPARAM DWORD ret = 0; int ok = 0; screenshotmode = 0; - //write_log (_T("'%s' '%s'\n"), rpsc->szScreenFiltered, rpsc->szScreenRaw); + if (log_rp & 2) + write_log (_T("'%s' '%s'\n"), rpsc->szScreenFiltered, rpsc->szScreenRaw); if (rpsc->szScreenFiltered[0]) ok = screenshotf (rpsc->szScreenFiltered, 1, 1, 0, NULL); if (rpsc->szScreenRaw[0]) { @@ -1047,11 +1048,14 @@ static LRESULT CALLBACK RPHostMsgFunction2 (UINT uMessage, WPARAM wParam, LPARAM set_custom_limits (-1, -1, -1, -1); draw_frame (&vb); ok |= screenshotf (rpsc->szScreenRaw, 1, 1, 1, &vb); + if (log_rp & 2) + write_log (_T("Rawscreenshot %dx%d\n"), w, h); //ok |= screenshotf (_T("c:\\temp\\1.bmp"), 1, 1, 1, &vb); freevidbuffer (&vb); } screenshotmode = ossm; - //write_log (_T("->%d\n"), ok); + if (log_rp & 2) + write_log (_T("->%d\n"), ok); if (!ok) return RP_SCREENCAPTURE_ERROR; if (WIN32GFX_IsPicassoScreen ()) { diff --git a/od-win32/srcrelease.cmd b/od-win32/srcrelease.cmd index 7eff6cb7..ae03e71c 100644 --- a/od-win32/srcrelease.cmd +++ b/od-win32/srcrelease.cmd @@ -125,6 +125,7 @@ rm -rf debug rm -rf release rm -rf fullrelease rm -rf test +rm -rf x64 cd .. cd singlefilehelper diff --git a/od-win32/sysconfig.h b/od-win32/sysconfig.h index bb4054a1..a2efff68 100644 --- a/od-win32/sysconfig.h +++ b/od-win32/sysconfig.h @@ -17,9 +17,6 @@ #define WINDOWS #define ZLIB_WINAPI -#define MAX_UAE_WIDTH 8192 -#define MAX_UAE_HEIGHT 8192 - #ifndef UAE_MINI #define DEBUGGER diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index 079a3e29..2dfee1e8 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -119,6 +119,8 @@ int cpu_mmx = 1; static int userdtsc = 0; int D3DEX = 1; int d3ddebug = 0; +int max_uae_width; +int max_uae_height; HINSTANCE hInst = NULL; HMODULE hUIDLL = NULL; @@ -5339,6 +5341,14 @@ static int PASCAL WinMain2 (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR if (!dxdetect ()) return 0; + if (os_vista) { + max_uae_width = 8192; + max_uae_height = 8192; + } else { + max_uae_width = 3072; + max_uae_height = 2048; + } + hInst = hInstance; hMutex = CreateMutex (NULL, FALSE, _T("WinUAE Instantiated")); // To tell the installer we're running diff --git a/od-win32/win32.h b/od-win32/win32.h index 2ccdaa39..2d889393 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -19,13 +19,14 @@ #define LANG_DLL 1 #if WINUAEPUBLICBETA -#define WINUAEBETA _T("18") +#define WINUAEBETA _T("19") #else #define WINUAEBETA _T("") #endif -#define WINUAEDATE MAKEBD(2013, 4, 25) +#define WINUAEDATE MAKEBD(2013, 5, 2) #define WINUAEEXTRA _T("") //#define WINUAEEXTRA _T("AmiKit Preview") +//#define WINUAEEXTRA _T("Amiga Forever Edition") #define WINUAEREV _T("") #define IHF_WINDOWHIDDEN 6 diff --git a/od-win32/win32_scaler.cpp b/od-win32/win32_scaler.cpp index 0ace59df..832b4ce8 100644 --- a/od-win32/win32_scaler.cpp +++ b/od-win32/win32_scaler.cpp @@ -772,10 +772,10 @@ bool S2X_init (int dw, int dh, int dd) temp_width = dst_width * m; temp_height = dst_height * m; } else { - temp_width = dst_width * 3; + temp_width = dst_width * 2; if (temp_width > dxcaps.maxwidth) temp_width = dxcaps.maxwidth; - temp_height = dst_height * 3; + temp_height = dst_height * 2; if (temp_height > dxcaps.maxheight) temp_height = dxcaps.maxheight; if (temp_width < dst_width) diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index a9ce287d..b7207ef8 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -260,7 +260,7 @@ int default_freq = 60; HWND hStatusWnd = NULL; -static uae_u8 scrlinebuf[MAX_UAE_WIDTH * 4]; /* this is too large, but let's rather play on the safe side here */ +static uae_u8 *scrlinebuf; static struct MultiDisplay *getdisplay2 (struct uae_prefs *p, int index) { @@ -512,8 +512,13 @@ static void addmode (struct MultiDisplay *md, DEVMODE *dm, int rawmode) int h = dm->dmPelsHeight; int d = dm->dmBitsPerPel; bool lace = false; - int freq = 0; + + if (w > max_uae_width || h > max_uae_height) { + write_log (_T("Ignored mode %d*%d\n"), w, h); + return; + } + if (dm->dmFields & DM_DISPLAYFREQUENCY) { freq = dm->dmDisplayFrequency; if (freq < 10) @@ -3965,12 +3970,12 @@ static void allocsoftbuffer (const TCHAR *name, struct vidbuffer *buf, int flags } else if (flags & DM_SWSCALE) { - int w = buf->width_allocated * 2; - int h = buf->height_allocated * 2; - int size = (w * 2) * (h * 3) * buf->pixbytes; - buf->realbufmem = xcalloc (uae_u8, size); - buf->bufmem_allocated = buf->bufmem = buf->realbufmem + (w + (w * 2) * h) * buf->pixbytes; + int w = buf->width_allocated; + int h = buf->height_allocated; + int size = (w * 2) * (h * 2) * buf->pixbytes; buf->rowbytes = w * 2 * buf->pixbytes; + buf->realbufmem = xcalloc (uae_u8, size); + buf->bufmem_allocated = buf->bufmem = buf->realbufmem + (h / 2) * buf->rowbytes + (w / 2) * buf->pixbytes; buf->bufmemend = buf->realbufmem + size - buf->rowbytes; buf->bufmem_lockable = true; @@ -4118,6 +4123,9 @@ static BOOL doInit (void) picasso_vidinfo.depth = currentmode->current_depth; picasso_vidinfo.offset = 0; #endif + if (!scrlinebuf) + scrlinebuf = xmalloc (uae_u8, max_uae_width * 4); + gfxvidinfo.drawbuffer.emergmem = scrlinebuf; // memcpy from system-memory to video-memory gfxvidinfo.drawbuffer.realbufmem = NULL; diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 4961b562..fcf05f11 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -2769,7 +2769,7 @@ static TCHAR *fgetsx (TCHAR *dst, FILE *f) return dst; } -static TCHAR configcachever[] = _T("WinUAE Configuration.Cache"); +static const TCHAR configcachever[] = _T("WinUAE Configuration.Cache"); static void setconfighosthard (struct ConfigStruct *config) { @@ -8626,6 +8626,7 @@ static void values_from_cpudlg (HWND hDlg) workprefs.cachesize = 0; } else if (jitena && !oldcache) { workprefs.cachesize = 8192; + workprefs.cpu_cycle_exact = false; if (cachesize_prev) { workprefs.cachesize = cachesize_prev; workprefs.comptrustbyte = trust_prev; diff --git a/od-win32/winuae_msvc11/Test/winuae.unsuccessfulbuild b/od-win32/winuae_msvc11/Test/winuae.unsuccessfulbuild deleted file mode 100644 index e69de29b..00000000 diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index fa4e29a9..c77ee038 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,6 +1,12 @@ - restore only single input target to default. +Beta 19: + +- Reduced internal display buffer memory usage, use MEM_TOP_DOWN VirtualAlloc() flag, this seems to + reduce Windows XP only memory reservation problems that cause mysterious crashes. +- GUI allowed cycle exact and JIT active at the same time. + Beta 18: - If config (for example default.uae) has keyboard layout A/B/C selected, it will be remembered as default -- 2.47.3