From 531895b77d92d03a87680922e3c9040b22a8477a Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 20 Dec 2009 17:58:31 +0200 Subject: [PATCH] imported winuaesrc2010b2.zip --- cfgfile.c | 4 +- custom - Copy.c | 6872 ---------------------------------- custom.c | 6 +- filesys.c | 17 - include/sysdeps.h | 12 +- inputdevice.c | 14 +- memory.c | 35 + od-win32/avioutput.c | 2 +- od-win32/fsdb_win32.c | 23 +- od-win32/unicode.c | 136 +- od-win32/win32.c | 2 + od-win32/win32.h | 4 +- od-win32/winuaechangelog.txt | 12 + od-win32/writelog.c | 17 +- 14 files changed, 235 insertions(+), 6921 deletions(-) delete mode 100644 custom - Copy.c diff --git a/cfgfile.c b/cfgfile.c index f832b365..54444a0f 100644 --- a/cfgfile.c +++ b/cfgfile.c @@ -2742,7 +2742,7 @@ static int cfgfile_handle_custom_event (TCHAR *custom, int mode) int cnt = 0, cnt_ok = 0; if (!mode) { - uae_u8 zero = 0; + TCHAR zero = 0; configstore = zfile_fopen_empty ("configstore", 50000); cfgfile_save_options (configstore, &currprefs, 0); cfg_write (&zero, configstore); @@ -3173,7 +3173,7 @@ void default_prefs (struct uae_prefs *p, int type) { int i; int roms[] = { 6, 7, 8, 9, 10, 14, 5, 4, 3, 2, 1, -1 }; - uae_u8 zero = 0; + TCHAR zero = 0; struct zfile *f; memset (p, 0, sizeof (*p)); diff --git a/custom - Copy.c b/custom - Copy.c deleted file mode 100644 index d4fb123a..00000000 --- a/custom - Copy.c +++ /dev/null @@ -1,6872 +0,0 @@ -/* -* UAE - The Un*x Amiga Emulator -* -* Custom chip emulation -* -* Copyright 1995-2002 Bernd Schmidt -* Copyright 1995 Alessandro Bissacco -* Copyright 2000-2009 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 "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" - -#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 int 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 (L"%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; - -static int rpt_did_reset; -struct ev eventtab[ev_max]; -struct ev2 eventtab2[ev2_max]; - -volatile frame_time_t vsynctime, vsyncmintime; - -#ifdef JIT -extern uae_u8* compiled_code; -#endif - -int vpos; -int hack_vpos; -static int hack_vpos2, hack_vpos2vpos; -static int lof, 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, intreqr; -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_max = MAXVPOS_PAL; -int minfirstline = VBLANK_ENDLINE_PAL; -int vblank_hz = VBLANK_HZ_PAL, fake_vblank_hz, vblank_skip, doublescan; -frame_time_t syncbase; -static int fmode; -uae_u16 beamcon0, new_beamcon0; -uae_u16 vtotal = MAXVPOS_PAL, htotal = MAXHPOS_PAL; -static uae_u16 hsstop, hbstrt, hbstop, vsstop, vbstrt, vbstop, hsstrt, vsstrt, hcenter; -static int ciavsyncmode; - -#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]; - -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 int bpl1dat_written, bpl1dat_early; -static uae_s16 bpl1mod, bpl2mod; -static uaecptr prevbpl[2][MAXVPOS][8]; -static uaecptr bplpt[8], bplptx[8]; -/* Used as a debugging aid, to offset any bitplane temporarily. */ -int bpl_off[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - -/*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 fmode; -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 plfstrt_start, plfstrt, plfstop; -static int sprite_minx, sprite_maxx; -static int first_bpl_vpos; -static int last_diw_pix_hpos, last_ddf_pix_hpos; -static int last_decide_line_hpos, last_sprite_decide_line_hpos; -static int last_fetch_hpos, last_sprite_hpos; -static int diwfirstword, diwlastword; -static int plfleft_real; -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 -*/ - -/* Used also by bebox.cpp */ -unsigned long int frametime = 0, lastframetime = 0, timeframes = 0; -unsigned long hsync_counter = 0, vsync_counter = 0, ciavsync_counter = 0; -unsigned long int idletime; -int bogusframe; - -/* Recording of custom chip register changes. */ -static int current_change_set; - -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT -/* sam: Those arrays uses around 7Mb of BSS... That seems */ -/* too much for AmigaDOS (uae crashes as soon as one loads */ -/* it. So I use a different strategy here (realloc the */ -/* arrays when needed. That strategy might be usefull for */ -/* computer with low memory. */ -struct sprite_entry *sprite_entries[2]; -struct color_change *color_changes[2]; -static int max_sprite_entry = 400; -static int delta_sprite_entry = 0; -static int max_color_change = 400; -static int delta_color_change = 0; -#else -static struct sprite_entry sprite_entries[2][MAX_SPR_PIXELS / 16]; -static struct color_change color_changes[2][MAX_REG_CHANGE]; -#endif - -struct decision line_decisions[2 * (MAXVPOS + 1) + 1]; -static struct draw_info line_drawinfo[2][2 * (MAXVPOS + 1) + 1]; -#define COLOR_TABLE_SIZE (MAXVPOS + 1) * 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_linedbl && doublescan < 0; -} - -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 (L"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 alloc_cycle (int hpos, int type) -{ -#ifdef CPUEMU_12 -#if 0 - if (cycle_line[hpos]) - write_log (L"hpos=%d, old=%d, new=%d\n", hpos, cycle_line[hpos], type); - if ((type == CYCLE_CPU || type == CYCLE_COPPER) && (hpos & 1)) - write_log (L"odd %d cycle %d\n", hpos); - if (!(hpos & 1) && (type == CYCLE_SPRITE || type == CYCLE_REFRESH || type == CYCLE_MISC)) - write_log (L"even %d cycle %d\n", type, hpos); -#endif - cycle_line[hpos] = type; -#endif -} -STATIC_INLINE 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_bank.check (plpt, bytecount)) { - static int count = 0; - if (!count) - count++, write_log (L"Warning: Bad playfield pointer\n"); - return NULL; - } - return chipmem_bank.xlateaddr (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) -{ - 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 */ - int pix_hpos = coord_diw_to_window_x (hpos == maxhpos ? hpos * 2 + 1 : hpos * 2); - if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1 - && pix_hpos >= diwfirstword && last_diw_pix_hpos < diwfirstword) - { - thisline_decision.diwfirstword = diwfirstword < 0 ? 0 : diwfirstword; - hdiwstate = DIW_waiting_stop; - } - if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1 - && pix_hpos >= diwlastword && last_diw_pix_hpos < diwlastword) - { - thisline_decision.diwlastword = diwlastword < 0 ? 0 : diwlastword; - hdiwstate = DIW_waiting_start; - } - last_diw_pix_hpos = pix_hpos; -} - -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 (L"FMODE %d\n=======\n", fm); - for (res = 0; res <= 2; res++) { - for (planes = 0; planes <= 8; planes++) { - write_log (L"%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 (L"%c",aa); - } - write_log (L" %d:%d\n", - cycle_diagram_free_cycles[fm][res][planes], cycle_diagram_total_cycles[fm][res][planes]); - } - write_log (L"\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 (L"%d:%d ", vpos, delayoffset); -#endif -} - -static void record_color_change2 (int hpos, int regno, unsigned long value) -{ - curr_color_changes[next_color_change].linepos = hpos * 2; - 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 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 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 bpl1day 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] + bpl_off[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_agnus_wget (p), p, hpos, vpos, DMARECORD_BITPLANE); -#endif - switch (fm) - { - case 0: - fetched[nr] = bplxdat[nr] = last_custom_value1 = chipmem_agnus_wget (p); - break; -#ifdef AGA - case 1: - fetched_aga0[nr] = chipmem_lget (p); - last_custom_value1 = (uae_u16)fetched_aga0[nr]; - break; - case 2: - fetched_aga1[nr] = chipmem_lget (p); - fetched_aga0[nr] = chipmem_lget (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] + bpl_off[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] + bpl_off[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++; - } - - 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 (L"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 (L"fm corrupt"); return 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 (L"fetchmode corrupt"); - } - } - maybe_check (hpos); - last_fetch_hpos = hpos; - } -} - -static void start_bpl_dma (int hpos, int hstart) -{ - 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][vpos][i] = bplptx[i]; - if (!lof && (bplcon0 & 4)) - bplpt[i] = prevbpl[1 - lof][vpos][i]; - if (!(bplcon0 & 4) || interlace_seen < 0) - prevbpl[1 - lof][vpos][i] = prevbpl[lof][vpos][i] = 0; - } - } - - 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_dma (hpos, hpos); -} - -/* 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) { - 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) { - if (dmaen (DMA_BITPLANE)) { - start_bpl_dma (hpos, plfstrt); - estimate_last_fetch_cycle (plfstrt); - } - last_decide_line_hpos = hpos; -#ifndef CUSTOM_SIMPLE - do_sprites (plfstrt); -#endif - return; - } - } - -#ifndef CUSTOM_SIMPLE - if (last_sprite_decide_line_hpos < SPR0_HPOS + 4 * MAX_SPRITES) - do_sprites (hpos); - last_sprite_decide_line_hpos = 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 (); - -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT - if (next_color_change >= max_color_change) { - ++delta_color_change; - return; - } -#endif - if (regno < 0x1000 && hpos < HBLANK_OFFSET && !(beamcon0 & 0x80) && prev_lineno >= 0) { - struct draw_info *pdip = curr_drawinfo + prev_lineno; - int idx = pdip->last_color_change; - /* 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) - */ - pdip->last_color_change++; - pdip->nr_color_changes++; - curr_color_changes[idx].linepos = (hpos + maxhpos) * 2; - curr_color_changes[idx].regno = regno; - curr_color_changes[idx].value = value; - curr_color_changes[idx + 1].regno = -1; - } - record_color_change2 (hpos, regno, value); -} - -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) */ -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 (L"%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 (L"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 BPL0DAT write to end of line - * (another 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 (thisline_decision.plfleft != -1 && thisline_decision.plflinelen == -1) { - if (fetch_state != fetch_not_started) { - write_log (L"fetch_state=%d plfleft=%d,len=%d,vpos=%d,hpos=%d\n", - fetch_state, thisline_decision.plfleft, thisline_decision.plflinelen, - vpos, hpos); - uae_abort (L"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) - thisline_decision.diwlastword = max_diwlastword; - - 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; -} - -/* 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_sprite_decide_line_hpos = -1; - last_diw_pix_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 (!currprefs.gfx_afullscreen || picasso_on || !currprefs.gfx_avsync) - return 0; - return currprefs.gfx_avsync; -} - -int vsynctime_orig; - -void compute_vsynctime (void) -{ - fake_vblank_hz = 0; - if (currprefs.chipset_refreshrate) { - 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) { -#ifdef OPENGL - OGL_refresh (); -#endif -#ifdef D3D - D3D_refresh (); -#endif - } - if (currprefs.produce_sound > 1) - update_sound (fake_vblank_hz, (bplcon0 & 4) ? -1 : lof, islinetoggle ()); -} - - -static void dumpsync (void) -{ - static int cnt = 100; - if (cnt < 0) - return; - cnt--; - write_log (L"BEAMCON0=%04X VTOTAL=%04X HTOTAL=%04X\n", new_beamcon0, vtotal, htotal); - write_log (L"HSSTOP=%04X HBSTRT=%04X HBSTOP=%04X\n", hsstop, hbstrt, hbstop); - write_log (L"VSSTOP=%04X VBSTRT=%04X VBSTOP=%04X\n", vsstop, vbstrt, vbstop); - write_log (L"HSSTRT=%04X VSSTRT=%04X HCENTER=%04X\n", hsstrt, vsstrt, hcenter); -} - -/* set PAL/NTSC or custom timing variables */ -void init_hz (void) -{ - int isntsc; - int odbl = doublescan, omaxvpos = maxvpos; - int hzc = 0; - - if (vsync_switchmode (-1, 0) > 0) - currprefs.gfx_avsync = changed_prefs.gfx_avsync = vsync_switchmode (-1, 0); - - if (!isvsync () && ((currprefs.chipset_refreshrate == 50 && !currprefs.ntscmode) || - (currprefs.chipset_refreshrate == 60 && currprefs.ntscmode))) { - currprefs.chipset_refreshrate = changed_prefs.chipset_refreshrate = 0; - } - - doublescan = 0; - if ((beamcon0 & 0xA0) != (new_beamcon0 & 0xA0)) - hzc = 1; - if (beamcon0 != new_beamcon0) { - hack_vpos = 0; - write_log (L"BEAMCON0 %04x -> %04x\n", beamcon0, new_beamcon0); - } - if (beamcon0 & 0x80) - hack_vpos = -1; - beamcon0 = new_beamcon0; - isntsc = (beamcon0 & 0x20) ? 0 : 1; - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - isntsc = currprefs.ntscmode ? 1 : 0; - if (hack_vpos > 0) { - if (maxvpos == hack_vpos) { - hack_vpos = -1; - return; - } - maxvpos = hack_vpos; - vblank_hz = 15600 / hack_vpos; - hack_vpos = -1; - } else if (hack_vpos < 0) { - hack_vpos = 0; - } - if (hack_vpos == 0) { - if (!isntsc) { - maxvpos = MAXVPOS_PAL; - maxhpos = MAXHPOS_PAL; - minfirstline = VBLANK_ENDLINE_PAL; - vblank_hz = VBLANK_HZ_PAL; - sprite_vblank_endline = VBLANK_SPRITE_PAL; - } else { - maxvpos = MAXVPOS_NTSC; - maxhpos = MAXHPOS_NTSC; - minfirstline = VBLANK_ENDLINE_NTSC; - vblank_hz = VBLANK_HZ_NTSC; - sprite_vblank_endline = VBLANK_SPRITE_NTSC; - } - maxvpos_max = maxvpos; - } - if (beamcon0 & 0x80) { - if (vtotal >= MAXVPOS) - vtotal = MAXVPOS - 1; - maxvpos = vtotal + 1; - if (htotal >= MAXHPOS) - htotal = MAXHPOS - 1; - maxhpos = htotal + 1; - vblank_hz = 227 * 312 * 50 / (maxvpos * maxhpos); - minfirstline = vsstop; - if (minfirstline < 2) - minfirstline = 2; - if (minfirstline >= maxvpos) - minfirstline = maxvpos - 1; - sprite_vblank_endline = minfirstline - 2; - maxvpos_max = maxvpos; - doublescan = htotal <= 164 ? 1 : 0; - dumpsync (); - hzc = 1; - } - 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; - 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 ((vblank_hz == 50 || vblank_hz == 60) && isvsync () == 2) { - if (getvsyncrate (currprefs.gfx_refreshrate) != vblank_hz) - vsync_switchmode (vblank_hz, currprefs.gfx_refreshrate); - } - if (isvsync ()) { - changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate = abs (currprefs.gfx_refreshrate); - } - - compute_vsynctime (); -#ifdef OPENGL - OGL_refresh (); -#endif -#ifdef PICASSO96 - init_hz_p96 (); -#endif - inputdevice_tablet_strobe (); - write_log (L"%s mode%s%s V=%dHz H=%dHz (%dx%d)\n", - isntsc ? L"NTSC" : L"PAL", - (bplcon0 & 4) ? L" interlaced" : L"", - doublescan > 0 ? L" dblscan" : L"", - vblank_hz, vblank_hz * maxvpos, - maxhpos, maxvpos); - -} - -static void calcdiw (void) -{ - int hstrt = diwstrt & 0xFF; - int hstop = diwstop & 0xFF; - int vstrt = diwstrt >> 8; - int vstop = diwstop >> 8; - - if (diwhigh_written) { - hstrt |= ((diwhigh >> 5) & 1) << 8; - hstop |= ((diwhigh >> 13) & 1) << 8; - vstrt |= (diwhigh & 7) << 8; - vstop |= ((diwhigh >> 8) & 7) << 8; - } else { - hstop += 0x100; - if ((vstop & 0x80) == 0) - vstop |= 0x100; - } - - 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 (); - 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); - put_long (m68k_areg (regs, 0), tv.tv_sec - (((365 * 8 + 2) * 24) * 60 * 60)); - 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) - return 0xF8; -#endif - if (currprefs.chipset_mask & CSMASK_ECS_DENISE) - return 0xFC; - 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 intreqr; -} -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 ()); -} - -#define HPOS_OFFSET 3 - -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) - 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 ? 0x8000 : 0) | csbit; - if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) - vp |= lol ? 0x80 : 0; -#if 0 - if (M68K_GETPC < 0xf00000) - write_log (L"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) - write_log (L"VPOSW %04X PC=%08x\n", v, M68K_GETPC); -#endif - if (lof != ((v & 0x8000) ? 1 : 0)) - lof_changed = 1; - lof = (v & 0x8000) ? 1 : 0; - if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) - lol = (v & 0x0080) ? 1 : 0; - hack_vpos2 = (vpos & 0xff); - if (v & 1) - hack_vpos2 |= 0x100; - hack_vpos2vpos = vpos; - if (hack_vpos2 > maxvpos) - hack_vpos2 = maxvpos; - // do not allow changing vpos backwards or vsync may never happen.. - if (vpos < hack_vpos2) - vpos = hack_vpos2; -} - -static void VHPOSW (uae_u16 v) -{ -#if 0 - if (M68K_GETPC < 0xf00000) - write_log (L"VHPOSW %04X PC=%08x\n", v, M68K_GETPC); -#endif - v >>= 8; - if (hack_vpos2 & 0x100) - v |= 0x100; - else if (vpos & 0x100) - v |= 0x100; - hack_vpos2 = v; - hack_vpos2vpos = vpos; - if (hack_vpos2 > maxvpos) - hack_vpos2 = maxvpos; - if (vpos < hack_vpos2) - vpos = hack_vpos2; -} - -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) - vp = 0; - } - hp += 1; - if (hp >= maxhpos) - hp -= maxhpos; - - vp <<= 8; - vp |= hp; - if (currprefs.cpu_model >= 68020) - hsyncdelay (); -#if 0 - if (M68K_GETPC < 0xf00000 && (vpos >= maxhpos || vpos <= 1)) - write_log (L"VPOS %04x %04x at %08x\n", VPOSR (), vp, M68K_GETPC); -#endif - return vp; -} - -static int test_copper_dangerous (unsigned int address) -{ - if ((address & 0x1fe) < ((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_agnus_wget (cop_state.ip); - cop_state.i2 = chipmem_agnus_wget (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 (L"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_hsync (hpos); - - if (changed & (DMA_MASTER | DMA_BITPLANE)) { - ddf_change = vpos; - if (dmaen (DMA_BITPLANE)) - maybe_start_bpl_dma (hpos); - } - - events_schedule(); -} - -static int irq_nmi; - -void NMI_delayed (void) -{ - irq_nmi = 1; -} - -int intlev (void) -{ - uae_u16 imask = intreq & intena; - if (irq_nmi) { - irq_nmi = 0; - return 7; - } - if (!(imask && (intena & 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; -} - -STATIC_INLINE int use_eventmode (void) -{ - return currprefs.cpu_cycle_exact != 0; -} - -STATIC_INLINE void INTENA (uae_u16 v) -{ - setclr (&intena,v); -#if 0 - if (v & 0x40) - write_log (L"INTENA %04X (%04X) %p\n", intena, v, M68K_GETPC); -#endif - if (v & 0x8000) { - if (use_eventmode ()) - prepare_interrupt (); - doint (); - } -} - -void INTREQ_0 (uae_u16 v) -{ - intreqr = intreq; - /* data in intreq is immediately available (vsync only currently because there is something unknown..) */ - setclr (&intreqr, v & (0x8000 | 0x20)); - - if (use_eventmode ()) - prepare_interrupt (); - if (v & (0x80 | 0x100 | 0x200 | 0x400)) - audio_update_irq (v); - setclr (&intreq, v); - intreqr = intreq; - 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 (); - - setclr (&adkcon,v); - audio_update_adkmasks (); - DISK_update (hpos); - 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 (L"warning: %04X written to BEAMCON0 PC=%08X\n", v, M68K_GETPC); - } - } -} - -#ifndef CUSTOM_SIMPLE - -static void varsync (void) -{ -#ifdef PICASSO96 - if (p96refresh_active) - { - extern int p96hack_vpos2; - static int p96hack_vpos_old; - if (p96hack_vpos_old == p96hack_vpos2) return; - vtotal = p96hack_vpos2; - p96hack_vpos_old = p96hack_vpos2; - hack_vpos = -1; - return; - } -#endif - if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE)) - return; - if (!(beamcon0 & 0x80)) - return; - hack_vpos = -1; - dumpsync (); -} -#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 (L"%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); - bplpt[num] = (bplpt[num] & 0xffff0000) | (v & 0x0000fffe); - bplptx[num] = (bplptx[num] & 0xffff0000) | (v & 0x0000fffe); - //write_log (L"%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 &= ~0x00B1; - 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 &= ~0x00B1; - 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); -} - -#if 0 - -ddf_change = vpos; -decide_line (hpos); -decide_fetch (hpos); -decide_blitter (hpos); - -bplcon0 = v; - -badmode = GET_RES_AGNUS (bplcon0) != GET_RES_DENISE (bplcon0); - -// fake unused 0x0080 bit as an EHB bit (see above) -if (isehb (bplcon0, bplcon2)) - v |= 0x80; - -BPLCON0_Denise (hpos, v); - -expand_fmodes (); - -record_register_change (hpos, 0x100, v); - -calcdiw (); -estimate_last_fetch_cycle (hpos); - -} -#endif - -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 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) { - thisline_decision.plfleft = hpos; - compute_delay_offset (); - } - } -} - -static void DIWSTRT (int hpos, uae_u16 v) -{ - if (diwstrt == v && ! diwhigh_written) - return; - decide_line (hpos); - diwhigh_written = 0; - diwstrt = v; - calcdiw (); -} - -static void DIWSTOP (int hpos, uae_u16 v) -{ - if (diwstop == v && ! diwhigh_written) - return; - decide_line (hpos); - diwhigh_written = 0; - diwstop = v; - calcdiw (); -} - -static void DIWHIGH (int hpos, uae_u16 v) -{ - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - return; - 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 (L"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 (L"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; - 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 = 32768; - if (!blt_info.hblitsize) - blt_info.hblitsize = 0x800; - 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 (L"%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 (L"%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 (L"%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 (L"%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 (L"%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; - } -#if SPRITE_DEBUG > 0 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log (L"%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 (L"%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; - - debug_wputpeek (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 (L"%s: vpos=%d until_hpos=%d\n", - error, vpos, until_hpos); - write_log (L"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 (L"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 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 (L"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; - - if (cop_state.strobe) { - if (cop_state.strobe > 0) - cop_state.ip = cop_state.strobe == 1 ? cop1lc : cop2lc; - cop_state.strobe = 0; - } - - 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_agnus_wget (cop_state.ip), cop_state.ip, old_hpos, vpos, DMARECORD_COPPER); -#endif - 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_agnus_wget (cop_state.ip + 2), cop_state.ip + 2, old_hpos, vpos, DMARECORD_COPPER); - 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); - break; - - case COP_read1: - if (copper_cant_read (old_hpos, 1)) - continue; - cop_state.i1 = last_custom_value1 = chipmem_agnus_wget (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_agnus_wget (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 - 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.ip = cop1lc; - cop_state.state = COP_strobe_delay1; - } else if (reg == 0x8A) { - cop_state.ip = cop2lc; - cop_state.state = COP_strobe_delay1; - } 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); - } - } - } -#ifdef DEBUGGER - if (debug_copper) - record_copper (cop_state.ip - 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) - s->ptxhpos = hpos; - data = last_custom_value1 = chipmem_agnus_wget (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 dma, int hpos, int cycle, int mode) -{ - uae_u16 data = last_custom_value1; - if (dma) { - data = last_custom_value1 = chipmem_agnus_wget (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; - int isdma = dmaen (DMA_SPRITE); - - 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 (L"%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 (L"%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 (L"%d:%d:SPR%d STOP\n", vpos, hpos, num); -#endif - s->dmastate = 0; -#if 1 - 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 || 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, dma, hpos, cycle, 0); - sprite_fetch2 (s, dma, hpos, cycle, 0); - case 32: - sprite_fetch2 (s, dma, hpos, cycle, 0); - break; - } - } else { - data = cycle == 0 ? sprpos[num] : sprctl[num]; - } -#if SPRITE_DEBUG > 1 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log (L"%d:%d:dma:P=%06X ", vpos, hpos, s->pt); - } -#endif - //write_log (L"%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 (s->dmastate && !posctl) { - 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 (L"%d:%d:dma:P=%06X ", vpos, hpos, s->pt); - } -#endif - if (cycle == 0) { - SPRxDATA_1 (dma ? data : sprdata[num][0], num, hpos); - s->dmacycle = 1; - } else { - SPRxDATB_1 (dma ? data : sprdatb[num][0], num, hpos); - spr_arm (num, 1); - } -#ifdef AGA - switch (sprite_width) - { - case 64: - { - uae_u16 data32 = sprite_fetch2 (s, dma, hpos, cycle, 1); - uae_u16 data641 = sprite_fetch2 (s, dma, hpos, cycle, 1); - uae_u16 data642 = sprite_fetch2 (s, dma, 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, dma, 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 >= SPR0_HPOS + MAX_SPRITES * 4 || maxspr < SPR0_HPOS) - return; - - if (maxspr > SPR0_HPOS + MAX_SPRITES * 4) - maxspr = SPR0_HPOS + MAX_SPRITES * 4; - if (minspr < SPR0_HPOS) - minspr = SPR0_HPOS; - - 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 && num >= 0 && num < MAX_SPRITES) { - 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); -} - -/* -* On systems without virtual memory or with low memory, we allocate the -* sprite_entries and color_changes tables dynamically rather than having -* them declared static. We don't initially allocate at their maximum sizes; -* we start the tables off small and grow them as required. -* -* This function expands the tables if necessary. -*/ -static void adjust_array_sizes (void) -{ -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT - if (delta_sprite_entry) { - void *p1; - void *p2; - int mcc = max_sprite_entry + 50 + delta_sprite_entry; - - delta_sprite_entry = 0; - - p1 = realloc (sprite_entries[0], mcc * sizeof (struct sprite_entry)); - p2 = realloc (sprite_entries[1], mcc * sizeof (struct sprite_entry)); - - if (p1 && p2) { - sprite_entries[0] = p1; - sprite_entries[1] = p2; - - memset (&sprite_entries[0][max_sprite_entry], (mcc - max_sprite_entry) * sizeof(struct sprite_entry), 0); - memset (&sprite_entries[1][max_sprite_entry], (mcc - max_sprite_entry) * sizeof(struct sprite_entry), 0); - - write_log (L"New max_sprite_entry=%d\n", mcc); - - max_sprite_entry = mcc; - } else - write_log (L"WARNING: Failed to enlarge sprite_entries table\n"); - } - if (delta_color_change) { - void *p1; - void *p2; - int mcc = max_color_change + 200 + delta_color_change; - - delta_color_change = 0; - - p1 = realloc (color_changes[0], mcc * sizeof (struct color_change)); - p2 = realloc (color_changes[1], mcc * sizeof (struct color_change)); - - if (p1 && p2) { - color_changes[0] = p1; - color_changes[1] = p2; - - write_log (L"New max_color_change=%d\n", mcc); - - max_color_change = mcc; - } else - write_log (L"WARNING: Failed to enlarge color_changes table\n"); - } -#endif -} - -static void init_hardware_frame (void) -{ - first_bpl_vpos = -1; - next_lineno = 0; - prev_lineno = -1; - nextline_how = nln_normal; - diwstate = DIW_waiting_start; - hdiwstate = 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 = maxvpos; -} - -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; - - adjust_array_sizes (); - - 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; - - if (isvsync ()) { - vsyncmintime = vsynctime; - return; - } - for (;;) { - double v = rpt_vsync () / (syncbase / 1000.0); - if (v >= -4) - break; - sleep_millis (2); - } - 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; - } -} - -static void vsync_handler (void) -{ - fpscounter (); - - if (!isvsync () -#ifdef AVIOUTPUT - && ((avioutput_framelimiter && avioutput_enabled) || !avioutput_enabled) -#endif - ) { -#ifdef JIT - if (!compiled_code) { -#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; - } else if (rpt_available) { - framewait (); - } -#ifdef JIT - } else { - if (rpt_available && currprefs.m68k_speed == 0) { - framewait (); - } - } -#endif - } else { - framewait (); - } - - if (bogusframe > 0) - bogusframe--; - - handle_events (); - - INTREQ (0x8000 | 0x0020); - if (bplcon0 & 4) - lof ^= 1; - -#ifdef PICASSO96 - picasso_handle_vsync (); -#endif - audio_vsync (); - - if (quit_program > 0) { - /* prevent possible infinite loop at wait_cycles().. */ - framecnt = 0; - reset_decisions (); - return; - } - - { - static int cnt = 0; - if (cnt == 0) { - /* resolution_check_change (); */ - DISK_check_change (); - cnt = 5; - } - cnt--; - } - - if (debug_copper) - record_copper_reset (); - if (debug_dma) - record_dma_reset (); - - vsync_handle_redraw (lof, lof_changed); - - /* For now, let's only allow this to change at vsync time. It gets too - * hairy otherwise. */ - if (hack_vpos2) { - hack_vpos = hack_vpos2vpos + 1; - if (hack_vpos2 < maxvpos) - hack_vpos += maxvpos - hack_vpos2; - if (hack_vpos > maxvpos) - hack_vpos = maxvpos; - if (hack_vpos < 10) - hack_vpos = 10; - hack_vpos2 = 0; - } - if ((beamcon0 & (0x20|0x80)) != (new_beamcon0 & (0x20|0x80)) || hack_vpos) - init_hz (); - - lof_changed = 0; - - COPJMP (1, 1); - - if (timehack_alive > 0) - timehack_alive--; - inputdevice_vsync (); - filesys_vsync (); - - init_hardware_frame (); - -} - -#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; - /* @@@ 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; - 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 (L"COPPER BUG %d: vp=%d vpos=%d vcmp=%d act=%d thisline=%d\n", n, vp, vpos, cop_state.vcmp, copper_enabled_thisline); - } - } -} - -static void CIA_vsync_prehandler (int dotod) -{ - CIA_vsync_handler (dotod); -#if 0 - if (input_recording > 0) { - inprec_rstart(INPREC_CIAVSYNC); - inprec_ru32(ciavsync_counter); - inprec_rend(); - } else if (input_recording < 0) { - uae_u32 v = -1; - while (inprec_pstart(INPREC_CIAVSYNC)) { - v = inprec_pu32(); - inprec_pend(); - } - if (v != ciavsync_counter) - write_log (L"INPREC: ciavsync sync error %d <> %d\n", v, ciavsync_counter); - } -#endif - ciavsync_counter++; -} - -/* - -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][vpos][i] && prevbpl[1 - lof][vpos][i]) { - diff = prevbpl[lof][vpos][i] - prevbpl[1 - lof][vpos][i]; - if (lof) { - if (bplcon0 & 4) - bplpt[i] = prevbpl[lof][vpos][i] - diff; - } else { - if (bplcon0 & 4) - bplpt[i] = prevbpl[lof][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 hsync_handler (void) -{ - int hpos = current_hpos (); - - if (!nocustom ()) { - sync_copper_with_cpu (maxhpos, 0); - last_copper_hpos = 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; - } - } -#ifdef A2065 - a2065_hsync_handler (); -#endif -#ifdef CD32 - AKIKO_hsync_handler (); -#endif -#ifdef CDTV - CDTV_hsync_handler (); -#endif -#ifdef CPUEMU_12 - if (currprefs.cpu_cycle_exact || currprefs.blitter_cycle_exact) { - decide_blitter (-1); - memset (cycle_line, 0, sizeof cycle_line); - } -#endif - - if (islinetoggle ()) - lol ^= 1; - - maxhpos = maxhpos_short + lol; - eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME; - eventtab[ev_hsync].oldcycles = get_cycles (); - - CIA_hsync_handler (!(bplcon0 & 2) || ((bplcon0 & 2) && currprefs.genlock)); - if (currprefs.cs_ciaatod > 0) { - static int cia_hsync; - cia_hsync -= 256; - if (cia_hsync <= 0) { - CIA_vsync_prehandler (1); - cia_hsync += ((MAXVPOS_PAL * MAXHPOS_PAL * 50 * 256) / (maxhpos * (currprefs.cs_ciaatod == 2 ? 60 : 50))); - } - } - - -#ifdef PICASSO96 - picasso_handle_hsync (); -#endif - { - void ahi_hsync (void); - ahi_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)]); - } - hardware_line_completed (next_lineno); - if (doflickerfix () && interlace_seen) - hsync_scandoubler (); - } - - /* In theory only an equality test is needed here - but if a program - goes haywire with the VPOSW register, it can cause us to miss this, - with vpos going into the thousands (and all the nasty consequences - this has). */ - if (++vpos >= maxvpos + lof) { - if ((bplcon0 & 8) && !lightpen_triggered) { - vpos_lpen = vpos - 1; - hpos_lpen = maxhpos; - lightpen_triggered = 1; - } - vpos = 0; - vsync_handler (); -#if 0 - if (input_recording > 0) { - inprec_rstart (INPREC_VSYNC); - inprec_ru32 (vsync_counter); - inprec_rend (); - } else if (input_recording < 0) { - uae_u32 v = -1; - while (inprec_pstart(INPREC_VSYNC)) { - v = inprec_pu32(); - inprec_pend(); - } - if (v != vsync_counter) - write_log (L"INPREC: vsync sync error %d <> %d\n", v, vsync_counter); - } -#endif - vsync_counter++; - if (currprefs.cs_ciaatod == 0) - CIA_vsync_prehandler (!(bplcon0 & 2) || ((bplcon0 & 2) && currprefs.genlock)); - } - -#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) - record_dma (i == 0 ? (vpos + 1 == maxvpos + lof ? 0x38 : 0x3c) : 0x1fe, 0xffff, 0xffffffff, hp, vpos, DMARECORD_REFRESH); -#endif - hp += 2; - if (hp >= maxhpos) - hp -= maxhpos; - } - } -#endif - - - DISK_hsync (maxhpos); - if (currprefs.produce_sound) - audio_hsync (-1); - -#ifdef JIT - if (compiled_code) { - 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 && currprefs.m68k_speed == -1; -#ifdef JIT - } -#endif - - if (!nocustom ()) { - int lineno = vpos; - if ((bplcon0 & 4) && currprefs.gfx_linedbl) - notice_interlace_seen (); - nextline_how = nln_normal; - if (doflickerfix () && interlace_seen) { - lineno *= 2; - } else if (currprefs.gfx_linedbl && (doublescan <= 0 || interlace_seen > 0)) { - lineno *= 2; - nextline_how = currprefs.gfx_linedbl == 1 ? nln_doubled : nln_nblack; - if ((bplcon0 & 4) || (interlace_seen > 0 && !lof)) { - if (!lof) { - 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 (); - } - - /* 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 - - while (input_recording < 0 && inprec_pstart (INPREC_KEY)) { - record_key_direct (inprec_pu8 ()); - inprec_pend (); - } - while (input_recording < 0 && inprec_pstart (INPREC_DISKREMOVE)) { - disk_eject (inprec_pu8 ()); - inprec_pend (); - } - while (input_recording < 0 && inprec_pstart (INPREC_DISKINSERT)) { - int drv = inprec_pu8 (); - inprec_pstr (currprefs.df[drv]); - _tcscpy (changed_prefs.df[drv], currprefs.df[drv]); - disk_insert_force (drv, currprefs.df[drv]); - inprec_pend (); - } - - inputdevice_hsync (); - gayle_hsync (); - scsi_hsync (); - - hsync_counter++; - //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; - } else if (vpos == 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 MISC_handler (void) -{ - int i, recheck; - evt mintime; - evt ct = get_cycles (); - static int recursive; - - if (recursive) - return; - recursive++; - eventtab[ev_misc].active = 0; - recheck = 1; - while (recheck) { - recheck = 0; - mintime = ~0L; - for (i = 0; i < ev2_max; i++) { - if (eventtab2[i].active) { - if (eventtab2[i].evtime == ct) { - eventtab2[i].active = 0; - eventtab2[i].handler (eventtab2[i].data); - if (eventtab2[i].active) - recheck = 1; - } else { - evt eventtime = eventtab2[i].evtime - ct; - if (eventtime < mintime) - mintime = eventtime; - } - } - } - } - if (mintime != ~0L) { - eventtab[ev_misc].active = 1; - eventtab[ev_misc].oldcycles = ct; - eventtab[ev_misc].evtime = ct + mintime; - events_schedule (); - } - recursive--; -} - -STATIC_INLINE void event2_newevent_x (int no, evt t, uae_u32 data, evfunc2 func) -{ - evt et; - - if (((int)t) <= 0) { - func (data); - return; - } - - et = t * CYCLE_UNIT + get_cycles (); - - if (no < 0) { - for (no = ev2_misc; no < ev2_max; no++) { - if (!eventtab2[no].active) - break; - if (eventtab2[no].evtime == et && eventtab2[no].handler == func) { - eventtab2[no].handler (eventtab2[no].data); - break; - } - } - if (no == ev2_max) { - write_log (L"out of event2's! PC=%x\n", M68K_GETPC); - return; - } - } - eventtab2[no].active = 1; - eventtab2[no].evtime = et; - eventtab2[no].handler = func; - eventtab2[no].data = data; - MISC_handler (); -} -void event2_newevent (int no, evt t) -{ - event2_newevent_x (no, t, 0, eventtab2[no].handler); -} -void event2_newevent2 (evt t, uae_u32 data, evfunc2 func) -{ - event2_newevent_x (-1, t, data, func); -} - -void event2_remevent (int no) -{ - eventtab2[no].active = 0; -} - -void init_eventtab (void) -{ - int i; - - nextevent = 0; - set_cycles (0); - for (i = 0; i < ev_max; i++) { - eventtab[i].active = 0; - eventtab[i].oldcycles = 0; - } - 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 customreset (int hardreset) -{ - int i; - int zero = 0; - - target_reset (); - reset_all_systems (); - write_log (L"Reset at %08X\n", M68K_GETPC); - memory_map_dump (); - - hsync_counter = 0; - vsync_counter = 0; - ciavsync_counter = 0; - lightpen_x = lightpen_y = -1; - lightpen_triggered = 0; - lightpen_cx = lightpen_cy = -1; - if (! savestate_state) { - 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 = intena = 0; - - copcon = 0; - DSKLEN (0, 0); - - bplcon0 = 0; - bplcon4 = 0x0011; /* Get AGA chipset into ECS compatibility mode */ - bplcon3 = 0x0C00; - - diwhigh = 0; - diwhigh_written = 0; - - FMODE (0, 0); - CLXCON (0); - setup_fmodes (0); - sprite_width = GET_SPRITEWIDTH (fmode); - new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20; - } - - 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; - - 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); - - bltstate = BLT_done; - cop_state.state = COP_stop; - diwstate = DIW_waiting_start; - hdiwstate = DIW_waiting_start; - set_cycles (0); - - hack_vpos = 0; - init_hz (); - vpos_lpen = -1; - - audio_reset (); - if (savestate_state != STATE_RESTORE) { - /* 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 (savestate_state == STATE_RESTORE) { - 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 (L"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 (L"DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR (current_hpos ()), - (unsigned int)intena, (unsigned int)intreq, (unsigned int)vpos, (unsigned int)current_hpos()); - console_out_f (L"COP1LC: %08lx, COP2LC: %08lx COPPTR: %08lx\n", (unsigned long)cop1lc, (unsigned long)cop2lc, cop_state.ip); - console_out_f (L"DIWSTRT: %04x DIWSTOP: %04x DDFSTRT: %04x DDFSTOP: %04x\n", - (unsigned int)diwstrt, (unsigned int)diwstop, (unsigned int)ddfstrt, (unsigned int)ddfstop); - console_out_f (L"BPLCON 0: %04x 1: %04x 2: %04x 3: %04x 4: %04x\n", bplcon0, bplcon1, bplcon2, bplcon3, bplcon4); - if (timeframes) { - console_out_f (L"Average frame time: %.2f ms [frames: %d time: %d]\n", - (double)frametime / timeframes, timeframes, frametime); - if (total_skipped) - console_out_f (L"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; -} - -static int allocate_sprite_tables (void) -{ -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT - int num; - - delta_sprite_entry = 0; - delta_color_change = 0; - - if (!sprite_entries[0]) { - max_sprite_entry = DEFAULT_MAX_SPRITE_ENTRY; - max_color_change = DEFAULT_MAX_COLOR_CHANGE; - - for (num = 0; num < 2; num++) { - sprite_entries[num] = xmalloc (max_sprite_entry * sizeof (struct sprite_entry)); - color_changes[num] = xmalloc (max_color_change * sizeof (struct color_change)); - - if (sprite_entries[num] && color_changes[num]) { - memset (sprite_entries[num], 0, max_sprite_entry * sizeof (struct sprite_entry)); - memset (color_changes[num], 0, max_color_change * sizeof (struct color_change)); - } else - return 0; - } - } - - if (!spixels) { - spixels = xmalloc (2 * MAX_SPR_PIXELS * sizeof *spixels); - if (!spixels) - return 0; - } -#endif - return 1; -} - -int custom_init (void) -{ - - if (!allocate_sprite_tables ()) - return 0; - -#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, L"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 (L"%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 (BLTDAT) 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;//last_custom_value; - decide_line (hpos); - decide_fetch (hpos); - decide_blitter (hpos); - debug_wputpeek (0xdff000 + addr, l); - r = custom_wput_1 (hpos, addr, l, 1); - if (currprefs.chipset_mask & CSMASK_AGA) { - v = l; - last_custom_value1 = 0xffff; - } else if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) { - v = old; - } else { - if ((addr & 0x1fe) == 0) { - if (is_cycle_ce ()) - v = old; - else - v = l; - } else { - v = old; - } - } -#if CUSTOM_DEBUG > 0 - write_log (L"%08X read = %04X. Value written=%04X PC=%08x\n", 0xdff000 | addr, v, l, M68K_GETPC); -#endif - - } - return 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) -{ -#ifdef JIT - special_mem |= S_READ; -#endif - return custom_wget2 (addr & ~1) >> (addr & 1 ? 0 : 8); -} - -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) -{ - 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 (L"%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 (L"%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 (addr & 1) { - rval = 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); - } - if (warned < 10) { - if (M68K_GETPC < 0xe00000 || M68K_GETPC >= 0x10000000) { - write_log (L"Byte put to custom register %04X PC=%08X\n", addr, M68K_GETPC); - warned++; - } - } -} - -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 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; - update_mirrors (); - RW; /* 000 BLTDDAT */ - RW; /* 002 DMACONR */ - RW; /* 004 VPOSR */ - RW; /* 006 VHPOSR */ - RW; /* 008 DSKDATR (dummy register) */ - RW; /* 00A JOY0DAT */ - 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 = (i & 0x8000) ? 1 : 0; lol = (i & 0x0080); /* 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 = RW; /* 09A INTENA */ - intreq = intreqr = RW | 0x20; /* 09C 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; - diwhigh &= 0x7fff; - RW; /* 1E6 ? */ - RW; /* 1E8 ? */ - RW; /* 1EA ? */ - RW; /* 1EC ? */ - RW; /* 1EE ? */ - RW; /* 1F0 ? */ - RW; /* 1F2 ? */ - RW; /* 1F4 ? */ - RW; /* 1F6 ? */ - RW; /* 1F8 ? */ - RW; /* 1FA ? */ - 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 = malloc (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 (JOY0DAT ()); /* 00A JOY0DAT */ - SW (JOY1DAT ()); /* 00C JOY1DAT */ - SW (clxdat | 0x8000); /* 00E CLXDAT */ - SW (ADKCONR ()); /* 010 ADKCONR */ - SW (POT0DAT ()); /* 012 POT0DAT */ - SW (POT0DAT ()); /* 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 ? 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)); /* 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 (0); /* 1FA */ - 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 (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) -{ - 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 (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; -} - -#endif /* SAVESTATE */ - -void check_prefs_changed_custom (void) -{ - currprefs.gfx_framerate = changed_prefs.gfx_framerate; - 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.gfx_avsync != changed_prefs.gfx_avsync || - currprefs.gfx_pvsync != changed_prefs.gfx_pvsync || - currprefs.picasso96_nocustom != changed_prefs.picasso96_nocustom || - currprefs.ntscmode != changed_prefs.ntscmode) { - currprefs.picasso96_nocustom = changed_prefs.picasso96_nocustom; - currprefs.gfx_avsync = changed_prefs.gfx_avsync; - currprefs.gfx_pvsync = changed_prefs.gfx_pvsync; - 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; - currprefs.gfx_filter_filtermode = changed_prefs.gfx_filter_filtermode; -#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 < 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!) - -STATIC_INLINE int dma_cycle (void) -{ - int hpos, hpos_old; - - blitter_nasty = 1; - 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 (); -#ifdef DEBUGGER - if (debug_dma) { - dr = record_dma (0x1000, 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 - do_cycles_ce (2 * CYCLE_UNIT); - regs.ce020memcycles -= 2 * CYCLE_UNIT; - return v; -} - -uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode) -{ - return wait_cpu_cycle_read (addr, mode); -} - -void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v) -{ - int hpos; - - hpos = dma_cycle (); -#ifdef DEBUGGER - if (debug_dma) { - record_dma (0x1001, 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); - do_cycles_ce (2 * CYCLE_UNIT); - regs.ce020memcycles -= 2 * CYCLE_UNIT; -} - -void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v) -{ - wait_cpu_cycle_write (addr, mode, v); -} - -void do_cycles_ce (long cycles) -{ - static int extra; - - cycles += extra; - while (cycles >= 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); - cycles -= CYCLE_UNIT; - } - extra = cycles; -} - -int is_cycle_ce (void) -{ - int hpos = current_hpos (); - return cycle_line[hpos]; -} - -#endif - -int ispal (void) -{ - if (beamcon0 & 0x80) - return currprefs.ntscmode == 0; - return maxvpos >= MAXVPOS_NTSC + (MAXVPOS_PAL - MAXVPOS_NTSC) / 2; -} \ No newline at end of file diff --git a/custom.c b/custom.c index 929e0676..59b95b7d 100644 --- a/custom.c +++ b/custom.c @@ -183,6 +183,7 @@ uae_u16 beamcon0, new_beamcon0; uae_u16 vtotal = MAXVPOS_PAL, htotal = MAXHPOS_PAL; static uae_u16 hsstop, hbstrt, hbstop, vsstop, vbstrt, vbstop, hsstrt, vsstrt, hcenter; static int ciavsyncmode; +static int hstrt_nodetect; #define HSYNCTIME (maxhpos * CYCLE_UNIT); @@ -579,7 +580,7 @@ static void decide_diw (int hpos) /* Last hpos = hpos + 0.5, eg. normal PAL end hpos is 227.5 * 2 = 455 */ int pix_hpos = coord_diw_to_window_x (hpos == maxhpos ? hpos * 2 + 1 : hpos * 2); if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1 - && pix_hpos >= diwfirstword && last_diw_pix_hpos < diwfirstword) + && pix_hpos >= diwfirstword && !hstrt_nodetect && last_diw_pix_hpos < diwfirstword) { thisline_decision.diwfirstword = diwfirstword < 0 ? 0 : diwfirstword; hdiwstate = DIW_waiting_stop; @@ -2815,6 +2816,9 @@ static void calcdiw (void) vstop |= 0x100; } + // hstrt <= 1: diw start detector not active + hstrt_nodetect = hstrt <= 1; + diwfirstword = coord_diw_to_window_x (hstrt); diwlastword = coord_diw_to_window_x (hstop); if (diwfirstword >= diwlastword) { diff --git a/filesys.c b/filesys.c index 7ef9dd35..947c84b7 100644 --- a/filesys.c +++ b/filesys.c @@ -69,23 +69,6 @@ static uae_u32 dlg (uae_u32 a) return (dbg (a + 0) << 24) | (dbg (a + 1) << 16) | (dbg (a + 2) << 8) | (dbg (a + 3) << 0); } -static char *ua_fs (const TCHAR *src) -{ - return uacp (src, currprefs.win32_fscodepage); -} -static TCHAR *au_fs (const char *src) -{ - return aucp (src, currprefs.win32_fscodepage); -} -static TCHAR *au_fs_copy (TCHAR *dst, int maxlen, const char *src) -{ - return aucp_copy (dst, maxlen, src, currprefs.win32_fscodepage); -} -static char *ua_fs_copy (char *dst, int maxlen, const TCHAR *src) -{ - return uacp_copy (dst, maxlen, src, currprefs.win32_fscodepage); -} - static void aino_test (a_inode *aino) { #ifdef AINO_DEBUG diff --git a/include/sysdeps.h b/include/sysdeps.h index 4cfe712a..cd3a39d4 100644 --- a/include/sysdeps.h +++ b/include/sysdeps.h @@ -232,15 +232,17 @@ extern TCHAR *my_strdup (const TCHAR*s); extern TCHAR *my_strdup_ansi (const char*); extern TCHAR *au (const char*); extern char *ua (const TCHAR*); -extern TCHAR *aucp (const char*, unsigned int cp); -extern char *uacp (const TCHAR*, unsigned int cp); +extern TCHAR *aucp (const char *s, unsigned int cp); +extern char *uacp (const TCHAR *s, unsigned int cp); +extern TCHAR *au_fs (const char*); +extern char *ua_fs (const TCHAR*); extern char *ua_copy (char *dst, int maxlen, const TCHAR *src); extern TCHAR *au_copy (TCHAR *dst, int maxlen, const char *src); -extern char *uacp_copy (char *dst, int maxlen, const TCHAR *src, unsigned int cp); -extern TCHAR *aucp_copy (TCHAR *dst, int maxlen, const char *src, unsigned int cp); +extern char *ua_fs_copy (char *dst, int maxlen, const TCHAR *src); +extern TCHAR *au_fs_copy (TCHAR *dst, int maxlen, const char *src); extern char *uutf8 (const TCHAR *s); extern TCHAR *utf8u (const char *s); -extern int charset_test (const TCHAR *s, unsigned int cp); +extern void unicode_init (void); extern void *xmalloc (size_t); extern void *xcalloc (size_t, size_t); diff --git a/inputdevice.c b/inputdevice.c index a372f606..ea652e4d 100644 --- a/inputdevice.c +++ b/inputdevice.c @@ -1016,7 +1016,7 @@ static void mousehack_enable (void) mode |= 1; if (inputdevice_is_tablet () > 0) mode |= 2; - write_log (L"Tablet driver enabled (%s)\n", ((mode & 3) == 3 ? "tablet+mousehack" : ((mode & 3) == 2) ? "tablet" : "mousehack")); + write_log (L"Mouse driver enabled (%s)\n", ((mode & 3) == 3 ? L"tablet+mousehack" : ((mode & 3) == 2) ? L"tablet" : L"mousehack")); rtarea[off + MH_E] = 0x80; } @@ -1057,7 +1057,7 @@ void input_mousehack_status (int mode, uaecptr diminfo, uaecptr dispinfo, uaecpt dimensioninfo_dbl = (props & 0x00020000) ? 1 : 0; write_log (L"%08x %08x %08x (%dx%d)-(%dx%d) d=%dx%d %s\n", diminfo, props, vp, x1, y1, x2, y2, vp_xoffset, vp_yoffset, - (props & 0x00020000) ? "dbl" : ""); + (props & 0x00020000) ? L"dbl" : L""); } else if (mode == 2) { if (mousehack_alive_cnt == 0) mousehack_alive_cnt = -100; @@ -1362,7 +1362,7 @@ static void mousehack_helper (void) int x, y; int fdy, fdx, fmx, fmy; - if (currprefs.input_magic_mouse == 0 || currprefs.input_tablet < TABLET_MOUSEHACK) + if (currprefs.input_magic_mouse == 0 && currprefs.input_tablet < TABLET_MOUSEHACK) return; #if 0 if (kickstart_version >= 36) { @@ -1390,6 +1390,14 @@ static void mousehack_helper (void) y = y * fmy / 1000; x -= fdx * fmx / 1000 - 1; y -= fdy * fmy / 1000 - 2; + if (x < 0) + x = 0; + if (x >= gfxvidinfo.width) + x = gfxvidinfo.width - 1; + if (y < 0) + y = 0; + if (y >= gfxvidinfo.height) + y = gfxvidinfo.height - 1; x = coord_native_to_amiga_x (x); y = coord_native_to_amiga_y (y) << 1; } diff --git a/memory.c b/memory.c index 0940c4ae..2d0434f4 100644 --- a/memory.c +++ b/memory.c @@ -2673,6 +2673,39 @@ struct zfile *read_rom_name (const TCHAR *filename) return f; } +struct zfile *read_rom_name_guess (const TCHAR *filename) +{ + int i, j; + struct zfile *f; + TCHAR *name; + + for (i = _tcslen (filename) - 1; i >= 0; i--) { + if (filename[i] == '/' || filename[i] == '\\') + break; + } + if (i < 0) + return NULL; + name = &filename[i]; + + for (i = 0; i < romlist_cnt; i++) { + TCHAR *n = rl[i].path; + for (j = _tcslen (n) - 1; j >= 0; j--) { + if (n[j] == '/' || n[j] == '\\') + break; + } + if (j < 0) + continue; + if (!_tcsicmp (name, n + j)) { + struct romdata *rd = rl[i].rd; + f = read_rom (&rd); + if (f) { + write_log (L"ROM %s not found, using %s\n", filename, rl[i].path); + return f; + } + } + } + return NULL; +} static void kickstart_fix_checksum (uae_u8 *mem, int size) { @@ -2931,6 +2964,8 @@ static int load_kickstart (void) if (f == NULL) { _stprintf (currprefs.romfile, L"%s../System/rom/kick.rom", start_path_data); f = rom_fopen (currprefs.romfile, L"rb", ZFD_NORMAL); + if (f == NULL) + f = read_rom_name_guess (tmprom); } } } diff --git a/od-win32/avioutput.c b/od-win32/avioutput.c index b2245292..b8202d5a 100644 --- a/od-win32/avioutput.c +++ b/od-win32/avioutput.c @@ -860,7 +860,7 @@ static int getFromBuffer (struct avientry *ae, int original) if (original) { src = getfilterbuffer (&w, &h, &spitch, &d); } else { - spitch = ((avioutput_width * avioutput_bits + 31) & ~31) / 8; + spitch = gfxvidinfo.rowbytes; src = bufmem_ptr; } if (!src) diff --git a/od-win32/fsdb_win32.c b/od-win32/fsdb_win32.c index 0e4795cf..0c836dc0 100644 --- a/od-win32/fsdb_win32.c +++ b/od-win32/fsdb_win32.c @@ -268,9 +268,11 @@ static a_inode *aino_from_buf (a_inode *base, uae_u8 *buf, int *winmode) } /* Return nonzero for any name we can't create on the native filesystem. */ -int fsdb_name_invalid (const TCHAR *n) +static int fsdb_name_invalid_2 (const TCHAR *n) { int i; + static char s1[MAX_DPATH]; + static WCHAR s2[MAX_DPATH]; TCHAR a = n[0]; TCHAR b = (a == '\0' ? a : n[1]); TCHAR c = (b == '\0' ? b : n[2]); @@ -299,7 +301,7 @@ int fsdb_name_invalid (const TCHAR *n) /* spaces and periods at the end are a no-no */ i = l - 1; if (n[i] == '.' || n[i] == ' ') - return 1; + return -1; /* these characters are *never* allowed */ for (i = 0; i < NUM_EVILCHARS; i++) { @@ -309,10 +311,27 @@ int fsdb_name_invalid (const TCHAR *n) /* the reserved fsdb filename */ if (_tcscmp (n, FSDB_FILE) == 0) + return -1; + + s1[0] = 0; + s2[0] = 0; + ua_fs_copy (s1, MAX_DPATH, n); + au_fs_copy (s2, MAX_DPATH, s1); + if (_tcsicmp (s2, n) != 0) return 1; + return 0; /* the filename passed all checks, now it should be ok */ } +int fsdb_name_invalid (const TCHAR *n) +{ + int v = fsdb_name_invalid_2 (n); + if (v <= 0) + return v; + write_log (L"FILESYS: '%s' illegal filename\n", n); + return v; +} + uae_u32 filesys_parse_mask(uae_u32 mask) { return mask ^ 0xf; diff --git a/od-win32/unicode.c b/od-win32/unicode.c index 09a0ed73..4917f515 100644 --- a/od-win32/unicode.c +++ b/od-win32/unicode.c @@ -4,7 +4,12 @@ #include "sysconfig.h" #include "sysdeps.h" -#define DWFLAGS (WC_COMPOSITECHECK | WC_DISCARDNS) +#include "options.h" + +#define DWFLAGS (0) +#define FS_TEST 0 + +static WCHAR aufstable[256]; static void err (const char *func, const WCHAR *w, const char *c, UINT cp) { @@ -69,13 +74,13 @@ static char *ua_2 (const WCHAR *s, UINT cp) if (s == NULL) return NULL; - len = WideCharToMultiByte (cp, DWFLAGS, s, -1, NULL, 0, 0, FALSE); + len = WideCharToMultiByte (cp, 0, s, -1, NULL, 0, 0, FALSE); if (!len) { err (__FUNCTION__, s, NULL, cp); return strdup (""); } d = xmalloc (len + 1); - WideCharToMultiByte (cp, DWFLAGS, s, -1, d, len, 0, FALSE); + WideCharToMultiByte (cp, 0, s, -1, d, len, 0, FALSE); return d; } @@ -136,18 +141,123 @@ char *uacp_copy (char *dst, int maxlen, const TCHAR *src, UINT cp) return dst; } -int charset_test (const TCHAR *s, UINT cp) +TCHAR *my_strdup_ansi (const char *src) { - static char s1[MAX_DPATH]; - static WCHAR s2[MAX_DPATH]; - s1[0] = 0; - s2[0] = 0; - uacp_copy (s1, MAX_DPATH, s, cp); - aucp_copy (s2, MAX_DPATH, s1, cp); - return !_tcscmp (s2, s); + return au (src); } -TCHAR *my_strdup_ansi (const char *src) +char *ua_fs (const WCHAR *s) { - return au (src); + char *d; + int len, i; + BOOL dc; + char def = 0; + + if (s == NULL) + return NULL; + dc = FALSE; + len = WideCharToMultiByte (28605, DWFLAGS | WC_NO_BEST_FIT_CHARS, s, -1, NULL, 0, &def, &dc); + if (!len) { + err (__FUNCTION__, s, NULL, currprefs.win32_fscodepage); + return strdup (""); + } + d = xmalloc (len + 1); + dc = FALSE; + WideCharToMultiByte (28605, DWFLAGS | WC_NO_BEST_FIT_CHARS, s, -1, d, len, &def, &dc); + if (dc) { + for (i = 0; i < len; i++) { + if (d[i] == 0 || (d[i] < 32 || (d[i] >= 0x7f && d[i] <= 0x9f))) { + WCHAR s2[2]; + char d2[2]; + s2[0] = s[i]; + s2[1] = 0; + d2[0] = (char)s[i]; + WideCharToMultiByte (0, DWFLAGS, s2, -1, d2, 1, 0, FALSE); + d[i] = d2[0]; + } + } + } + return d; +} + +char *ua_fs_copy (char *dst, int maxlen, const TCHAR *src) +{ + int len, i; + BOOL dc; + char def = 0; + + if (src == NULL) + return NULL; + dc = FALSE; + len = WideCharToMultiByte (28605, DWFLAGS | WC_NO_BEST_FIT_CHARS, src, -1, dst, maxlen, &def, &dc); + if (dc) { + for (i = 0; i < len; i++) { + if (dst[i] == 0) { + WCHAR s2[2]; + char d2[2]; + s2[0] = src[i]; + s2[1] = 0; + d2[0] = (char)src[i]; + WideCharToMultiByte (0, DWFLAGS, s2, -1, d2, 1, 0, FALSE); + dst[i] = d2[0]; + } + } + } + return dst; +} + +WCHAR *au_fs (const char *s) +{ + int i, len; + WCHAR *d; + + len = strlen (s); + d = xmalloc ((len + 1) * sizeof (WCHAR)); + for (i = 0; i < len; i++) + d[i] = aufstable[(uae_u8)s[i]]; + d[len] = 0; + return d; +} +WCHAR *au_fs_copy (TCHAR *dst, int maxlen, const char *src) +{ + int i; + + for (i = 0; src[i] && i < maxlen - 1; i++) + dst[i] = aufstable[(uae_u8)src[i]]; + dst[i] = 0; + return dst; +} + +void unicode_init (void) +{ + int i; + + write_log (L"Filesystem charset conversion table:\n"); + for (i = 0; i < 256; i++) { + TCHAR dst1[2], dst2[2]; + char src[2]; + + src[0] = i; + src[1] = 0; + dst1[0] = 0; + dst1[1] = 0; + dst2[0] = 0; + dst2[1] = 0; + aufstable[i] = 0; + aucp_copy (dst1, 1, src, 0); + aucp_copy (dst2, 1, src, 28605); // iso-8859-15 + if (dst2[0] != dst1[0]) + write_log (L" %02X: %04X (%04X)", i, dst1[0], dst2[0]); + else + write_log (L" %02X: %04X ", i, dst1[0]); + if ((i & 3) == 3) + write_log (L"\n"); + if (i < 32 || (i >= 0x7f && i <= 0x9f)) + aufstable[i] = dst1[0]; + else + aufstable[i] = dst2[0]; + if (aufstable[i] == 0) + aufstable[i] = (unsigned char)i; + } + write_log (L"End\n"); } diff --git a/od-win32/win32.c b/od-win32/win32.c index ae37dcab..fc8028db 100644 --- a/od-win32/win32.c +++ b/od-win32/win32.c @@ -1930,6 +1930,7 @@ static int WIN32_InitLibraries (void) pre_gui_message (L"MMTimer second initialization failed, exiting.."); return 0; } + write_log (L"ACP=%u\n", GetACP ()); pSetCurrentProcessExplicitAppUserModelID = (SETCURRENTPROCESSEXPLICITAPPUSERMODEIDD)GetProcAddress ( GetModuleHandle (L"shell32.dll"), "SetCurrentProcessExplicitAppUserModelID"); if (pSetCurrentProcessExplicitAppUserModelID) @@ -4285,6 +4286,7 @@ static int PASCAL WinMain2 (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR WIN32_InitLang (); WIN32_InitHtmlHelp (); DirectDraw_Release (); + unicode_init (); if (betamessage ()) { keyboard_settrans (); #ifdef CATWEASEL diff --git a/od-win32/win32.h b/od-win32/win32.h index c8314512..d7f98983 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -18,8 +18,8 @@ #define WINUAEPUBLICBETA 1 #define LANG_DLL 1 -#define WINUAEBETA L"Beta 1" -#define WINUAEDATE MAKEBD(2009, 12, 18) +#define WINUAEBETA L"Beta 2" +#define WINUAEDATE MAKEBD(2009, 12, 20) #define WINUAEEXTRA L"" #define WINUAEREV L"" diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index a57bfa9a..17a5cb5c 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,4 +1,16 @@ +- if rom load fails, try to find matching rom file using rom scanner + data by comparing file names without paths +- improved file/directory name Amiga<>unicode conversion +- hide directory filesystem file/directory names if they have characters + that do not exist in Amiga charset (again, was accidentally changed in + 1.6.0), they would have been inaccessible anyway +- non-tablet mouse driver mode was not enabled without magic mouse +- fixed potential crash in mouse driver mode +- "capture before filtering" not enabled mode was broken (b1) +- DIWSTRT hpos <=1: DIW state machine does not change (stop hpos > + max was emulated long long time ago) + Beta 1: - blitter linedraw onedot mode was partially broken in non-ce modes (2.0) diff --git a/od-win32/writelog.c b/od-win32/writelog.c index d05bc9bc..23b22a65 100644 --- a/od-win32/writelog.c +++ b/od-win32/writelog.c @@ -15,15 +15,24 @@ static void premsg (void) { +#if 0 static int done; char *as; + char ast[32]; TCHAR *ws; - return; if (done) return; done = 1; + ast[0] = 'A'; + ast[1] = 0x7f; + ast[2] = 0x80; + ast[3] = 0x81; + ast[4] = 0x9f; + ast[5] = 0; + ws = au_fs (ast); + MessageBoxA(NULL, "español", "ANSI", MB_OK); MessageBoxW(NULL, L"español", L"UTF-16", MB_OK); @@ -40,6 +49,7 @@ static void premsg (void) MessageBoxA(NULL, as, "ANSI:3", MB_OK); xfree (ws); xfree (as); +#endif } #define SHOW_CONSOLE 0 @@ -375,6 +385,9 @@ void write_log (const TCHAR *format, ...) if (!cs_init) return; + + premsg(); + EnterCriticalSection (&cs); va_start (parms, format); bufp = buffer; @@ -476,8 +489,6 @@ void *log_open (const TCHAR *name, int append, int bootlog) } } - premsg(); - return f; } -- 2.47.3